Example #1
0
 def __init__(self):
     self.env = Environment.getInstance()
     self.ldap_handler = LDAPHandler.get_instance()
     self.nfs_root = self.env.config.get("nfs_root", default="/srv/nfsroot")
     self.nfs_opts = self.env.config.get("nfs_opts", default="nfs4")
     self.fai_flags = self.env.config.get("fai_flags", default="verbose,sshd,syslogd,createvt,reboot")
     self.union = self.env.config.get("union", default="unionfs")
Example #2
0
    def resolve(self, number):
        number = self.replaceNumber(number)

        filtr = ldap.filter.filter_format("(&(uid=*)(telephoneNumber=%s))", str(number))
        attrs = ['cn', 'uid', 'telephoneNumber']

        # search ldap
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE, filtr, attrs)
            if len(res) == 1:
                result = {
                        'company_id': '',
                        'company_name': 'Intern',
                        'company_phone': '',
                        'company_detail_url': '',
                        'contact_id': res[0][1]['uid'][0],
                        'contact_name': unicode(res[0][1]['cn'][0], 'UTF-8'),
                        'contact_phone': res[0][1]['telephoneNumber'][0],
                        'contact_detail_url': '',
                        'ldap_uid': res[0][1]['uid'][0],
                        'resource': 'ldap',
                }
                return result
            else:
                return None
Example #3
0
    def getBaseInstallParameters(self, device_uuid, data=None):
        """
        Return parameters used to bootstrap a device.

        =============== ====================
        Parameter       Description
        =============== ====================
        device_uuid     Unique device ID
        =============== ====================

        Please take a look at
        :meth:`libinst.interface.BaseInstallMethod.setBaseInstallParameters`
        for more information about the returned properties.

        ``Return:`` dict
        """
        res = {}
        if not data:
            data = load_system(device_uuid, None, False)

        for key, value in self.attributes.items():
            if key in data:
                res[value] = data[key]

        if 'installTemplateDN' in data:
            lh = LDAPHandler.get_instance()
            with lh.get_handle() as conn:
                lres = conn.search_s(data['installTemplateDN'][0],
                        ldap.SCOPE_BASE, "(objectClass=installTemplate)", ["cn"])

            res['template'] = lres[0][1]['cn'][0]

        return res
Example #4
0
    def __init__(self):
        # Load LDAP handler class
        self.env = Environment.getInstance()
        self.log = getLogger(__name__)

        self.lh = LDAPHandler.get_instance()
        self.con = self.lh.get_connection()
        self.uuid_entry = self.env.config.get("ldap.uuid_attribute", "entryUUID")
Example #5
0
    def __update_node(self, device_uuid, remove=False):
        # Load template and get the install method
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                ldap.filter.filter_format("(&(objectClass=configRecipe)(objectClass=installRecipe)(deviceUUID=%s))",
                    [device_uuid]),
                ['cn', 'installRecipeDN', 'configVariable', 'configItem',
                'installRelease'])

        # Bail out if not present
        if len(res) != 1:
            raise ValueError("unknown device %s" % device_uuid)

        data = res[0][1]

        # Load device variables
        variables = {}
        if 'configVariable' in data:
            for var in data['configVariable']:
                key, value =  var.split('=', 1)
                variables[key] = value

        # Get FQDN / Release
        fqdn = data['cn'][0].lower()
        release = "/".join(data['installRelease'][0].split("/")[1:])

        # Open nodes.pp and maintain it
        target_path, target_name = self.__get_target(release, "/")
        nodes_file = os.path.join(target_path, "manifests", "nodes.pp")

        #TODO: resolve recipe chain
        #data['installRecipe'][0]
        #->
        #node ldap-server {
        #  import "dns"
        #  include sudo
        #  include openldap
        #  include resolv
        #}
        inherit = None

        nm = PuppetNodeManager(nodes_file)
        if remove:
            nm.remove(fqdn)
        else:
            nm.add(fqdn, variables, data['configItem'] if data['configItem'] else [], None)
        nm.write()
        del nm

        self.gitPush(self.getBaseDir(release), "Updated node %s" % device_uuid)
Example #6
0
    def systemGetStatus(self, device_uuid):
        """
        TODO
        """
        lh = LDAPHandler.get_instance()
        fltr = "deviceUUID=%s" % device_uuid

        with lh.get_handle() as conn:
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                "(&(objectClass=device)(%s))" % fltr, ['deviceStatus'])

            if len(res) != 1:
                raise ValueError("no device '%s' available" % device_uuid)

            return res[0][1]["deviceStatus"][0]

        return ""
Example #7
0
    def __get_client_release(self, device_uuid):
        # Load template and get the install method
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                ldap.filter.filter_format("(&(objectClass=configRecipe)(objectClass=installRecipe)(deviceUUID=%s))",
                    [device_uuid]),
                ['cn', 'installRecipeDN', 'configVariable', 'configItem',
                'installRelease'])

        # Bail out if not present
        if len(res) != 1:
            raise ValueError("unknown device %s" % device_uuid)

        #TODO: resolve recipe chain
        data = "/".join(res[0][1]['installRelease'][0].split("/")[1:])
        return data
Example #8
0
    def systemSetStatus(self, device_uuid, status):
        """
        TODO
        """
        # Check params
        valid = [STATUS_SYSTEM_ON, STATUS_LOCKED, STATUS_UPDATABLE,
            STATUS_UPDATING, STATUS_INVENTORY, STATUS_CONFIGURING,
            STATUS_INSTALLING, STATUS_VM_INITIALIZING, STATUS_WARNING,
            STATUS_ERROR, STATUS_OCCUPIED, STATUS_BOOTING,
            STATUS_NEEDS_INSTALL, STATUS_NEEDS_CONFIG,
            STATUS_NEEDS_INITIAL_CONFIG, STATUS_NEEDS_REMOVE_CONFIG]

        # Write to LDAP
        lh = LDAPHandler.get_instance()
        fltr = "deviceUUID=%s" % device_uuid

        with lh.get_handle() as conn:
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                "(&(objectClass=device)(%s))" % fltr, ['deviceStatus'])

            if len(res) != 1:
                raise ValueError("no device '%s' available" % device_uuid)

            devstat = res[0][1]['deviceStatus'][0] if 'deviceStatus' in res[0][1] else ""
            is_new = not bool(devstat)
            devstat = list(devstat.strip("[]"))

            r = re.compile(r"([+-].)")
            for stat in r.findall(status):
                if not stat[1] in valid:
                    raise ValueError("invalid status %s" % stat[1])
                if stat.startswith("+"):
                    if not stat[1] in devstat:
                        devstat.append(stat[1])
                else:
                    if stat[1] in devstat:
                        devstat.remove(stat[1])

            devstat = "[" + "".join(devstat).encode('utf8') + "]"
            if is_new:
                conn.modify(res[0][0], [(ldap.MOD_ADD, "deviceStatus", [devstat])])
            else:
                conn.modify(res[0][0], [(ldap.MOD_REPLACE, "deviceStatus", [devstat])])
Example #9
0
    def removeBaseInstallParameters(self, device_uuid, data=None):
        """
        Disable device base install capabilities.

        =========== ===========================================
        Parameter   Description
        =========== ===========================================
        device_uuid Unique identifier of a device
        =========== ===========================================
        """
        if not data:
            data = load_system(device_uuid)

        mods = [(ldap.MOD_DELETE, 'objectClass', 'installRecipe')]
        for attr in self.attributes.keys() + ["installTemplateDN"]:
            if attr in data:
                mods.append((ldap.MOD_DELETE, attr, None))

        # Do LDAP operations to remove the device
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            conn.modify_s(data['dn'], mods)
Example #10
0
    def removeConfigParameters(self, device_uuid, data=None):
        """
        Disable device configuration managmenet.

        =========== ===========================================
        Parameter   Description
        =========== ===========================================
        device_uuid Unique identifier of a device
        =========== ===========================================

        ``Return:`` True on success
        """
        if not data:
            data = load_system(device_uuid)

        mods = [(ldap.MOD_DELETE, 'objectClass', 'configRecipe')]
        for attr in ["configMethod", "configItem", "configVariable"]:
            mods.append((ldap.MOD_DELETE, attr, None))

        # Do LDAP operations to remove the device
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            conn.modify_s(data['dn'], mods)
Example #11
0
    def joinClient(self, user, device_uuid, mac, info=None):
        """
        TODO
        """
        uuid_check = re.compile(r"^[0-9a-f]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$", re.IGNORECASE)
        if not uuid_check.match(device_uuid):
            raise ValueError("join with invalid UUID %s" % device_uuid)

        lh = LDAPHandler.get_instance()

        # Handle info, if present
        more_info = []

        if info:
            # Check string entries
            for entry in filter(lambda x: x in info,
                ["serialNumber", "ou", "o", "l", "description"]):

                if not re.match(r"^[\w\s]+$", info[entry]):
                    raise ValueError("invalid data (%s) provided for '%s'" % (info[entry], entry))

                more_info.append((entry, info[entry]))

            # Check desired device type if set
            if "deviceType" in info:
                if re.match(r"^(terminal|workstation|server|sipphone|switch|router|printer|scanner)$",
                    info["deviceType"]):

                    more_info.append(("deviceType", info["deviceType"]))
                else:
                    raise ValueError("invalid device type '%s' specified" % info["deviceType"])

            # Check owner for presence
            if "owner" in info:
                with lh.get_handle() as conn:

                    # Take a look at the directory to see if there's
                    # such an owner DN
                    try:
                        conn.search_s(info["owner"], ldap.SCOPE_BASE, attrlist=['dn'])
                        more_info.append(("owner", info["owner"]))
                    except Exception as e:
                        raise ValueError("owner %s not found: %s" % (info["owner"], str(e)))

        # Generate random client key
        random.seed()
        key = ''.join(random.Random().sample(string.letters + string.digits, 32))
        salt = os.urandom(4)
        h = hashlib.sha1(key)
        h.update(salt)

        # Do LDAP operations to add the system
        with lh.get_handle() as conn:

            # Take a look at the directory to see if there's
            # already a joined client with this uuid
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                "(&(objectClass=registeredDevice)(macAddress=%s))" % mac, ["macAddress"])

            # Already registered?
            if res:
                raise Exception("device with hardware address %s has already been joined" % mac)

            # While the client is going to be joined, generate a random uuid and
            # an encoded join key
            cn = str(uuid4())
            device_key = self.__encrypt_key(device_uuid.replace("-", ""), cn + key)

            # Resolve manger
            res = conn.search_s(lh.get_base(), ldap.SCOPE_SUBTREE,
                    "(uid=%s)" % user, [])
            if len(res) != 1:
                raise Exception("failed to get current users DN: %s" %
                    ("not unique" if res else "not found"))
            manager = res[0][0]

            # Create new machine entry
            record = [
                ('objectclass', ['device', 'ieee802Device', 'simpleSecurityObject', 'registeredDevice']),
                ('deviceUUID', cn),
                ('deviceKey', [device_key]),
                ('cn', [cn] ),
                ('manager', [manager] ),
                ('macAddress', [mac.encode("ascii", "ignore")] ),
                ('userPassword', ["{SSHA}" + encode(h.digest() + salt)])
            ]
            record += more_info

            # Evaluate base
            #TODO: take hint from "info" parameter, to allow "joiner" to provide
            #      a target base
            base = lh.get_base()

            # Add record
            dn = ",".join(["cn=" + cn, self.env.config.get("goto.machine-rdn",
                default="ou=systems"), base])
            conn.add_s(dn, record)

        self.log.info("UUID '%s' joined as %s" % (device_uuid, dn))
        return [key, cn]
Example #12
0
    def setConfigParameters(self, device_uuid, data, current_data=None):
        """
        Set the system config parameters that are used
        provision the config management system.

        =========== ===========================================
        Parameter   Description
        =========== ===========================================
        device_uuid Unique device identifier
        data        Dictionary specifying the properties
        =========== ===========================================

        The data dictionary has the following property keys:
        always lists**):

        ====== ===================================
        Key    Description
        ====== ===================================
        item    List of assigned items
        method  Config management method to use
        var     Dict of variables and their values
        ====== ===================================

        ``Return:`` True no success
        """
        if not current_data:
            current_data = load_system(device_uuid, None, False)

        is_new = not 'configRecipe' in current_data['objectClass']
        dn = current_data['dn']
        current_data = self.getConfigParameters(device_uuid, current_data)

        mods = []

        # Add eventually missing objectclass
        if is_new:
            mods.append((ldap.MOD_ADD, 'objectClass', 'configRecipe'))

        # Map variables
        if 'var' in data:
            tmp = copy(data['var'])
            data['var'] = []
            if tmp:
                for key, value in tmp.items():
                    if "=" in key:
                        raise ValueError("variable key doesn't allow equal signs")
                    data['var'].append("%s=%s" % (key, value))

        # Transfer changed parameters
        for ldap_key, key in self.attributes.items():

            # New value?
            if key in data and not key in current_data:
                mods.append((ldap.MOD_ADD, ldap_key,
                    normalize_ldap(unicode2utf8(data[key]))))
                continue

            # Changed value?
            if key in data and key in current_data \
                    and data[key] != current_data[key]:

                mods.append((ldap.MOD_REPLACE, ldap_key,
                    normalize_ldap(unicode2utf8(data[key]))))
                continue

        # Removed values
        for key in current_data.keys():
            if key in self.rev_attributes and not key in data:
                mods.append((ldap.MOD_DELETE, self.rev_attributes[key], None))

        # Do LDAP operations to add the system
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            conn.modify_s(dn, mods)
Example #13
0
    def setBaseInstallParameters(self, device_uuid, data, current_data=None):
        """
        Set the system base install parameters that are used
        to fill up the template.

        =============== ==============================
        Parameter       Description
        =============== ==============================
        device_uuid     Unique device ID
        data            Hash describing the parameters
        =============== ==============================

        The return parameters are encoded as a dictionary with these keys:

        =============== ======================================================
        Key             Description
        =============== ======================================================
        utc             Flag to specify if system uses UTC
        timezone        String to specify time zone
        ntp-servers     List of time server names/IPs
        kernel          The boot kernel package name
        root-hash       Hashed version of the root password
        root-user       Flag to decide if there's a root user
        disk-setup      String oriented at the RedHat kickstart device string
        template        String containing the system template
        system-locale   Locale definition for the system
        release         Release to install on the system
        keyboard-layout Keyboard layout to use
        =============== ======================================================

        ``Return:`` dict
        """
        # Load device
        if not current_data:
            current_data = load_system(device_uuid, None, False)

        is_new = not 'installRecipe' in current_data['objectClass']
        dn = current_data['dn']
        current_data = self.getBaseInstallParameters(device_uuid, current_data)

        mods = []

        # Add eventually missing objectclass
        if is_new:
            mods.append((ldap.MOD_ADD, 'objectClass', 'installRecipe'))

        # Transfer changed parameters
        for ldap_key, key in self.attributes.items():

            # New value?
            if key in data and not key in current_data:
                mods.append((ldap.MOD_ADD, ldap_key,
                    normalize_ldap(unicode2utf8(data[key]))))
                continue

            # Changed value?
            if key in data and key in current_data \
                    and data[key] != current_data[key]:

                mods.append((ldap.MOD_REPLACE, ldap_key,
                    normalize_ldap(unicode2utf8(data[key]))))
                continue

        # Removed values
        for key in current_data.keys():
            if key in self.rev_attributes and not key in data:
                mods.append((ldap.MOD_DELETE, self.rev_attributes[key], None))

        # Do LDAP operations to add the system
        res = None
        lh = LDAPHandler.get_instance()
        with lh.get_handle() as conn:
            res = conn.search_s(",".join([self.env.config.get("libinst.template-rdn",
                "cn=templates,cn=libinst,cn=config"), lh.get_base()]),
                ldap.SCOPE_SUBTREE, "(&(objectClass=installTemplate)(cn=%s))" % data['template'], ["cn"])
            if len(res) != 1:
                raise ValueError("template '%s' not found" % data['template'])

            template_dn = res[0][0]
            if is_new:
                mods.append((ldap.MOD_ADD, 'installTemplateDN', [template_dn]))
            else:
                mods.append((ldap.MOD_REPLACE, 'installTemplateDN', [template_dn]))

            res = conn.modify_s(dn, mods)

        return res