def _check_bond_interface_change(self, phy_interface, attr_obj): """Check if there's any change in bond interface. First check if the interface passed itself is a bond-interface and then retrieve the member list and compare. Next, check if the interface passed is a part of the bond interface and then retrieve the member list and compare. """ bond_phy = sys_utils.get_bond_intf(phy_interface) if sys_utils.is_intf_bond(phy_interface): bond_intf = phy_interface else: bond_intf = bond_phy # This can be an addition or removal of the interface to a bond. bond_intf_change = attr_obj.cmp_update_bond_intf(bond_intf) return bond_intf_change
def uplink_bond_intf_process(self): """Process the case when uplink interface becomes part of a bond. This is called to check if the phy interface became a part of the bond. If the below condition is True, this means, a physical interface that was not a part of a bond was earlier discovered as uplink and now that interface became part of the bond. Usually, this doesn't happen as LLDP and in turn this function will first detect a 'down' followed by an 'up'. When regular interface becomes part of bond, it's rare for it to hit this 'normal' case. But, still providing the functionality if it happens. The following is done : a. Bring down the physical interface by sending a 'down' event b. Add the bond interface by sending an 'up' event Consquently, when bond is added that will be assigned to self.phy_uplink. Then, the below condition will be False. i.e.. 'get_bond_intf' will return False, when the argument is 'bond0'. """ bond_intf = sys_utils.get_bond_intf(self.phy_uplink) if bond_intf is None: return False self.save_uplink( fail_reason=constants.port_transition_bond_down_reason) self.process_uplink_ongoing = True upl_msg = VdpQueMsg(constants.UPLINK_MSG_TYPE, status='down', phy_uplink=self.phy_uplink, br_int=self.br_integ, br_ex=self.br_ex, root_helper=self.root_helper) self.que.enqueue(constants.Q_UPL_PRIO, upl_msg) self.phy_uplink = None self.veth_intf = None self.uplink_det_compl = False # No veth interface self.save_uplink( uplink=bond_intf, fail_reason=constants.port_transition_bond_up_reason) self.phy_uplink = bond_intf self.process_uplink_ongoing = True upl_msg = VdpQueMsg(constants.UPLINK_MSG_TYPE, status='up', phy_uplink=self.phy_uplink, br_int=self.br_integ, br_ex=self.br_ex, root_helper=self.root_helper) self.que.enqueue(constants.Q_UPL_PRIO, upl_msg) return True
def vdp_uplink_proc(self): """Periodic handler to detect the uplink interface to the switch. -> restart_uplink_called: should be called by agent initially to set the stored uplink and veth from DB -> process_uplink_ongoing: Will be set when uplink message is enqueue and reset when dequeued and processed completely -> uplink_det_compl: Will be set to True when a valid uplink is detected and object created. Will be reset when uplink is down -> phy_uplink: Is the uplink interface -> veth_intf : Signifies the veth interface. """ LOG.info("In Periodic Uplink Task") if not self.is_os_run: if not self.is_openstack_running(): LOG.info("OpenStack is not running") return else: self.is_os_run = True if not self.restart_uplink_called or self.process_uplink_ongoing: LOG.info("Uplink before restart not refreshed yet..states " "%(ruc)d %(puo)d", {'ruc': self.restart_uplink_called, 'puo': self.process_uplink_ongoing}) return if self.phy_uplink is not None: if (self.uplink_det_compl and ( self.phy_uplink not in self.ovs_vdp_obj_dict)): LOG.error("Not Initialized for phy %s", self.phy_uplink) return if self.phy_uplink in self.ovs_vdp_obj_dict: self.veth_intf = (self.ovs_vdp_obj_dict[self.phy_uplink]. get_lldp_local_bridge_port()) # The below logic has a bug when agent is started # and openstack is not running fixme(padkrish) else: if self.veth_intf is None: LOG.error("Incorrect state, Bug") return if self.static_uplink: ret = self.static_uplink_detect(self.veth_intf) else: ret = uplink_det.detect_uplink(self.veth_intf) if ret is 'down': if self.phy_uplink is None: LOG.error("Wrong status down") return # Call API to set the uplink as "" DOWN event self.uplink_down_cnt = self.uplink_down_cnt + 1 if not self.static_uplink and ( self.uplink_down_cnt < constants.UPLINK_DOWN_THRES): return self.process_uplink_ongoing = True upl_msg = VdpQueMsg(constants.UPLINK_MSG_TYPE, status='down', phy_uplink=self.phy_uplink, br_int=self.br_integ, br_ex=self.br_ex, root_helper=self.root_helper) self.que.enqueue(constants.Q_UPL_PRIO, upl_msg) self.phy_uplink = None self.veth_intf = None self.uplink_det_compl = False self.uplink_down_cnt = 0 elif ret is None: if self.veth_intf is not None: LOG.error("Wrong status None") return # Call API to set the uplink as "" Uplink not discovered yet self.save_uplink(fail_reason=constants.uplink_undiscovered_reason) elif ret is 'normal': if self.veth_intf is None: LOG.error("Wrong status Normal") return # Uplink already discovered, nothing to be done here # Resetting it back, happens when uplink was down for a very short # time and no need to remove flows self.uplink_down_cnt = 0 bond_det = self.uplink_bond_intf_process() # Revisit this logic. # If uplink detection fails, it will be put in Error queue, which # will dequeue and put it back in the main queue # At the same time this periodic task will also hit this normal # state and will put the message in main queue. fixme(padkrish) # The below lines are put here because after restart when # eth/veth are passed to uplink script, it will return normal # But OVS object would not have been created for the first time, # so the below lines ensures it's done. if not self.uplink_det_compl and not bond_det: if self.phy_uplink is None: LOG.error("Incorrect state, bug") return self.process_uplink_ongoing = True upl_msg = VdpQueMsg(constants.UPLINK_MSG_TYPE, status='up', phy_uplink=self.phy_uplink, br_int=self.br_integ, br_ex=self.br_ex, root_helper=self.root_helper) self.que.enqueue(constants.Q_UPL_PRIO, upl_msg) # yield LOG.info("Enqueued Uplink Msg from normal") self.check_periodic_bulk_vm_notif_rcvd() else: LOG.info("In Periodic Uplink Task uplink found %s", ret) bond_intf = sys_utils.get_bond_intf(ret) if bond_intf is not None: ret = bond_intf LOG.info("Interface %(memb)s part of bond %(bond)s" % {'memb': ret, 'bond': bond_intf}) # Call API to set the uplink as ret self.save_uplink(uplink=ret, veth_intf=self.veth_intf) self.phy_uplink = ret self.process_uplink_ongoing = True upl_msg = VdpQueMsg(constants.UPLINK_MSG_TYPE, status='up', phy_uplink=self.phy_uplink, br_int=self.br_integ, br_ex=self.br_ex, root_helper=self.root_helper) self.que.enqueue(constants.Q_UPL_PRIO, upl_msg) # yield LOG.info("Enqueued Uplink Msg")