def updateDetails(self, details): """Updates the details of the interface. details should be a dictionary containing only those parameters that have changed and need to be updated in the database. Returns ccs_interface.SUCCESS, """ session = getSessionE(self._session_id) # Check the data validateInterface(self._session_id, details) # Extract values for ease of use. host_id = "host_id" in details.keys() and \ int(details["host_id"]) or self["host_id"] link_id = "link_id" in details.keys() and \ int(details["link_id"]) or self["link_id"] subasset_id = "subasset_id" in details.keys() and \ int(details["subasset_id"]) or self["subasset_id"] interface_type = "interface_type" in details.keys() and \ int(details["interface_type"]) or self["interface_type"] bridge_interface = "bridge_interface" in details.keys() and \ int(details["bridge_interface"]) or self["bridge_interface"] monitor_interface = "monitor_interface" in details.keys() and \ details["monitor_interface"] or self["monitor_interface"] # Check subasset is valid if it is specified if subasset_id != self["subasset_id"] and subasset_id != -1: subasset = ccs_subasset(self._session_id, subasset_id) if not subasset.supportsFunction("interface"): raise ccs_interface_error("Invalid subasset type!") if not subasset.availableForInterface(host_id): raise ccs_interface_error("Subasset already in use!") # Check this host doesn't already have an interface on the new link if link_id != self["link_id"] and \ (bridge_interface=="" or bridge_interface==-1): link = ccs_link(self._session_id, link_id) if link.connectsHost(host_id, self.interface_id): raise ccs_interface_error("Host already has an interface on " \ "the specified link!") if "ip_address" not in details.keys(): raise ccs_interface_error("IP Address must change when " \ "modifing the link!") # Check interface type if interface_type != self["interface_type"]: if interface_type <= INTERFACE_TYPE_MIN or \ interface_type >= INTERFACE_TYPE_MAX: raise ccs_interface_error("Invalid interface type!") # Check IP is specified and is correct for the link if "ip_address" in details.keys() and \ (bridge_interface=="" or bridge_interface==-1): link = ccs_link(self._session_id, link_id) if details["ip_address"] == "": details["ip_address"] = link.allocateIP(host_id, False) elif not link.isValidIP(details["ip_address"]): raise ccs_interface_error("Invalid IP address for link!") # Check interface is in master mode if a channel was specified if "master_channel" in details.keys() or \ "master_mode" in details.keys(): if "master_interface" not in details.keys(): if not self._properties["master_interface"]: log_warn("Interface channel may only " \ "be set for Master mode interfaces!") del details["master_channel"] del details["master_mode"] else: if details["master_interface"]!="t": log_warn("Interface channel may only " \ "be set for Master mode interfaces!") del details["master_channel"] del details["master_mode"] # Check VLAN properties if interface_type == INTERFACE_TYPE_VLAN: # Check the vid is valid if specified if "vid" in interface.keys() and \ interface["vid"] != "": try: vid = int(interface["vid"]) except: raise ccs_interface_error("Alias VLAN ID must be an integer") # VLAN interfaces have a name derived from their parent interface parent_iface = ccs_interface(session_id, interface["raw_interface"]) interface["name"] = "%s.%s" % \ (parent_iface["name"], interface["vid"]) # Check alias properties if interface_type == INTERFACE_TYPE_ALIAS: # Check the netmask is valid if specified if "alias_netmask" in details.keys() and \ details["alias_netmask"] != "": if details["alias_netmask"].startswith("/"): details["alias_netmask"] = details["alias_netmask"][1:] try: details["alias_netmask"] = int(details["alias_netmask"]) except: raise ccs_interface_error("Alias netmask must be an integer") # Alias interfaces have a name derived from their parent interface parent_iface = ccs_interface(self._session_id, details["raw_interface"]) details["name"] = "%s-alias-%s" % (parent_iface["name"], link_id) details["ifname"] = details["name"] # Deal with ifname/name dictionary entries if "ifname" in details.keys(): details["name"] = details["ifname"] # Wrap changes into a changeset self._forceChangeset("Interface details updated") # Deal with subasset changes if subasset_id != self["subasset_id"] and \ interface_type != INTERFACE_TYPE_VAP: if self.hasSubasset(): self.detachSubasset() subasset = ccs_subasset(self._session_id, subasset_id) from ccs_host import ccs_host host = ccs_host(self._session_id, host_id) if host.hasAsset(): subasset.attachTo(host["asset_id"]) elif host.hasSite(): subasset.moveToSite(host["site_id"]) # Build list of properties for the interface type props = [ "interface_id", "interface_type", "host_id", "link_id", \ "name", "use_gateway", "interface_active", "master_mode", \ "master_interface", "master_channel", "module_id", \ "monitor_interface" ] nProps = [] if interface_type == INTERFACE_TYPE_PHYSICAL or \ interface_type == INTERFACE_TYPE_VAP: props.extend(["subasset_id"]) nProps.extend(["raw_interface", "alias_netmask"]) elif interface_type == INTERFACE_TYPE_VLAN: props.extend(["raw_interface", "vid"]) nProps.extend(["subasset_id", "alias_netmask"]) elif interface_type == INTERFACE_TYPE_ALIAS: props.extend(["raw_interface",]) nProps.extend(["subasset_id"]) if "alias_netmask" in details.keys() and \ details["alias_netmask"] != "": props.extend(["alias_netmask"]) if monitor_interface=="t": nProps.extend(["ip_address", "bridge_interface"]) elif bridge_interface != "" and bridge_interface!=-1: props.extend(["bridge_interface"]) nProps.extend(["ip_address"]) else: props.extend(["ip_address"]) nProps.extend(["bridge_interface"]) # Build update string (sql, values) = buildUpdateFromDict("interface", props, details, \ "interface_id", self.interface_id, True, nProps) if values is None: # No changes made... ? return self.returnSuccess() # Run the query session.execute(sql, values) # Fire the trigger triggerHostEvent(self._session_id, "interfaceModified", host_id, \ interface_id=self.interface_id); return self.returnSuccess()
def addInterface(session_id, interface): """Creates a new interface on a host Throws an exception on error or returns the new interface ID """ session = getSessionE(session_id) from ccs_host import ccs_host, getHostName print interface["vid"] # Check interface details validateInterface(session_id, interface) # Check interface type if "interface_type" in interface.keys(): try: it = int(interface["interface_type"]) except: ccs_interface_error("Invalid interface type! Must be an integer.") if it <= INTERFACE_TYPE_MIN or it >= INTERFACE_TYPE_MAX: raise ccs_interface_error("Invalid interface type! - %s" % \ interface["interface_type"]) else: raise ccs_interface_error("Interface type must be specified!") # Check subasset is valid if it is specified if "subasset_id" in interface.keys() and interface["subasset_id"]!="" \ and int(interface["subasset_id"])!=-1: subasset = ccs_subasset(session_id, interface["subasset_id"]) if not subasset.supportsFunction("interface"): raise ccs_interface_error("Invalid subasset type for interface!") if it == INTERFACE_TYPE_VAP: # Check specified subasset supports virtual APs if not subasset.supportsFunction("vap"): raise ccs_interface_error("Invalid subasset type for VAP " \ "interface") # XXX: Check we're not over the maximum number of vaps... elif not subasset.availableForInterface(interface["host_id"]): raise ccs_interface_error("Subasset already in use!") else: try: del interface["subasset_id"] except KeyError: pass # If interface is active check subasset_id is specified if "interface_active" in interface.keys() and \ interface["interface_active"]=="t": if it == INTERFACE_TYPE_PHYSICAL or it == INTERFACE_TYPE_VAP: if "subasset_id" not in interface.keys(): raise ccs_interface_error("Cannot create active " \ "interface without specifying a subasset!") elif it == INTERFACE_TYPE_VLAN or it == INTERFACE_TYPE_ALIAS: if "raw_interface" not in interface.keys(): raise ccs_interface_error("Cannot create active " \ "interface without specifying a raw interface!") # Check VLAN properties if it == INTERFACE_TYPE_VLAN: # Check the vid is valid if specified if "vid" in interface.keys() and \ interface["vid"] != "": print interface["vid"] try: print interface["vid"] vid = int(interface["vid"]) except: raise ccs_interface_error("VLAN ID must be an integer") # VLAN interfaces have a name derived from their parent interface parent_iface = ccs_interface(session_id, interface["raw_interface"]) interface["name"] = "%s.%s" % \ (parent_iface["name"], interface["vid"]) # Check alias properties if it == INTERFACE_TYPE_ALIAS: # Check the netmask is valid if specified if "alias_netmask" in interface.keys() and \ interface["alias_netmask"] != "": if interface["alias_netmask"].startswith("/"): interface["alias_netmask"] = interface["alias_netmask"][1:] try: interface["alias_netmask"] = int(interface["alias_netmask"]) except: raise ccs_interface_error("Alias netmask must be an integer") # Alias interfaces have a name derived from their parent interface parent_iface = ccs_interface(session_id, interface["raw_interface"]) interface["name"] = "%s-alias-%s" % \ (parent_iface["name"], interface["link_id"]) # XXX: Check raw interface is valid if specified # Ensure boolean values are specified correctly for f in ["use_gateway", "interface_active", "master_interface", \ "monitor_interface"]: if f not in interface.keys(): interface[f] = "f" else: if interface[f]!="t" and interface[f]!="f": raise ccs_interface_error("Invalid value for " \ "%s parameter" % f) link = ccs_link(session_id, interface["link_id"]) # Check IP Parameters if applicable if interface["monitor_interface"]=="f" and \ (interface["bridge_interface"]=="" or \ int(interface["bridge_interface"])==-1): # Check this host doesn't already have an interface on this link if link.connectsHost(interface["host_id"]): raise ccs_interface_error("Host already has an interface on the " \ "specified link!") # Check IP specified is correct for the link, or allocate an IP if "ip_address" not in interface.keys(): interface["ip_address"] = "" if interface["ip_address"] == "": interface["ip_address"] = \ link.allocateIP(interface["host_id"], \ interface["master_interface"]) elif not link.isValidIP(interface["ip_address"]): raise ccs_interface_error("Invalid IP address for link!") elif interface["monitor_interface"]=="f": # XXX: Check bridge parameters are valid pass # Create changeset to wrap all of this commit = 0 if session.changeset == 0: session.begin("Created interface (%s) on host %s" % \ (interface["name"], \ getHostName(session_id, interface["host_id"]))) commit = 1 # Make sure the subasset is attached to the host try: if "subasset_id" in interface.keys(): subasset = ccs_subasset(session_id, interface["subasset_id"]) host = ccs_host(session_id, interface["host_id"]) if subasset["asset_id"] != host["asset_id"]: subasset.attachTo(host["asset_id"]) except: log_warn("Could not attach subasset (%s) to host (%s)! Interface " \ "creation may fail!" % \ (interface["subasset_id"], interface["host_id"]), \ sys.exc_info()) # Build list of properties for the interface type props = [ "interface_id", "interface_type", "host_id", "link_id", \ "name", "use_gateway", "interface_active", "master_interface", \ "master_mode", "master_channel", "module_id", "monitor_interface"] nProps = [] if it == INTERFACE_TYPE_PHYSICAL or it == INTERFACE_TYPE_VAP : props.extend(["subasset_id"]) nProps.extend(["raw_interface"]) nProps.extend(["raw_interface", "alias_netmask"]) elif it == INTERFACE_TYPE_VLAN: props.extend(["raw_interface", "vid"]) nProps.extend(["subasset_id", "alias_netmask"]) elif it == INTERFACE_TYPE_ALIAS: props.extend(["raw_interface"]) nProps.extend(["subasset_id"]) if "alias_netmask" in interface.keys() and \ interface["alias_netmask"] != "": props.extend(["alias_netmask"]) if interface["monitor_interface"]=="t": nProps.extend(["ip_address", "bridge_interface"]) elif interface["bridge_interface"] != "" and \ int(interface["bridge_interface"])!=-1: props.extend(["bridge_interface"]) nProps.extend(["ip_address"]) elif interface["ip_address"] == "": nProps.extend(["ip_address"]) else: props.extend(["ip_address"]) nProps.extend(["bridge_interface"]) # Create the interface in the database (sql, values) = buildInsertFromDict("interface", props, interface, True, \ nProps) session.execute(sql, values) # Get the new interface id sql = "SELECT currval('interface_interface_id_seq') as interface_id" res = session.query(sql, ()) if len(res) != 1: raise ccs_interface_error("Could not retrieve new interface ID!") interface_id = res[0]["interface_id"] # If we started a changeset, then finish it off if commit == 1: session.commit() # Fire the trigger triggerHostEvent(session_id, "interfaceAdded", interface["host_id"], \ interface_id=interface_id) return interface_id