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

Last change on this file since 1082 was 1082, checked in by joergs, on Aug 20, 2012 at 10:45:22 PM

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.