def __pre_check(self): # Check if the name of the new node is given if not self.node_id: emsg = "Missing name of the new virtual node that IP address should be managed." self.logger.error("[localhost] HappyNodeAddress: %s" % (emsg)) self.exit() # Check if the name of new node is not a duplicate (that it does not already exists). if not self._nodeExists(): emsg = "virtual node %s does not exist." % (self.node_id) self.logger.warning("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) # Check if the name of the interface is given if not self.interface: emsg = "Missing name of the network interface in virtual node." self.logger.error("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) self.exit() # Check if node has a given interface if not self._nodeInterfaceExists(self.interface, self.node_id): emsg = "virtual node %s does not have interface %s." % ( self.node_id, self.interface) self.logger.warning("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) self.exit() # Check if address is given if not self.address: emsg = "Missing IP address for virtual node." self.logger.error("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) self.exit() self.ip_address, self.ip_mask = IP.splitAddressMask(self.address) self.ip_address = IP.paddingZeros(self.ip_address) if not self.delete: self.add = True # Check if node has given prefix addr_prefix = IP.getPrefix(self.ip_address, self.ip_mask) if self.delete and addr_prefix not in self.getNodeInterfacePrefixes( self.interface): emsg = "virtual node %s may not have any addresses on prefix %s." % ( self.node_id, addr_prefix) self.logger.warning("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) # Check if node has this address already if self.add and self.address in self.getNodeInterfaceAddresses( self.interface): emsg = "virtual node %s already has addresses %s." % (self.node_id, self.address) self.logger.error("[%s] HappyNodeAddress: %s" % (self.node_id, emsg)) self.done = True
def __delete_route(self): if self.to == "default" and self.via_device: self.__call_delete_route(4) self.__call_delete_route(6) else: if IP.isIpv6(self.to) or IP.isIpv6(self.via_address): self.__call_delete_route(6) else: self.__call_delete_route(4)
def __getNodeIPv6AddressOnPrefix(self, prefix, id): prefix_addr, prefix_mask = IP.splitAddressMask(prefix) addr = prefix_addr + "::" + id if addr.count(":") == 8: addr = addr.replace("::", ":") addr = IP.paddingZeros(addr) return addr
def __check_node_hw_addr(self): hw_addr = self.getHwAddress(self.node_interface_name, self.node_id) hw_addr_int = IP.mac48_string_to_int(hw_addr) if (hw_addr_int & (1 << 41)): hw_addr_int = hw_addr_int & ~(1 << 41) new_hw_addr = IP.mac48_string_to_int(hw_addr_int) cmd = "ip link set " + self.node_interface_name + " address " + str(new_hw_addr) cmd = self.runAsRoot(cmd) r = self.CallAtNode(self.node_id, cmd)
def setNodeRoute(self, node_id, to, record, state=None): node_record = self.getNode(node_id, state) if node_record is not None: if "route" not in node_record.keys(): node_record["route"] = {} if ("via" in record.keys() and IP.isIpv6(record["via"])) or \ ("prefix" in record.keys() and IP.isIpv6(record["prefix"])): to = to + "_v6" else: to = to + "_v4" node_record["route"][to] = record
def setNetworkRoute(self, network_id, to, record, state=None): network_record = self.getNetwork(network_id, state) if network_record is not None: if "route" not in list(network_record.keys()): network_record["route"] = {} if ("via" in list(record.keys()) and IP.isIpv6(record["via"])) or \ ("prefix" in list(record.keys()) and IP.isIpv6(record["prefix"])): to = to + "_v6" else: to = to + "_v4" network_record["route"][to] = record
def __pre_check(self): # Check if the name of the new network is given if not self.network_id: emsg = "Missing name of the virtual network that should be configured with a route." self.logger.error("[localhost] WeaveNetworkGateway: %s" % (emsg)) self.exit() # Check if the name of new network is not a duplicate (that it does not already exists). if not self._networkExists(): emsg = "virtual network %s does not exist." % (self.network_id) self.logger.error("[%s] WeaveNetworkGateway: %s" % (self.network_id, emsg)) self.exit() if not self.delete: self.add = True self.fabric_id = self.getFabricId() if not self.fabric_id: emsg = "weave fabric id is unknown." self.logger.error("[%s] WeaveNetworkGateway: %s" % (self.network_id, emsg)) self.exit() self.global_prefix = self.getWeaveGlobalPrefix(self.fabric_id) if not self.global_prefix: emsg = "weave fabric prefix is unknown." self.logger.error("[%s] WeaveNetworkGateway: %s" % (self.network_id, emsg)) self.exit() # Check if 'gateway' is given if not self.gateway: emsg = "Missing gateway address for weave fabric." self.logger.error("[%s] WeaveNetworkGateway: %s" % (self.network_id, emsg)) self.exit() if not self._nodeExists(self.gateway): emsg = "Proposed gateway node %s does not exist." % (self.gateway) self.logger.error("[%s] WeaveNetworkGateway: %s" % (self.network_id, emsg)) self.exit() if IP.isIpAddress(self.gateway): self.gateway = IP.paddingZeros(self.gateway) self.to = IP.paddingZeros(self.global_prefix)
def __traceroute_to_address(self, addr): cmd = "" if IP.isIpv6(addr): cmd += "traceroute6" else: cmd += "traceroute" if IP.isMulticast(addr): cmd += "" cmd += " " + addr out, err = self.CallAtNodeForOutput(self.source, cmd) return (out, err)
def __configure_node_address(self): network_links = self.getNetworkLinkIds(self.network_id) for link_id in network_links: node_id = self.getLinkNode(link_id) options = happy.HappyNodeAddress.option() options["quiet"] = self.quiet options["node_id"] = node_id interface_id = self.getNodeInterfaceFromLink(link_id, node_id) options["interface"] = interface_id if IP.isIpv6(self.address): nid = self.getInterfaceId(interface_id, node_id) else: nid = self.getNextNetworkIPv4Id(self.ip_prefix, self.network_id) options["address"] = self.getNodeAddressOnPrefix( self.ip_prefix, nid) if self.add: options["add"] = True else: options["delete"] = True addrctrl = happy.HappyNodeAddress.HappyNodeAddress(options) ret = addrctrl.run() self.readState()
def getNodeAddressesOnPrefix(self, prefix, node_id=None, state=None): addrs = self.getNodeAddresses(node_id, state) res = [] for addr in addrs: if IP.prefixMatchAddress(prefix, addr): res.append(addr) return res
def __pre_check(self): # Check if the name of the new node is given if not self.source: emsg = "Missing name of the virtual source node." self.logger.error("[localhost] Traceroute: %s" % (emsg)) self.exit() # Check if the source node exists. if not self._nodeExists(self.source): emsg = "virtual source node %s does not exist." % (self.source) self.logger.error("[%s] Traceroute: %s" % (self.source, emsg)) self.exit() # Check if the traceroute destination is given. if not self.destination: emsg = "Missing destination for traceroute." self.logger.error("[localhost] Traceroute: %s" % (emsg)) self.exit() # Check if the destination node exists. if not IP.isIpAddress(self.destination) and not self._nodeExists( self.destination): emsg = "virtual destination node %s does not exist." % ( self.destination) self.logger.error("[%s] Traceroute: %s" % (self.source, emsg)) self.exit()
def __pre_check(self): # Check if the name of the new node is given if not self.node_id: emsg = "Missing name of the new virtual node that should be created." self.logger.error("[localhost] HappyNodeAdd: %s" % (emsg)) self.exit() # Check if dot is in the name if IP.isDomainName(self.node_id): emsg = "Using . (dot) in the name is not allowed." self.logger.error("[localhost] HappyNodeAdd: %s" % (emsg)) self.exit() # Check if node type is valid if self.type is not None and self.type not in self.node_special_type: emsg = "Unknown node type %s." % (self.type) self.logger.error("[localhost] HappyNodeAdd: %s" % (emsg)) self.exit() # Check if the name of new node is not a duplicate (that it does not already exists). if self._nodeExists(): emsg = "virtual node %s already exists." % (self.node_id) self.logger.warning("[%s] HappyNodeAdd: %s" % (self.node_id, emsg)) self.__deleteExistingNode() # Check if there is some old record of a node if self.node_id in self.getNodeIds(): self.__deleteExistingNode()
def run(self): self.__pre_check() self.__get_addresses() if self.addresses == {}: emsg = "No address to ping at " + str(self.destination) + "." self.logger.warning("[%s] Ping: %s" % (self.source, emsg)) print hyellow(emsg) return ReturnMsg(100, self.addresses) for addr in self.addresses.keys(): out, err = self.__ping_on_address(addr) self.__parse_output(addr, out, err) self.__post_check() for addr in self.addresses.keys(): if IP.isIpAddress(self.destination): self.logger.info("ping from " + self.source + " to address " + addr + " -> " + str(self.addresses[addr]) + "% packet loss") else: self.logger.info("ping from " + self.source + " to " + self.destination + " on address " + addr + " -> " + str(self.addresses[addr]) + "% packet loss") return ReturnMsg(self.ret, self.addresses)
def __pre_check(self): # Check if the name of the new node is given if not self.source: emsg = "Missing name of the virtual source node." self.logger.error("[localhost] Ping: %s" % (emsg)) self.exit() # Check if the source node exists. if not self._nodeExists(self.source): emsg = "virtual source node %s does not exist." % (self.source) self.logger.error("[%s] Ping: %s" % (self.source, emsg)) self.exit() # Check if the ping destination is given. if not self.destination: emsg = "Missing destination for ping." self.logger.error("[localhost] Ping: %s" % (emsg)) self.exit() # Check if the destination node exists. if not IP.isIpAddress(self.destination) and not self._nodeExists( self.destination): emsg = "virtual destination node %s does not exist." % ( self.destination) self.logger.error("[%s] Ping: %s" % (self.source, emsg)) self.exit() if self.count is not None and self.count.isdigit(): self.count = int(float(self.count)) else: self.count = 1
def __delete_address(self): cmd = "ip " if IP.isIpv6(self.address): cmd += "-6 " cmd += "addr del " + str(self.ip_address) + "/" + str(self.ip_mask) + " dev " + self.interface cmd = self.runAsRoot(cmd) ret = self.CallAtNode(self.node_id, cmd)
def getInterfaceId(self, interface_id, node_id=None): eui = self.getInterfaceEUI64(interface_id, node_id) if eui is None: return None iid = IP.EUI64toIID(eui) return iid
def __nodeRouteExistsViaDevice(self, to, dev): if to != 'default': to = IP.paddingZeros(to) # IPv4 cmd = "ip route" cmd = self.runAsRoot(cmd) out, err = self.CallAtNodeForOutput(self.node_id, cmd) if out is not None: for line in out.split("\n"): l = line.split() if len(l) < 3: continue if to == 'default': if l[0] == to and l[1] == "dev" and l[2] == dev: if self.route_table is not None: if self.nodeIpv4TableExist(self.node_id) is True: return True return True else: if IP.paddingZeros( l[0]) == to and l[1] == "dev" and l[2] == dev: if self.route_table is not None: if self.nodeIpv4TableExist(self.node_id) is True: return True return True # IPv6 cmd = "ip -6 route" cmd = self.runAsRoot(cmd) out, err = self.CallAtNodeForOutput(self.node_id, cmd) if out is not None: for line in out.split("\n"): l = line.split() if len(l) < 3: continue if IP.paddingZeros( l[0]) == to and l[1] == "dev" and l[2] == dev: return True return False
def getNodePublicIPv4Address(self, node_id=None, state=None): node_public_interfaces = self.getNodePublicInterfaces(node_id, state) for interface_id in node_public_interfaces: addresses = self.getNodeInterfaceAddresses(interface_id, node_id, state) for addr in addresses: if IP.isIpv4(addr): return addr return None
def __getNodeIPv4AddressOnPrefix(self, prefix, id): prefix_addr, prefix_mask = IP.splitAddressMask(prefix) prefix_mask = int(float(prefix_mask)) addr = prefix_addr.split(".")[:prefix_mask // 8] addr.append(str(id % 255)) addr = ".".join(addr) return addr
def getNodeWeaveIPAddress(self, node_id=None, state=None): weave_global_prefix = self.getFabricGlobalPrefix(state) if weave_global_prefix is None: return None node_addresses = self.getNodeAddresses(node_id, state) if node_addresses == []: return None for addr in node_addresses: if IP.prefixMatchAddress(weave_global_prefix, addr): return addr return None
def getInterfaceEUI64(self, interface_id, node_id=None): eui = None node_interface = self.getNodeInterface(interface_id, node_id) if "customized_eui64" in list(node_interface.keys()): eui = str(node_interface["customized_eui64"]) else: hwAddr = self.getHwAddress(interface_id, node_id) if hwAddr is not None: eui = IP.MAC48toEUI64(hwAddr) return eui
def __ping_on_address(self, addr): cmd = "" if IP.isIpv6(addr): cmd += "ping6" else: cmd += "ping" cmd += " -c " + str(self.count) if self.size is not None: cmd += " -s " + str(self.size) if IP.isMulticast(addr): cmd += "" cmd += " " + addr out, err = self.CallAtNodeForOutput(self.source, cmd) return (out, err)
def __get_addresses(self): self.addresses = {} if IP.isIpAddress(self.destination): self.addresses[self.destination] = None return if self._nodeExists(self.destination): node_addresses = self.getNodeAddresses(self.destination) for addr in node_addresses: self.addresses[addr] = {}
def __get_weave_params(self, node_name=None, node_params={}): """ Returns weave params for a node. If weave_node_id is empty, it will pick one at random from a list of test weave node ids. """ weave_node_id = node_params.get('weave_node_id', None) cert = node_params.get('weave_certificate', None) key = node_params.get('private_key', None) pairing_code = node_params.get('pairing_code', None) if weave_node_id: # bail if it is already in use by a different node nodes = self.weave_state.getWeaveNodeRecord() for node in nodes.keys(): if node == node_name: continue if nodes[node].get("weave_node_id", None) == weave_node_id: emsg = "weave_node_id (%s) already in use." % weave_node_id self.logger.error("[localhost] WeaveNodeConfigure: %s" % emsg) self.weave_state.exit() else: weave_node_id = self.__get_available_weave_node_id() if not (cert and key): # check if a cert/key are available and use them node_cert = self.weave_device_certs.get(weave_node_id, None) if node_cert: cert = self.weave_device_certs[weave_node_id].get('cert', None) key = self.weave_device_certs[weave_node_id].get('key', None) # NOTE: self.weave_device_certs[weave_node_id]['cert-256'] is also available else: emsg = "WARNING: could not find weave cert/key for id=%s" % ( weave_node_id) self.weave_state.logger.debug( "[localhost] WeaveNodeConfigure: %s" % emsg) # while we don't sys.exit() at this point, note that tests # that require cert/key will fail if they are not configured. params = {} params['weave_node_id'] = weave_node_id params['eui64'] = self.weave_state.WeaveIdtoEUI64(weave_node_id) params['iid'] = IP.EUI64toIID(params['eui64']) params['serial_num'] = weave_node_id if cert and key: # these keys are only written if they are available params['weave_certificate'] = cert params['private_key'] = key params['pairing_code'] = self.__get_pairing_code(pairing_code) return params
def __pre_check(self): # Check if the name of the new network is given if not self.network_id: emsg = "Missing name of the new virtual network that should be created." self.logger.error("[localhost] HappyNetworkAddress: %s" % (emsg)) self.exit() # Check if the name of new network is not a duplicate (that it does not already exists). if not self._networkExists(): emsg = "virtual network %s does not exist." % (self.network_id) self.logger.warning("[%s] HappyNetworkAddress: %s" % (self.network_id, emsg)) self.exit() # Check if address is given if not self.address: emsg = "Missing IP preifx for network %s." % (self.network_id) self.logger.error("[%s] HappyNetworkAddress: %s" % (self.network_id, emsg)) self.exit() self.ip_prefix, self.ip_mask = IP.splitAddressMask(self.address) self.ip_prefix = IP.getPrefix(self.ip_prefix, self.ip_mask) # Check if successfully parsed prefix if self.ip_prefix is None or self.ip_mask is None: emsg = "Did not understand address format %s." % (self.address) self.logger.error("[%s] HappyNetworkAddress: %s" % (self.network_id, emsg)) self.exit() if not self.delete: self.add = True # Check if network has given prefix if self.delete and self.ip_prefix not in self.getNetworkPrefixes(): emsg = "Network %s may not have prefix %s." % (self.network_id, self.ip_prefix) self.logger.warning("[%s] HappyNetworkAddress: %s" % (self.network_id, emsg))
def getIpAddressStatus(self, address, interface_id=None, node_id=None): out = self.getIpAddressesRecords(interface_id, node_id) for line in out.split("\n"): l = line.split() if l[0][:4] == "inet": addr = l[1] addr, mask = addr.split("/") addr = IP.paddingZeros(addr) if addr != address: continue return line return None
def __add_address(self): cmd = "ip " if IP.isIpv6(self.address): cmd += "-6 " cmd += "addr add " + str(self.ip_address) + "/" + str(self.ip_mask) + " dev " + self.interface cmd = self.runAsRoot(cmd) ret = self.CallAtNode(self.node_id, cmd) # We have disabled DAD, but under high load we can still see the # address in "tentative" for a few milliseconds. # If DAD is re-enabled, we should poll all interfaces at once after the topology # has been brought up, so the interfaces can come up in parallel. self.waitForDAD()
def getNodeInterfacePrefixes(self, interface_id, node_id=None, state=None): if node_id is None: node_id = self.node_id if node_id is None: return [] if node_id not in self.getNodeIds(state): return [] if interface_id not in self.getNodeInterfaceIds(node_id, state): return [] prefixes = [] for addr in self.getNodeInterfaceAddresses(interface_id, node_id, state): mask = self.getNodeInterfaceAddressMask(interface_id, addr, node_id, state) prefix = IP.getPrefix(addr, mask) prefixes.append(prefix) return prefixes
def getNodeAddrMatchingPrefix(self, node_id, interface, prefix): """Each interface may have multiple addresses, this function will get addresses based on interface and prefix. Args: node_id (str): A string containing the node_id, example: "cloud", "BorderRouter" interface (str): A string containing interface id, example: "wpan0", "wlan0" prefix (str): A string containing an IP prefix, example: "10.0.1" Returns: addresses_matchPrefix: A string list containing IP addresses """ addresses = self.getNodeInterfaceAddresses(interface, node_id) addresses_matchPrefix = [] for address in addresses: if IP.prefixMatchAddress(prefix, address): addresses_matchPrefix.append(address) return addresses_matchPrefix
def getIpAddresses(self, interface_id=None, node_id=None): out = self.getIpAddressesRecords(interface_id, node_id) ipaddrs = [] for line in out.split("\n"): l = line.split() if len(l) < 4: continue if l[0][:4] == "inet": addr = l[1] addr, mask = addr.split("/") addr = IP.paddingZeros(addr) ipaddrs.append(addr) return ipaddrs