Пример #1
0
 def set_parent(self, parent_name):
     """
     Instead of a --distro, set the parent of this object to another profile
     and use the values from the parent instead of this one where the values
     for this profile aren't filled in, and blend them together where they
     are hashes.  Basically this enables profile inheritance.  To use this,
     the object MUST have been constructed with is_subobject=True or the
     default values for everything will be screwed up and this will likely NOT
     work.  So, API users -- make sure you pass is_subobject=True into the
     constructor when using this.
     """
     old_parent = self.get_parent()
     if isinstance(old_parent, item.Item):
         old_parent.children.pop(self.name, 'pass')
     if parent_name is None or parent_name == '':
         self.parent = ''
         return True
     if parent_name == self.name:
         # check must be done in two places as set_parent could be called before/after
         # set_name...
         raise CX(_("self parentage is weird"))
     found = self.config.profiles().find(name=parent_name)
     if found is None:
         raise CX(
             _("profile %s not found, inheritance not possible") %
             parent_name)
     self.parent = parent_name
     self.depth = found.depth + 1
     parent = self.get_parent()
     if isinstance(parent, item.Item):
         parent.children[self.name] = self
     return True
Пример #2
0
    def set_name(self, name):
        """
        Set the name.  If the name is a MAC or IP, and the first MAC and/or IP is not defined, go ahead
        and fill that value in.
        """

        if self.name not in ["", None] and self.parent not in [
                "", None
        ] and self.name == self.parent:
            raise CX(_("self parentage is weird"))
        if not isinstance(name, basestring):
            raise CX(_("name must be a string"))
        for x in name:
            if not x.isalnum() and not x in ["_", "-", ".", ":", "+"]:
                raise CX(_("invalid characters in name: %s") % x)

        # Stuff here defaults to eth0. Yes, it's ugly and hardcoded, but so was
        # the default interface behaviour that's now removed. ;)
        # --Jasper Capel
        if utils.is_mac(name):
            intf = self.__get_interface("eth0")
            if intf["mac_address"] == "":
                intf["mac_address"] = name
        elif utils.is_ip(name):
            intf = self.__get_interface("eth0")
            if intf["ip_address"] == "":
                intf["ip_address"] = name
        self.name = name

        return True
Пример #3
0
    def sync_dhcp(self):
        restart_dhcp = str(self.settings.restart_dhcp).lower()
        which_dhcp_module = module_loader.get_module_name("dhcp", "module").strip()

        if self.settings.manage_dhcp:
            self.write_dhcp()
            if which_dhcp_module == "manage_isc":
                service_name = utils.dhcp_service_name(self.api)
                if restart_dhcp != "0":
                    rc = utils.subprocess_call(self.logger, "dhcpd -t -q", shell=True)
                    if rc != 0:
                        error_msg = "dhcpd -t failed"
                        self.logger.error(error_msg)
                        raise CX(error_msg)
                    service_restart = "service %s restart" % service_name
                    rc = utils.subprocess_call(self.logger, service_restart, shell=True)
                    if rc != 0:
                        error_msg = "%s failed" % service_name
                        self.logger.error(error_msg)
                        raise CX(error_msg)
            elif which_dhcp_module == "manage_dnsmasq":
                if restart_dhcp != "0":
                    rc = utils.subprocess_call(self.logger, "service dnsmasq restart")
                    if rc != 0:
                        error_msg = "service dnsmasq restart failed"
                        self.logger.error(error_msg)
                        raise CX(error_msg)
Пример #4
0
 def check_if_valid(self):
     if self.name is None or self.name == "":
         raise CX("name is required")
     distro = self.get_conceptual_parent()
     if distro is None:
         raise CX("Error with profile %s - distro is required" %
                  (self.name))
Пример #5
0
    def auto_add_repos(self):
        """
        Import any repos this server knows about and mirror them.
        Credit: Seth Vidal.
        """
        self.log("auto_add_repos")
        try:
            import yum
        except:
            raise CX(_("yum is not installed"))

        version = yum.__version__
        (a, b, c) = version.split(".")
        version = a * 1000 + b * 100 + c
        if version < 324:
            raise CX(_("need yum > 3.2.4 to proceed"))

        base = yum.YumBase()
        base.doRepoSetup()
        repos = base.repos.listEnabled()
        if len(repos) == 0:
            raise CX(_("no repos enabled/available -- giving up."))

        for repo in repos:
            url = repo.urls[0]
            cobbler_repo = self.new_repo()
            auto_name = repo.name.replace(" ", "")
            # FIXME: probably doesn't work for yum-rhn-plugin ATM
            cobbler_repo.set_mirror(url)
            cobbler_repo.set_name(auto_name)
            print "auto adding: %s (%s)" % (auto_name, url)
            self._config.repos().add(cobbler_repo, save=True)

        # run cobbler reposync to apply changes
        return True
Пример #6
0
 def set_class_name(self, name):
     if not isinstance(name, basestring):
         raise CX(_("class name must be a string"))
     for x in name:
         if not x.isalnum() and x not in ["_", "-", ".", ":", "+"]:
             raise CX(_("invalid characters in class name: '%s'" % name))
     self.class_name = name
     return True
Пример #7
0
 def check_if_valid(self):
     if self.name is None or self.name == "":
         raise CX("name is required")
     if self.profile is None or self.profile == "":
         if self.image is None or self.image == "":
             raise CX(
                 "Error with system %s - profile or image is required" %
                 (self.name))
Пример #8
0
 def set_initrd(self, initrd):
     """
     Specifies an initrd image.  Path search works as in set_kernel.
     File must be named appropriately.
     """
     if initrd is None or initrd == "":
         raise CX("initrd not specified")
     if utils.find_initrd(initrd):
         self.initrd = initrd
         return True
     raise CX(_("initrd not found"))
Пример #9
0
 def set_power_type(self, power_type):
     # FIXME: modularize this better
     if power_type is None:
         power_type = ""
     choices = utils.get_power_types()
     if not choices:
         raise CX("you need to have fence-agents installed")
     if power_type not in choices:
         raise CX("power management type must be one of: %s" %
                  ",".join(choices))
     self.power_type = power_type
     return True
Пример #10
0
    def copy_single_distro_files(self, d, dirtree, symlink_ok):
        distros = os.path.join(dirtree, "images")
        distro_dir = os.path.join(distros, d.name)
        utils.mkdir(distro_dir)
        kernel = utils.find_kernel(d.kernel)    # full path
        initrd = utils.find_initrd(d.initrd)    # full path

        if kernel is None:
            raise CX("kernel not found: %(file)s, distro: %(distro)s" % {"file": d.kernel, "distro": d.name})

        if initrd is None:
            raise CX("initrd not found: %(file)s, distro: %(distro)s" % {"file": d.initrd, "distro": d.name})

        # Koan manages remote kernel itself, but for consistent PXE
        # configurations the synchronization is still necessary
        if not utils.file_is_remote(kernel):
            b_kernel = os.path.basename(kernel)
            dst1 = os.path.join(distro_dir, b_kernel)
            utils.linkfile(kernel, dst1, symlink_ok=symlink_ok, api=self.api, logger=self.logger)
        else:
            b_kernel = os.path.basename(kernel)
            dst1 = os.path.join(distro_dir, b_kernel)
            utils.copyremotefile(kernel, dst1, api=None, logger=self.logger)

        if not utils.file_is_remote(initrd):
            b_initrd = os.path.basename(initrd)
            dst2 = os.path.join(distro_dir, b_initrd)
            utils.linkfile(initrd, dst2, symlink_ok=symlink_ok, api=self.api, logger=self.logger)
        else:
            b_initrd = os.path.basename(initrd)
            dst1 = os.path.join(distro_dir, b_initrd)
            utils.copyremotefile(initrd, dst1, api=None, logger=self.logger)

        if "nexenta" == d.breed:
            try:
                os.makedirs(os.path.join(distro_dir, 'platform', 'i86pc', 'kernel', 'amd64'))
                os.makedirs(os.path.join(distro_dir, 'platform', 'i86pc', 'amd64'))
            except OSError:
                pass
            b_kernel = os.path.basename(kernel)
            utils.linkfile(kernel, os.path.join(distro_dir, 'platform', 'i86pc', 'kernel', 'amd64', b_kernel),
                           symlink_ok=symlink_ok, api=self.api, logger=self.logger)
            b_initrd = os.path.basename(initrd)
            utils.linkfile(initrd, os.path.join(distro_dir, 'platform', 'i86pc', 'amd64', b_initrd),
                           symlink_ok=symlink_ok, api=self.api, logger=self.logger)

            # the [:-7] removes the architecture
            if os.path.isdir(os.path.join('/var', 'www', 'cobbler', 'links', d.name, 'install_profiles')):
                shutil.rmtree(os.path.join('/var', 'www', 'cobbler', 'links', d.name, 'install_profiles'))
            shutil.copytree(os.path.join('/var', 'lib', 'cobbler', 'kickstarts', 'install_profiles'),
                            os.path.join('/var', 'www', 'cobbler', 'links', d.name, 'install_profiles'))
Пример #11
0
 def set_kernel(self, kernel):
     """
     Specifies a kernel.  The kernel parameter is a full path, a filename
     in the configured kernel directory (set in /etc/cobbler.conf) or a
     directory path that would contain a selectable kernel.  Kernel
     naming conventions are checked, see docs in the utils module
     for find_kernel.
     """
     if kernel is None or kernel == "":
         raise CX("kernel not specified")
     if utils.find_kernel(kernel):
         self.kernel = kernel
         return True
     raise CX("kernel not found: %s" % kernel)
Пример #12
0
def validate_power_type(power_type):
    """
    Check if a power management type is valid

    @param str power_type power management type
    @raise CX if power management type is invalid
    """

    power_types = get_power_types()
    if not power_types:
        raise CX("you need to have fence-agents installed")
    if power_type not in power_types:
        raise CX("power management type must be one of: %s" %
                 ",".join(power_types))
Пример #13
0
    def rename_interface(self, names):
        """
        Used to rename an interface.
        """
        (name, newname) = names
        if not name in self.interfaces:
            raise CX(_("Interface %s does not exist" % name))
        if newname in self.interfaces:
            raise CX(_("Interface %s already exists" % newname))
        else:
            self.interfaces[newname] = self.interfaces[name]
            del self.interfaces[name]

        return True
Пример #14
0
    def set_file(self, filename):
        """
        Stores the image location.  This should be accessible on all nodes
        that need to access it.  Format: can be one of the following:
        * username:password@hostname:/path/to/the/filename.ext
        * username@hostname:/path/to/the/filename.ext
        * hostname:/path/to/the/filename.ext
        * /path/to/the/filename.ext
        """
        uri = ""
        scheme = auth = hostname = path = ""
        # we'll discard the protocol if it's supplied, for legacy support
        if filename.find("://") != -1:
            scheme, uri = filename.split("://")
            filename = uri
        else:
            uri = filename

        if filename.find("@") != -1:
            auth, filename = filename.split("@")
        # extract the hostname
        # 1. if we have a colon, then everything before it is a hostname
        # 2. if we don't have a colon, then check if we had a scheme; if
        #    we did, then grab all before the first forward slash as the
        #    hostname; otherwise, we've got a bad file
        if filename.find(":") != -1:
            hostname, filename = filename.split(":")
        elif filename[0] != '/':
            if len(scheme) > 0:
                index = filename.find("/")
                hostname = filename[:index]
                filename = filename[index:]
            else:
                raise CX(_("invalid file: %s" % filename))
        # raise an exception if we don't have a valid path
        if len(filename) > 0 and filename[0] != '/':
            raise CX(_("file contains an invalid path: %s" % filename))
        if filename.find("/") != -1:
            path, filename = filename.rsplit("/", 1)

        if len(filename) == 0:
            raise CX(_("missing filename"))
        if len(auth) > 0 and len(hostname) == 0:
            raise CX(
                _("a hostname must be specified with authentication details"))

        self.file = uri
        return True
Пример #15
0
    def set_image(self, image_name):
        """
        Set the system to use a certain named image.  Works like set_profile
        but cannot be used at the same time.  It's one or the other.
        """
        old_parent = self.get_parent()
        if image_name in ["delete", "None", "~", ""] or image_name is None:
            self.image = ""
            if isinstance(old_parent, item.Item):
                old_parent.children.pop(self.name, 'pass')
            return True

        self.profile = ""  # mutual exclusion rule

        img = self.config.images().find(name=image_name)

        if img is not None:
            self.image = image_name
            self.depth = img.depth + 1
            if isinstance(old_parent, item.Item):
                old_parent.children.pop(self.name, 'pass')
            new_parent = self.get_parent()
            if isinstance(new_parent, item.Item):
                new_parent.children[self.name] = self
            return True
        raise CX(_("invalid image name (%s)") % image_name)
Пример #16
0
    def set_profile(self, profile_name):
        """
        Set the system to use a certain named profile.  The profile
        must have already been loaded into the Profiles collection.
        """
        old_parent = self.get_parent()
        if profile_name in ["delete", "None", "~", ""] or profile_name is None:
            self.profile = ""
            if isinstance(old_parent, item.Item):
                old_parent.children.pop(self.name, 'pass')
            return True

        self.image = ""  # mutual exclusion rule

        p = self.config.profiles().find(name=profile_name)
        if p is not None:
            self.profile = profile_name
            self.depth = p.depth + 1  # subprofiles have varying depths.
            if isinstance(old_parent, item.Item):
                old_parent.children.pop(self.name, 'pass')
            new_parent = self.get_parent()
            if isinstance(new_parent, item.Item):
                new_parent.children[self.name] = self
            return True
        raise CX(_("invalid profile name: %s") % profile_name)
Пример #17
0
    def run(self,
            adduser=None,
            addgroup=None,
            removeuser=None,
            removegroup=None):
        """
        Automate setfacl commands
        """

        ok = False
        if adduser:
            ok = True
            self.modacl(True, True, adduser)
        if addgroup:
            ok = True
            self.modacl(True, False, addgroup)
        if removeuser:
            ok = True
            self.modacl(False, True, removeuser)
        if removegroup:
            ok = True
            self.modacl(False, False, removegroup)
        if not ok:
            raise CX("no arguments specified, nothing to do")
        return True
Пример #18
0
def run(api, args, logger):
    # FIXME: use the logger

    if len(args) < 3:
        raise CX("invalid invocation")

    # objtype = args[0]      # "system" or "profile"
    name = args[1]  # name of system or profile
    # ip = args[2]           # ip or "?"

    settings = api.settings()
    anamon_enabled = str(settings.anamon_enabled)

    # Remove any files matched with the given glob pattern
    def unlink_files(globex):
        for f in glob.glob(globex):
            if os.path.isfile(f):
                try:
                    os.unlink(f)
                except OSError:
                    pass

    if str(anamon_enabled) in ["true", "1", "y", "yes"]:
        dirname = "/var/log/cobbler/anamon/%s" % name
        if os.path.isdir(dirname):
            unlink_files(os.path.join(dirname, "*"))

    # TODO - log somewhere that we cleared a systems anamon logs
    return 0
Пример #19
0
    def deserialize(self):
        """
        Load all collections from disk

        @raise CX if there is an error in deserialization
        """

        for collection in (
                self._settings,
                self._distros,
                self._repos,
                self._profiles,
                self._images,
                self._systems,
                self._mgmtclasses,
                self._packages,
                self._files,
        ):
            try:
                if not serializer.deserialize(collection):
                    raise ""
            except:
                raise CX(
                    "serializer: error loading collection %s. Check /etc/cobbler/modules.conf"
                    % collection.collection_type())
Пример #20
0
    def remove(self, name, with_delete=True, with_sync=True, with_triggers=True, recursive=False, logger=None):
        """
        Remove element named 'name' from the collection
        """
        name = name.lower()
        obj = self.find(name=name)

        if obj is not None:

            if with_delete:
                if with_triggers:
                    utils.run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/system/pre/*", [], logger)
                if with_sync:
                    lite_sync = action_litesync.BootLiteSync(self.config, logger=logger)
                    lite_sync.remove_single_system(name)
            self.lock.acquire()
            try:
                del self.listing[name]
            finally:
                self.lock.release()
            self.config.serialize_delete(self, obj)
            if with_delete:
                if with_triggers:
                    utils.run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/system/post/*", [], logger)
                    utils.run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/change/*", [], logger)

            return True

        raise CX(_("cannot delete an object that does not exist: %s") % name)
Пример #21
0
 def set_name(self, name):
     """
     All objects have names, and with the exception of System
     they aren't picky about it.
     """
     if self.name not in ["", None] and self.parent not in [
             "", None
     ] and self.name == self.parent:
         raise CX(_("self parentage is weird"))
     if not isinstance(name, basestring):
         raise CX(_("name must be a string"))
     for x in name:
         if not x.isalnum() and not x in ["_", "-", ".", ":", "+"]:
             raise CX(_("invalid characters in name: '%s'" % name))
     self.name = name
     return True
Пример #22
0
    def remove(self,
               name,
               with_delete=True,
               with_sync=True,
               with_triggers=True,
               recursive=False,
               logger=None):
        """
        Remove element named 'name' from the collection
        """
        name = name.lower()
        obj = self.find(name=name)
        if obj is not None:
            if with_delete:
                if with_triggers:
                    utils.run_triggers(
                        self.config.api, obj,
                        "/var/lib/cobbler/triggers/delete/file/*", [], logger)

            del self.listing[name]
            self.config.serialize_delete(self, obj)

            if with_delete:
                if with_triggers:
                    utils.run_triggers(
                        self.config.api, obj,
                        "/var/lib/cobbler/triggers/delete/file/post/*", [],
                        logger)
                    utils.run_triggers(self.config.api, obj,
                                       "/var/lib/cobbler/triggers/change/*",
                                       [], logger)

            return True

        raise CX(_("cannot delete an object that does not exist: %s") % name)
Пример #23
0
    def rsync_gen(self):
        """
        Generate rsync modules of all repositories and distributions
        """
        template_file = "/etc/cobbler/rsync.template"

        try:
            template = open(template_file, "r")
        except:
            raise CX(_("error reading template %s") % template_file)

        template_data = ""
        template_data = template.read()
        template.close()

        distros = []

        for link in glob.glob(os.path.join(self.settings.webdir, 'links', '*')):
            distro = {}
            distro["path"] = os.path.realpath(link)
            distro["name"] = os.path.basename(link)
            distros.append(distro)

        repos = [repo.name for repo in self.api.repos()
                 if os.path.isdir(os.path.join(self.settings.webdir, "repo_mirror", repo.name))]

        metadata = {
            "date": time.asctime(time.gmtime()),
            "cobbler_server": self.settings.server,
            "distros": distros,
            "repos": repos,
            "webdir": self.settings.webdir
        }

        self.templar.render(template_data, metadata, "/etc/rsyncd.conf", None)
Пример #24
0
 def set_network_count(self, num):
     if num is None or num == "":
         num = 1
     try:
         self.network_count = int(num)
     except:
         raise CX("invalid network count (%s)" % num)
     return True
Пример #25
0
 def sync_dhcp(self):
     restart_dhcp = str(self.settings.restart_dhcp).lower()
     service_name = utils.dhcp_service_name(self.api)
     if restart_dhcp != "0":
         rc = utils.subprocess_call(self.logger, "dhcpd -t -q", shell=True)
         if rc != 0:
             error_msg = "dhcpd -t failed"
             self.logger.error(error_msg)
             raise CX(error_msg)
         service_restart = "service %s restart" % service_name
         rc = utils.subprocess_call(self.logger,
                                    service_restart,
                                    shell=True)
         if rc != 0:
             error_msg = "%s failed" % service_name
             self.logger.error(error_msg)
             raise CX(error_msg)
Пример #26
0
 def set_gateway(self, gateway):
     if gateway is None:
         gateway = ""
     if utils.is_ip(gateway) or gateway == "":
         self.gateway = gateway
     else:
         raise CX(_("invalid format for gateway IP address (%s)") % gateway)
     return True
Пример #27
0
def __connect():
    # TODO: detect connection error
    global mongodb
    try:
        mongodb = Connection('localhost', 27017)['cobbler']
    except:
        # FIXME: log error
        raise CX("Unable to connect to Mongo database")
Пример #28
0
 def sync_dhcp(self):
     restart_dhcp = str(self.settings.restart_dhcp).lower()
     if restart_dhcp != "0":
         rc = utils.subprocess_call(self.logger, "service dnsmasq restart")
         if rc != 0:
             error_msg = "service dnsmasq restart failed"
             self.logger.error(error_msg)
             raise CX(error_msg)
Пример #29
0
    def __write_named_conf(self):
        """
        Write out the named.conf main config file from the template.
        """
        settings_file = self.settings.bind_chroot_path + self.settings_file
        template_file = "/etc/cobbler/named.template"
        # forward_zones = self.settings.manage_forward_zones
        # reverse_zones = self.settings.manage_reverse_zones

        metadata = {'forward_zones': self.__forward_zones().keys(),
                    'reverse_zones': [],
                    'zone_include': ''}

        for zone in metadata['forward_zones']:
                txt = """
zone "%(zone)s." {
    type master;
    file "%(zone)s";
};
""" % {'zone': zone}
                metadata['zone_include'] = metadata['zone_include'] + txt

        for zone in self.__reverse_zones().keys():
            # IPv6 zones are : delimited
            if ":" in zone:
                # if IPv6, assume xxxx:xxxx:xxxx:xxxx
                #                 0123456789012345678
                long_zone = (self.__expand_IPv6(zone + '::1'))[:19]
                tokens = list(re.sub(':', '', long_zone))
                tokens.reverse()
                arpa = '.'.join(tokens) + '.ip6.arpa'
            else:
                # IPv4 address split by '.'
                tokens = zone.split('.')
                tokens.reverse()
                arpa = '.'.join(tokens) + '.in-addr.arpa'
                #
            metadata['reverse_zones'].append((zone, arpa))
            txt = """
zone "%(arpa)s." {
    type master;
    file "%(zone)s";
};
""" % {'arpa': arpa, 'zone': zone}
            metadata['zone_include'] = metadata['zone_include'] + txt

        try:
            f2 = open(template_file, "r")
        except:
            raise CX(_("error reading template from file: %s") % template_file)
        template_data = ""
        template_data = f2.read()
        f2.close()

        if self.logger is not None:
            self.logger.info("generating %s" % settings_file)
        self.templar.render(template_data, metadata, settings_file, None)
Пример #30
0
def get_module_from_file(category,
                         field,
                         fallback_module_name=None,
                         just_name=False):

    try:
        value = cp.get(category, field)
    except:
        if fallback_module_name is not None:
            value = fallback_module_name
        else:
            raise CX(_("Cannot find config file setting for: %s") % field)
    if just_name:
        return value
    rc = MODULE_CACHE.get(value, None)
    if rc is None:
        raise CX(_("Failed to load module for %s/%s") % (category, field))
    return rc