rel-eng/packages/spacecmd | 2
spacecmd/spacecmd.spec | 20 ++
spacecmd/src/lib/activationkey.py | 337 ++++++++++++++++++++++++++++++++++++++
spacecmd/src/lib/system.py | 23 +-
spacecmd/src/lib/utils.py | 30 +++
5 files changed, 399 insertions(+), 13 deletions(-)
New commits:
commit bdcf5e881724442be87ab87e12e356f91a548b1b
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 15:15:27 2011 -0500
Automatic commit of package [spacecmd] release [1.6.9-1].
diff --git a/rel-eng/packages/spacecmd b/rel-eng/packages/spacecmd
index 6e6f67f..af32ade 100644
--- a/rel-eng/packages/spacecmd
+++ b/rel-eng/packages/spacecmd
@@ -1 +1 @@
-1.6.7-1 spacecmd/
+1.6.9-1 spacecmd/
diff --git a/spacecmd/spacecmd.spec b/spacecmd/spacecmd.spec
index d5d5ece..d4e9c61 100644
--- a/spacecmd/spacecmd.spec
+++ b/spacecmd/spacecmd.spec
@@ -4,7 +4,7 @@
%endif
Name: spacecmd
-Version: 1.6.7
+Version: 1.6.9
Release: 1%{?dist}
Summary: Command-line interface to Spacewalk and Satellite servers
@@ -61,6 +61,24 @@ touch %{buildroot}/%{python_sitelib}/spacecmd/__init__.py
%doc %{_mandir}/man1/spacecmd.1.gz
%changelog
+* Wed Nov 23 2011 Aron Parsons <parsonsa(a)bit-sys.com> 1.6.9-1
+- spacecmd: fix some errors in system_runscript (parsonsa(a)bit-sys.com)
+- spacecmd: changed some non-critical errors to warnings (parsonsa(a)bit-sys.com)
+- spacecmd: cleaned up error messages (parsonsa(a)bit-sys.com)
+- spacecmd: activationkey_clone cleanup (parsonsa(a)bit-sys.com)
+- spacecmd enhancement : Add activationkey_clone command (shardy(a)redhat.com)
+- spacecmd enhancement : Add activationkey_import command (shardy(a)redhat.com)
+- spacecmd enhancement : Add activationkey_export command (shardy(a)redhat.com)
+
+* Wed Nov 23 2011 Aron Parsons <parsonsa(a)bit-sys.com>
+- spacecmd: fix some errors in system_runscript (parsonsa(a)bit-sys.com)
+- spacecmd: changed some non-critical errors to warnings (parsonsa(a)bit-sys.com)
+- spacecmd: cleaned up error messages (parsonsa(a)bit-sys.com)
+- spacecmd: activationkey_clone cleanup (parsonsa(a)bit-sys.com)
+- spacecmd enhancement : Add activationkey_clone command (shardy(a)redhat.com)
+- spacecmd enhancement : Add activationkey_import command (shardy(a)redhat.com)
+- spacecmd enhancement : Add activationkey_export command (shardy(a)redhat.com)
+
* Wed Nov 16 2011 Aron Parsons <aparsons(a)redhat.com> 1.6.7-1
- spacecmd: remove comma from softwarechannel_setorgaccess output
(aparsons(a)redhat.com)
commit 8ea73edad86104331f377b6c376097cfeb86689d
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 15:02:52 2011 -0500
spacecmd: fix some errors in system_runscript
diff --git a/spacecmd/src/lib/system.py b/spacecmd/src/lib/system.py
index ccc00b7..7080c4a 100644
--- a/spacecmd/src/lib/system.py
+++ b/spacecmd/src/lib/system.py
@@ -335,19 +335,19 @@ def do_system_runscript(self, args):
options.start_time = prompt_user('Start Time [now]:')
options.start_time = parse_time_input(options.start_time)
- script_file = prompt_user('Script File [create]:')
+ options.file = prompt_user('Script File [create]:')
# read the script provided by the user
- if script_file:
+ if options.file:
keep_script_file = True
- options.script = read_file(os.path.abspath(script_file))
+ script_contents = read_file(os.path.abspath(options.file))
else:
# have the user write their script
- (options.script, script_file) = editor('#!/bin/bash')
+ (script_contents, options.file) = editor('#!/bin/bash')
keep_script_file = False
- if not options.script:
+ if not script_contents:
logging.error('No script provided')
return
else:
@@ -360,7 +360,8 @@ def do_system_runscript(self, args):
logging.error('A script file is required')
return
- options.script = read_file(options.file)
+ script_contents = read_file(options.file)
+ keep_script_file = True
# display a summary
print
@@ -371,7 +372,7 @@ def do_system_runscript(self, args):
print
print 'Script Contents'
print '---------------'
- print options.script
+ print script_contents
# have the user confirm
if not self.user_confirm(): return
@@ -389,7 +390,7 @@ def do_system_runscript(self, args):
options.user,
options.group,
options.timeout,
- options.script,
+ script_contents,
options.start_time)
logging.info('Action ID: %i' % action_id)
@@ -408,7 +409,7 @@ def do_system_runscript(self, args):
options.user,
options.group,
options.timeout,
- options.script,
+ script_contents,
options.start_time)
logging.info('Action ID: %i' % action_id)
@@ -422,9 +423,9 @@ def do_system_runscript(self, args):
# don't delete a pre-existing script that the user provided
if not keep_script_file:
try:
- os.remove(script_file)
+ os.remove(options.file)
except OSError:
- logging.error('Could not remove %s' % script_file)
+ logging.error('Could not remove %s' % options.file)
####################
commit 59b48c006f6a4262d5f05a298ead4a1ac76c4e30
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 14:29:25 2011 -0500
spacecmd: changed some non-critical errors to warnings
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index e8134bb..aad3208 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -1061,8 +1061,7 @@ def import_activationkey_fromdetails(self, keydetails):
existing_keys = self.do_activationkey_list('', True)
if keydetails['key'] in existing_keys:
- logging.error("ERROR : key %s already exists! Skipping!" % \
- keydetails['key'])
+ logging.warning("%s already exists! Skipping!" %
keydetails['key'])
return False
else:
# create the key, we need to drop the org prefix from the key name
@@ -1216,7 +1215,7 @@ def do_activationkey_clone(self, args):
new_child_channel_labels.append(newc)
else:
- logging.error("Found child channel %s key %s, but %s" % \
+ logging.warning("Found child channel %s key %s, but %s" %
\
(c, keydetails['key'], newc) + \
" does not exist, skipping!")
@@ -1241,7 +1240,7 @@ def do_activationkey_clone(self, args):
new_config_channels.append(newcc)
else:
- logging.error("Found config channel %s for key %s, but %s " %
\
+ logging.warning("Found config channel %s for key %s, but %s " %
\
(cc, keydetails['key'], newcc) + \
"does not exist, skipping!")
commit 6781aa1ad6819588d9f406ae85cc2ca262bedaa0
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 14:25:38 2011 -0500
spacecmd: cleaned up error messages
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 7152d5b..e8134bb 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -996,8 +996,7 @@ def do_activationkey_export(self, args):
(args, keys))
if (len(keys) == 0):
- logging.error("Error, no valid key passed, check key-name is " + \
- " correct with spacecmd activationkey_list")
+ logging.error("Invalid activation key passed")
return
if len(filename) == 0:
@@ -1026,7 +1025,7 @@ def do_activationkey_export(self, args):
return
if json_dump_to_file(keydetails_list, filename) != True:
- logging.error("Error saving exported keys to file" % filename)
+ logging.error("Failed to save exported keys to file" % filename)
return
####################
@@ -1053,7 +1052,7 @@ def do_activationkey_import(self, args):
for keydetails in keydetails_list:
if self.import_activationkey_fromdetails(keydetails) != True:
- logging.error("Error importing activationkey %s" % \
+ logging.error("Failed to import key %s" % \
keydetails['key'])
# create a new key based on the dict from export_activationkey_getdetails
@@ -1087,7 +1086,7 @@ def import_activationkey_fromdetails(self, keydetails):
keydetails['entitlements'],
keydetails['universal_default'])
if len(newkey) == 0:
- logging.error("Error, activation key import failed for %s" % \
+ logging.error("Failed to import key %s" % \
keyname)
return False
@@ -1226,7 +1225,7 @@ def do_activationkey_clone(self, args):
keydetails['child_channel_labels'] = new_child_channel_labels
else:
- logging.error("Error, regex-replacement results in new " + \
+ logging.error("Regex-replacement results in new " + \
"base-channel %s which does not exist!" % newbasech)
# Finally, any config-channels
@@ -1253,7 +1252,7 @@ def do_activationkey_clone(self, args):
# Finally : import the key from the modified keydetails dict
if self.import_activationkey_fromdetails(keydetails) != True:
- logging.error("Error cloning activationkey %s to %s" % \
+ logging.error("Failed to clone %s to %s" % \
(options.name, options.clonename))
# vim:ts=4:expandtab:
commit 29bf21fb886c8c2ad738f37e9d7079a44cc36d82
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 14:23:14 2011 -0500
spacecmd: cosmetics
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 43481b3..7152d5b 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -920,8 +920,9 @@ def do_activationkey_setuniversaldefault(self, args):
####################
def help_activationkey_export(self):
- print 'activationkey_export: export activation key(s) to json format file'
- print '''usage: activationkey_export <KEY> <KEY> [options]
+ print 'activationkey_export: Export activation key(s) to JSON format file'
+ print '''usage: activationkey_export [options] [<KEY> ...]
+
options:
-f outfile.json : specify an output filename, defaults to <KEY>.json
if exporting a single key, akeys.json for multiple keys,
@@ -946,6 +947,7 @@ def export_activationkey_getdetails(self, key):
except Exception, E:
logging.debug("activationkey.listConfigChannel threw an exeception, \
probably not provisioning entitled, setting config_channels=False")
+
cclist = [ c['label'] for c in ccdlist ]
logging.debug("Got config channel label list of %s" % cclist)
details['config_channels'] = cclist
@@ -961,8 +963,10 @@ def export_activationkey_getdetails(self, key):
grp_detail_list=[]
for grp in details['server_group_ids']:
grp_details = self.client.systemgroup.getDetails(self.session, grp)
+
if grp_details:
grp_detail_list.append(grp_details)
+
details['server_groups'] = [ g['name'] for g in grp_detail_list
]
# Now append the details dict describing the key to the specified file
@@ -990,10 +994,12 @@ def do_activationkey_export(self, args):
keys = filter_results(self.do_activationkey_list('', True), args)
logging.debug("activationkey_export called with args %s, keys=%s" % \
(args, keys))
+
if (len(keys) == 0):
logging.error("Error, no valid key passed, check key-name is " + \
" correct with spacecmd activationkey_list")
return
+
if len(filename) == 0:
# No filename arg, so we try to do something sensible:
# If we are exporting exactly one key, we default to keyname.json
@@ -1011,12 +1017,14 @@ def do_activationkey_export(self, args):
logging.debug("About to dump %d keys to %s" % \
(len(keydetails_list), filename))
+
# Check if filepath exists, if it is an existing file
# we prompt the user for confirmation
if os.path.isfile(filename):
if not self.user_confirm("File %s exists, confirm overwrite file?
(y/n)" % \
filename):
return
+
if json_dump_to_file(keydetails_list, filename) != True:
logging.error("Error saving exported keys to file" % filename)
return
@@ -1024,23 +1032,25 @@ def do_activationkey_export(self, args):
####################
def help_activationkey_import(self):
- print 'activationkey_import: import activation key(s) from json file'
- print '''usage: activationkey_import <JSONFILES...>'''
+ print 'activationkey_import: import activation key(s) from JSON file(s)'
+ print '''usage: activationkey_import <JSONFILE ...>'''
def do_activationkey_import(self, args):
(args, options) = parse_arguments(args)
if len(args) == 0:
- logging.error("Error, no filename passed")
+ logging.error("No filename passed")
self.help_activationkey_import()
return
for filename in args:
logging.debug("Passed filename do_activationkey_import %s" % filename)
keydetails_list = json_read_from_file(filename)
+
if len(keydetails_list) == 0:
- logging.error("Error, could not read json data from %s" %
filename)
+ logging.error("Could not read json data from %s" % filename)
return
+
for keydetails in keydetails_list:
if self.import_activationkey_fromdetails(keydetails) != True:
logging.error("Error importing activationkey %s" % \
@@ -1048,9 +1058,9 @@ def do_activationkey_import(self, args):
# create a new key based on the dict from export_activationkey_getdetails
def import_activationkey_fromdetails(self, keydetails):
-
# First we check that an existing key with the same name does not exist
existing_keys = self.do_activationkey_list('', True)
+
if keydetails['key'] in existing_keys:
logging.error("ERROR : key %s already exists! Skipping!" % \
keydetails['key'])
@@ -1060,6 +1070,7 @@ def import_activationkey_fromdetails(self, keydetails):
keyname = re.sub('^[0-9]-', '', keydetails['key'])
logging.info("Found key %s, importing as %s" % \
(keydetails['key'], keyname))
+
if keydetails['usage_limit'] != 0:
newkey = self.client.activationkey.create(self.session,
keyname,
@@ -1079,9 +1090,11 @@ def import_activationkey_fromdetails(self, keydetails):
logging.error("Error, activation key import failed for %s" % \
keyname)
return False
+
# add child channels
self.client.activationkey.addChildChannels(self.session, newkey,\
keydetails['child_channel_labels'])
+
# set config channel options and channels (missing are skipped)
if keydetails['config_deploy'] != 0:
self.client.activationkey.enableConfigDeployment(self.session,\
@@ -1089,9 +1102,11 @@ def import_activationkey_fromdetails(self, keydetails):
else:
self.client.activationkey.disableConfigDeployment(self.session,\
newkey)
+
if len(keydetails['config_channels']) > 0:
self.client.activationkey.addConfigChannels(self.session, [newkey],\
keydetails['config_channels'], False)
+
# set groups (missing groups are created)
gids = []
for grp in keydetails['server_groups']:
@@ -1101,8 +1116,10 @@ def import_activationkey_fromdetails(self, keydetails):
grpdetails = self.client.systemgroup.create(self.session, grp,\
grp)
gids.append(grpdetails.get('id'))
+
logging.debug("Adding groups %s to key %s" % (gids, newkey))
self.client.activationkey.addServerGroups(self.session, newkey, gids)
+
# Finally add the package list
self.client.activationkey.addPackages(self.session, newkey, \
keydetails['packages'])
commit ef0f7397d04f159301e2717a03df93b6d8f88160
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 14:18:04 2011 -0500
spacecmd: cosmetics
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 3921e3b..43481b3 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -1189,6 +1189,7 @@ def do_activationkey_clone(self, args):
# If it doesn't we can only skip it and print a warning
all_childch = self.list_child_channels(system=None,\
parent=newbasech, subscribed=False)
+
new_child_channel_labels = []
for c in keydetails['child_channel_labels']:
newc = re.sub(findstr, replacestr, c)
@@ -1196,13 +1197,16 @@ def do_activationkey_clone(self, args):
logging.debug("Found child channel %s for key %s, " % \
(c, keydetails['key']) + \
"replacing with %s" % newc)
+
new_child_channel_labels.append(newc)
else:
logging.error("Found child channel %s key %s, but %s" % \
(c, keydetails['key'], newc) + \
" does not exist, skipping!")
+
logging.debug("Processed all child channels, " + \
"new_child_channel_labels=%s" % new_child_channel_labels)
+
keydetails['child_channel_labels'] = new_child_channel_labels
else:
logging.error("Error, regex-replacement results in new " + \
@@ -1213,17 +1217,21 @@ def do_activationkey_clone(self, args):
allccs = self.do_configchannel_list('', True)
for cc in keydetails['config_channels']:
newcc = re.sub(findstr, replacestr, cc)
+
if newcc in allccs:
logging.debug("Found config channel %s for key %s, " % \
(cc, keydetails['key']) + \
"replacing with %s" % newcc)
+
new_config_channels.append(newcc)
else:
logging.error("Found config channel %s for key %s, but %s " %
\
(cc, keydetails['key'], newcc) + \
"does not exist, skipping!")
+
logging.debug("Processed all config channels, " + \
"new_config_channels = %s" % new_config_channels)
+
keydetails['config_channels'] = new_config_channels
# Finally : import the key from the modified keydetails dict
commit fd9ad7a0209c3749b052c1e7028938ee084d6789
Author: Aron Parsons <parsonsa(a)bit-sys.com>
Date: Wed Nov 23 14:16:54 2011 -0500
spacecmd: activationkey_clone cleanup
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 341d60c..3921e3b 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -1112,7 +1112,7 @@ def import_activationkey_fromdetails(self, keydetails):
####################
def help_activationkey_clone(self):
- print 'activationkey_clone: Clone a Kickstart profile'
+ print 'activationkey_clone: Clone an activation key'
print '''usage: activationkey_clone [options]
options:
@@ -1140,26 +1140,24 @@ def do_activationkey_clone(self, args):
print '\n'.join(sorted(allkeys))
print
- options.name = prompt_user('Origianl Profile:', noblank = True)
+ options.name = prompt_user('Original Key:', noblank = True)
- options.clonename = prompt_user('Cloned Profile:', noblank = True)
+ options.clonename = prompt_user('Cloned Key:', noblank = True)
else:
-
if not options.name:
- logging.error('The Activationkey name is required')
+ logging.error('The --name option is required')
return
if not options.clonename:
- logging.error('The Activationkey clone name is required')
+ logging.error('The --clonename option is required')
return
if not options.name in allkeys:
- logging.error("Error, key %s does not seem to exist satellite?"\
- % options.name)
+ logging.error("Key %s does not exist" % options.name)
return
if options.clonename in allkeys:
- logging.error("Error, clone name %s already exists!" % options.name)
+ logging.error("Key %s already exists" % options.clonename)
return
# Replace the key-name with the clonename specified by the user
@@ -1233,5 +1231,4 @@ def do_activationkey_clone(self, args):
logging.error("Error cloning activationkey %s to %s" % \
(options.name, options.clonename))
-
# vim:ts=4:expandtab:
commit 165ab4ca10c021a1893933719c3d85bee06e8272
Author: Steve Hardy <shardy(a)redhat.com>
Date: Thu Nov 17 17:55:04 2011 +0000
spacecmd enhancement : Add activationkey_clone command
Add new command to clone activationkeys, including regex-replacement
of the key content
Signed-off-by: Steve Hardy <shardy(a)redhat.com>
Signed-off-by: Aron Parsons <parsonsa(a)bit-sys.com>
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index bccc324..341d60c 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -1109,4 +1109,129 @@ def import_activationkey_fromdetails(self, keydetails):
return True
+####################
+
+def help_activationkey_clone(self):
+ print 'activationkey_clone: Clone a Kickstart profile'
+ print '''usage: activationkey_clone [options]
+
+options:
+ -n NAME : Name of the key to be cloned
+ -c CLONE_NAME : Name of the resulting key
+ -x "s/foo/bar" : Optional regex replacement, replaces foo with bar in the
+ clone description, base-channel label, child-channel
+ labels, config-channel names '''
+
+def complete_activationkey_clone(self, text, line, beg, end):
+ return tab_completer(self.do_activationkey_list('', True), text)
+
+def do_activationkey_clone(self, args):
+ options = [ Option('-n', '--name', action='store'),
+ Option('-c', '--clonename', action='store'),
+ Option('-x', '--regex', action='store') ]
+
+ (args, options) = parse_arguments(args, options)
+ allkeys = self.do_activationkey_list('', True)
+
+ if is_interactive(options):
+ print
+ print 'Activation Keys'
+ print '------------------'
+ print '\n'.join(sorted(allkeys))
+ print
+
+ options.name = prompt_user('Origianl Profile:', noblank = True)
+
+ options.clonename = prompt_user('Cloned Profile:', noblank = True)
+ else:
+
+ if not options.name:
+ logging.error('The Activationkey name is required')
+ return
+
+ if not options.clonename:
+ logging.error('The Activationkey clone name is required')
+ return
+
+ if not options.name in allkeys:
+ logging.error("Error, key %s does not seem to exist satellite?"\
+ % options.name)
+ return
+
+ if options.clonename in allkeys:
+ logging.error("Error, clone name %s already exists!" % options.name)
+ return
+
+ # Replace the key-name with the clonename specified by the user
+ keydetails = self.export_activationkey_getdetails(options.name)
+ keydetails['key'] = options.clonename
+
+ # If the -x/--regex option is passed, do a sed-style replacement over
+ # everything contained by the key. This makes it easier to clone when
+ # content is based on a known naming convention
+ if options.regex:
+ # Expect this option to be formatted like a sed-replacement, s/foo/bar
+ findstr = options.regex.split("/")[1]
+ replacestr = options.regex.split("/")[2]
+ logging.debug("Regex option selected with %s, replacing %s with %s" %
\
+ (options.regex, findstr, replacestr))
+
+ # First we do the description
+ newdesc = re.sub(findstr, replacestr, keydetails['description'])
+ keydetails['description'] = newdesc
+
+ # Then the base-channel label
+ newbasech = re.sub(findstr, replacestr, \
+ keydetails['base_channel_label'])
+ if newbasech in self.list_base_channels():
+ keydetails['base_channel_label'] = newbasech
+ # Now iterate over any child-channel labels
+ # Since we have the new base-channel, we can check if the new child
+ # label exists under the new base-channel:
+ # If it doesn't we can only skip it and print a warning
+ all_childch = self.list_child_channels(system=None,\
+ parent=newbasech, subscribed=False)
+ new_child_channel_labels = []
+ for c in keydetails['child_channel_labels']:
+ newc = re.sub(findstr, replacestr, c)
+ if newc in all_childch:
+ logging.debug("Found child channel %s for key %s, " % \
+ (c, keydetails['key']) + \
+ "replacing with %s" % newc)
+ new_child_channel_labels.append(newc)
+ else:
+ logging.error("Found child channel %s key %s, but %s" % \
+ (c, keydetails['key'], newc) + \
+ " does not exist, skipping!")
+ logging.debug("Processed all child channels, " + \
+ "new_child_channel_labels=%s" % new_child_channel_labels)
+ keydetails['child_channel_labels'] = new_child_channel_labels
+ else:
+ logging.error("Error, regex-replacement results in new " + \
+ "base-channel %s which does not exist!" % newbasech)
+
+ # Finally, any config-channels
+ new_config_channels = []
+ allccs = self.do_configchannel_list('', True)
+ for cc in keydetails['config_channels']:
+ newcc = re.sub(findstr, replacestr, cc)
+ if newcc in allccs:
+ logging.debug("Found config channel %s for key %s, " % \
+ (cc, keydetails['key']) + \
+ "replacing with %s" % newcc)
+ new_config_channels.append(newcc)
+ else:
+ logging.error("Found config channel %s for key %s, but %s " %
\
+ (cc, keydetails['key'], newcc) + \
+ "does not exist, skipping!")
+ logging.debug("Processed all config channels, " + \
+ "new_config_channels = %s" % new_config_channels)
+ keydetails['config_channels'] = new_config_channels
+
+ # Finally : import the key from the modified keydetails dict
+ if self.import_activationkey_fromdetails(keydetails) != True:
+ logging.error("Error cloning activationkey %s to %s" % \
+ (options.name, options.clonename))
+
+
# vim:ts=4:expandtab:
commit a18748f55be11a740e7bd29942832ca3bd3dbfbd
Author: Steve Hardy <shardy(a)redhat.com>
Date: Thu Nov 17 17:48:52 2011 +0000
spacecmd enhancement : Add activationkey_import command
Adds option to import activationkeys from JSON files as generated
with spacecmd activationkey_export
Signed-off-by: Steve Hardy <shardy(a)redhat.com>
Signed-off-by: Aron Parsons <parsonsa(a)bit-sys.com>
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 221ba6d..bccc324 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -1021,4 +1021,92 @@ def do_activationkey_export(self, args):
logging.error("Error saving exported keys to file" % filename)
return
+####################
+
+def help_activationkey_import(self):
+ print 'activationkey_import: import activation key(s) from json file'
+ print '''usage: activationkey_import <JSONFILES...>'''
+
+def do_activationkey_import(self, args):
+ (args, options) = parse_arguments(args)
+
+ if len(args) == 0:
+ logging.error("Error, no filename passed")
+ self.help_activationkey_import()
+ return
+
+ for filename in args:
+ logging.debug("Passed filename do_activationkey_import %s" % filename)
+ keydetails_list = json_read_from_file(filename)
+ if len(keydetails_list) == 0:
+ logging.error("Error, could not read json data from %s" %
filename)
+ return
+ for keydetails in keydetails_list:
+ if self.import_activationkey_fromdetails(keydetails) != True:
+ logging.error("Error importing activationkey %s" % \
+ keydetails['key'])
+
+# create a new key based on the dict from export_activationkey_getdetails
+def import_activationkey_fromdetails(self, keydetails):
+
+ # First we check that an existing key with the same name does not exist
+ existing_keys = self.do_activationkey_list('', True)
+ if keydetails['key'] in existing_keys:
+ logging.error("ERROR : key %s already exists! Skipping!" % \
+ keydetails['key'])
+ return False
+ else:
+ # create the key, we need to drop the org prefix from the key name
+ keyname = re.sub('^[0-9]-', '', keydetails['key'])
+ logging.info("Found key %s, importing as %s" % \
+ (keydetails['key'], keyname))
+ if keydetails['usage_limit'] != 0:
+ newkey = self.client.activationkey.create(self.session,
+ keyname,
+ keydetails['description'],
+ keydetails['base_channel_label'],
+ keydetails['usage_limit'],
+ keydetails['entitlements'],
+ keydetails['universal_default'])
+ else:
+ newkey = self.client.activationkey.create(self.session,
+ keyname,
+ keydetails['description'],
+ keydetails['base_channel_label'],
+ keydetails['entitlements'],
+ keydetails['universal_default'])
+ if len(newkey) == 0:
+ logging.error("Error, activation key import failed for %s" % \
+ keyname)
+ return False
+ # add child channels
+ self.client.activationkey.addChildChannels(self.session, newkey,\
+ keydetails['child_channel_labels'])
+ # set config channel options and channels (missing are skipped)
+ if keydetails['config_deploy'] != 0:
+ self.client.activationkey.enableConfigDeployment(self.session,\
+ newkey)
+ else:
+ self.client.activationkey.disableConfigDeployment(self.session,\
+ newkey)
+ if len(keydetails['config_channels']) > 0:
+ self.client.activationkey.addConfigChannels(self.session, [newkey],\
+ keydetails['config_channels'], False)
+ # set groups (missing groups are created)
+ gids = []
+ for grp in keydetails['server_groups']:
+ grpdetails = self.client.systemgroup.getDetails(self.session, grp)
+ if grpdetails == None:
+ logging.info("System group %s doesn't exist, creating" %
grp)
+ grpdetails = self.client.systemgroup.create(self.session, grp,\
+ grp)
+ gids.append(grpdetails.get('id'))
+ logging.debug("Adding groups %s to key %s" % (gids, newkey))
+ self.client.activationkey.addServerGroups(self.session, newkey, gids)
+ # Finally add the package list
+ self.client.activationkey.addPackages(self.session, newkey, \
+ keydetails['packages'])
+
+ return True
+
# vim:ts=4:expandtab:
diff --git a/spacecmd/src/lib/utils.py b/spacecmd/src/lib/utils.py
index 491b1c4..2ee4c4e 100644
--- a/spacecmd/src/lib/utils.py
+++ b/spacecmd/src/lib/utils.py
@@ -580,4 +580,17 @@ def json_dump_to_file(obj, filename, indent = 2):
return True
+def json_read_from_file(filename):
+ try:
+ data = open(filename).read()
+ try:
+ jsondata = json.loads(data)
+ return jsondata
+ except:
+ print "could not read in data from %s" % filename
+ except IOError, E:
+ if verbose:
+ print "could not open file %s for reading, check permissions?" %
filename
+ return None
+
# vim:ts=4:expandtab:
commit e1c18dc76a8e102450930a90cb8ee4a0c1256a1b
Author: Steve Hardy <shardy(a)redhat.com>
Date: Thu Nov 17 17:47:59 2011 +0000
spacecmd enhancement : Add activationkey_export command
Adds command which exports activationkeys to JSON format files
Signed-off-by: Steve Hardy <shardy(a)redhat.com>
Signed-off-by: Aron Parsons <parsonsa(a)bit-sys.com>
diff --git a/spacecmd/src/lib/activationkey.py b/spacecmd/src/lib/activationkey.py
index 519201f..221ba6d 100644
--- a/spacecmd/src/lib/activationkey.py
+++ b/spacecmd/src/lib/activationkey.py
@@ -917,4 +917,108 @@ def do_activationkey_setuniversaldefault(self, args):
self.client.activationkey.setDetails(self.session, key, details)
+####################
+
+def help_activationkey_export(self):
+ print 'activationkey_export: export activation key(s) to json format file'
+ print '''usage: activationkey_export <KEY> <KEY> [options]
+options:
+ -f outfile.json : specify an output filename, defaults to <KEY>.json
+ if exporting a single key, akeys.json for multiple keys,
+ or akey_all.json of no KEY specified (export ALL)
+
+Note : KEY list is optional, default is to export ALL keys '''
+
+def complete_activationkey_export(self, text, line, beg, end):
+ return tab_completer(self.do_activationkey_list('', True), text)
+
+def export_activationkey_getdetails(self, key):
+ # Get the key details
+ logging.info("Getting activation key details for %s" % key)
+ details = self.client.activationkey.getDetails(self.session, key)
+
+ # Get the key config-channel data, add it to the existing details
+ logging.debug("activationkey.listConfigChannels %s" % key)
+ ccdlist = []
+ try:
+ ccdlist = self.client.activationkey.listConfigChannels(self.session, \
+ key)
+ except Exception, E:
+ logging.debug("activationkey.listConfigChannel threw an exeception, \
+ probably not provisioning entitled, setting config_channels=False")
+ cclist = [ c['label'] for c in ccdlist ]
+ logging.debug("Got config channel label list of %s" % cclist)
+ details['config_channels'] = cclist
+
+ logging.debug("activationkey.checkConfigDeployment %s" % key)
+ details['config_deploy'] = \
+ self.client.activationkey.checkConfigDeployment(self.session, key)
+
+ # Get group details, as the server group IDs are not necessarily the same
+ # across servers, so we need the group name on import
+ details['server_groups'] = []
+ if len(details['server_group_ids']) != 0:
+ grp_detail_list=[]
+ for grp in details['server_group_ids']:
+ grp_details = self.client.systemgroup.getDetails(self.session, grp)
+ if grp_details:
+ grp_detail_list.append(grp_details)
+ details['server_groups'] = [ g['name'] for g in grp_detail_list
]
+
+ # Now append the details dict describing the key to the specified file
+ return details
+
+def do_activationkey_export(self, args):
+ options = [ Option('-f', '--file', action='store') ]
+ (args, options) = parse_arguments(args, options)
+
+ filename=""
+ if options.file != None:
+ logging.debug("Passed filename do_activationkey_export %s" % \
+ options.file)
+ filename=options.file
+
+ # Get the list of keys to export and sort out the filename if required
+ keys=[]
+ if not len(args):
+ if len(filename) == 0:
+ filename="akey_all.json"
+ logging.info("Exporting ALL activation keys to %s" % filename)
+ keys = self.do_activationkey_list('', True)
+ else:
+ # allow globbing of activationkey channel names
+ keys = filter_results(self.do_activationkey_list('', True), args)
+ logging.debug("activationkey_export called with args %s, keys=%s" % \
+ (args, keys))
+ if (len(keys) == 0):
+ logging.error("Error, no valid key passed, check key-name is " + \
+ " correct with spacecmd activationkey_list")
+ return
+ if len(filename) == 0:
+ # No filename arg, so we try to do something sensible:
+ # If we are exporting exactly one key, we default to keyname.json
+ # otherwise, generic akeys.json name
+ if len(keys) == 1:
+ filename="%s.json" % keys[0]
+ else:
+ filename="akeys.json"
+
+ # Dump as a list of dict
+ keydetails_list=[]
+ for k in keys:
+ logging.info("Exporting key %s to %s" % (k, filename))
+ keydetails_list.append(self.export_activationkey_getdetails(k))
+
+ logging.debug("About to dump %d keys to %s" % \
+ (len(keydetails_list), filename))
+ # Check if filepath exists, if it is an existing file
+ # we prompt the user for confirmation
+ if os.path.isfile(filename):
+ if not self.user_confirm("File %s exists, confirm overwrite file?
(y/n)" % \
+ filename):
+ return
+ if json_dump_to_file(keydetails_list, filename) != True:
+ logging.error("Error saving exported keys to file" % filename)
+ return
+
# vim:ts=4:expandtab:
diff --git a/spacecmd/src/lib/utils.py b/spacecmd/src/lib/utils.py
index a8fd5ee..491b1c4 100644
--- a/spacecmd/src/lib/utils.py
+++ b/spacecmd/src/lib/utils.py
@@ -562,5 +562,22 @@ def parse_api_args(args, sep=','):
def json_dump(obj, fp, indent=2, **kwargs):
json.dump(obj, fp, ensure_ascii=False, indent=indent, **kwargs)
+def json_dump_to_file(obj, filename, indent = 2):
+
+ json_data = json.dumps(obj, indent)
+ if json_data == None:
+ logging.error("Could not generate json data object!" % k)
+ return False
+ try:
+ fd = open(filename, 'w')
+ fd.write(json_data)
+ fd.close()
+ except IOError, E:
+ logging.error("Could not open file %s for writing, permissions?" % \
+ filename)
+ print E.strerror
+ return False
+
+ return True
# vim:ts=4:expandtab: