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")
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
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
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")
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)
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 ""
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
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])])
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)
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)
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]
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)
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