"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "cobbler/cli.py" between
cobbler-2.8.4.tar.gz and cobbler-3.0.0.tar.gz

About: cobbler is a Linux installation and deployment server that allows for rapid setup of network installation environments. It can help with installation, DNS, DHCP, package updates, power management, configuration management orchestration, and much more.

cli.py  (cobbler-2.8.4):cli.py  (cobbler-3.0.0)
skipping to change at line 23 skipping to change at line 23
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
""" """
import sys from future import standard_library
import xmlrpclib standard_library.install_aliases()
import traceback from builtins import str
from builtins import object
import optparse import optparse
import exceptions
import time
import os import os
import sys
import time
import traceback
import xmlrpc.client
import utils from cobbler import field_info
import item_distro from cobbler import item_distro
import item_profile from cobbler import item_profile
import item_system from cobbler import item_system
import item_repo from cobbler import item_repo
import item_image from cobbler import item_image
import item_mgmtclass from cobbler import item_mgmtclass
import item_package from cobbler import item_package
import item_file from cobbler import item_file
import settings from cobbler import settings
from cobbler import utils
OBJECT_ACTIONS_MAP = { from cobbler.cexceptions import NotImplementedException
"distro" : "add copy edit find list remove rename report".split(" "),
"profile" : "add copy dumpvars edit find getks list remove rename report".s OBJECT_ACTIONS_MAP = {
plit(" "), "distro": "add copy edit find list remove rename report".split(" "),
"system" : "add copy dumpvars edit find getks list remove rename report po "profile": "add copy dumpvars edit find get-autoinstall list remove rename r
weron poweroff powerstatus reboot".split(" "), eport".split(" "),
"image" : "add copy edit find list remove rename report".split(" "), "system": "add copy dumpvars edit find get-autoinstall list remove rename re
"repo" : "add copy edit find list remove rename report".split(" "), port poweron poweroff powerstatus reboot".split(" "),
"mgmtclass" : "add copy edit find list remove rename report".split(" "), "image": "add copy edit find list remove rename report".split(" "),
"package" : "add copy edit find list remove rename report".split(" "), "repo": "add copy edit find list remove rename report".split(" "),
"file" : "add copy edit find list remove rename report".split(" "), "mgmtclass": "add copy edit find list remove rename report".split(" "),
"setting" : "edit report".split(" "), "package": "add copy edit find list remove rename report".split(" "),
"signature" : "reload report update".split(" "), "file": "add copy edit find list remove rename report".split(" "),
"setting": "edit report".split(" "),
"signature": "reload report update".split(" ")
} }
OBJECT_TYPES = OBJECT_ACTIONS_MAP.keys()
OBJECT_TYPES = list(OBJECT_ACTIONS_MAP.keys())
# would like to use from_iterable here, but have to support python 2.4 # would like to use from_iterable here, but have to support python 2.4
OBJECT_ACTIONS = [] OBJECT_ACTIONS = []
for actions in OBJECT_ACTIONS_MAP.values(): for actions in list(OBJECT_ACTIONS_MAP.values()):
OBJECT_ACTIONS += actions OBJECT_ACTIONS += actions
DIRECT_ACTIONS = "aclsetup buildiso import list replicate report reposync sync v DIRECT_ACTIONS = "aclsetup buildiso import list replicate report reposync sync v
alidateks version signature get-loaders hardlink".split() alidate-autoinstalls version signature get-loaders hardlink".split()
#################################################### ####################################################
def report_items(remote, otype): def report_items(remote, otype):
if otype == "setting": if otype == "setting":
items = remote.get_settings() items = remote.get_settings()
keys = items.keys() keys = list(items.keys())
keys.sort() keys.sort()
for key in keys: for key in keys:
item = {'name':key, 'value':items[key]} item = {'name': key, 'value': items[key]}
report_item(remote,otype,item=item) report_item(remote, otype, item=item)
elif otype == "signature": elif otype == "signature":
items = remote.get_signatures() items = remote.get_signatures()
total_breeds = 0 total_breeds = 0
total_sigs = 0 total_sigs = 0
if items.has_key("breeds"): if "breeds" in items:
print "Currently loaded signatures:" print("Currently loaded signatures:")
bkeys = items["breeds"].keys() bkeys = list(items["breeds"].keys())
bkeys.sort() bkeys.sort()
total_breeds = len(bkeys) total_breeds = len(bkeys)
for breed in bkeys: for breed in bkeys:
print "%s:" % breed print("%s:" % breed)
oskeys = items["breeds"][breed].keys() oskeys = list(items["breeds"][breed].keys())
oskeys.sort() oskeys.sort()
if len(oskeys) > 0: if len(oskeys) > 0:
total_sigs += len(oskeys) total_sigs += len(oskeys)
for osversion in oskeys: for osversion in oskeys:
print "\t%s" % osversion print("\t%s" % osversion)
else: else:
print "\t(none)" print("\t(none)")
print "\n%d breeds with %d total signatures loaded" % (total_breeds,t print("\n%d breeds with %d total signatures loaded" % (total_breeds,
otal_sigs) total_sigs))
else: else:
print "No breeds found in the signature, a signature update is recomm print("No breeds found in the signature, a signature update is recom
ended" mended")
sys.exit(1) sys.exit(1)
else: else:
items = remote.get_items(otype) items = remote.get_items(otype)
for x in items: for x in items:
report_item(remote,otype,item=x) report_item(remote, otype, item=x)
def report_item(remote,otype,item=None,name=None): def report_item(remote, otype, item=None, name=None):
if item is None: if item is None:
if otype == "setting": if otype == "setting":
cur_settings = remote.get_settings() cur_settings = remote.get_settings()
try: try:
item = {'name':name, 'value':cur_settings[name]} item = {'name': name, 'value': cur_settings[name]}
except: except:
print "Setting not found: %s" % name print("Setting not found: %s" % name)
sys.exit(1) sys.exit(1)
elif otype == "signature": elif otype == "signature":
items = remote.get_signatures() items = remote.get_signatures()
total_sigs = 0 total_sigs = 0
if items.has_key("breeds"): if "breeds" in items:
print "Currently loaded signatures:" print("Currently loaded signatures:")
if items["breeds"].has_key(name): if name in items["breeds"]:
print "%s:" % name print("%s:" % name)
oskeys = items["breeds"][name].keys() oskeys = list(items["breeds"][name].keys())
oskeys.sort() oskeys.sort()
if len(oskeys) > 0: if len(oskeys) > 0:
total_sigs += len(oskeys) total_sigs += len(oskeys)
for osversion in oskeys: for osversion in oskeys:
print "\t%s" % osversion print("\t%s" % osversion)
else: else:
print "\t(none)" print("\t(none)")
print "\nBreed '%s' has %d total signatures" % (name,total_sig print("\nBreed '%s' has %d total signatures" % (name, total_
s) sigs))
else: else:
print "No breed named '%s' found" % name print("No breed named '%s' found" % name)
sys.exit(1) sys.exit(1)
else: else:
print "No breeds found in the signature, a signature update is rec print("No breeds found in the signature, a signature update is r
ommended" ecommended")
sys.exit(1) sys.exit(1)
return return
else: else:
item = remote.get_item(otype, name) item = remote.get_item(otype, name)
if item == "~": if item == "~":
print "No %s found: %s" % (otype, name) print("No %s found: %s" % (otype, name))
sys.exit(1) sys.exit(1)
if otype == "distro": if otype == "distro":
data = utils.printable_from_fields(item, item_distro.FIELDS) data = utils.to_string_from_fields(item, item_distro.FIELDS)
elif otype == "profile": elif otype == "profile":
data = utils.printable_from_fields(item, item_profile.FIELDS) data = utils.to_string_from_fields(item, item_profile.FIELDS)
elif otype == "system": elif otype == "system":
data = utils.printable_from_fields(item, item_system.FIELDS) data = utils.to_string_from_fields(item, item_system.FIELDS,
elif otype == "repo": item_system.NETWORK_INTERFACE_FIELDS)
data = utils.printable_from_fields(item, item_repo.FIELDS) elif otype == "repo":
elif otype == "image": data = utils.to_string_from_fields(item, item_repo.FIELDS)
data = utils.printable_from_fields(item, item_image.FIELDS) elif otype == "image":
elif otype == "mgmtclass": data = utils.to_string_from_fields(item, item_image.FIELDS)
data = utils.printable_from_fields(item,item_mgmtclass.FIELDS) elif otype == "mgmtclass":
elif otype == "package": data = utils.to_string_from_fields(item, item_mgmtclass.FIELDS)
data = utils.printable_from_fields(item,item_package.FIELDS) elif otype == "package":
elif otype == "file": data = utils.to_string_from_fields(item, item_package.FIELDS)
data = utils.printable_from_fields(item,item_file.FIELDS) elif otype == "file":
elif otype == "setting": data = utils.to_string_from_fields(item, item_file.FIELDS)
data = "%-40s: %s" % (item['name'],item['value']) elif otype == "setting":
print data data = "%-40s: %s" % (item['name'], item['value'])
print(data)
def list_items(remote,otype):
items = remote.get_item_names(otype) def list_items(remote, otype):
items.sort() items = remote.get_item_names(otype)
for x in items: items.sort()
print " %s" % x for x in items:
print(" %s" % x)
def n2s(data): def n2s(data):
""" """
Return spaces for None Return spaces for None
""" """
if data is None: if data is None:
return "" return ""
return data return data
def opt(options, k, defval=""): def opt(options, k, defval=""):
""" """
Returns an option from an Optparse values instance Returns an option from an Optparse values instance
""" """
try: try:
data = getattr(options, k) data = getattr(options, k)
except: except:
# FIXME: debug only # FIXME: debug only
# traceback.print_exc() # traceback.print_exc()
return defval return defval
return n2s(data) return n2s(data)
def _add_parser_option_from_field(parser, field, settings):
# extract data from field dictionary
name = field[0]
default = field[1]
if isinstance(default, str) and default.startswith("SETTINGS:"):
setting_name = default.replace("SETTINGS:", "", 1)
default = settings[setting_name]
description = field[3]
tooltip = field[5]
choices = field[6]
if choices and default not in choices:
raise Exception("field %s default value (%s) is not listed in choices (%
s)" % (name, default, str(choices)))
if tooltip != "":
description += " (%s)" % tooltip
# generate option string
option_string = "--%s" % name.replace("_", "-")
# generate option aliases
aliases = []
for deprecated_field in list(field_info.DEPRECATED_FIELDS.keys()):
if field_info.DEPRECATED_FIELDS[deprecated_field] == name:
aliases.append("--%s" % deprecated_field)
# add option to parser
if isinstance(choices, list) and len(choices) != 0:
description += " (valid options: %s)" % ",".join(choices)
parser.add_option(option_string, dest=name, help=description, choices=ch
oices)
for alias in aliases:
parser.add_option(alias, dest=name, help=description, choices=choice
s)
else:
parser.add_option(option_string, dest=name, help=description)
for alias in aliases:
parser.add_option(alias, dest=name, help=description)
def add_options_from_fields(object_type, parser, fields, network_interface_field
s, settings, object_action):
if object_action in ["add", "edit", "find", "copy", "rename"]:
for field in fields:
_add_parser_option_from_field(parser, field, settings)
# system object
if object_type == "system":
for field in network_interface_fields:
_add_parser_option_from_field(parser, field, settings)
parser.add_option("--interface", dest="interface", help="the interfa
ce to operate on (can only be specified once per command line)")
if object_action in ["add", "edit"]:
parser.add_option("--delete-interface", dest="delete_interface",
action="store_true")
parser.add_option("--rename-interface", dest="rename_interface")
if object_action in ["copy", "rename"]:
parser.add_option("--newname", help="new object name")
if object_action not in ["find"] and object_type != "setting":
parser.add_option("--in-place", action="store_true", default=False,
dest="in_place", help="edit items in kopts or autoinstall without clearing the o
ther items")
elif object_action == "remove":
parser.add_option("--name", help="%s name to remove" % object_type)
parser.add_option("--recursive", action="store_true", dest="recursive",
help="also delete child objects")
# FIXME: not supported in 2.0 ?
# if not object_action in ["dumpvars","find","remove","report","list"]:
# parser.add_option("--no-sync", action="store_true", dest="nosync",
help="suppress sync for speed")
class BootCLI: class CobblerCLI(object):
def __init__(self): def __init__(self):
# Load server ip and ports from local config # Load server ip and ports from local config
self.url_cobbler_api = utils.local_get_cobbler_api_url() self.url_cobbler_api = utils.local_get_cobbler_api_url()
self.url_cobbler_xmlrpc = utils.local_get_cobbler_xmlrpc_url() self.url_cobbler_xmlrpc = utils.local_get_cobbler_xmlrpc_url()
# FIXME: allow specifying other endpoints, and user+pass # FIXME: allow specifying other endpoints, and user+pass
self.parser = optparse.OptionParser() self.parser = optparse.OptionParser()
self.remote = xmlrpclib.Server(self.url_cobbler_api) self.remote = xmlrpc.client.Server(self.url_cobbler_api)
self.shared_secret = utils.get_shared_secret() self.shared_secret = utils.get_shared_secret()
def start_task(self, name, options): def start_task(self, name, options):
options = utils.strip_none(vars(options), omit_none=True) options = utils.strip_none(vars(options), omit_none=True)
fn = getattr(self.remote, "background_%s" % name) fn = getattr(self.remote, "background_%s" % name)
return fn(options, self.token) return fn(options, self.token)
def get_object_type(self, args): def get_object_type(self, args):
""" """
If this is a CLI command about an object type, e.g. "cobbler distro add" , return the type, like "distro" If this is a CLI command about an object type, e.g. "cobbler distro add" , return the type, like "distro"
skipping to change at line 241 skipping to change at line 314
return "version" return "version"
else: else:
return args[1] return args[1]
def check_setup(self): def check_setup(self):
""" """
Detect permissions and service accessibility problems and provide Detect permissions and service accessibility problems and provide
nicer error messages for them. nicer error messages for them.
""" """
s = xmlrpclib.Server(self.url_cobbler_xmlrpc) s = xmlrpc.client.Server(self.url_cobbler_xmlrpc)
try: try:
s.ping() s.ping()
except Exception, e: except Exception as e:
print >> sys.stderr, "cobblerd does not appear to be running/accessi print("cobblerd does not appear to be running/accessible: %s" % repr
ble: %s" % repr(e) (e), file=sys.stderr)
sys.exit(411) sys.exit(411)
s = xmlrpclib.Server(self.url_cobbler_api) s = xmlrpc.client.Server(self.url_cobbler_api)
try: try:
s.ping() s.ping()
except: except:
print >> sys.stderr, "httpd does not appear to be running and proxyi ng cobbler, or SELinux is in the way. Original traceback:" print("httpd does not appear to be running and proxying cobbler, or SELinux is in the way. Original traceback:", file=sys.stderr)
traceback.print_exc() traceback.print_exc()
sys.exit(411) sys.exit(411)
if not os.path.exists("/var/lib/cobbler/web.ss"): if not os.path.exists("/var/lib/cobbler/web.ss"):
print >> sys.stderr, "Missing login credentials file. Has cobblerd failed to start?" print("Missing login credentials file. Has cobblerd failed to start ?", file=sys.stderr)
sys.exit(411) sys.exit(411)
if not os.access("/var/lib/cobbler/web.ss", os.R_OK): if not os.access("/var/lib/cobbler/web.ss", os.R_OK):
print >> sys.stderr, "User cannot run command line, need read access to /var/lib/cobbler/web.ss" print("User cannot run command line, need read access to /var/lib/co bbler/web.ss", file=sys.stderr)
sys.exit(411) sys.exit(411)
def run(self, args): def run(self, args):
""" """
Process the command line and do what the user asks. Process the command line and do what the user asks.
""" """
self.token = self.remote.login("", self.shared_secret) self.token = self.remote.login("", self.shared_secret)
object_type = self.get_object_type(args) object_type = self.get_object_type(args)
object_action = self.get_object_action(object_type, args) object_action = self.get_object_action(object_type, args)
direct_action = self.get_direct_action(object_type, args) direct_action = self.get_direct_action(object_type, args)
try: try:
if object_type is not None: if object_type is not None:
if object_action is not None: if object_action is not None:
self.object_command(object_type, object_action) self.object_command(object_type, object_action)
else: else:
self.print_object_help(object_type) self.print_object_help(object_type)
elif direct_action is not None: elif direct_action is not None:
self.direct_command(direct_action) self.direct_command(direct_action)
else: else:
self.print_help() self.print_help()
except xmlrpclib.Fault, err: except xmlrpc.client.Fault as err:
if err.faultString.find("cobbler.cexceptions.CX") != -1: if err.faultString.find("cobbler.cexceptions.CX") != -1:
print self.cleanup_fault_string(err.faultString) print(self.cleanup_fault_string(err.faultString))
else: else:
print "### ERROR ###" print("### ERROR ###")
print "Unexpected remote error, check the server side logs for f print("Unexpected remote error, check the server side logs for f
urther info" urther info")
print err.faultString print(err.faultString)
sys.exit(1) sys.exit(1)
def cleanup_fault_string(self,str): def cleanup_fault_string(self, str):
""" """
Make a remote exception nicely readable by humans so it's not evident th at is a remote Make a remote exception nicely readable by humans so it's not evident th at is a remote
fault. Users should not have to understand tracebacks. fault. Users should not have to understand tracebacks.
""" """
if str.find(">:") != -1: if str.find(">:") != -1:
(first, rest) = str.split(">:",1) (first, rest) = str.split(">:", 1)
if rest.startswith("\"") or rest.startswith("\'"): if rest.startswith("\"") or rest.startswith("\'"):
rest = rest[1:] rest = rest[1:]
if rest.endswith("\"") or rest.endswith("\'"): if rest.endswith("\"") or rest.endswith("\'"):
rest = rest[:-1] rest = rest[:-1]
return rest return rest
else: else:
return str return str
def get_fields(self, object_type): def get_fields(self, object_type):
""" """
skipping to change at line 337 skipping to change at line 410
return item_package.FIELDS return item_package.FIELDS
elif object_type == "file": elif object_type == "file":
return item_file.FIELDS return item_file.FIELDS
elif object_type == "setting": elif object_type == "setting":
return settings.FIELDS return settings.FIELDS
def object_command(self, object_type, object_action): def object_command(self, object_type, object_action):
""" """
Process object-based commands such as "distro add" or "profile rename" Process object-based commands such as "distro add" or "profile rename"
""" """
task_id = -1 # if assigned, we must tail the logfile task_id = -1 # if assigned, we must tail the logfile
settings = self.remote.get_settings()
fields = self.get_fields(object_type) fields = self.get_fields(object_type)
if object_action in [ "add", "edit", "copy", "rename", "find", "remove" network_interface_fields = None
]: if object_type == "system":
utils.add_options_from_fields(object_type, self.parser, fields, obje network_interface_fields = item_system.NETWORK_INTERFACE_FIELDS
ct_action) if object_action in ["add", "edit", "copy", "rename", "find", "remove"]:
elif object_action in [ "list" ]: add_options_from_fields(object_type, self.parser, fields,
network_interface_fields, settings, object_a
ction)
elif object_action in ["list"]:
pass pass
elif object_action not in ("reload","update"): elif object_action not in ("reload", "update"):
self.parser.add_option("--name", dest="name", help="name of object") self.parser.add_option("--name", dest="name", help="name of object")
elif object_action == "reload": elif object_action == "reload":
self.parser.add_option("--filename", dest="filename", help="filename to load data from") self.parser.add_option("--filename", dest="filename", help="filename to load data from")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
# the first three don't require a name # the first three don't require a name
if object_action == "report": if object_action == "report":
if options.name is not None: if options.name is not None:
report_item(self.remote,object_type,None,options.name) report_item(self.remote, object_type, None, options.name)
else: else:
report_items(self.remote,object_type) report_items(self.remote, object_type)
elif object_action == "list": elif object_action == "list":
list_items(self.remote, object_type) list_items(self.remote, object_type)
elif object_action == "find": elif object_action == "find":
items = self.remote.find_items(object_type, utils.strip_none(vars(op tions), omit_none=True), "name", False) items = self.remote.find_items(object_type, utils.strip_none(vars(op tions), omit_none=True), "name", False)
for item in items: for item in items:
print item print(item)
elif object_action in OBJECT_ACTIONS: elif object_action in OBJECT_ACTIONS:
if opt(options, "name") == "" and object_action not in ("reload","up if opt(options, "name") == "" and object_action not in ("reload", "u
date"): pdate"):
print "--name is required" print("--name is required")
sys.exit(1) sys.exit(1)
if object_action in [ "add", "edit", "copy", "rename", "remove" ]: if object_action in ["add", "edit", "copy", "rename", "remove"]:
try: try:
if object_type == "setting": if object_type == "setting":
settings = self.remote.get_settings() settings = self.remote.get_settings()
if options.value == None: if options.value is None:
raise RuntimeError("You must specify a --value when editing a setting") raise RuntimeError("You must specify a --value when editing a setting")
elif not settings.get('allow_dynamic_settings',False): elif not settings.get('allow_dynamic_settings', False):
raise RuntimeError("Dynamic settings changes are not enabled. Change the allow_dynamic_settings to 1 and restart cobblerd to enable dynamic settings changes") raise RuntimeError("Dynamic settings changes are not enabled. Change the allow_dynamic_settings to 1 and restart cobblerd to enable dynamic settings changes")
elif options.name == 'allow_dynamic_settings': elif options.name == 'allow_dynamic_settings':
raise RuntimeError("Cannot modify that setting live" ) raise RuntimeError("Cannot modify that setting live" )
elif self.remote.modify_setting(options.name,options.val ue,self.token): elif self.remote.modify_setting(options.name, options.va lue, self.token):
raise RuntimeError("Changing the setting failed") raise RuntimeError("Changing the setting failed")
else: else:
self.remote.xapi_object_edit(object_type, options.name, object_action, utils.strip_none(vars(options), omit_none=True), self.token) self.remote.xapi_object_edit(object_type, options.name, object_action, utils.strip_none(vars(options), omit_none=True), self.token)
except xmlrpclib.Fault, (err): except xmlrpc.client.Fault as xxx_todo_changeme:
(etype, emsg) = err.faultString.split(":",1) (err) = xxx_todo_changeme
print "exception on server: %s" % emsg (etype, emsg) = err.faultString.split(":", 1)
print("exception on server: %s" % emsg)
sys.exit(1) sys.exit(1)
except RuntimeError, (err): except RuntimeError as xxx_todo_changeme1:
print err.args[0] (err) = xxx_todo_changeme1
print(err.args[0])
sys.exit(1) sys.exit(1)
elif object_action == "getks": elif object_action == "get-autoinstall":
if object_type == "profile": if object_type == "profile":
data = self.remote.generate_kickstart(options.name,"") data = self.remote.generate_profile_autoinstall(options.name )
elif object_type == "system": elif object_type == "system":
data = self.remote.generate_kickstart("",options.name) data = self.remote.generate_system_autoinstall(options.name)
print data print(data)
elif object_action == "dumpvars": elif object_action == "dumpvars":
if object_type == "profile": if object_type == "profile":
data = self.remote.get_blended_data(options.name,"") data = self.remote.get_blended_data(options.name, "")
elif object_type == "system": elif object_type == "system":
data = self.remote.get_blended_data("",options.name) data = self.remote.get_blended_data("", options.name)
# FIXME: pretty-printing and sorting here # FIXME: pretty-printing and sorting here
keys = data.keys() keys = list(data.keys())
keys.sort() keys.sort()
for x in keys: for x in keys:
print "%s : %s" % (x, data[x]) print("%s: %s" % (x, data[x]))
elif object_action in [ "poweron", "poweroff", "powerstatus", "reboo elif object_action in ["poweron", "poweroff", "powerstatus", "reboot
t" ]: "]:
power={} power = {}
power["power"] = object_action.replace("power","") power["power"] = object_action.replace("power", "")
power["systems"] = [options.name] power["systems"] = [options.name]
task_id = self.remote.background_power_system(power, self.token) task_id = self.remote.background_power_system(power, self.token)
elif object_action == "update": elif object_action == "update":
task_id = self.remote.background_signature_update(utils.strip_no ne(vars(options),omit_none=True), self.token) task_id = self.remote.background_signature_update(utils.strip_no ne(vars(options), omit_none=True), self.token)
elif object_action == "reload": elif object_action == "reload":
filename = opt(options,"filename") filename = opt(options, "filename", "/var/lib/cobbler/distro_sig
if filename in ["", None]: natures.json")
filename = "/var/lib/cobbler/distro_signatures.json" try:
if not utils.load_signatures(filename,cache=True): utils.load_signatures(filename, cache=True)
print "There was an error loading the signature data in %s." except:
% filename print("There was an error loading the signature data in %s."
print "Please check the JSON file or run 'cobbler signature % filename)
update'." print("Please check the JSON file or run 'cobbler signature
return False update'.")
return
else: else:
print "Signatures were successfully loaded" print("Signatures were successfully loaded")
else: else:
raise exceptions.NotImplementedError() raise NotImplementedException()
else: else:
raise exceptions.NotImplementedError() raise NotImplementedException()
# FIXME: add tail/polling code here # FIXME: add tail/polling code here
if task_id != -1: if task_id != -1:
self.print_task(task_id) self.print_task(task_id)
self.follow_task(task_id) self.follow_task(task_id)
return True
# BOOKMARK # BOOKMARK
def direct_command(self, action_name): def direct_command(self, action_name):
""" """
Process non-object based commands like "sync" and "hardlink" Process non-object based commands like "sync" and "hardlink"
""" """
task_id = -1 # if assigned, we must tail the logfile task_id = -1 # if assigned, we must tail the logfile
self.parser.set_usage('Usage: %%prog %s [options]' % (action_name)) self.parser.set_usage('Usage: %%prog %s [options]' % (action_name))
if action_name == "buildiso": if action_name == "buildiso":
defaultiso = os.path.join(os.getcwd(), "generated.iso") defaultiso = os.path.join(os.getcwd(), "generated.iso")
self.parser.add_option("--iso", dest="iso", default=defaultiso , help="(OPTIONAL) output ISO to this path") self.parser.add_option("--iso", dest="iso", default=defaultiso, help ="(OPTIONAL) output ISO to this file")
self.parser.add_option("--profiles", dest="profiles", help="(OPTIONA L) use these profiles only") self.parser.add_option("--profiles", dest="profiles", help="(OPTIONA L) use these profiles only")
self.parser.add_option("--systems", dest="systems", help="(OPTIONA self.parser.add_option("--systems", dest="systems", help="(OPTIONAL)
L) use these systems only") use these systems only")
self.parser.add_option("--tempdir", dest="buildisodir", help="(OPT self.parser.add_option("--tempdir", dest="buildisodir", help="(OPTIO
IONAL) working directory") NAL) working directory")
self.parser.add_option("--distro", dest="distro", help="(OPTIONA self.parser.add_option("--distro", dest="distro", help="(OPTIONAL) u
L) used with --standalone to create a distro-based ISO including all associated sed with --standalone and --airgapped to create a distro-based ISO including all
profiles/systems") associated profiles/systems")
self.parser.add_option("--standalone", dest="standalone", action="st self.parser.add_option("--standalone", dest="standalone", action="st
ore_true", help="(OPTIONAL) creates a standalone ISO with all required distro fi ore_true", help="(OPTIONAL) creates a standalone ISO with all required distro fi
les on it") les, but without any added repos")
self.parser.add_option("--source", dest="source", help="(OPTIONA self.parser.add_option("--airgapped", dest="airgapped", action="stor
L) used with --standalone to specify a source for the distribution files") e_true", help="(OPTIONAL) creates a standalone ISO with all distro and repo file
s for disconnected system installation")
self.parser.add_option("--source", dest="source", help="(OPTIONAL) u
sed with --standalone to specify a source for the distribution files")
self.parser.add_option("--exclude-dns", dest="exclude_dns", action=" store_true", help="(OPTIONAL) prevents addition of name server addresses to the kernel boot options") self.parser.add_option("--exclude-dns", dest="exclude_dns", action=" store_true", help="(OPTIONAL) prevents addition of name server addresses to the kernel boot options")
self.parser.add_option("--mkisofs-opts", dest="mkisofs_opts", help=" (OPTIONAL) extra options for mkisofs") self.parser.add_option("--mkisofs-opts", dest="mkisofs_opts", help=" (OPTIONAL) extra options for mkisofs")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("buildiso",options) task_id = self.start_task("buildiso", options)
elif action_name == "replicate": elif action_name == "replicate":
self.parser.add_option("--master", dest="master", h self.parser.add_option("--master", dest="master", help="Cobbler serv
elp="Cobbler server to replicate from.") er to replicate from.")
self.parser.add_option("--port", dest="port", h self.parser.add_option("--port", dest="port", help="Remote port.")
elp="Remote port.") self.parser.add_option("--distros", dest="distro_patterns", help="pa
self.parser.add_option("--distros", dest="distro_patterns", h tterns of distros to replicate")
elp="patterns of distros to replicate") self.parser.add_option("--profiles", dest="profile_patterns", help="
self.parser.add_option("--profiles", dest="profile_patterns", h patterns of profiles to replicate")
elp="patterns of profiles to replicate") self.parser.add_option("--systems", dest="system_patterns", help="pa
self.parser.add_option("--systems", dest="system_patterns", h tterns of systems to replicate")
elp="patterns of systems to replicate") self.parser.add_option("--repos", dest="repo_patterns", help="patter
self.parser.add_option("--repos", dest="repo_patterns", h ns of repos to replicate")
elp="patterns of repos to replicate") self.parser.add_option("--image", dest="image_patterns", help="patte
self.parser.add_option("--image", dest="image_patterns", h rns of images to replicate")
elp="patterns of images to replicate")
self.parser.add_option("--mgmtclasses", dest="mgmtclass_patterns", h elp="patterns of mgmtclasses to replicate") self.parser.add_option("--mgmtclasses", dest="mgmtclass_patterns", h elp="patterns of mgmtclasses to replicate")
self.parser.add_option("--packages", dest="package_patterns", h self.parser.add_option("--packages", dest="package_patterns", help="
elp="patterns of packages to replicate") patterns of packages to replicate")
self.parser.add_option("--files", dest="file_patterns", h self.parser.add_option("--files", dest="file_patterns", help="patter
elp="patterns of files to replicate") ns of files to replicate")
self.parser.add_option("--omit-data", dest="omit_data", action="st self.parser.add_option("--omit-data", dest="omit_data", action="stor
ore_true", help="do not rsync data") e_true", help="do not rsync data")
self.parser.add_option("--sync-all", dest="sync_all", action="st self.parser.add_option("--sync-all", dest="sync_all", action="store_
ore_true", help="sync all data") true", help="sync all data")
self.parser.add_option("--prune", dest="prune", action="st self.parser.add_option("--prune", dest="prune", action="store_true",
ore_true", help="remove objects (of all types) not found on the master") help="remove objects (of all types) not found on the master")
self.parser.add_option("--use-ssl", dest="use_ssl", action="st self.parser.add_option("--use-ssl", dest="use_ssl", action="store_tr
ore_true", help="use ssl to access the Cobbler master server api") ue", help="use ssl to access the Cobbler master server api")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("replicate",options) task_id = self.start_task("replicate", options)
elif action_name == "aclsetup": elif action_name == "aclsetup":
self.parser.add_option("--adduser", dest="adduser", self.parser.add_option("--adduser", dest="adduser", help="give acls
help="give acls to this user") to this user")
self.parser.add_option("--addgroup", dest="addgroup", self.parser.add_option("--addgroup", dest="addgroup", help="give acl
help="give acls to this group") s to this group")
self.parser.add_option("--removeuser", dest="removeuser", self.parser.add_option("--removeuser", dest="removeuser", help="remo
help="remove acls from this user") ve acls from this user")
self.parser.add_option("--removegroup", dest="removegroup", self.parser.add_option("--removegroup", dest="removegroup", help="re
help="remove acls from this group") move acls from this group")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("aclsetup",options) task_id = self.start_task("aclsetup", options)
elif action_name == "version": elif action_name == "version":
version = self.remote.extended_version() version = self.remote.extended_version()
print "Cobbler %s" % version["version"] print("Cobbler %s" % version["version"])
print " source: %s, %s" % (version["gitstamp"], version["gitdate"]) print(" source: %s, %s" % (version["gitstamp"], version["gitdate"])
print " build time: %s" % version["builddate"] )
print(" build time: %s" % version["builddate"])
elif action_name == "hardlink": elif action_name == "hardlink":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("hardlink",options) task_id = self.start_task("hardlink", options)
elif action_name == "reserialize": elif action_name == "reserialize":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("reserialize",options) task_id = self.start_task("reserialize", options)
elif action_name == "status": elif action_name == "status":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
print self.remote.get_status("text",self.token) print(self.remote.get_status("text", self.token))
elif action_name == "validateks": elif action_name == "validate-autoinstalls":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("validateks",options) task_id = self.start_task("validate_autoinstall_files", options)
elif action_name == "get-loaders": elif action_name == "get-loaders":
self.parser.add_option("--force", dest="force", action="store_true", help="overwrite any existing content in /var/lib/cobbler/loaders") self.parser.add_option("--force", dest="force", action="store_true", help="overwrite any existing content in /var/lib/cobbler/loaders")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("dlcontent",options) task_id = self.start_task("dlcontent", options)
elif action_name == "import": elif action_name == "import":
self.parser.add_option("--arch", dest="arch", help self.parser.add_option("--arch", dest="arch", help="OS architecture
="OS architecture being imported") being imported")
self.parser.add_option("--breed", dest="breed", help self.parser.add_option("--breed", dest="breed", help="the breed bein
="the breed being imported") g imported")
self.parser.add_option("--os-version", dest="os_version", help self.parser.add_option("--os-version", dest="os_version", help="the
="the version being imported") version being imported")
self.parser.add_option("--path", dest="path", help=" self.parser.add_option("--path", dest="path", help="local path or rs
local path or rsync location") ync location")
self.parser.add_option("--name", dest="name", help self.parser.add_option("--name", dest="name", help="name, ex 'RHEL-5
="name, ex 'RHEL-5'") '")
self.parser.add_option("--available-as", dest="available_as", help self.parser.add_option("--available-as", dest="available_as", help="
="tree is here, don't mirror") tree is here, don't mirror")
self.parser.add_option("--kickstart", dest="kickstart_file", help self.parser.add_option("--autoinstall", dest="autoinstall_file", hel
="assign this kickstart file") p="assign this autoinstall file")
self.parser.add_option("--rsync-flags", dest="rsync_flags", help self.parser.add_option("--rsync-flags", dest="rsync_flags", help="pa
="pass additional flags to rsync") ss additional flags to rsync")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
if options.path: if options.path and "rsync://" not in options.path:
# convert relative path to absolute path # convert relative path to absolute path
options.path = os.path.abspath(options.path) options.path = os.path.abspath(options.path)
task_id = self.start_task("import",options) task_id = self.start_task("import", options)
elif action_name == "reposync": elif action_name == "reposync":
self.parser.add_option("--only", dest="only", self.parser.add_option("--only", dest="only", help="update only this
help="update only this repository name") repository name")
self.parser.add_option("--tries", dest="tries", self.parser.add_option("--tries", dest="tries", help="try each repo
help="try each repo this many times", default=1) this many times", default=1)
self.parser.add_option("--no-fail", dest="nofail", self.parser.add_option("--no-fail", dest="nofail", help="don't stop
help="don't stop reposyncing if a failure occurs", action="store_true") reposyncing if a failure occurs", action="store_true")
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
task_id = self.start_task("reposync",options) task_id = self.start_task("reposync", options)
elif action_name == "aclsetup": elif action_name == "aclsetup":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
# FIXME: missing options, add them here # FIXME: missing options, add them here
task_id = self.start_task("aclsetup",options) task_id = self.start_task("aclsetup", options)
elif action_name == "check": elif action_name == "check":
results = self.remote.check(self.token) results = self.remote.check(self.token)
ct = 0 ct = 0
if len(results) > 0: if len(results) > 0:
print "The following are potential configuration items that you may want to fix:\n" print("The following are potential configuration items that you may want to fix:\n")
for r in results: for r in results:
ct = ct + 1 ct += 1
print "%s : %s" % (ct, r) print("%s: %s" % (ct, r))
print "\nRestart cobblerd and then run 'cobbler sync' to apply c print("\nRestart cobblerd and then run 'cobbler sync' to apply c
hanges." hanges.")
else: else:
print "No configuration problems found. All systems go." print("No configuration problems found. All systems go.")
elif action_name == "sync": elif action_name == "sync":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
self.parser.add_option("--verbose", dest="verbose", action="store_tr ue", help="run sync with more output") self.parser.add_option("--verbose", dest="verbose", action="store_tr ue", help="run sync with more output")
task_id = self.start_task("sync",options) task_id = self.start_task("sync", options)
elif action_name == "report": elif action_name == "report":
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
print "distros:\n==========" print("distros:\n==========")
report_items(self.remote,"distro") report_items(self.remote, "distro")
print "\nprofiles:\n==========" print("\nprofiles:\n==========")
report_items(self.remote,"profile") report_items(self.remote, "profile")
print "\nsystems:\n==========" print("\nsystems:\n==========")
report_items(self.remote,"system") report_items(self.remote, "system")
print "\nrepos:\n==========" print("\nrepos:\n==========")
report_items(self.remote,"repo") report_items(self.remote, "repo")
print "\nimages:\n==========" print("\nimages:\n==========")
report_items(self.remote,"image") report_items(self.remote, "image")
print "\nmgmtclasses:\n==========" print("\nmgmtclasses:\n==========")
report_items(self.remote,"mgmtclass") report_items(self.remote, "mgmtclass")
print "\npackages:\n==========" print("\npackages:\n==========")
report_items(self.remote,"package") report_items(self.remote, "package")
print "\nfiles:\n==========" print("\nfiles:\n==========")
report_items(self.remote,"file") report_items(self.remote, "file")
elif action_name == "list": elif action_name == "list":
# no tree view like 1.6? This is more efficient remotely # no tree view like 1.6? This is more efficient remotely
# for large configs and prevents xfering the whole config # for large configs and prevents xfering the whole config
# though we could consider that... # though we could consider that...
(options, args) = self.parser.parse_args() (options, args) = self.parser.parse_args()
print "distros:" print("distros:")
list_items(self.remote,"distro") list_items(self.remote, "distro")
print "\nprofiles:" print("\nprofiles:")
list_items(self.remote,"profile") list_items(self.remote, "profile")
print "\nsystems:" print("\nsystems:")
list_items(self.remote,"system") list_items(self.remote, "system")
print "\nrepos:" print("\nrepos:")
list_items(self.remote,"repo") list_items(self.remote, "repo")
print "\nimages:" print("\nimages:")
list_items(self.remote,"image") list_items(self.remote, "image")
print "\nmgmtclasses:" print("\nmgmtclasses:")
list_items(self.remote,"mgmtclass") list_items(self.remote, "mgmtclass")
print "\npackages:" print("\npackages:")
list_items(self.remote,"package") list_items(self.remote, "package")
print "\nfiles:" print("\nfiles:")
list_items(self.remote,"file") list_items(self.remote, "file")
else: else:
print "No such command: %s" % action_name print("No such command: %s" % action_name)
sys.exit(1) sys.exit(1)
# FIXME: run here # FIXME: run here
# FIXME: add tail/polling code here # FIXME: add tail/polling code here
if task_id != -1: if task_id != -1:
self.print_task(task_id) self.print_task(task_id)
self.follow_task(task_id) self.follow_task(task_id)
return True return True
def print_task(self, task_id): def print_task(self, task_id):
print "task started: %s" % task_id print("task started: %s" % task_id)
events = self.remote.get_events() events = self.remote.get_events()
(etime, name, status, who_viewed) = events[task_id] (etime, name, status, who_viewed) = events[task_id]
atime = time.asctime(time.localtime(etime)) atime = time.asctime(time.localtime(etime))
print "task started (id=%s, time=%s)" % (name, atime) print("task started (id=%s, time=%s)" % (name, atime))
def follow_task(self, task_id): def follow_task(self, task_id):
logfile = "/var/log/cobbler/tasks/%s.log" % task_id logfile = "/var/log/cobbler/tasks/%s.log" % task_id
# adapted from: http://code.activestate.com/recipes/157035/ # adapted from: http://code.activestate.com/recipes/157035/
file = open(logfile,'r') file = open(logfile, 'r')
#Find the size of the file and move to the end # Find the size of the file and move to the end
#st_results = os.stat(filename) # st_results = os.stat(filename)
#st_size = st_results[6] # st_size = st_results[6]
#file.seek(st_size) # file.seek(st_size)
while 1: while 1:
where = file.tell() where = file.tell()
line = file.readline() line = file.readline()
if line.find("### TASK COMPLETE ###") != -1: if line.find("### TASK COMPLETE ###") != -1:
print "*** TASK COMPLETE ***" print("*** TASK COMPLETE ***")
sys.exit(0) sys.exit(0)
if line.find("### TASK FAILED ###") != -1: if line.find("### TASK FAILED ###") != -1:
print "!!! TASK FAILED !!!" print("!!! TASK FAILED !!!")
sys.exit(1) sys.exit(1)
if not line: if not line:
time.sleep(1) time.sleep(1)
file.seek(where) file.seek(where)
else: else:
if line.find(" | "): if line.find(" | "):
line = line.split(" | ")[-1] line = line.split(" | ")[-1]
print line, # already has newline print(line, end='')
def print_object_help(self, object_type): def print_object_help(self, object_type):
""" """
Prints the subcommands for a given object, e.g. "cobbler distro --help" Prints the subcommands for a given object, e.g. "cobbler distro --help"
""" """
commands = OBJECT_ACTIONS_MAP[object_type] commands = OBJECT_ACTIONS_MAP[object_type]
commands.sort() commands.sort()
print "usage\n=====" print("usage\n=====")
for c in commands: for c in commands:
print "cobbler %s %s" % (object_type, c) print("cobbler %s %s" % (object_type, c))
sys.exit(2) sys.exit(2)
def print_help(self): def print_help(self):
""" """
Prints general-top level help, e.g. "cobbler --help" or "cobbler" or "co bbler command-does-not-exist" Prints general-top level help, e.g. "cobbler --help" or "cobbler" or "co bbler command-does-not-exist"
""" """
print "usage\n=====" print("usage\n=====")
print "cobbler <distro|profile|system|repo|image|mgmtclass|package|file> print("cobbler <distro|profile|system|repo|image|mgmtclass|package|file>
... " ... ")
print " [add|edit|copy|getks*|list|remove|rename|report] [options print(" [add|edit|copy|get-autoinstall*|list|remove|rename|report
|--help]" ] [options|--help]")
print "cobbler <%s> [options|--help]" % "|".join(DIRECT_ACTIONS) print("cobbler <%s> [options|--help]" % "|".join(DIRECT_ACTIONS))
sys.exit(2) sys.exit(2)
def main(): def main():
""" """
CLI entry point CLI entry point
""" """
cli = BootCLI() cli = CobblerCLI()
cli.check_setup() cli.check_setup()
rc = cli.run(sys.argv) rc = cli.run(sys.argv)
if rc == True or rc is None: if rc or rc is None:
sys.exit(0) sys.exit(0)
elif rc == False: elif not rc:
sys.exit(1) sys.exit(1)
return sys.exit(rc) return sys.exit(rc)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
 End of changes. 89 change blocks. 
369 lines changed or deleted 460 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)