def __init__(self, collection_mgr, 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.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.logger) self.tftpgen = tftpgen.TFTPGen(collection_mgr, self.logger) self.dns = dns self.dhcp = dhcp self.tftpd = tftpd self.bootloc = self.settings.tftpboot_location self.tftpgen.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.rendered_dir = os.path.join(self.settings.webdir, "rendered")
def run(api, args, logger): settings = api.settings() for distro in api.distros(): # 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(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("/tftpboot/images", distro.name) # Create the templar instance templater = templar.Templar() # Loop through the hash of fetchable files, # executing a cp for each one for file in target["fetchable_files"].keys(): file_dst = templater.render(file, metadata, None) try: shutil.copyfile(target["fetchable_files"][file], file_dst) api.log( "copied file %s to %s for %s" % (target["fetchable_files"][file], file_dst, distro.name)) except: logger.error( "failed to copy file %s to %s for %s" % (target["fetchable_files"][file], file_dst, distro.name)) return 1 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): """ This class can manage a New-DJBDNS server. :param config: Currently an usused parameter. """ self.config = config self.systems = config.systems() self.templar = templar.Templar(config)
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)
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"
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): """ Constructor :param collection_mgr: The collection manager to resolve all information with. """ self.logger = logging.getLogger() self.collection_mgr = collection_mgr self.templar = templar.Templar(collection_mgr) self.tftpgen = tftpgen.TFTPGen(collection_mgr) self.systems = collection_mgr.systems() self.bootloc = collection_mgr.settings().tftpboot_location
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, collection_mgr, logger): """ Constructor :param collection_mgr: The instance who holds all the information from Cobbler. :param logger: The logger to audit all actions with. """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.collection_mgr = collection_mgr self.bootloc = collection_mgr.settings().tftpboot_location self.templar = templar.Templar(collection_mgr)
def __init__(self, collection_mgr): """ Constructor :param collection_mgr: The main collection manager instance which is used by the current running server. """ 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, config, logger): """ This class can manage a New-DJBDNS server. :param config: Currently an usused parameter. :param logger: The logger to audit the actions with. """ 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, 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 = self.settings.tftpboot_location
def __init__(self, collection_mgr): """ Constructor :param collection_mgr: The collection manager to resolve all information with. """ self.logger = logging.getLogger() 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): """ Constructor :param collection_mgr: The collection manager instance which is used for this object. Normally there is only one instance of the collection manager. """ 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 :param collection_mgr: The collection manager to resolve all information with. :param logger: The logger to audit all actions with. """ self.logger = logger if self.logger is None: self.logger = clogger.Logger() self.collection_mgr = collection_mgr self.templar = templar.Templar(collection_mgr) self.tftpgen = tftpgen.TFTPGen(collection_mgr, self.logger) self.systems = collection_mgr.systems() self.bootloc = collection_mgr.settings().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, collection_mgr, logger): """ Constructor :param collection_mgr: The collection manager to resolve all information with. :param logger: The logger to audit all actions with. """ 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()
def __init__(self, collection_mgr, verbose=True, dhcp=None, dns=None, logger=None, tftpd=None): """ Constructor :param collection_mgr: The collection manager instance which holds all information about cobbler. :param verbose: Whether to log the actions performed in this module verbose or not. :param dhcp: The DHCP manager which can update the DHCP config. :param dns: The DNS manager which can update the DNS config. :param logger: The logger to audit all action with. :param tftpd: The TFTP manager which can update the TFTP config. """ self.logger = logger if logger is None: self.logger = clogger.Logger() self.verbose = verbose 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.logger) self.tftpgen = tftpgen.TFTPGen(collection_mgr, self.logger) self.dns = dns self.dhcp = dhcp self.tftpd = tftpd self.bootloc = self.settings.tftpboot_location self.tftpgen.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.ipxe_dir = os.path.join(self.bootloc, "ipxe") self.rendered_dir = os.path.join(self.settings.webdir, "rendered")
def __init__(self, collection_mgr, logger, dhcp=None): """ Constructor :param collection_mgr: The collection manager to resolve all information with. :param logger: The logger to audit all actions with. :param dhcp: This parameter is unused currently. """ 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)
def __init__(self, collection_mgr): """ Constructor to create a default BindManager object. :param collection_mgr: The collection manager to resolve all information with. """ self.logger = logging.getLogger() 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.zonefile_base = utils.zonefile_base()
def __init__(self, collection_mgr): """ Main constructor for our class. :param collection_mgr: This is the collection manager which has every information in Cobbler available. """ self.logger = logging.getLogger() 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, 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 dicts/arrays into a flat string. target = utils.blender(self.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(self.bootloc, "images", distro.name) metadata["web_img_path"] = os.path.join(self.webdir, "distro_mirror", distro.name) # Create the templar instance. Used to template the target directory templater = templar.Templar(self.collection_mgr) # Loop through the dict of boot files, executing a cp for each one self.logger.info("processing boot_files for distro: %s" % distro.name) for boot_file in list(target["boot_files"].keys()): rendered_target_file = templater.render(boot_file, metadata, None) rendered_source_file = templater.render( target["boot_files"][boot_file], metadata, None) try: for file in glob.glob(rendered_source_file): if file == rendered_source_file: # this wasn't really a glob, so just copy it as is filedst = rendered_target_file else: # this was a glob, so figure out what the destination file path/name should be tgt_path, tgt_file = os.path.split(file) rnd_path, rnd_file = os.path.split( rendered_target_file) filedst = os.path.join(rnd_path, tgt_file) if not os.path.isdir(rnd_path): utils.mkdir(rnd_path) if not os.path.isfile(filedst): shutil.copyfile(file, filedst) self.collection_mgr.api.log("copied file %s to %s for %s" % (file, filedst, distro.name)) except: self.logger.error("failed to copy file %s to %s for %s", file, filedst, distro.name) return 0
def __init__(self, collection_mgr, verbose: bool = True, dhcp=None, dns=None, tftpd=None): """ Constructor :param collection_mgr: The collection manager instance which holds all information about cobbler. :param verbose: Whether to log the actions performed in this module verbose or not. :param dhcp: The DHCP manager which can update the DHCP config. :param dns: The DNS manager which can update the DNS config. :param tftpd: The TFTP manager which can update the TFTP config. """ self.logger = logging.getLogger() self.verbose = verbose 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.images = collection_mgr.images() self.settings = collection_mgr.settings() self.repos = collection_mgr.repos() self.templar = templar.Templar(collection_mgr) self.tftpgen = tftpgen.TFTPGen(collection_mgr) self.dns = dns self.dhcp = dhcp self.tftpd = tftpd self.bootloc = self.settings.tftpboot_location 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.ipxe_dir = os.path.join(self.bootloc, "ipxe") self.rendered_dir = os.path.join(self.settings.webdir, "rendered") self.links = os.path.join(self.settings.webdir, "links") self.distromirror_config = os.path.join(self.settings.webdir, "distro_mirror/config") # FIXME: See https://github.com/cobbler/cobbler/issues/2453 # Move __create_tftpboot_dirs() outside of sync.py. self.__create_tftpboot_dirs()
def __init__(self, collection_mgr, logger): """ Constructor :param collection_mgr: This is the collection manager which has every information in Cobbler available. :param logger: This is the logger to audit all actions with. """ 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 run(api, args, logger): # FIXME: make everything use the logger settings = api.settings() # go no further if this feature is turned off if not str(settings.build_reporting_enabled).lower() in [ "1", "yes", "y", "true" ]: return 0 objtype = args[0] # "target" or "profile" name = args[1] # name of target or profile boot_ip = args[2] # ip or "?" if objtype == "system": target = api.find_system(name) else: target = api.find_profile(name) # collapse the object down to a rendered datastructure target = utils.blender(api, False, target) if target == {}: raise CX("failure looking up target") to_addr = settings.build_reporting_email if to_addr == "": return 0 # add the ability to specify an MTA for servers that don't run their own smtp_server = settings.build_reporting_smtp_server if smtp_server == "": smtp_server = "localhost" # use a custom from address or fall back to a reasonable default from_addr = settings.build_reporting_sender if from_addr == "": from_addr = "cobbler@%s" % settings.server subject = settings.build_reporting_subject if subject == "": subject = '[Cobbler] install complete ' to_addr = ", ".join(to_addr) metadata = { "from_addr": from_addr, "to_addr": to_addr, "subject": subject, "boot_ip": boot_ip } metadata.update(target) input_template = open("/etc/cobbler/reporting/build_report_email.template") input_data = input_template.read() input_template.close() message = templar.Templar().render(input_data, metadata, None) # for debug, call # print message # Send the mail # FIXME: on error, return non-zero server_handle = smtplib.SMTP(smtp_server) server_handle.sendmail(from_addr, to_addr, message) server_handle.quit() return 0
def run(api, args): settings = api.settings() if not settings.windows_enabled: return 0 if not HAS_HIVEX: logger.info( "python3-hivex or python3-pefile not found. If you need Automatic Windows Installation support, " "please install.") return 0 profiles = api.profiles() systems = api.systems() templ = templar.Templar(api._collection_mgr) tgen = tftpgen.TFTPGen(api._collection_mgr) with open( os.path.join(settings.windows_template_dir, post_inst_cmd_template_name)) as template_win: post_tmpl_data = template_win.read() with open( os.path.join(settings.windows_template_dir, answerfile_template_name)) as template_win: tmpl_data = template_win.read() with open( os.path.join(settings.windows_template_dir, startnet_template_name)) as template_start: tmplstart_data = template_start.read() def gen_win_files(distro, meta): (kernel_path, kernel_name) = os.path.split(distro.kernel) distro_path = utils.find_distro_path(settings, distro) distro_dir = wim_file_name = os.path.join(settings.tftpboot_location, "images", distro.name) web_dir = os.path.join(settings.webdir, "images", distro.name) is_winpe = "winpe" in meta and meta['winpe'] != "" is_bcd = "bcd" in meta and meta['bcd'] != "" if "kernel" in meta: kernel_name = meta["kernel"] kernel_name = os.path.basename(kernel_name) is_wimboot = "wimboot" in kernel_name if is_wimboot: distro_path = os.path.join(settings.webdir, "distro_mirror", distro.name) kernel_path = os.path.join(distro_path, "Boot") if "kernel" in meta and "wimboot" not in distro.kernel: tgen.copy_single_distro_file( os.path.join(settings.tftpboot_location, kernel_name), distro_dir, False) tgen.copy_single_distro_file( os.path.join(distro_dir, kernel_name), web_dir, True) if "post_install_script" in meta: post_install_dir = distro_path if distro.os_version not in ("XP", "2003"): post_install_dir = os.path.join(post_install_dir, "sources") post_install_dir = os.path.join(post_install_dir, "$OEM$", "$1") if not os.path.exists(post_install_dir): utils.mkdir(post_install_dir) data = templ.render(post_tmpl_data, meta, None) post_install_script = os.path.join(post_install_dir, meta["post_install_script"]) logger.info('Build post install script: ' + post_install_script) with open(post_install_script, "w+") as pi_file: pi_file.write(data) if "answerfile" in meta: data = templ.render(tmpl_data, meta, None) answerfile_name = os.path.join(distro_dir, meta["answerfile"]) logger.info('Build answer file: ' + answerfile_name) with open(answerfile_name, "w+") as answerfile: answerfile.write(data) tgen.copy_single_distro_file(answerfile_name, distro_path, False) tgen.copy_single_distro_file(answerfile_name, web_dir, True) if "kernel" in meta and "bootmgr" in meta: wk_file_name = os.path.join(distro_dir, kernel_name) wl_file_name = os.path.join(distro_dir, meta["bootmgr"]) tl_file_name = os.path.join(kernel_path, "bootmgr.exe") if distro.os_version in ("XP", "2003") and not is_winpe: tl_file_name = os.path.join(kernel_path, "setupldr.exe") if len(meta["bootmgr"]) != 5: logger.error( "The loader name should be EXACTLY 5 character") return 1 pat1 = re.compile(br'NTLDR', re.IGNORECASE) pat2 = re.compile(br'winnt\.sif', re.IGNORECASE) with open(tl_file_name, 'rb') as file: out = data = file.read() if "answerfile" in meta: if len(meta["answerfile"]) != 9: logger.error( "The response file name should be EXACTLY 9 character" ) return 1 out = pat2.sub(bytes(meta["answerfile"], 'utf-8'), data) else: if len(meta["bootmgr"]) != 11: logger.error( "The Boot manager file name should be EXACTLY 11 character" ) return 1 bcd_name = "bcd" if is_bcd: bcd_name = meta["bcd"] if len(bcd_name) != 3: logger.error( "The BCD file name should be EXACTLY 3 character") return 1 if not os.path.isfile(tl_file_name): logger.error("File not found: %s" % tl_file_name) return 1 pat1 = re.compile(br'bootmgr\.exe', re.IGNORECASE) pat2 = re.compile(br'(\\.B.o.o.t.\\.)(B)(.)(C)(.)(D)', re.IGNORECASE) bcd_name = bytes( "\\g<1>" + bcd_name[0] + "\\g<3>" + bcd_name[1] + "\\g<5>" + bcd_name[2], 'utf-8') with open(tl_file_name, 'rb') as file: out = file.read() if not is_wimboot: logger.info('Patching build Loader: %s' % wl_file_name) out = pat2.sub(bcd_name, out) if tl_file_name != wl_file_name: logger.info('Build Loader: %s from %s' % (wl_file_name, tl_file_name)) with open(wl_file_name, 'wb+') as file: file.write(out) tgen.copy_single_distro_file(wl_file_name, web_dir, True) if not is_wimboot: if distro.os_version not in ("XP", "2003") or is_winpe: pe = pefile.PE(wl_file_name, fast_load=True) pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum() pe.write(filename=wl_file_name) with open(distro.kernel, 'rb') as file: data = file.read() out = pat1.sub(bytes(meta["bootmgr"], 'utf-8'), data) if wk_file_name != distro.kernel: logger.info("Build PXEBoot: %s from %s" % (wk_file_name, distro.kernel)) with open(wk_file_name, 'wb+') as file: file.write(out) tgen.copy_single_distro_file(wk_file_name, web_dir, True) if is_bcd: obcd_file_name = os.path.join(kernel_path, "bcd") bcd_file_name = os.path.join(distro_dir, meta["bcd"]) wim_file_name = 'winpe.wim' if not os.path.isfile(obcd_file_name): logger.error("File not found: %s" % obcd_file_name) return 1 if is_winpe: wim_file_name = meta["winpe"] if is_wimboot: wim_file_name = '\\Boot\\' + wim_file_name sdi_file_name = '\\Boot\\' + 'boot.sdi' else: wim_file_name = os.path.join("/images", distro.name, wim_file_name) sdi_file_name = os.path.join("/images", distro.name, os.path.basename(distro.initrd)) logger.info('Build BCD: %s from %s for %s' % (bcd_file_name, obcd_file_name, wim_file_name)) bcdedit(obcd_file_name, bcd_file_name, wim_file_name, sdi_file_name) tgen.copy_single_distro_file(bcd_file_name, web_dir, True) if is_winpe: ps_file_name = os.path.join(distro_dir, meta["winpe"]) wim_pl_name = os.path.join(kernel_path, "winpe.wim") cmd = ["/usr/bin/cp", "--reflink=auto", wim_pl_name, ps_file_name] utils.subprocess_call(logger, cmd, shell=False) tgen.copy_single_distro_file(ps_file_name, web_dir, True) if os.path.exists(wimupdate): data = templ.render(tmplstart_data, meta, None) pi_file = tempfile.NamedTemporaryFile() pi_file.write(bytes(data, 'utf-8')) pi_file.flush() cmd = [ wimupdate, ps_file_name, "--command=add " + pi_file.name + " /Windows/System32/startnet.cmd" ] utils.subprocess_call(cmd, shell=False) pi_file.close() for profile in profiles: distro = profile.get_conceptual_parent() if distro and distro.breed == "windows": logger.info('Profile: ' + profile.name) meta = utils.blender(api, False, profile) autoinstall_meta = meta.get("autoinstall_meta", {}) meta.update(autoinstall_meta) gen_win_files(distro, meta) for system in systems: profile = system.get_conceptual_parent() autoinstall_meta = system.autoinstall_meta if not profile or not autoinstall_meta or autoinstall_meta == {}: continue distro = profile.get_conceptual_parent() if distro and distro.breed == "windows": logger.info('System: ' + system.name) meta = utils.blender(api, False, system) gen_win_files(distro, autoinstall_meta) return 0
def run(api, args): if not HAS_HIVEX: logger.info("python3-hivex or python3-pefile not found. If you need Automatic Windows Installation support, " "please install.") return 0 distros = api.distros() profiles = api.profiles() templ = templar.Templar(api._collection_mgr) template_win = open(post_inst_cmd_template_name) tmpl_data = template_win.read() template_win.close() for distro in distros: if distro.breed == "windows": meta = utils.blender(api, False, distro) if "post_install" in distro.kernel_options: data = templ.render(tmpl_data, meta, None) pi_file = open(distro.kernel_options["post_install"], "w+") pi_file.write(data) pi_file.close() template_win = open(sif_template_name) tmpl_data = template_win.read() template_win.close() template_start = open(startnet_template_name) tmplstart_data = template_start.read() template_start.close() logger.info("\nWindows profiles:") for profile in profiles: distro = profile.get_conceptual_parent() if distro.breed == "windows": logger.info('Profile: ' + profile.name) meta = utils.blender(api, False, profile) (distro_path, pxeboot_name) = os.path.split(distro.kernel) if "sif" in profile.kernel_options: data = templ.render(tmpl_data, meta, None) if distro.os_version in ("7", "2008", "8", "2012", "2016", "2019", "10"): sif_file_name = os.path.join(distro_path, 'sources', profile.kernel_options["sif"]) else: sif_file_name = os.path.join(distro_path, profile.kernel_options["sif"]) sif_file = open(sif_file_name, "w+") sif_file.write(data) sif_file.close() logger.info('Build answer file: ' + sif_file_name) if "pxeboot" in profile.kernel_options and "bootmgr" in profile.kernel_options: wk_file_name = os.path.join(distro_path, profile.kernel_options["pxeboot"]) wl_file_name = os.path.join(distro_path, profile.kernel_options["bootmgr"]) logger.info("Build PXEBoot: " + wk_file_name) if distro.os_version in ("7", "2008", "8", "2012", "2016", "2019", "10"): if len(profile.kernel_options["bootmgr"]) != 11: logger.error("The loader name should be EXACTLY 11 character") return 1 if "bcd" in profile.kernel_options: if len(profile.kernel_options["bcd"]) != 3: logger.error("The BCD name should be EXACTLY 5 character") return 1 tl_file_name = os.path.join(distro_path, 'bootmgr.exe') pat1 = re.compile(br'bootmgr\.exe', re.IGNORECASE) pat2 = re.compile(br'(\\.B.o.o.t.\\.)(B)(.)(C)(.)(D)', re.IGNORECASE) bcd_name = 'BCD' if "bcd" in profile.kernel_options: bcd_name = profile.kernel_options["bcd"] bcd_name = bytes("\\g<1>" + bcd_name[0] + "\\g<3>" + bcd_name[1] + "\\g<5>" + bcd_name[2], 'utf-8') data = open(tl_file_name, 'rb').read() out = pat2.sub(bcd_name, data) else: if len(profile.kernel_options["bootmgr"]) != 5: logger.error("The loader name should be EXACTLY 5 character") return 1 if len(profile.kernel_options["sif"]) != 9: logger.error("The response should be EXACTLY 9 character") return 1 tl_file_name = os.path.join(distro_path, 'setupldr.exe') pat1 = re.compile(br'NTLDR', re.IGNORECASE) pat2 = re.compile(br'winnt\.sif', re.IGNORECASE) data = open(tl_file_name, 'rb').read() out = pat2.sub(bytes(profile.kernel_options["sif"], 'utf-8'), data) logger.info('Build Loader: ' + wl_file_name) if out != data: open(wl_file_name, 'wb+').write(out) if distro.os_version in ("7", "2008", "8", "2012", "2016", "2019", "10"): pe = pefile.PE(wl_file_name, fast_load=True) pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum() pe.write(filename=wl_file_name) data = open(distro.kernel, 'rb').read() out = pat1.sub(bytes(profile.kernel_options["bootmgr"], 'utf-8'), data) if out != data: open(wk_file_name, 'wb+').write(out) if "bcd" in profile.kernel_options: obcd_file_name = os.path.join(distro_path, 'boot', 'BCD') bcd_file_name = os.path.join(distro_path, 'boot', profile.kernel_options["bcd"]) wim_file_name = 'winpe.wim' if "winpe" in profile.kernel_options: wim_file_name = profile.kernel_options["winpe"] if distro.boot_loader == "ipxe": wim_file_name = '\\Boot\\' + wim_file_name sdi_file_name = '\\Boot\\' + 'boot.sdi' else: wim_file_name = os.path.join('/winos', distro.name, 'boot', wim_file_name) sdi_file_name = os.path.join('/winos', distro.name, 'boot', 'boot.sdi') logger.info('Build BCD: ' + bcd_file_name + ' for ' + wim_file_name) bcdedit(obcd_file_name, bcd_file_name, wim_file_name, sdi_file_name) if "winpe" in profile.kernel_options: ps_file_name = os.path.join(distro_path, "boot", profile.kernel_options["winpe"]) if distro.os_version in ("7", "2008"): wim_pl_name = wim7_template_name elif distro.os_version in ("8", "2012", "2016", "2019", "10"): wim_pl_name = wim8_template_name else: raise ValueError("You are trying to use an unsupported distro!") cmd = "/usr/bin/cp --reflink=auto " + wim_pl_name + " " + ps_file_name utils.subprocess_call(cmd, shell=True) if os.path.exists(wimupdate): data = templ.render(tmplstart_data, meta, None) pi_file = tempfile.NamedTemporaryFile() pi_file.write(bytes(data, 'utf-8')) pi_file.flush() cmd = wimupdate + ' ' + ps_file_name + ' --command="add ' + pi_file.name cmd += ' /Windows/System32/startnet.cmd"' utils.subprocess_call(cmd, shell=True) pi_file.close() return 0