def removeInterfaceSubassetLinks(self): """Removes the subasset associated with each interface on the host This function is called when the host's asset is removed, for each subasset that was part of the host's asset the associated interface is disabled and set to have no associated hardware. Assets that are attached to the hosts's asset and are configured as an interface are relocated to the site the host is present at. This needs to be called before the internal properties are updated so that self._properties["asset_id"] contains the ID of the asset that is being removed. """ session = getSessionE(self._session_id) # Disable the interfaces that used subassets of the host asset session.execute("UPDATE interface SET subasset_id=NULL, " \ "interface_active='f' WHERE host_id=%s AND subasset_id IN " \ "(SELECT subasset_id FROM interface_subassets WHERE " \ "asset_id=%s)", (self.host_id, self._properties["asset_id"])) # Move attached assets configured as an interface to the hosts site res = session.query("SELECT a.asset_id FROM interface i, subasset s, " \ "asset a WHERE i.subasset_id=s.subasset_id AND " \ "s.asset_id=a.asset_id AND i.host_id=%s AND " \ "i.subasset_id NOT IN (SELECT subasset_id FROM " \ "interface_subassets WHERE asset_id=%s)", (self.host_id, self._properties["asset_id"])) for iface in res: asset = ccs_asset(self._session_id, iface["asset_id"]) if self.hasSite(): asset.moveToSite(self._properties["site_id"]) else: asset.moveToStock()
def setRurallinkDeviceConfig(session_id, asset_id, type): """Updates the device asset record to reflect the configuration type""" session = getSessionE(session_id) if asset_id == -1: # Called by a device itself, use the CN of the certificate to # lookup the mac address and find an asset ID mac = ":".join([session.username[(i * 2) - 2 : i * 2] for i in range(1, 7)]) if not isValidMAC(mac): raise ccs_rurallink_error("Asset not specified!") asset = getAssetByMac(session_id, mac) asset_id = asset["asset_id"] asset = ccs_asset(session_id, asset_id) if type == "CPE": asset.updateAssetDetail("description", "RuralLink Farm Terminal") elif type == "Repeater": asset.updateAssetDetail("description", "RuralLink Farm Repeater") elif type == "Master": asset.updateAssetDetail("description", "Rurallink Farm AP (Master Node)") else: raise ccs_rurallink_error("Unknown configuration type!") return True
def registerRurallinkWirelessCard(session_id, host_asset_id, mac): """Called by pxe-scripts to register a new wireless card The card is also attached to the device that is used to PXE boot it """ # Validate MAC address if not isValidMAC(mac): raise ccs_asset_error("Invalid MAC address!") try: asset = getAssetByMac(session_id, mac) except ccs_asset_error: # Asset does not exist asset = addRurallinkWirelessAsset(session_id, mac) # Check current location location = getAssetLocation(session_id, asset["asset_id"]) if location["attached_to"] == host_asset_id: # Up to date return asset # Get an asset object and attach it to the host asset assetobj = ccs_asset(session_id, asset["asset_id"]) assetobj.attachTo(host_asset_id) # Return the asset return asset
def getDevicePassword(session_id, asset_id): """Returns the device's password This password is generated by taking the Rural Link root password, concatenating it with the devices MAC address and returning the last 8 characters of an md5sum of the two """ # Get the master rurallink password s = rurallink_service(session_id, rurallink_service.service_id) d = s.getDetails() rl_pass = d["properties"][ROOTPASS_PROPERTY]["network_value"] # Get the MAC address of the specified device asset = ccs_asset(session_id, asset_id) mac = asset.getMAC() # Calculate and return the password sum = md5("%s%s" % (rl_pass, mac)).hexdigest() return sum[-8:]
def addHost(session_id, host): """Adds a new host to the database""" session = getSessionE(session_id) # Check host details validateHost(session_id, host, True) # Get loopback IP if not specified if "ip_address" not in host.keys() or host["ip_address"] == "": link_class_id = None if "link_class_id" in host.keys(): link_class_id = host["link_class_id"] host["ip_address"] = allocateLoopbackIP(session_id, link_class_id) # Build query props = ["host_id", "host_name", "distribution_id", "kernel_id", \ "ip_address", "asset_id", "site_id", "host_active", "is_gateway"] (sql, values) = buildInsertFromDict("host", props, host) # Run query session.execute(sql, values) # Get new host id res = session.query("SELECT currval('host_host_id_seq') " \ "AS host_id", ()) if len(res) != 1 or res[0]["host_id"]<1: return xmlrpclib.Fault(CCSD_BADPARAM, "Could not retrieve host ID") host_id = res[0]["host_id"] # Update asset location if required if "site_id" in host.keys() and "asset_id" in host.keys() and \ int(host["site_id"])!=-1 and int(host["asset_id"])!=-1: asset = ccs_asset(session_id, host["asset_id"]) asset.moveToSite(host["site_id"]) # Fire trigger triggerHostEvent(session_id, "hostAdded", host_id) return host_id
def setAssetLocation(self, newAsset=-1, newSite=-1): """Moves the host asset to a new location If newAsset or newSite are present and are not -1 they override the values stored in our current properties. """ # Process overrides if newAsset != -1: asset_id = newAsset else: asset_id = self["asset_id"] if newSite != -1: site_id = newSite else: site_id = self["site_id"] # Check asset and site are specified if site_id == -1 or asset_id == -1: return # Move to site asset = ccs_asset(self._session_id, asset_id) asset.moveToSite(site_id)
def validateHost(session_id, details, required=False): """Validates the details are valid. This routine does not check for the existance of required data, it only verifies that the fields in the supplied dictionary are valid. """ session = getSessionE(session_id) if "host_name" in details.keys(): if len(details["host_name"])<=0: raise ccs_host_error("Hostname must be greater than 0 " \ "characters long!") if len(details["host_name"]) > 64: raise ccs_host_error("Hostname must be less than 64 " \ "characters long!") if details["host_name"].find(" ") != -1: raise ccs_host_error("Hostname must not contain spaces") elif required: raise ccs_host_error("Hostname is a required field") if "distribution_id" in details.keys(): validateDistributionId(session_id, details["distribution_id"]) elif required: raise ccs_host_error("Distribution is a required field") if "kernel_id" in details.keys(): validateKernelId(session_id, details["kernel_id"]) elif required: raise ccs_host_error("Kernel is a required field") if "host_active" in details.keys(): if details["host_active"] != "t" and details["host_active"] != "f": raise ccs_host_error("Invalid host status value. Must be 't' " \ "or 'f'") elif required: raise ccs_host_error("Host status is a required field") if "is_gateway" in details.keys(): if details["is_gateway"] != "t" and details["is_gateway"] != "f": raise ccs_host_error("Invalid is gateway value. Must be 't' " \ "or 'f'") elif required: raise ccs_host_error("Gateway is a required field") # XXX: Check ip_address field # Site if "site_id" in details.keys() and int(details["site_id"])!=-1: validateSiteId(session_id, details["site_id"]) # Asset if "asset_id" in details.keys() and int(details["asset_id"])!=-1: asset = ccs_asset(session_id, details["asset_id"]) # Check asset is of the correct type if not asset.supportsFunction("host"): raise ccs_host_error("Specified asset is not of the " \ "appropriate type to use as a host!") # Check asset isn't assigned elsewhere if "site_id" in details.keys(): site_id = details["site_id"] else: site_id = -1 if not asset.availableForHost(site_id): raise ccs_host_error("Specified asset already in use or " \ "not available!") return
def moveAssetToStock(self): """Moves the host asset to stock, leaving it attached to the host""" asset = ccs_asset(self._sesion_id, self["asset_id"]) asset.moveToStock()
def removeAssetToStock(self): """Removes the host asset and shifts it to stock""" asset = ccs_asset(self._session_id, self["asset_id"]) asset.moveToStock() self._properties["asset_id"] = -1
def updateInterfaceSubassetLinks(self, new_asset_id): """Updates the subasset associated with each interface on the host This function is called when a hosts asset is changed. For each subasset that was part of the old host asset, the new asset is search for a subasset that matches the type and name, if one is found the interface is updated to use it. Any remaining subassets on the original host asset after this step are matched with any free subassets of the appropriate type on the new asset. Any remaining subassets on the original host after both these steps are disabled. Assets that are attached to hosts asset and are configured as an interface are reattached to the new host asset. This needs to be called before the internal properties are updated so that self._properties["asset_id"] contains the ID of the asset that is being removed. """ session = getSessionE(self._session_id) used = [] remaining = False # Exit now if the host did not have an asset assigned previously if self._properties["asset_id"] == "": return # Get a list of configured interface subassets on the old host and # their matching pair (based on name) on the new host res = session.query("SELECT a.name, a.asset_id AS old_asset_id, " \ "a.subasset_id AS old_subasset_id, b.asset_id AS " \ "new_asset_id, b.subasset_id AS new_subasset_id FROM " \ "interface_subassets a LEFT JOIN interface_subassets b ON " \ "a.name=b.name AND b.asset_id=%s WHERE a.asset_id=%s", (new_asset_id, self._properties["asset_id"])) for match in res: if match["new_subasset_id"] == "": remaining = True continue session.execute("UPDATE interface SET subasset_id=%s WHERE " \ "host_id=%s AND subasset_id=%s", (match["new_subasset_id"], self.host_id, \ match["old_subasset_id"])) used.append(match["new_subasset_id"]) # Now deal with the remainders, don't both matching names if remaining: # Fetch a list of interface subassets on the new asset idx = 0 res2 = session.query("SELECT * FROM interface_subassets WHERE " \ "asset_id=%s", new_asset_id) # Loop through each remaining subasset from the old asset for match in res: if match["new_subasset_id"] != "": continue fixed = False while idx < len(res2): # Check this subasset wasn't used above if res2[idx]["subasset_id"] in used: idx += 1 continue # Use it session.execute("UPDATE interface SET subasset_id=%s " \ "WHERE host_id=%s AND subasset_id=%s", (res2[idx]["subasset_id"], self.host_id, \ match["old_subasset_id"])) used.append(res2[idx]["new_subasset_id"]) idx += 1 fixed = True break # Disable if not fixed if not fixed: session.execute("UPDATE interface SET subasset_id=NULL, " \ "interface_active='f' WHERE host_id=%s AND " \ "subasset_id=%s", (self.host_id, \ match["old_subasset_id"])) # Move attached assets configured as an interface to the hosts site res = session.query("SELECT a.asset_id FROM interface i, subasset s, " \ "asset a WHERE i.subasset_id=s.subasset_id AND " \ "s.asset_id=a.asset_id AND i.host_id=%s AND " \ "i.subasset_id NOT IN (SELECT subasset_id FROM " \ "interface_subassets WHERE asset_id=%s OR asset_id=%s)", (self.host_id, self._properties["asset_id"], new_asset_id)) for iface in res: asset = ccs_asset(self._session_id, iface["asset_id"]) asset.attachTo(new_asset_id)