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

Last change on this file was 1084, checked in by joergs, on Aug 20, 2012 at 10:48:35 PM

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.