def setUp(self): self.logbuf = StringIO.StringIO() openLog(self.logbuf, logging.NOTSET) self.state = [ MACPCI("01:23:45:67:89:0a", "0000:00:01.0", kname="side-11-eth2", ppn="p1p1", label="Ethernet1"), MACPCI("03:23:45:67:89:0a", "0000:00:10.0", kname="side-12-eth34", ppn="p2p1", label=""), MACPCI("03:23:45:67:89:0a", "0000:00:02.0", kname="side-4-eth23", ppn="em1", label=""), MACPCI("04:23:45:67:89:0a", "0000:00:10.1", kname="side-123-eth23", ppn="p2p2", label="") ]
def generate(self, state): """ Make rules from the formulae based on global state. """ # CA-75599 - check that state has no shared ppns. # See net.biodevname.has_ppn_quirks() for full reason ppns = [ x.ppn for x in state if x.ppn is not None ] ppn_quirks = ( len(ppns) != len(set(ppns)) ) if ppn_quirks: LOG.warning("Discovered physical policy naming quirks in provided " "state. Disabling 'method=ppn' generation") for target, (method, value) in self.formulae.iteritems(): if method == "mac": for nic in state: if nic.mac == value: try: rule = MACPCI(nic.mac, nic.pci, tname=target) except Exception, e: LOG.warning("Error creating rule: %s" % (e,)) continue self.rules.append(rule) break else: LOG.warning("No NIC found with a MAC address of '%s' for " "the %s dynamic rule" % (value, target)) continue elif method == "ppn": if ppn_quirks: LOG.info("Not considering formula for '%s' due to ppn " "quirks" % (target,)) continue for nic in state: if nic.ppn == value: try: rule = MACPCI(nic.mac, nic.pci, tname=target) except Exception, e: LOG.warning("Error creating rule: %s" % (e,)) continue self.rules.append(rule) break
def remap_netdevs(remap_list): # # rename everything sideways to safe faffing with temp renanes # for x in ( x for x in os.listdir("/sys/class/net/") if x[:3] == "eth" ): # util.runCmd2(['ip', 'link', 'set', x, 'name', 'side-'+x]) for cmd in remap_list: parse_arg(cmd) # Grab the current state from biosdevname current_eths = all_devices_all_names() current_state = [] for nic in current_eths.keys(): eth = current_eths[nic] if not ("BIOS device" in eth and "Kernel name" in eth and "Assigned MAC" in eth and "Bus Info" in eth and "all_ethN" in eth["BIOS device"] and "physical" in eth["BIOS device"]): LOG.error("Interface information for '%s' from biosdevname is " "incomplete; Discarding." % (eth.get("Kernel name", "Unknown"), )) try: current_state.append( MACPCI(eth["Assigned MAC"], eth["Bus Info"], kname=eth["Kernel name"], order=int(eth["BIOS device"]["all_ethN"][3:]), ppn=eth["BIOS device"]["physical"], label=eth.get("SMBIOS Label", ""))) except Exception, e: LOG.error("Can't generate current state for interface '%s' - " "%s" % (eth, e))
def test_single_label_matching(self): fd = StringIO.StringIO('eth0:label="Ethernet1"') sr = StaticRules(fd=fd) self.assertTrue(sr.load_and_parse()) sr.generate(self.state) self.assertEqual( sr.rules, [MACPCI("01:23:45:67:89:0a", "0000:00:01.0", tname="eth0")])
def test_single_ppn_slot_matching(self): fd = StringIO.StringIO('eth0:ppn="p2p2"') sr = StaticRules(fd=fd) self.assertTrue(sr.load_and_parse()) sr.generate(self.state) self.assertEqual( sr.rules, [MACPCI("04:23:45:67:89:0a", "0000:00:10.1", tname="eth0")])
def validate(entry): try: # iBFT NICs are ignored so don't have a tname if entry[2] is None: return False MACPCI(entry[0], entry[1], tname=entry[2]) return True except Exception, e: LOG.warning("Failed to validate '%s' because '%s'" % (entry, e)) return False
def test_one_valid_lastboot(self): fd = StringIO.StringIO( '{"lastboot":[],"old":[["01:23:45:67:89:0a","00:10.2","eth2"]]}') dr = DynamicRules(fd=fd) self.assertTrue(dr.load_and_parse()) self.assertEqual(dr.lastboot, []) self.assertEqual( dr.old, [MACPCI("01:23:45:67:89:0a", "00:10.2", tname="eth2")])
def test_ppn_quirks(self): # Test case taken from example on CA-75599 dr = DynamicRules() dr.formulae = {"eth0": ("ppn", "em1"), "eth1": ("ppn", "em2")} dr.generate([ MACPCI("00:1E:67:31:59:89", "0000:00:19.0", kname="eth0", ppn="em1", label="Intel 82579LM VPRO"), MACPCI("00:1E:67:31:59:88", "0000:02:00.0", kname="eth1", ppn="em1", label="Intel 82574L") ]) # The quirks test should kick in and prevent any ppn rules from # being generated self.assertEqual(dr.rules, [])
def test_ppn_quirks(self): # Test case taken from example on CA-75599 fd = StringIO.StringIO('eth0:ppn="em1"\n' 'eth1:ppn="em2"') sr = StaticRules(fd=fd) self.assertTrue(sr.load_and_parse()) sr.generate([ MACPCI("00:1E:67:31:59:89", "0000:00:19.0", kname="eth0", ppn="em1", label="Intel 82579LM VPRO"), MACPCI("00:1E:67:31:59:88", "0000:02:00.0", kname="eth1", ppn="em1", label="Intel 82574L") ]) # The quirks test should kick in and prevent any ppn rules from # being generated self.assertEqual(sr.rules, [])
def load_and_parse(self): """ Parse the dynamic rules file. Returns boolean indicating success or failure. """ fd = None try: try: # If we were given a path, try opening and reading it if self.path: if not pathexists(self.path): LOG.error("Dynamic rule file '%s' does not exist" % (self.path,)) return False fd = open(self.path, "r") raw_lines = fd.readlines() # else if we were given a file descriptor, just read it elif self.fd: raw_lines = self.fd.readlines() # else there is nothing we can do else: LOG.error("No source of data to parse") return False except IOError, e: LOG.error("IOError while reading file: %s" % (e,)) return False finally: # Ensure we alway close the file descriptor we opened if fd: fd.close() # Strip out line comments data = "\n".join([ l.strip() for l in raw_lines if len(l.strip()) and l.strip()[0] != '#' ] ) # If the data is empty, dont pass it to json if not len( data.strip() ): return True try: info = json.loads(data) except ValueError: LOG.warning("Dynamic rules appear to be corrupt") return False # The installer has no json. except NameError: LOG.warning("Module json not available. Cant parse dynamic rules.") return False if "lastboot" in info: for entry in info["lastboot"]: try: if len(entry) != 3: raise ValueError("Expected 3 entries") macpci = MACPCI(entry[0], entry[1], tname=entry[2]) except (TypeError, ValueError), e: LOG.warning("Invalid lastboot data entry: %s" % (e,)) continue self.lastboot.append(macpci)
except Exception, e: LOG.warning("Error creating rule: %s" % (e,)) continue self.rules.append(rule) break else: LOG.warning("No NIC found with a ppn of '%s' for the " "%s dynamic rule" % (value, target)) continue elif method == "pci": for nic in state: if nic.pci == value: try: rule = MACPCI(nic.mac, nic.pci, tname=target) except Exception, e: LOG.warning("Error creating rule: %s" % (e,)) continue self.rules.append(rule) break else: LOG.warning("No NIC found with a PCI ID of '%s' for the " "%s dynamic rule" % (value, target)) continue elif method == "label": for nic in state: if nic.label == value: try:
def remap_netdevs(remap_list): # # rename everything sideways to safe faffing with temp renanes # for x in ( x for x in os.listdir("/sys/class/net/") if x[:3] == "eth" ): # util.runCmd2(['ip', 'link', 'set', x, 'name', 'side-'+x]) for cmd in remap_list: parse_arg(cmd) # Grab the current state from biosdevname current_eths = all_devices_all_names() current_state = [] for nic in current_eths: eth = current_eths[nic] if not ("BIOS device" in eth and "Kernel name" in eth and "Assigned MAC" in eth and "Bus Info" in eth and "all_ethN" in eth["BIOS device"] and "physical" in eth["BIOS device"]): LOG.error("Interface information for '%s' from biosdevname is " "incomplete; Discarding." % (eth.get("Kernel name", "Unknown"), )) try: current_state.append( MACPCI(eth["Assigned MAC"], eth["Bus Info"], kname=eth["Kernel name"], order=int(eth["BIOS device"]["all_ethN"][3:]), ppn=eth["BIOS device"]["physical"], label=eth.get("SMBIOS Label", ""))) except Exception as e: LOG.error("Can't generate current state for interface '%s' - " "%s" % (eth, e)) current_state.sort() LOG.debug("Current state = %s" % (niceformat(current_state), )) static_rules.generate(current_state) dynamic_rules.generate(current_state) static_eths = [x.tname for x in static_rules.rules] last_boot = [x for x in dynamic_rules.rules if x.tname not in static_eths] LOG.debug("StaticRules Formulae = %s" % (niceformat(static_rules.formulae), )) LOG.debug("StaticRules Rules = %s" % (niceformat(static_rules.rules), )) LOG.debug("DynamicRules Lastboot = %s" % (niceformat(last_boot), )) # Invoke the renaming logic try: transactions = rename(static_rules=static_rules.rules, cur_state=current_state, last_state=last_boot, old_state=[]) except Exception as e: LOG.critical("Problem from rename logic: %s. Giving up" % (e, )) return # Apply transactions, or explicitly state that there are none if len(transactions): for src, dst in transactions: ip_link_set_name(src, dst) else: LOG.info("No transactions. No need to rename any nics") # Regenerate dynamic configuration def macpci_as_list(x): return [str(x.mac), str(x.pci), x.tname] new_lastboot = map(macpci_as_list, current_state) dynamic_rules.lastboot = new_lastboot LOG.info("All done ordering the network devices")