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

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

set Id property

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