示例#1
0
    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")
示例#2
0
def test_copy_single_distro_files(create_kernel_initrd, fk_initrd, fk_kernel):
    # Arrange
    # Create fake files
    directory = create_kernel_initrd(fk_kernel, fk_initrd)
    # Create test API
    test_api = CobblerAPI()
    # Get Collection Manager used by the API
    test_collection_mgr = test_api._collection_mgr
    # Create a test Distro
    test_distro = Distro(test_api)
    test_distro.name = "test_copy_single_distro_files"
    test_distro.kernel = str(os.path.join(directory, fk_kernel))
    test_distro.initrd = str(os.path.join(directory, fk_initrd))
    # Add test distro to the API
    test_api.add_distro(test_distro)
    # Create class under test
    test_gen = tftpgen.TFTPGen(test_collection_mgr)

    # Act
    test_gen.copy_single_distro_files(test_distro, directory, False)

    # Assert that path created by function under test is actually there
    result_kernel = os.path.join(directory, "images", test_distro.name,
                                 fk_kernel)
    result_initrd = os.path.join(directory, "images", test_distro.name,
                                 fk_initrd)
    assert os.path.exists(result_kernel)
    assert os.path.exists(result_initrd)
示例#3
0
    def sync(self, verbose=True):
        """
        Write out files to /tftpdboot.  Mostly unused for the python server

        :param verbose: This parameter is unused.
        """
        self.logger.info("copying bootloaders")
        tftpgen.TFTPGen(self.collection_mgr,
                        self.logger).copy_bootloaders(self.bootloc)
示例#4
0
    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
示例#5
0
    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()
示例#6
0
    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
示例#7
0
    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")
示例#8
0
def test_copy_single_distro_file():
    # Instantiate TFTPGen class with collection_mgr parameter
    test_api = CobblerAPI()
    test_collection_mgr = CollectionManager(test_api)
    generator = tftpgen.TFTPGen(test_collection_mgr)

    # Arrange
    distro_file = "/code/tests/test_data/dummy_initramfs"
    distro_dir = "/srv/tftpboot/images/"
    symlink_ok = True
    initramfs_dst_path = "/srv/tftpboot/images/dummy_initramfs"

    # Act
    generator.copy_single_distro_file(distro_file, distro_dir, symlink_ok)

    # Assert
    assert os.path.isfile(initramfs_dst_path)
示例#9
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()
示例#10
0
def test_copy_bootloaders(tmpdir):
    # Instantiate TFTPGen class with collection_mgr parameter
    test_api = CobblerAPI()
    test_collection_mgr = CollectionManager(test_api)
    generator = tftpgen.TFTPGen(test_collection_mgr)

    # Arrange
    ## Create temporary bootloader files using tmpdir fixture
    file_contents = "I am a bootloader"
    sub_path = tmpdir.mkdir("loaders")
    sub_path.join("bootloader1").write(file_contents)
    sub_path.join("bootloader2").write(file_contents)

    ## Copy temporary bootloader files from tmpdir to expected source directory
    for file in glob.glob(str(sub_path + "/*")):
        bootloader_src = "/var/lib/cobbler/loaders/"
        shutil.copy(file, bootloader_src + file.split("/")[-1])

    # Act
    generator.copy_bootloaders("/srv/tftpboot")

    # Assert
    assert os.path.isfile("/srv/tftpboot/bootloader1")
    assert os.path.isfile("/srv/tftpboot/bootloader2")
示例#11
0
    def __init__(self, is_cobblerd=False):
        """
        Constructor
        """

        # FIXME: this should be switchable through some simple system

        self.__dict__ = CobblerAPI.__shared_state
        self.perms_ok = False
        if not CobblerAPI.__has_loaded:

            # NOTE: we do not log all API actions, because
            # a simple CLI invocation may call adds and such
            # to load the config, which would just fill up
            # the logs, so we'll do that logging at CLI
            # level (and remote.py web service level) instead.

            random.seed()
            self.is_cobblerd = is_cobblerd

            try:
                self.logger = clogger.Logger("/var/log/cobbler/cobbler.log")
            except CX:
                # return to CLI/other but perms are not valid
                # perms_ok is False
                return

            # FIXME: conslidate into 1 server instance

            self.selinux_enabled = utils.is_selinux_enabled()
            self.dist = utils.check_dist()
            self.os_version = utils.os_release()

            CobblerAPI.__has_loaded = True

            # load the modules first, or nothing else works...
            module_loader.load_modules()

            self._collection_mgr = collection_manager.CollectionManager(self)
            self.deserialize()

            # import signatures
            try:
                utils.load_signatures(self.settings().signature_path)
            except Exception as e:
                self.log("Failed to load signatures from %s: %s" % (self.settings().signature_path, e))
                return

            self.log("%d breeds and %d OS versions read from the signature file" % (
                len(utils.get_valid_breeds()), len(utils.get_valid_os_versions()))
            )

            self.authn = self.get_module_from_file(
                "authentication",
                "module",
                "authn_configfile"
            )
            self.authz = self.get_module_from_file(
                "authorization",
                "module",
                "authz_allowall"
            )

            # FIXME: pass more loggers around, and also see that those
            # using things via tasks construct their own yumgen/tftpgen
            # versus reusing this one, which has the wrong logger
            # (most likely) for background tasks.

            self.yumgen = yumgen.YumGen(self._collection_mgr)
            self.tftpgen = tftpgen.TFTPGen(self._collection_mgr, logger=self.logger)
            self.power_mgr = power_manager.PowerManager(self, self._collection_mgr)
            self.logger.debug("API handle initialized")
            self.perms_ok = True
示例#12
0
    def __init__(self, collection_mgr):
        super().__init__(collection_mgr)

        self.tftpgen = tftpgen.TFTPGen(collection_mgr)
        self.bootloc = collection_mgr.settings().tftpboot_location
        self.webdir = collection_mgr.settings().webdir
示例#13
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