def get_fdbs(_self): output = exec_cmd("bridge fdb show dev %s" % _self._dev_name, die_on_err=False)[0] br_fdb_info_list = [] for line in output.split("\n"): match = re.match( r'([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})', line) if match: hwaddr = normalize_hwaddr(match.groups()[0]) match = re.match(r'.*\s+vlan (\d+)', line) vlan_id = int(match.groups()[0]) if match else 0 self = True if re.match(r'.*\s+self', line) else False master = True if re.match(r'.*\s+master', line) else False offload = True if re.match(r'.*\s+offload', line) else False extern_learn = True if re.match(r'.*\s+extern_learn', line) else False br_fdb_info = { "hwaddr": hwaddr, "vlan_id": vlan_id, "self": self, "master": master, "offload": offload, "extern_learn": extern_learn } br_fdb_info_list.append(br_fdb_info) return br_fdb_info_list
def create(self): domain_ctl = self.host.get_domain_ctl() if self.orig_hwaddr: if self.host.get_dev_by_hwaddr(self.orig_hwaddr): msg = "Device with hwaddr %s already exists" % self.orig_hwaddr raise DeviceError(msg) else: mac_pool = self.host.get_mac_pool() while True: hwaddr = normalize_hwaddr(mac_pool.get_addr()) if not self.host.get_dev_by_hwaddr(hwaddr): self.orig_hwaddr = hwaddr break bridges = self.host.get_network_bridges() if self.network in bridges: net_ctl = bridges[self.network] else: bridges[self.network] = net_ctl = VirtNetCtl() net_ctl.init() net_name = net_ctl.get_name() logging.info("Creating virtual device with hwaddr='%s' on machine %s", self.orig_hwaddr, self.host.get_id()) domain_ctl.attach_interface(self.orig_hwaddr, net_name, self.virt_driver) # The sleep here is necessary, because udev sometimes renames the # newly created device sleep(1)
def update_netlink(self, nl_msg): if self._if_index == nl_msg['index']: self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self._ip = None #TODO self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) link = nl_msg.get_attr("IFLA_LINK") if link != None: # IFLA_LINK is an index of device that's closer to physical # interface in the stack, e.g. index of eth0 for eth0.100 # so to properly deconfigure the stack we have to save # parent index in the child device; this is the opposite # to IFLA_MASTER link_dev = self._if_manager.get_device(link) if link_dev != None: link_dev.set_master(self._if_index, primary=False) # This reference shouldn't change - you can't change the realdev # of a vlan, you need to create a new vlan. Therefore the # the following add_slave shouldn't be a problem. self.add_slave(link) if self._conf_dict: self._conf_dict["name"] = self._name self._initialized = True #return an update message that will be sent to the controller return {"type": "if_update", "devname": self._name, "hwaddr": self._hwaddr} return None
def hwaddr(self): """hwaddr attribute Returns string hardware address of the device as reported by the kernel. """ #TODO implement HwAddress object return normalize_hwaddr(self._nl_msg.get_attr("IFLA_ADDRESS"))
def assign_name(self, config): if "name" in config: return config["name"] dev_type = config["type"] if dev_type == "eth": if (not "hwaddr" in config or "name" in config): return hwaddr = normalize_hwaddr(config["hwaddr"]) for dev in self._devices: if dev.get_hwaddr() == hwaddr: return dev.get_name() elif dev_type == "bond": return self.assign_name_generic("t_bond") elif dev_type == "bridge" or dev_type == "ovs_bridge": return self.assign_name_generic("t_br") elif dev_type == "macvlan": return self.assign_name_generic("t_macvlan") elif dev_type == "team": return self.assign_name_generic("t_team") elif dev_type == "vlan": netdev_name = self.get_mapped_device(config["slaves"][0]).get_name() vlan_tci = get_option(config, "vlan_tci") prefix = "%s.%s_" % (netdev_name, vlan_tci) return self.assign_name_generic(prefix) elif dev_type == "veth": return self._assign_name_pair("veth") elif dev_type == "vti": return self.assign_name_generic("vti") elif dev_type == "vti6": return self.assign_name_generic("t_ip6vti") elif dev_type == "vxlan": return self.assign_name_generic("vxlan") else: return self.assign_name_generic("dev")
def assign_name(self, config): if "name" in config: return config["name"] dev_type = config["type"] if dev_type == "eth": if (not "hwaddr" in config or "name" in config): return hwaddr = normalize_hwaddr(config["hwaddr"]) for dev in self._devices: if dev.get_hwaddr() == hwaddr: return dev.get_name() elif dev_type == "bond": return self._assign_name_generic("t_bond") elif dev_type == "bridge" or dev_type == "ovs_bridge": return self._assign_name_generic("t_br") elif dev_type == "macvlan": return self._assign_name_generic("t_macvlan") elif dev_type == "team": return self._assign_name_generic("t_team") elif dev_type == "vlan": netdev_name = self.get_mapped_device(config["slaves"][0]).get_name() vlan_tci = get_option(config, "vlan_tci") prefix = "%s.%s_" % (netdev_name, vlan_tci) return self._assign_name_generic(prefix) elif dev_type == "veth": return self._assign_name_pair("veth") elif dev_type == "vti": return self._assign_name_generic("vti") elif dev_type == "vti6": return self._assign_name_generic("t_ip6vti") else: return self._assign_name_generic("dev")
def update_netlink(self, nl_msg): if self._if_index != nl_msg['index']: return None if nl_msg['header']['type'] == RTM_NEWLINK: self._ifi_type = nl_msg['ifi_type'] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._mtu = nl_msg.get_attr("IFLA_MTU") if nl_msg.get_nested("IFLA_LINKINFO", "IFLA_INFO_KIND") == "vxlan": link = nl_msg.get_nested("IFLA_LINKINFO", "IFLA_INFO_DATA", "IFLA_VXLAN_LINK") elif nl_msg.get_nested("IFLA_LINKINFO", "IFLA_INFO_KIND") == "vti": link = nl_msg.get_nested("IFLA_LINKINFO", "IFLA_INFO_DATA", "IFLA_VTI_LINK") else: link = nl_msg.get_attr("IFLA_LINK") if link != None: # IFLA_LINK is an index of device that's closer to physical # interface in the stack, e.g. index of eth0 for eth0.100 # so to properly deconfigure the stack we have to save # parent index in the child device; this is the opposite # to IFLA_MASTER link_dev = self._if_manager.get_device(link) if link_dev != None: link_dev.set_master(self._if_index, primary=False) # This reference shouldn't change - you can't change the realdev # of a vlan, you need to create a new vlan. Therefore the # the following add_slave shouldn't be a problem. self.add_slave(link) if self._conf_dict: self._conf_dict["name"] = self._name if self._driver is None: self._driver = self._ethtool_get_driver() self._initialized = True elif nl_msg['header']['type'] == RTM_NEWADDR: scope = nl_msg['scope'] addr_val = nl_msg.get_attr('IFA_ADDRESS') prefix_len = str(nl_msg['prefixlen']) addr = {"addr": addr_val, "prefix": prefix_len, "scope": scope} if self.find_addrs(addr) == []: self._ip_addrs.append(addr) elif nl_msg['header']['type'] == RTM_DELADDR: scope = nl_msg['scope'] addr_val = nl_msg.get_attr('IFA_ADDRESS') prefix_len = str(nl_msg['prefixlen']) addr = {"addr": addr_val, "prefix": prefix_len, "scope": scope} matching_addrs = self.find_addrs(addr) for ip_addr in matching_addrs: self._ip_addrs.remove(ip_addr) #return an update message that will be sent to the controller return {"type": "if_update", "if_data": self.get_if_data()}
def get_devices_by_hwaddr(self, hwaddr): name_scan = scan_netdevs() netdevs = [] for entry in name_scan: if entry["hwaddr"] == normalize_hwaddr(hwaddr): netdevs.append(entry) return netdevs
def init_netlink(self, nl_msg): self._if_index = nl_msg["index"] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self._ip = None # TODO self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._initialized = True
def update_netlink(self, nl_msg): if self._if_index != nl_msg['index']: return None if nl_msg['header']['type'] == RTM_NEWLINK: self._ifi_type = nl_msg['ifi_type'] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._mtu = nl_msg.get_attr("IFLA_MTU") link = nl_msg.get_attr("IFLA_LINK") if link != None: # IFLA_LINK is an index of device that's closer to physical # interface in the stack, e.g. index of eth0 for eth0.100 # so to properly deconfigure the stack we have to save # parent index in the child device; this is the opposite # to IFLA_MASTER link_dev = self._if_manager.get_device(link) if link_dev != None: link_dev.set_master(self._if_index, primary=False) # This reference shouldn't change - you can't change the realdev # of a vlan, you need to create a new vlan. Therefore the # the following add_slave shouldn't be a problem. self.add_slave(link) if self._conf_dict: self._conf_dict["name"] = self._name if self._driver is None: self._driver = self._ethtool_get_driver() self._initialized = True elif nl_msg['header']['type'] == RTM_NEWADDR: scope = nl_msg['scope'] addr_val = nl_msg.get_attr('IFA_ADDRESS') prefix_len = str(nl_msg['prefixlen']) addr = {"addr": addr_val, "prefix": prefix_len, "scope": scope} if self.find_addrs(addr) == []: self._ip_addrs.append(addr) elif nl_msg['header']['type'] == RTM_DELADDR: scope = nl_msg['scope'] addr_val = nl_msg.get_attr('IFA_ADDRESS') prefix_len = str(nl_msg['prefixlen']) addr = {"addr": addr_val, "prefix": prefix_len, "scope": scope} matching_addrs = self.find_addrs(addr) for ip_addr in matching_addrs: self._ip_addrs.remove(ip_addr) #return an update message that will be sent to the controller return {"type": "if_update", "if_data": self.get_if_data()}
def _get_map(self, hwaddr): try: leases_file = open(self._lease_file, "r") except IOError as err: raise VirtUtilsError("Unable to resolve IP mapping (%s)" % err) addr = None normalized_hwaddr = normalize_hwaddr(hwaddr) for entry in leases_file: match = re.match(r"\d+\s+([0-9a-f:]+)\s+([0-9\.]+)", entry) if match: entry_hwaddr = normalize_hwaddr(match.group(1)) entry_addr = match.group(2) if entry_hwaddr == normalized_hwaddr: addr = entry_addr break leases_file.close() return addr
def assign_name_by_scan(self, dev_id, netdev): if (not "hwaddr" in netdev or "name" in netdev): # name was previously assigned return hwaddr = normalize_hwaddr(netdev["hwaddr"]) for entry in self._scan: if hwaddr == entry["hwaddr"]: netdev["name"] = entry["name"] if not "name" in netdev: logging.error("Name for addr \"%s\" (netdevice id \"%s\") not found" % (hwaddr, dev_id)) raise Exception
def assign_name_by_scan(self, dev_id, netdev): if (not "hwaddr" in netdev or "name" in netdev): # name was previously assigned return hwaddr = normalize_hwaddr(netdev["hwaddr"]) for entry in self._scan: if hwaddr == entry["hwaddr"]: netdev["name"] = entry["name"] if not "name" in netdev: logging.error( "Name for addr \"%s\" (netdevice id \"%s\") not found" % (hwaddr, dev_id)) raise Exception
def init_netlink(self, nl_msg): self._if_index = nl_msg['index'] self._ifi_type = nl_msg['ifi_type'] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self._ip = None #TODO self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._netns = None self._mtu = nl_msg.get_attr("IFLA_MTU") if self._driver is None: self._driver = self._ethtool_get_driver() self._initialized = True
def initialize(self): domain_ctl = self._machine.get_domain_ctl() if self._hwaddr: query = self._machine._rpc_call('get_devices_by_hwaddr', self._hwaddr) if len(query): msg = "Device with hwaddr %s already exists" % self._hwaddr raise MachineError(msg) else: mac_pool = self._machine.get_mac_pool() while True: self._hwaddr = normalize_hwaddr(mac_pool.get_addr()) query = self._machine._rpc_call('get_devices_by_hwaddr', self._hwaddr) if not len(query): break bridges = self._machine.get_network_bridges() if self._network in bridges: net_ctl = bridges[self._network] else: bridges[self._network] = net_ctl = VirtNetCtl() net_ctl.init() net_name = net_ctl.get_name() logging.info("Creating interface %s (%s) on machine %s", self.get_id(), self._hwaddr, self._machine.get_id()) self._orig_hwaddr = self._hwaddr domain_ctl.attach_interface(self._hwaddr, net_name, self._driver) # The sleep here is necessary, because udev sometimes renames the # newly created device and if the query for name comes too early, # the controller will then try to configure an nonexistent device sleep(1) ready = wait_for(self.is_ready, timeout=10) if not ready: msg = "Netdevice initialization failed." \ "Unable to create device %s (%s) on machine %s" \ % (self.get_id(), self._hwaddr, self._machine.get_id()) raise MachineError(msg) super(VirtualInterface, self).initialize()
def get_fdbs(_self): output = exec_cmd("bridge fdb show dev %s" % _self._dev_name, die_on_err=False)[0] br_fdb_info_list = [] for line in output.split("\n"): match = re.match(r'([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})', line) if match: hwaddr = normalize_hwaddr(match.groups()[0]) match = re.match(r'.*\s+vlan (\d+)', line) vlan_id = int(match.groups()[0]) if match else 0 self = True if re.match(r'.*\s+self', line) else False master = True if re.match(r'.*\s+master', line) else False offload = True if re.match(r'.*\s+offload', line) else False br_fdb_info = {"hwaddr": hwaddr, "vlan_id": vlan_id, "self": self, "master": master, "offload": offload} br_fdb_info_list.append(br_fdb_info) return br_fdb_info_list
def init_netlink(self, nl_msg): self._if_index = nl_msg['index'] self._ifi_type = nl_msg['ifi_type'] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self._ip_addrs = [] self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._netns = None self._mtu = nl_msg.get_attr("IFLA_MTU") if self._driver is None: self._driver = self._ethtool_get_driver() self._initialized = True #return an update message that will be sent to the controller return {"type": "if_update", "if_data": self.get_if_data()}
def _process_iface_xml_data(self, m_id, iface): if_id = iface["id"] iface_spec = {"params": {}} iface_spec["network"] = iface["network"] for param in iface["params"]: name = str(param["name"]) value = str(param["value"]) if name == "hwaddr": iface_spec["params"][name] = normalize_hwaddr(value) else: iface_spec["params"][name] = value mandatory_params = ["hwaddr"] for p in mandatory_params: if p not in iface_spec["params"]: msg = "Mandatory parameter '%s' missing for machine %s, " "interface '%s'." % (p, m_id, if_id) raise SlaveMachineError(msg, iface["params"]) return iface_spec
def _process_iface_xml_data(self, m_id, iface): if_id = iface["id"] iface_spec = {"params": {}} iface_spec["network"] = iface["network"] for param in iface["params"]: name = str(param["name"]) value = str(param["value"]) if name == "hwaddr": iface_spec["params"][name] = normalize_hwaddr(value) else: iface_spec["params"][name] = value mandatory_params = ["hwaddr"] for p in mandatory_params: if p not in iface_spec["params"]: msg = "Mandatory parameter '%s' missing for machine %s, " \ "interface '%s'." % (p, m_id, if_id) raise PoolManagerError(msg, iface["params"]) return iface_spec
def _eth(self, node, params): machine = self._machine iface_id = self._get_attribute(node, "id") iface = machine["interfaces"][iface_id] = {} iface["network"] = self._get_attribute(node, "network") iface["params"] = {} iface["type"] = "eth" # parse interface parameters scheme = {"params": self._params} params = {"target": iface["params"]} self._process_child_nodes(node, scheme, params) if "hwaddr" in iface["params"]: iface["hwaddr"] = normalize_hwaddr(iface["params"]["hwaddr"]) else: msg = "Missing required parameter 'hwaddr'" raise XmlProcessingError(msg, node) if "name" in iface["params"]: iface["name"] = iface["params"]["name"]
def update_netlink(self, nl_msg): if self._if_index == nl_msg['index']: self._ifi_type = nl_msg['ifi_type'] self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS")) self._name = nl_msg.get_attr("IFLA_IFNAME") self._state = nl_msg.get_attr("IFLA_OPERSTATE") self._ip = None #TODO self.set_master(nl_msg.get_attr("IFLA_MASTER"), primary=True) self._mtu = nl_msg.get_attr("IFLA_MTU") link = nl_msg.get_attr("IFLA_LINK") if link != None: # IFLA_LINK is an index of device that's closer to physical # interface in the stack, e.g. index of eth0 for eth0.100 # so to properly deconfigure the stack we have to save # parent index in the child device; this is the opposite # to IFLA_MASTER link_dev = self._if_manager.get_device(link) if link_dev != None: link_dev.set_master(self._if_index, primary=False) # This reference shouldn't change - you can't change the realdev # of a vlan, you need to create a new vlan. Therefore the # the following add_slave shouldn't be a problem. self.add_slave(link) if self._conf_dict: self._conf_dict["name"] = self._name if self._driver is None: self._driver = self._ethtool_get_driver() self._initialized = True #return an update message that will be sent to the controller return {"type": "if_update", "if_data": self.get_if_data()} return None
def set_hwaddr(self, hwaddr): self._hwaddr = normalize_hwaddr(hwaddr)