def __init__(self,config,verbose=True,dhcp=None,dns=None,logger=None,tftpd=None): """ Constructor """ self.logger = logger if logger is None: self.logger = clogger.Logger() self.verbose = verbose self.config = config self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.templar = templar.Templar(config, self.logger) self.pxegen = pxegen.PXEGen(config, self.logger) self.dns = dns self.dhcp = dhcp self.tftpd = tftpd self.bootloc = utils.tftpboot_location() self.pxegen.verbose = verbose self.dns.verbose = verbose self.dhcp.verbose = verbose self.pxelinux_dir = os.path.join(self.bootloc, "pxelinux.cfg") self.grub_dir = os.path.join(self.bootloc, "grub") self.images_dir = os.path.join(self.bootloc, "images") self.yaboot_bin_dir = os.path.join(self.bootloc, "ppc") self.yaboot_cfg_dir = os.path.join(self.bootloc, "etc") self.s390_dir = os.path.join(self.bootloc, "s390x") self.rendered_dir = os.path.join(self.settings.webdir, "rendered")
def write_boot_files_distro(self,distro): # collapse the object down to a rendered datastructure # the second argument set to false means we don't collapse # hashes/arrays into a flat string target = utils.blender(self.config.api, False, distro) # Create metadata for the templar function # Right now, just using img_path, but adding more # cobbler variables here would probably be good metadata = {} metadata["img_path"] = os.path.join( utils.tftpboot_location(), "images",distro.name) # Create the templar instance. Used to template the target directory templater = templar.Templar() # Loop through the hash of boot files, # executing a cp for each one for file in target["boot_files"].keys(): file_dst = templater.render(file,metadata,None) try: shutil.copyfile(target["boot_files"][file], file_dst) self.config.api.log("copied file %s to %s for %s" % ( target["boot_files"][file], file_dst, distro.name)) except: self.logger.error("failed to copy file %s to %s for %s" % ( target["boot_files"][file], file_dst, distro.name)) # Continue on to sync what you can return 0
def __init__(self, config, logger): self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.config = config self.systems = config.systems() self.templar = templar.Templar(config)
def __init__(self, config, logger): """ Constructor """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.config = config self.templar = templar.Templar(config) self.settings_file = "/etc/xinetd.d/tftp"
def __init__(self, config): """ Constructor """ self.config = config self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.templar = templar.Templar(config)
def __init__(self, collection_mgr): """ Constructor """ self.collection_mgr = collection_mgr self.api = collection_mgr.api self.distros = collection_mgr.distros() self.profiles = collection_mgr.profiles() self.systems = collection_mgr.systems() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.templar = templar.Templar(collection_mgr)
def __init__(self, collection_mgr, logger): """ Constructor """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.collection_mgr = collection_mgr self.templar = templar.Templar(collection_mgr) self.settings_file = "/etc/xinetd.d/tftp" self.tftpgen = tftpgen.TFTPGen(collection_mgr, self.logger) self.systems = collection_mgr.systems() self.bootloc = utils.tftpboot_location()
def __init__(self,config,logger): """ Constructor """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.config = config self.templar = templar.Templar(config) self.settings_file = "/etc/xinetd.d/tftp" self.pxegen = pxegen.PXEGen(config, self.logger) self.systems = config.systems() self.bootloc = utils.tftpboot_location()
def __init__(self, config, logger): """ Constructor """ self.logger = logger self.config = config self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.templar = templar.Templar(config) self.settings_file = utils.dhcpconf_location(self.api)
def __init__(self, collection_mgr, logger): """ Constructor """ self.logger = logger self.collection_mgr = collection_mgr self.api = collection_mgr.api self.distros = collection_mgr.distros() self.profiles = collection_mgr.profiles() self.systems = collection_mgr.systems() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.templar = templar.Templar(collection_mgr) self.settings_file = utils.dhcpconf_location(self.api)
def __init__(self, collection_mgr, logger): """ Constructor """ self.collection_mgr = collection_mgr self.logger = logger self.api = collection_mgr.api self.distros = collection_mgr.distros() self.profiles = collection_mgr.profiles() self.systems = collection_mgr.systems() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.images = collection_mgr.images() self.templar = templar.Templar(collection_mgr) self.bootloc = utils.tftpboot_location()
def __init__(self, config, logger): """ Constructor """ self.config = config self.logger = logger self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.images = config.images() self.templar = templar.Templar(config) self.bootloc = utils.tftpboot_location()
def __init__(self, collection_mgr, logger): """ Constructor """ self.logger = logger self.collection_mgr = collection_mgr self.api = collection_mgr.api self.distros = collection_mgr.distros() self.profiles = collection_mgr.profiles() self.systems = collection_mgr.systems() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.templar = templar.Templar(collection_mgr) self.signature = None self.found_repos = {}
def __init__(self, config, logger): """ Constructor """ self.logger = logger self.config = config self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.templar = templar.Templar(config) self.signature = None self.found_repos = {}
def __init__(self, config, logger): """ Constructor """ self.config = config self.logger = logger self.api = config.api self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() self.settings = config.settings() self.repos = config.repos() self.images = config.images() self.templar = templar.Templar(config) self.bootloc = utils.tftpboot_location() # FIXME: not used anymore, can remove? self.verbose = False
def __init__(self, collection_mgr, logger): """ Constructor """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.collection_mgr = collection_mgr self.api = collection_mgr.api self.distros = collection_mgr.distros() self.profiles = collection_mgr.profiles() self.systems = collection_mgr.systems() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.templar = templar.Templar(collection_mgr) self.settings_file = utils.namedconf_location(self.api) self.zonefile_base = utils.zonefile_base(self.api)
def write_boot_files_distro(self, distro): # collapse the object down to a rendered datastructure # the second argument set to false means we don't collapse # hashes/arrays into a flat string target = utils.blender(self.config.api, False, distro) # Create metadata for the templar function # Right now, just using local_img_path, but adding more # cobbler variables here would probably be good metadata = {} metadata["local_img_path"] = os.path.join(utils.tftpboot_location(), "images", distro.name) # Create the templar instance. Used to template the target directory templater = templar.Templar(self.config) # Loop through the hash of boot files, # executing a cp for each one self.logger.info("processing boot_files for distro: %s" % distro.name) for file in target["boot_files"].keys(): rendered_file = templater.render(file, metadata, None) try: for f in glob.glob(target["boot_files"][file]): if f == target["boot_files"][file]: # this wasn't really a glob, so just copy it as is filedst = rendered_file else: # this was a glob, so figure out what the destination # file path/name should be tgt_path, tgt_file = os.path.split(f) rnd_path, rnd_file = os.path.split(rendered_file) filedst = os.path.join(rnd_path, tgt_file) if not os.path.isfile(filedst): shutil.copyfile(f, filedst) self.config.api.log("copied file %s to %s for %s" % (f, filedst, distro.name)) except: self.logger.error("failed to copy file %s to %s for %s" % (f, filedst, distro.name)) return 0
def power(self, desired_state): """ state is either "on" or "off". Rebooting is implemented at the api.py level. The user and password need not be supplied. If not supplied they will be taken from the environment, COBBLER_POWER_USER and COBBLER_POWER_PASS. If provided, these will override any other data and be used instead. Users interested in maximum security should take that route. """ template = self.get_command_template() template_file = open(template, "r") meta = utils.blender(self.api, False, self.system) meta["power_mode"] = desired_state # allow command line overrides of the username/password if self.force_user is not None: meta["power_user"] = self.force_user if self.force_pass is not None: meta["power_pass"] = self.force_pass tmp = templar.Templar(self.api._config) cmd = tmp.render(template_file, meta, None, self.system) template_file.close() cmd = cmd.strip() self.logger.info("cobbler power configuration is:") self.logger.info(" type : %s" % self.system.power_type) self.logger.info(" address: %s" % self.system.power_address) self.logger.info(" user : %s" % self.system.power_user) self.logger.info(" id : %s" % self.system.power_id) # if no username/password data, check the environment if meta.get("power_user", "") == "": meta["power_user"] = os.environ.get("COBBLER_POWER_USER", "") if meta.get("power_pass", "") == "": meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS", "") self.logger.info("- %s" % cmd) # use shell so we can have mutliple power commands chained together cmd = ['/bin/sh', '-c', cmd] # Try the power command 5 times before giving up. # Some power switches are flakey for x in range(0, 5): output, rc = utils.subprocess_sp(self.logger, cmd, shell=False) if rc == 0: # If the desired state is actually a query for the status # return different information than command return code if desired_state == 'status': match = re.match('(^Status:\s)(ON|OFF)', output) if match: power_status = match.groups()[1] if power_status == 'ON': return True else: return False utils.die( self.logger, "command succeeded (rc=%s), but output ('%s') was not understood" % (rc, output)) return None break else: time.sleep(2) if not rc == 0: utils.die( self.logger, "command failed (rc=%s), please validate the physical setup and cobbler config" % rc) return rc
def _power(self, system, power_operation, user=None, password=None, logger=None): """ Performs a power operation on a system. Internal method @param System system Cobbler system @param str power_operation power operation. Valid values: on, off, status. Rebooting is implemented as a set of 2 operations (off and on) in a higher level method. @param str user power management user. If user and password are not supplied, environment variables COBBLER_POWER_USER and COBBLER_POWER_PASS will be used. @param str password power management password @param Logger logger logger @return bool/None if power operation is 'status', return if system is on; otherwise, return None @raise CX if there are errors """ if logger is None: logger = self.logger power_command = get_power_command(system.power_type) if not power_command: utils.die(logger, "no power type set for system") meta = utils.blender(self.api, False, system) meta["power_mode"] = power_operation # allow command line overrides of the username/password if user is not None: meta["power_user"] = user if password is not None: meta["power_pass"] = password logger.info("cobbler power configuration is:") logger.info(" type : %s" % system.power_type) logger.info(" address: %s" % system.power_address) logger.info(" user : %s" % system.power_user) logger.info(" id : %s" % system.power_id) # if no username/password data, check the environment if meta.get("power_user", "") == "": meta["power_user"] = os.environ.get("COBBLER_POWER_USER", "") if meta.get("power_pass", "") == "": meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS", "") template = get_power_template(system.power_type) tmp = templar.Templar(self.collection_mgr) template_data = tmp.render(template, meta, None, system) logger.info("power command: %s" % power_command) logger.info("power command input: %s" % template_data) # Try the power command 5 times before giving up. # Some power switches are flakey for x in range(0, 5): output, rc = utils.subprocess_sp(logger, power_command, shell=False, input=template_data) if rc == 0: # If the desired state is actually a query for the status # return different information than command return code if power_operation == 'status': match = re.match('^(Status:|.+power\s=)\s(on|off)$', output, re.IGNORECASE | re.MULTILINE) if match: power_status = match.groups()[1] if power_status.lower() == 'on': return True else: return False error_msg = "command succeeded (rc=%s), but output ('%s') was not understood" % ( rc, output) utils.die(logger, error_msg) raise CX(error_msg) return None else: time.sleep(2) if not rc == 0: error_msg = "command failed (rc=%s), please validate the physical setup and cobbler config" % rc utils.die(logger, error_msg) raise CX(error_msg)
def power(self, desired_state): """ state is either "on" or "off". Rebooting is implemented at the api.py level. The user and password need not be supplied. If not supplied they will be taken from the environment, COBBLER_POWER_USER and COBBLER_POWER_PASS. If provided, these will override any other data and be used instead. Users interested in maximum security should take that route. """ power_command = utils.get_power(self.system.power_type) if not power_command: utils.die(self.logger, "no power type set for system") meta = utils.blender(self.api, False, self.system) meta["power_mode"] = desired_state # allow command line overrides of the username/password if self.force_user is not None: meta["power_user"] = self.force_user if self.force_pass is not None: meta["power_pass"] = self.force_pass self.logger.info("cobbler power configuration is:") self.logger.info(" type : %s" % self.system.power_type) self.logger.info(" address: %s" % self.system.power_address) self.logger.info(" user : %s" % self.system.power_user) self.logger.info(" id : %s" % self.system.power_id) # if no username/password data, check the environment if meta.get("power_user", "") == "": meta["power_user"] = os.environ.get("COBBLER_POWER_USER", "") if meta.get("power_pass", "") == "": meta["power_pass"] = os.environ.get("COBBLER_POWER_PASS", "") template = utils.get_power_template(self.system.power_type) tmp = templar.Templar(self.api._collection_mgr) template_data = tmp.render(template, meta, None, self.system) # Try the power command 5 times before giving up. # Some power switches are flakey for x in range(0, 5): output, rc = utils.subprocess_sp(self.logger, power_command, shell=False, input=template_data) if rc == 0: # If the desired state is actually a query for the status # return different information than command return code if desired_state == 'status': match = re.match('^(Status:|.+power\s=)\s(on|off)$', output, re.IGNORECASE | re.MULTILINE) if match: power_status = match.groups()[1] if power_status.lower() == 'on': return True else: return False error_msg = "command succeeded (rc=%s), but output ('%s') was not understood" % (rc, output) utils.die(self.logger, error_msg) raise CX(error_msg) return None else: time.sleep(2) if not rc == 0: error_msg = "command failed (rc=%s), please validate the physical setup and cobbler config" % rc utils.die(self.logger, error_msg) raise CX(error_msg)