def _cleanup_definitions(self, vfab_id, vlanid, ports, config, mac, commit=False): """Cleanup existing LAG/VLAN/interface definitions. @param self CFABdriver's instance @param vfab_id the string of VFAB ID @param vlanid the string of VLAN ID @param ports string of the ports which is separated by ',' @param config string of candidate-config @param mac string of the MAC address @param commit the boolean whether executes commit or not @return A string of modified ifgroups for vfab vlan or None """ self._dissociate_mac_from_port_profile(vfab_id, vlanid, mac, config=config, do_not_commit=True) lag_id = _get_associated_lag_id(ports, config) commit_interface = True if (commit and not lag_id) else False self._clear_interfaces(ports, commit=commit_interface) if commit_interface: LOG.debug(_('Skip clearing VLAN and LAG.')) return None modified = self._clear_vlans(vfab_id, ports, config, lag_id=lag_id) if lag_id: LOG.debug(_('Found LAG%s definiton and clear.'), lag_id) self._clear_lag(vfab_id, lag_id, ports, config, commit=commit) return modified.get(str(vlanid), None)
def _validate_pprofile_prefix(self): if len(self._pprofile_prefix) > (28 if self._share_pprofile else 15): raise ValueError(_("pprofile_prefix is too long.")) if (self._pprofile_prefix.find('"') >= 0 or self._pprofile_prefix.find("|") >= 0 or self._pprofile_prefix.find("?") >= 0): raise ValueError(_("pprofile_prefix contains illegal character."))
def _setup_vfab_vlan(self, vfab_id, vlanid, ifgroup_id, config, ifg=None, port_type=_EP, vlan_type='untag', commit=False): """Setup VFAB VLAN configuration.""" # Judge the result of cleanup process. # ifg is None # 'ifgroup' for vfab vlan hasn't changed at all. # ifg is ''(Empty string) # The definition of vfab vlan has been deleted in cleanup. # ifg is String(Not empty) # 'ifgroup' for vfab vlan has been changed in cleanup. modified = True if ifg is not None else False ifgroups = ifg if modified else _get_ifgroups_of_vfab_vlan( vfab_id, vlanid, config) # Need to re-define for the vfab vlan. if modified and ifg is '': ifgroups = None if _is_ifgroup_included(ifgroup_id, ifgroups): LOG.debug(_("ifgroup %(if_id)s has already configured" "in %(ifgs)s"), dict(if_id=ifgroup_id, ifgs=ifgroups)) elif ifgroups is None: ifgroups = str(ifgroup_id) else: ifgroups += "," + str(ifgroup_id) cmds = [ "vfab {vfab} vlan {vlan} {port_type} {vlan_type} {ifgroup}".format( vfab=vfab_id, vlan=vlanid, port_type=port_type, vlan_type=vlan_type, ifgroup=ifgroups)] self.mgr.configure(cmds, commit=commit)
def _get_all_vfab_vlans_and_ifgroups(vfab_id, config, vlan_type='untag'): """Gets all VFAB VLAN definitions and ifgroups. @param vfab_id the string of VFAB ID @param config the string of candidate-config @param vlan_type 'untag(default)' or 'tag'. @return the string of ifgroups otherwise None """ match = re.findall(_VFAB_VLANS.format(v=vfab_id, vlan_type=vlan_type), config, re.MULTILINE) result = dict(match) if result: LOG.debug(_('VFAB(%(vfab)s){VLANID: ifgroups}:%(result)s'), dict(vfab=vfab_id, result=result)) else: LOG.debug(_('VLAN and ifgroups not found.')) return result
def _clear_vlans(self, vfab_id, ports, config, port_type=_EP, vlan_type='untag', lag_id=None, commit=False): """Clear all VLAN definitions with specified ports. @param self CFABdriver's instance @param vfab_id the string of VFAB ID @param ports a string of the ports which is separated by ',' @param config a string of a candidate-config @return None or string of the modified ifgroups separated by ',' """ # (yushiro): ifgroup won't delete because it can not determine # whether ifgroup is created by plugin or not. indices = search_ifgroup_indices(ports, config, lag_id=lag_id) vlan_ifgs = _get_all_vfab_vlans_and_ifgroups(vfab_id, config, vlan_type='untag') updated_vlan_ifgs = copy.deepcopy(vlan_ifgs) cmds = [] for vlanid in sorted(vlan_ifgs.keys()): vlan = str(vlanid) is_delete = False # Target ifgroup_ids exists but vfab vlan definition does not exist # or ifgroup_id doesn't exist but vfab vlan definition exists. if None in [vlan_ifgs[vlan]] or not indices: LOG.debug(_("ifgroup with %(p)s for VLAN(%(v)s)has already" "deleted. Skip clear_vlan."), dict(p=ports, v=vlanid)) continue eliminated = fj_util.eliminate_val(vlan_ifgs[vlan], indices) updated_vlan_ifgs[vlan] = eliminated # VLAN is configured with the only ifgroup_id if not eliminated: is_delete = True common_def = "vfab {vfab} vlan {vlan} {port_type} {vlan_type}" # Delete VFAB VLAN definition if is_delete: command = "no" + " " + common_def cmds.append(command.format(vfab=vfab_id, vlan=vlanid, port_type=port_type, vlan_type=vlan_type)) # Reject ifgroup_id from VFAB VLAN definition else: command = common_def + " " + "{ifgroup}" cmds.append(command.format(vfab=vfab_id, vlan=vlanid, port_type=port_type, vlan_type=vlan_type, ifgroup=eliminated)) self.mgr.configure(cmds, commit=commit) return updated_vlan_ifgs
def search_ifgroup_indices(ports, candidate_config, lag_id=None): """Search ifgroup ids with specified ports.""" reg = r"^ifgroup\s+(\d+)\s+ether\s+{ports}$".format(ports=ports) if lag_id: domain_id = _get_domain_id(ports) reg = r"^ifgroup\s+(\d+)\s+{if_type}\s+{domain_id}\s+{lag_id}$".format( if_type=_LAG, domain_id=domain_id, lag_id=lag_id) match = re.findall(reg, candidate_config, re.MULTILINE) if match: ifgroup_indices = sorted([int(m) for m in match]) LOG.debug(_('Found ifgroup for port(%(p)s):%(ifg)s'), dict(p=ports, ifg=ifgroup_indices)) return ifgroup_indices return []
def _get_associated_lag_id(ports, config): """Get lag_id which is associated to the ports.""" ids = [] interfaces = ports.split(",") for port in interfaces: match = re.search( r'^interface\s+{port}$\n((?:\s+.+\n)' r'*(\s+type\s+{port_type}\s+(\d+))(?:\s+.+\n)*)\s+exit$'.format( port=port, port_type='linkaggregation'), config, re.MULTILINE) if match: ids.append(match.group(3)) lag_ids = list(set(ids)) if not lag_ids: return None if len(lag_ids) > 1: LOG.warning( _LW("Each port%(ports)s has different LAG ids(%(lag_ids)s)"), dict(ports=ports, lag_ids=lag_ids)) LOG.debug(_("Associated LAG%(lag_ids)s with interfaces:%(ports)s"), dict(lag_ids=lag_ids, ports=ports)) return sorted(lag_ids)[0]
def eliminate_val(source, reject): """Eliminate specified value from range value. ex. source='1,2,3-10', reject=[1], result: '2,3-10' @param source a string of range definition separated with "," ex. "1,2,3" or "1-5"(same as "1,2,3,4,5") @param reject a list of integer to reject. ex. [1, 2] @return eliminated a string of eliminated value separated with "," """ if source is None: return values = [str(i) for i in reject] rejected = source.split(',') found = False for val in values: for target in rejected: m = RANGE_DEFINITION.match(target) if m: low = m.group(1) high = m.group(2) if val in target: rejected.remove(target) # matches the lowest one if (val == low): # Case: source is "1-2" and target is "1" if ((int(val) + 1) == int(high)): rejected.append(high) else: rejected.append(str(int(val) + 1) + "-" + high) found = True break # matches the highest one else: # Ex. source is "1-2" and target is "2" if ((int(val) - 1) == int(low)): rejected.append(low) else: rejected.append(low + "-" + str(int(val) - 1)) found = True break # matches between lower one and higher one elif (int(low) < int(val) and int(val) < int(high)): rejected.remove(target) # Ex. source is "1-n" and target is "2" if ((int(val) - 1) == int(low)): rejected.append(low) # Ex. source is "1-3" and target is "2" if ((int(val) + 1) == int(high)): rejected.append(high) # Ex. source is "1-4" and target is "2" else: rejected.append(str(int(val) + 1) + "-" + high) # Ex. source is "n-5" and target is "4"(n is NOT "3") elif ((int(val) + 1) == int(high)): rejected.append(high) rejected.append(low + "-" + str(int(val) - 1)) # Ex. source is "1-5" and target is "3" else: rejected.append(low + "-" + str(int(val) - 1)) rejected.append(str(int(val) + 1) + "-" + high) found = True break # source is not defined with range "-" elif val == target: rejected.remove(target) found = True break if not found: LOG.debug(_('Reject target doesn\'t exist.')) return ','.join(rejected)