source: people/joerg.steffens/technical/spacecmd/stage.py @ 1082

Last change on this file since 1082 was 1082, checked in by joergs, 11 years ago

main function have been integrated to spacecmd upstream (1.8) and therefore removed here. Remaining code adapted to new code base

File size: 25.6 KB
Line 
1#
2# Licensed under the GNU General Public License Version 3
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17#
18# Copyright 2011,2012 Joerg Steffens <joerg.steffens@dass-it.de>
19#
20
21# NOTE: the 'self' variable is an instance of SpacewalkShell
22
23import shlex
24from optparse import Option
25from pprint import pprint
26import sys
27from spacecmd.utils import *
28
29_STAGE1='dev'
30_STAGE2='stg'
31_STAGE3='prd'
32
33_STAGES=[ _STAGE1, _STAGE2, _STAGE3 ]
34
35_STAGE_NAMES={
36    'dev': 'Development',
37    # alternative
38    'qas': 'QualityAssurance',
39    'stg': 'Staging',
40    'prd': 'Production'
41}
42_STAGE_TRANSITIONS={
43    _STAGE1: _STAGE2,
44    _STAGE2: _STAGE3
45}
46_STAGE_STATUS={
47    "uptodate":  " ",
48    "modified":  "M",
49    "dontexist": "!",
50    "unknown":   "?"
51}
52
53_DUMP_BASE_DIR="/tmp/spacecmd-stage-dump/"
54
55####################
56
57def do_stage_help( self, args, doreturn = False ):
58    print """
59Staging:
60
61The basic principle is to have every component in multiple stages.
62The stages in this environment are:"""
63    for stage in _STAGES:
64        successor=self.get_next_stage(stage)
65        print "    " + stage + ":" , _STAGE_NAMES.get(stage)
66
67    print """
68A stage can have a successor, in our enviroment these are:"""
69    for stage in _STAGES:
70        successor=self.get_next_stage(stage)
71        if successor:
72            print "    " + stage, "->" , successor
73
74    print """
75Workflow example:
76  * creating a new package/package version
77    the new package is added to a {stage1} softwarechannel.
78    If the package seams to work correctly,
79    a new integration phase can be started.
80    For this, the packages are copied from {stage1} to {stage2}.
81    The {stage2} stage is then tested.
82    After a successful test, all content of {stage2} is transfered to {stage3}.
83    When the content has arrived in {stage3},
84    all productively used systems are able to update to the new content.
85
86Summary:
87  {stage1}: all changes are done to {stage1}
88  {stage2}: integration tests are done in {stage2} only
89  {stage3}: productively used systems using {stage3} only
90
91Changes are not only adding new packages,
92but also changing configuration files in the configuration channels,
93changing kickstart settings or changing activation keys.
94
95For all these changes, spacecmd stage_* commands offers functionality
96to simplify staging.
97
98Usage:
99  * create your channels, actionvationkey and so on.
100    Because Spacewalk does not know about staging directly,
101    staging information must be coded into the name of the components.
102    The name must include the stage, separeted by '-',
103    eg. centos6-x86_64-{stage1}, centos6-x86_64-{stage1}-subchannel, ks-centos6-x86_64-{stage1}-common, ...
104    To create a initial structure, the comamnd 'stage_create_skel' can be used.
105
106  * check the staging status by 'stage_status STAGE'
107    This will select all components from stage 'STAGE' and compare each component with the correcponding component from the successor stage, eg.:
108    'stage_status {stage1}'
109    INFO: softwarechannel
110      centos6-x86_64-{stage1}                               -> centos6-x86_64-{stage2}
111    M   centos6-x86_64-{stage1}-app1                        ->   centos6-x86_64-{stage2}-app1
112    !   centos6-x86_64-{stage1}-app2
113    INFO: configchannel
114      cfg-centos6-x86_64-{stage1}-app1                      -> cfg-centos6-x86_64-{stage2}-app1
115    INFO: kickstart
116    M ks-centos6-x86_64-{stage1}-app1                       -> ks-centos6-x86_64-{stage2}-app1
117    INFO: activationkey
118      1-centos6-x86_64-{stage1}-app1                        -> 1-centos6-x86_64-{stage2}-app1
119
120    This first column indicates the state:
121      : empty: no differences. The components from both stages are indentical
122    ! : no correcponding component in successor stage found
123    M : modification. The component differs between the current and the successor stage
124
125  * The most interessting entries are the modified entires.
126    To check this more specifically, use the corresponding 'stage_*_diff' function, eg.
127    'stage_softwarechannel_diff centos7-x86_64-{stage1}-app1'
128    --- centos6-x86_64-{stage1}-app1
129
130    +++ centos6-x86_64-{stage2}-app1
131
132    @@ -1,1 +1,0 @@
133
134    -newpackage-1.0.1-1.1.noarch
135
136    (it is also possible to compare two specific subchannel, eg.
137    'stage_softwarechannel_diff centos6-x86_64-{stage1}-subchannel1 centos6-x86_64-{stage2}-subchannel1'
138    but the corresponding successor stage component is found automatically by its name)
139
140  * Softwarechannel and configchannel also offers the stage_*_sync function.
141    Use them, to copy the content of a component to the next stage, e.g.
142    'stage_softwarechannel_sync centos6-x86_64-{stage1}-app1'
143    INFO: syncing packages from softwarechannel centos6-x86_64-{stage1}-app1 to centos6-x86_64-{stage2}-app1
144    packages to add to channel "centos6-x86_64-{stage2}-app1":
145    newpackage-1.0.1-1.1.noarch
146    Perform these changes to channel centos6-x86_64-{stage2}-app1 [y/N]:
147
148  * Repeat these steps, until 'stage_status STAGE' shows no differences between the two stages
149    """.format(stage1=_STAGE1, stage2=_STAGE2, stage3=_STAGE3)
150
151def help_stage_create_skel(self):
152    print 'stage_create_skel: create initial staging structure'
153    print '''usage: stage_create_skel [options]
154
155options:
156  -l LABEL
157  -a ARCHITECTURE ['ia32', 'x86_64']
158  -s SUB (e.g. application1)'''
159
160def do_stage_create_skel(self, args):
161    options = [
162                Option('-l', '--label', action='store'),
163                Option('-a', '--arch',  action='store'),
164                Option('-s', '--sub',  action='store'),
165               ]
166
167    (args, options) = parse_arguments(args, options)
168
169    if is_interactive(options):
170        options.label = prompt_user('Channel Label:', noblank = True)
171
172        print
173        print 'Architecture'
174        print '------------'
175        print '\n'.join(sorted(self.ARCH_LABELS))
176        print
177        options.arch = prompt_user('Select:')
178        options.arch = prompt_user('Sub:')
179    else:
180        if not options.label:
181            logging.error('A channel label is required')
182            return
183
184        if not options.arch:
185            logging.error('An architecture is required')
186            return
187
188    if self.stage_create_skel( options.label, options.arch, options.sub, create=False ):
189        self.stage_create_skel( options.label, options.arch, options.sub, create=True )
190
191
192def stage_create_skel(self, dist, arch, sub, create = False):
193
194    org         = "1"
195    disttype    = "rhel_6"
196    application = sub
197
198    print
199    for stage in _STAGES:
200        base                 = dist + "-" + arch + "-" + stage
201        softwarechannel_base = base
202        softwarechannel_sub  = base + "-" + application
203        distribution         = "dist-"   + base
204        distributionpath     = "/srv/dist/" + base
205        configchannel        = "cfg-"    + base + "-" + application
206        activationkey_create = base + "-" + application
207        activationkey        = org + "-" + activationkey_create
208        kickstart            = "ks-"     + base + "-" + application
209
210        print "stage: " + stage
211
212        print "softwarechannel base:       " + softwarechannel_base,
213        if self.is_softwarechannel( softwarechannel_base ):
214            print " [exists]",
215        elif create:
216            self.do_softwarechannel_create( "-n " + softwarechannel_base + " -l " + softwarechannel_base + " -a " + arch )
217        print
218
219        print "softwarechannel subchannel: " + softwarechannel_sub,
220        if self.is_softwarechannel( softwarechannel_sub ):
221            print " [exists]",
222        elif create:
223            self.do_softwarechannel_create( "-n " + softwarechannel_sub  + " -l " + softwarechannel_sub  + " -a " + arch + " -p " + base )
224        print
225
226
227        print "distribution:               " + distribution + " (distribution path: " + distributionpath + ")",
228        if distribution in self.do_distribution_list(distribution, True):
229            print " [exists]",
230        elif create:
231            self.do_distribution_create( "--name " + distribution + " --path " + distributionpath + " --base-channel " + base + " --install-type " + disttype )
232        print
233
234        print "configchannel:              " + configchannel,
235        if self.is_configchannel( configchannel ):
236            print " [exists]",
237        elif create:
238            self.do_configchannel_create( "-n " + configchannel )
239        print
240
241        print "activationkey:              " + activationkey,
242        if self.is_activationkey( activationkey ):
243            print " [exists]",
244        elif create:
245            self.do_activationkey_create( "-n " + activationkey_create + " -d " + activationkey + " -b " + base + " -e provisioning_entitled" )
246            self.do_activationkey_addchildchannels( activationkey + " " + softwarechannel_sub )
247            self.do_activationkey_enableconfigdeployment( activationkey )
248            self.do_activationkey_addconfigchannels( activationkey + " " + configchannel + " -t" )
249        print
250
251        print "kickstart:                  " + kickstart,
252        if self.is_kickstart( kickstart ):
253            print " [exists]",
254        elif create:
255            self.do_kickstart_create( "--name=" + kickstart + " --distribution=" + distribution + " --root-password=CHANGEME --virt-type=none" )
256            self.do_kickstart_addactivationkeys( kickstart + " " + activationkey )
257            self.do_kickstart_enableconfigmanagement( kickstart )
258            self.do_kickstart_enablelogging( kickstart )
259        print
260
261        print
262
263    if not create:
264        print "Make sure, distribution trees are available at the specified distribution paths."
265        return self.user_confirm('Create this components [y/N]:')
266
267
268
269####################
270
271#
272# helper functions
273#
274
275def is_stage( self, name ):
276    return name in _STAGES
277
278def check_stage( self, name ):
279    """Checks if name describes a vaild stage"""
280    if not name:
281        logging.error( "no stage given" )
282        return False
283    if not self.is_stage( name ):
284        logging.error( "invalid stage " + name )
285        return False
286    return True
287
288def is_current_stage(self, name):
289    return "-"+self.stage in name
290
291def get_common_name( self, name ):
292    """Returns the name with the stage replaced by 'STAGE'
293
294    To check the differences from 2 components that are in different stages,
295    the specific stage is replaced by the word 'STAGE'
296    """
297    return self.replace_stage_in_name( name, self.stage, "STAGE" )
298
299
300def get_stage_from_name( self, name ):
301    for i in _STAGES:
302        if "-"+i in name:
303            return i
304
305def get_next_stage( self, current_stage ):
306    return _STAGE_TRANSITIONS.get(current_stage)
307
308def replace_stage_in_name( self, name, current_stage, new_stage ):
309    """Return the name with current stage replaced by new stage"""
310    return name.replace( "-"+current_stage, "-"+new_stage )
311
312def get_next_stage_name( self, name ):
313    current_stage = self.get_stage_from_name( name )
314    if not current_stage:
315        return
316    next_stage = self.get_next_stage( current_stage )
317    if not next_stage:
318        return
319    next_stage_name = self.replace_stage_in_name( name, current_stage, next_stage )
320    return next_stage_name
321
322def print_stage_status( self, name, name_next=None, status="unknown", indent="" ):
323    width=48-len(indent)
324    string = '{status_code} {indent}{name:{width}}'.format(status_code=_STAGE_STATUS.get(status), indent=indent, name=name, width=width )
325    if name_next:
326        string = string + " -> " + indent + name_next
327    print string
328
329def mkdir(self, name ):
330    try:
331        if not os.path.isdir( name ):
332            os.makedirs( name )
333            logging.debug( "creating directory " + name )
334        return True
335    except:
336        logging.error('Failed to create directory ' + name )
337        return False
338
339def dump(self, filename, data, raw=False):
340    """Writes data to filename"""
341    if not self.mkdir( os.path.dirname( filename )): return False
342    try:
343        fh = open( filename, 'w' )
344        if( raw ):
345            fh.write(data)
346        else:
347            fh.write("\n".join(data))
348        fh.close()
349    except:
350        logging.error('failed to create file ' + filename )
351        return False
352
353
354####################
355
356#
357# softwarechannel
358#
359
360def get_softwarechannel_childchannel( self, base_channel ):
361    result=[]
362    for child_channel in self.list_child_channels():
363        details = self.client.channel.software.getDetails(\
364                            self.session, child_channel)
365        if details.get('parent_channel_label') == base_channel:
366            result.append( child_channel )
367    return result
368
369   
370   
371# softwarechannel next
372
373def help_stage_softwarechannel_next(self):
374    print 'stage_softwarechannel_next: get softwarechannel name for the next stage'
375    print '                       '
376    print 'usage: stage_softwarechannel_next CHANNEL'
377
378def complete_stage_softwarechannel_next(self, text, line, beg, end):
379    parts = shlex.split(line)
380    if line[-1] == ' ': parts.append('')
381    args = len(parts)
382
383    if args == 2:
384        return tab_completer(self.do_softwarechannel_list('', True), text)
385    return []
386
387def do_stage_softwarechannel_next(self, args):
388    (args, options) = parse_arguments(args)
389
390    if len(args) != 1:
391        self.help_stage_softwarechannel_next()
392        return
393
394    source_name = args[0]
395    if not self.is_softwarechannel(source_name):
396        logging.warning( "invalid softwarechannel "+source_name )
397        return
398    logging.debug( "source: " + str(source_name) )
399    target_name = self.get_next_stage_name( source_name )
400    logging.debug( "target: " + str(target_name) )
401    if not target_name: return
402    # check target name
403    if not self.is_softwarechannel(target_name):
404        logging.debug( "a next stage softwarechannel for "+source_name+" ("+target_name+") does not exist" )
405        return
406
407    return target_name
408
409
410
411####################
412
413#
414# configchannel
415#
416
417# configchannel next
418
419def help_stage_configchannel_next(self):
420    print 'stage_configchannel_next: get configchannel name for the next stage'
421    print '                       '
422    print 'usage: stage_configchannel_next CHANNEL'
423
424def complete_stage_configchannel_next(self, text, line, beg, end):
425    parts = shlex.split(line)
426    if line[-1] == ' ': parts.append('')
427    args = len(parts)
428
429    if args == 2:
430        return tab_completer(self.do_configchannel_list('', True), text)
431    return []
432
433def do_stage_configchannel_next(self, args):
434    (args, options) = parse_arguments(args)
435
436    if len(args) != 1:
437        self.help_stage_configchannel_next()
438        return
439
440    source_name = args[0]
441    if not self.is_configchannel(source_name):
442        logging.warning( "invalid configchannel "+source_name )
443        return
444    logging.debug( "source: " + str(source_name) )
445    target_name = self.get_next_stage_name( source_name )
446    logging.debug( "target: " + str(target_name) )
447    if not target_name: return
448    # check target name
449    if not self.is_configchannel(target_name):
450        logging.debug( "a next stage configchannel for "+source_name+" ("+target_name+") does not exist" )
451        return
452    return target_name
453
454
455####################
456
457#
458# kickstart
459#
460
461# kickstart next
462
463def help_stage_kickstart_next(self):
464    print 'stage_kickstart_next: get kickstart name for the next stage'
465    print '                       '
466    print 'usage: stage_kickstart_next CHANNEL'
467
468def complete_stage_kickstart_next(self, text, line, beg, end):
469    parts = shlex.split(line)
470    if line[-1] == ' ': parts.append('')
471    args = len(parts)
472
473    if args == 2:
474        return tab_completer(self.do_kickstart_list('', True), text)
475    return []
476
477def do_stage_kickstart_next(self, args):
478    (args, options) = parse_arguments(args)
479
480    if len(args) != 1:
481        self.help_stage_kickstart_next()
482        return
483
484    source_name = args[0]
485    if not self.is_kickstart(source_name):
486        logging.warning( "invalid kickstart "+source_name )
487        return
488    logging.debug( "source: " + str(source_name) )
489    target_name = self.get_next_stage_name( source_name )
490    logging.debug( "target: " + str(target_name) )
491    if not target_name: return
492    # check target name
493    if not self.is_kickstart(target_name):
494        logging.debug( "a next stage kickstart for "+source_name+" ("+target_name+") does not exist" )
495        return
496    return target_name
497
498####################
499
500#
501# activationkey
502#
503
504# activationkey next
505
506def help_stage_activationkey_next(self):
507    print 'stage_activationkey_next: get activationkey name for the next stage'
508    print '                       '
509    print 'usage: stage_activationkey_next CHANNEL'
510
511def complete_stage_activationkey_next(self, text, line, beg, end):
512    parts = shlex.split(line)
513    if line[-1] == ' ': parts.append('')
514    args = len(parts)
515
516    if args == 2:
517        return tab_completer(self.do_activationkey_list('', True), text)
518    return []
519
520def do_stage_activationkey_next(self, args):
521    (args, options) = parse_arguments(args)
522
523    if len(args) != 1:
524        self.help_stage_activationkey_next()
525        return
526
527    source_name = args[0]
528    if not self.is_activationkey(source_name):
529        logging.warning( "invalid activationkey "+source_name )
530        return
531    logging.debug( "source: " + str(source_name) )
532    target_name = self.get_next_stage_name( source_name )
533    logging.debug( "target: " + str(target_name) )
534    if not target_name: return
535    # check target name
536    if not self.is_activationkey(target_name):
537        logging.debug( "a next stage activationkey for "+source_name+" ("+target_name+") does not exist" )
538        return
539    return target_name
540
541
542####################
543
544#
545# stage_status
546# stage_*_status
547#
548
549def help_stage_status(self):
550    print 'stage_status: status of a stage'
551    print ''
552    print 'usage: stage_status STAGE\n'
553    print 'STAGE: ' + " | ".join( _STAGES )
554
555def complete_stage_status(self, text, line, beg, end):
556    parts = shlex.split(line)
557    if line[-1] == ' ': parts.append('')
558    args = len(parts)
559
560    if args == 2:
561        return tab_completer( _STAGES, text)
562
563    return []
564
565def do_stage_status(self, args):
566    (args, options) = parse_arguments(args)
567
568    if not len(args):
569        self.help_stage_status()
570        return
571
572    stage = args[0]
573    if not self.check_stage( stage ): return
574    self.stage = stage
575
576    self.stage_softwarechannels_status()
577    self.stage_configchannels_status()
578    self.stage_kickstarts_status()
579    self.stage_activationkeys_status()
580
581def stage_softwarechannels_status( self ):
582    logging.info( "softwarechannel" )
583    base_channels = self.list_base_channels()
584    for base_channel in base_channels:
585        if self.is_current_stage( base_channel ):
586            self.check_stage_softwarechannel_status( base_channel, indent="" )
587            for child_channel in self.get_softwarechannel_childchannel( base_channel ):
588                self.check_stage_softwarechannel_status( child_channel, indent="  " )
589
590def check_stage_softwarechannel_status( self, name, indent="" ):
591    status="unknown"
592    name_next = self.do_stage_softwarechannel_next( name )
593    if name_next:
594        if self.do_softwarechannel_diff( name + " " + name_next ):
595            status="modified"
596        else:
597            status="uptodate"
598    else:
599        status="dontexist"
600    print_stage_status( self, name, name_next=name_next, status=status, indent=indent )
601    return status
602
603
604def stage_configchannels_status( self ):
605    logging.info( "configchannel" )
606    configchannels = self.do_configchannel_list('', True)
607
608    for name in configchannels:
609        if self.is_current_stage( name ):
610            self.check_stage_configchannels_status( name )
611
612def check_stage_configchannels_status( self, name, indent="" ):
613    status="unknown"
614    name_next = self.do_stage_configchannel_next( name )
615    if name_next:
616        if self.do_configchannel_diff( name + " " + name_next ):
617            status="modified"
618        else:
619            status="uptodate"
620    else:
621        status="dontexist"
622    print_stage_status( self, name, name_next=name_next, status=status, indent=indent )
623    return status
624
625
626
627def stage_kickstarts_status( self ):
628    logging.info( "kickstart" )
629    kickstarts = self.do_kickstart_list('', True)
630
631    for name in kickstarts:
632        if self.is_current_stage( name ):
633            self.check_stage_kickstarts_status( name )
634
635def check_stage_kickstarts_status( self, name, indent="" ):
636    status="unknown"
637    name_next = self.do_stage_kickstart_next( name )
638    if name_next:
639        if self.do_kickstart_diff( name + " " + name_next ):
640            status="modified"
641        else:
642            status="uptodate"
643    else:
644        status="dontexist"
645    print_stage_status( self, name, name_next=name_next, status=status, indent=indent )
646    return status
647
648
649
650def stage_activationkeys_status( self ):
651    logging.info( "activationkey" )
652    activationkeys = self.do_activationkey_list('', True)
653
654    for name in activationkeys:
655        if self.is_current_stage( name ):
656            self.check_stage_activationkey_status( name )
657
658def check_stage_activationkey_status( self, name, indent="" ):
659    status="unknown"
660    name_next = self.do_stage_activationkey_next( name )
661    if name_next:
662        if self.do_activationkey_diff( name + " " + name_next ):
663            status="modified"
664        else:
665            status="uptodate"
666    else:
667        status="dontexist"
668    print_stage_status( self, name, name_next=name_next, status=status, indent=indent )
669    return status
670
671
672
673####################
674
675#
676# stage_dump
677# dump_*
678#
679
680def help_stage_dump(self):
681    print 'stage_dump: dump infos about a stage to files'
682    print ''
683    print 'usage: stage_dump STAGE [OUTDIR]\n'
684    print 'STAGE: ' + " | ".join( _STAGES )
685    print 'OUTDIR defaults to ' + _DUMP_BASE_DIR
686
687def complete_stage_dump(self, text, line, beg, end):
688    parts = shlex.split(line)
689    if line[-1] == ' ': parts.append('')
690    args = len(parts)
691
692
693    if args == 2:
694        return tab_completer( _STAGES, text)
695
696    return []
697
698def do_stage_dump(self, args):
699    (args, options) = parse_arguments(args)
700
701    if not len(args):
702        self.help_stage_dump()
703        return
704
705    stage = args[0]
706    if not self.check_stage( stage ): return
707    self.stage = stage
708
709    if len(args) == 2:
710        outputpath_base = datetime.now().strftime(os.path.expanduser(args[1]))
711    else:
712        # make the final output path be <base>/date/channel
713        outputpath_base = os.path.join( _DUMP_BASE_DIR,
714                                        datetime.now().strftime("%Y-%m-%d"),
715                                        stage )
716
717    if not self.mkdir( outputpath_base ): return
718
719    self.dump_softwarechannels( outputpath_base + "/softwarechannel/" )
720    self.dump_configchannels( outputpath_base + "/configchannel/" )
721    self.dump_kickstarts( outputpath_base + "/kickstart/" )
722    self.dump_activationkeys( outputpath_base + "/activationkey/" )
723
724   
725   
726def dump_softwarechannels(self, basedir):
727    logging.info( "softwarechannel" )
728    base_channels = self.list_base_channels()
729    for base_channel in base_channels:
730        if self.is_current_stage( base_channel ):
731            logging.info( "  " + base_channel )
732            base_channel_dir = basedir + self.get_common_name(base_channel)
733            if not self.mkdir( base_channel_dir ): return
734
735            packages = self.do_softwarechannel_listallpackages( base_channel, doreturn=True )
736            self.dump( base_channel_dir + '/' + self.get_common_name(base_channel), packages )
737            # get all child channels and pick the channels that belongs to the base channel
738            for child_channel in self.get_softwarechannel_childchannel( base_channel ):
739                logging.info( "    " + child_channel )
740                packages = self.dump_softwarechannel( child_channel )
741                self.dump( base_channel_dir + '/' + self.get_common_name(child_channel), packages )
742
743               
744               
745def dump_configchannels(self, basedir):
746    logging.info( "configchannel" )
747    configchannels = self.do_configchannel_list( '', doreturn = True)
748
749    for name in configchannels:
750        if self.is_current_stage( name ):
751            logging.info( "  " + name )
752            directory = basedir + self.get_common_name(name)
753            self.do_configchannel_backup( name+" "+directory )   
754
755           
756def dump_kickstarts(self, basedir):
757    logging.info( "kickstart" )
758    kickstarts = self.client.kickstart.listKickstarts(self.session)
759
760    for kickstart in kickstarts:
761        name = kickstart.get('name')
762        if self.is_current_stage( name ):
763            logging.info( "  " + name )
764            dir = basedir + self.get_common_name(name)
765            content = self.dump_kickstart( name )
766            # dump kickstart details and ks file content.
767            # use  separate files
768            self.dump( dir + '/' + self.get_common_name(name), content )
769            #self.dump( dir + '/' + self.get_common_name(name) + ".content", dump_kickstart_content(self, name) )
770
771
772def dump_activationkeys(self, basedir):
773    logging.info( "activationkey" )
774    activationkeys = self.do_activationkey_list('', True)
775
776    for name in activationkeys:
777        if self.is_current_stage( name ):
778            logging.info( "  " + name )
779
780            content = self.dump_activationkey( name )
781
782            dir = basedir + self.get_common_name(name)
783            self.dump( dir + '/' + self.get_common_name(name), content )
784
785           
786# vim:ts=4:expandtab:
Note: See TracBrowser for help on using the repository browser.