def update_port_filter(self, port): LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: self.prepare_port_filter(port) return old_port = self._security_ports[port['device']] rules = old_port['security_group_rules'] param_port_rules = port['security_group_rules'] new_rules = [r for r in param_port_rules if r not in rules] remove_rules = [r for r in rules if r not in param_port_rules] LOG.info( _LI("Creating %(new)s new rules, removing %(old)s " "old rules."), { 'new': len(new_rules), 'old': len(remove_rules) }) self._remove_port_rules(old_port['id'], remove_rules) self._create_port_rules(port['id'], new_rules) self._security_ports[port['device']] = port
def _treat_devices_added(self): try: devices_details_list = self.plugin_rpc.get_devices_details_list( self.context, self._added_ports, self.agent_id) except Exception as e: LOG.debug( "Unable to get ports details for " "devices %(devices)s: %(e)s", { 'devices': self._added_ports, 'e': e }) return for device_details in devices_details_list: device = device_details['device'] LOG.info(_LI("Adding port %s"), device) if 'port_id' in device_details: LOG.info( _LI("Port %(device)s updated. Details: " "%(device_details)s"), { 'device': device, 'device_details': device_details }) self._workers.submit(self._process_added_port, device_details) # remove the port from added ports set, so it doesn't get # reprocessed. self._added_ports.discard(device)
def update_port_filter(self, port): LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: LOG.info(_LI("Device %(port)s not yet added."), {'port': port['id']}) return old_port = self._security_ports[port['device']] old_provider_rules = old_port['security_group_rules'] added_provider_rules = port['security_group_rules'] # Generate the rules added_rules = self._generate_rules([port]) # Consider added provider rules (if any) new_rules = [r for r in added_provider_rules if r not in old_provider_rules] # Build new rules to add new_rules.extend([r for r in added_rules[port['id']] if r not in self._sec_group_rules[port['id']]]) # Remove non provider rules remove_rules = [r for r in self._sec_group_rules[port['id']] if r not in added_rules[port['id']]] # Remove for non provider rules remove_rules.extend([r for r in old_provider_rules if r not in added_provider_rules]) LOG.info(_("Creating %(new)s new rules, removing %(old)s " "old rules."), {'new': len(new_rules), 'old': len(remove_rules)}) self._create_port_rules(port['id'], new_rules) self._remove_port_rules(old_port['id'], remove_rules) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = added_rules[port['id']]
def _treat_devices_added(self, devices): try: devices_details_list = self.plugin_rpc.get_devices_details_list(self.context, devices, self.agent_id) except Exception as e: LOG.debug("Unable to get ports details for " "devices %(devices)s: %(e)s", {"devices": devices, "e": e}) # resync is needed return True for device_details in devices_details_list: device = device_details["device"] LOG.info(_LI("Adding port %s"), device) if "port_id" in device_details: LOG.info( _LI("Port %(device)s updated. Details: " "%(device_details)s"), {"device": device, "device_details": device_details}, ) self._treat_vif_port( device_details["port_id"], device_details["network_id"], device_details["network_type"], device_details["physical_network"], device_details["segmentation_id"], device_details["admin_state_up"], ) # check if security groups is enabled. # if not, teardown the security group rules if self.enable_security_groups: self.sec_groups_agent.prepare_devices_filter([device]) else: self._utils.remove_all_security_rules(device_details["port_id"]) self.plugin_rpc.update_device_up(self.context, device, self.agent_id, self._host) return False
def _treat_devices_added(self): try: devices_details_list = self.plugin_rpc.get_devices_details_list( self.context, self._added_ports, self.agent_id) except Exception as e: LOG.debug("Unable to get ports details for " "devices %(devices)s: %(e)s", {'devices': self._added_ports, 'e': e}) return for device_details in devices_details_list: device = device_details['device'] LOG.info(_LI("Adding port %s"), device) if 'port_id' in device_details: LOG.info(_LI("Port %(device)s updated. Details: " "%(device_details)s"), {'device': device, 'device_details': device_details}) self._workers.submit(self._process_added_port, device_details) # remove the port from added ports set, so it doesn't get # reprocessed. self._added_ports.discard(device)
def update_port_filter(self, port): if not port.get('port_security_enabled'): LOG.info( _LI('Port %s does not have security enabled. ' 'Removing existing rules if any.'), port['id']) existing_rules = self._sec_group_rules.pop(port['id'], None) if existing_rules: self._utils.remove_all_security_rules(port['id']) return LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: LOG.info(_LI("Device %(port)s not yet added. Adding."), {'port': port['id']}) self.prepare_port_filter(port) return old_port = self._security_ports[port['device']] old_provider_rules = old_port['security_group_rules'] added_provider_rules = port['security_group_rules'] # Generate the rules added_rules = self._generate_rules([port]) # Expand wildcard rules expanded_rules = self._sg_gen.expand_wildcard_rules( added_rules[port['id']]) # Consider added provider rules (if any) new_rules = [ r for r in added_provider_rules if r not in old_provider_rules ] # Build new rules to add new_rules.extend([ r for r in added_rules[port['id']] if r not in self._sec_group_rules[port['id']] ]) # Remove non provider rules remove_rules = [ r for r in self._sec_group_rules[port['id']] if r not in added_rules[port['id']] ] # Remove for non provider rules remove_rules.extend( [r for r in old_provider_rules if r not in added_provider_rules]) # Avoid removing or adding rules which are contained in wildcard rules new_rules = [r for r in new_rules if r not in expanded_rules] remove_rules = [r for r in remove_rules if r not in expanded_rules] LOG.info( _("Creating %(new)s new rules, removing %(old)s " "old rules."), { 'new': len(new_rules), 'old': len(remove_rules) }) self._create_port_rules(port['id'], new_rules) self._remove_port_rules(old_port['id'], remove_rules) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = added_rules[port['id']]
def update_port_filter(self, port): if not port['port_security_enabled']: LOG.info(_LI('Port %s does not have security enabled. ' 'Removing existing rules if any.'), port['id']) existing_rules = self._sec_group_rules.pop(port['id'], None) if existing_rules: self._utils.remove_all_security_rules(port['id']) return LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: LOG.info(_LI("Device %(port)s not yet added. Adding."), {'port': port['id']}) self.prepare_port_filter(port) return old_port = self._security_ports[port['device']] old_provider_rules = old_port['security_group_rules'] added_provider_rules = port['security_group_rules'] # Generate the rules added_rules = self._generate_rules([port]) # Expand wildcard rules expanded_rules = self._sg_gen.expand_wildcard_rules( added_rules[port['id']]) # Consider added provider rules (if any) new_rules = [r for r in added_provider_rules if r not in old_provider_rules] # Build new rules to add new_rules.extend([r for r in added_rules[port['id']] if r not in self._sec_group_rules[port['id']]]) # Remove non provider rules remove_rules = [r for r in self._sec_group_rules[port['id']] if r not in added_rules[port['id']]] # Remove for non provider rules remove_rules.extend([r for r in old_provider_rules if r not in added_provider_rules]) # Avoid removing or adding rules which are contained in wildcard rules new_rules = [r for r in new_rules if r not in expanded_rules] remove_rules = [r for r in remove_rules if r not in expanded_rules] LOG.info(_("Creating %(new)s new rules, removing %(old)s " "old rules."), {'new': len(new_rules), 'old': len(remove_rules)}) self._create_port_rules(port['id'], new_rules) self._remove_port_rules(old_port['id'], remove_rules) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = added_rules[port['id']]
def _provision_network(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.info(_LI("Provisioning network %s"), net_uuid) vswitch_name = self._get_vswitch_name(network_type, physical_network) if network_type == constants.TYPE_VLAN: self._utils.set_switch_external_port_trunk_vlan( vswitch_name, segmentation_id, constants.TRUNK_ENDPOINT_MODE) elif network_type == constants.TYPE_FLAT: # Nothing to do pass elif network_type == constants.TYPE_LOCAL: # TODO(alexpilotti): Check that the switch type is private # or create it if not existing pass else: raise utils.HyperVException( msg=(_("Cannot provision unknown network type %(network_type)s" " for network %(net_uuid)s") % dict(network_type=network_type, net_uuid=net_uuid))) map = { 'network_type': network_type, 'vswitch_name': vswitch_name, 'ports': [], 'vlan_id': segmentation_id} self._network_vswitch_map[net_uuid] = map
def daemon_loop(self): sync = True ports = set() while True: try: start = time.time() if sync: LOG.info(_LI("Agent out of sync with plugin!")) ports.clear() sync = False port_info = self._update_ports(ports) # notify plugin about port deltas if port_info: LOG.debug("Agent loop has new devices!") # If treat devices fails - must resync with plugin sync = self._process_network_ports(port_info) ports = port_info['current'] self._port_enable_control_metrics() except Exception: LOG.exception(_LE("Error in agent event loop")) sync = True # sleep till end of polling interval elapsed = (time.time() - start) if (elapsed < self._polling_interval): time.sleep(self._polling_interval - elapsed) else: LOG.debug("Loop iteration exceeded interval " "(%(polling_interval)s vs. %(elapsed)s)", {'polling_interval': self._polling_interval, 'elapsed': elapsed})
def create_customer_routes(self, vsid, network_name, dest_prefix, gateway): cust_route_string = network_name + dest_prefix + str(vsid) rdid_uuid = uuid.uuid5(uuid.NAMESPACE_X500, cust_route_string) rdid_uuid = str(rdid_uuid) routes = self._scimv2.MSFT_NetVirtualizationCustomerRouteSettingData( VirtualSubnetID=vsid) for route in routes: route.Delete_() # TODO(claudiub): the logic should be moved to nvgre_ops. This should # create only one router per call. self._create_cust_route(vsid, dest_prefix, constants.IPV4_DEFAULT, rdid_uuid) if not gateway: LOG.info(_LI('Subnet does not have gateway configured. Skipping.')) return if gateway.split('.')[-1] == '1': LOG.error( _LE('Subnet has unsupported gateway IP ending in 1: %s. ' 'Any other gateway IP is supported.'), gateway) return # TODO(claudiub): what if there is no gateway? self._create_cust_route(vsid, '%s/0' % constants.IPV4_DEFAULT, gateway, rdid_uuid) # customer route for metadata is also necessary. self._create_cust_route(vsid, '%s/32' % CONF.AGENT.neutron_metadata_address, gateway, rdid_uuid)
def _create_customer_routes(self, segmentation_id, cidr, gw, rdid_uuid): self._nvgre_utils.clear_customer_routes(segmentation_id) # create cidr -> 0.0.0.0/0 customer route self._nvgre_utils.create_customer_route(segmentation_id, cidr, constants.IPV4_DEFAULT, rdid_uuid) if not gw: LOG.info( _LI('Subnet does not have gateway configured. ' 'Skipping.')) elif gw.split('.')[-1] == '1': LOG.error( _LE('Subnet has unsupported gateway IP ending in 1: ' '%s. Any other gateway IP is supported.'), gw) else: # create 0.0.0.0/0 -> gateway customer route self._nvgre_utils.create_customer_route( segmentation_id, '%s/0' % constants.IPV4_DEFAULT, gw, rdid_uuid) # create metadata address -> gateway customer route metadata_addr = '%s/32' % CONF.AGENT.neutron_metadata_address self._nvgre_utils.create_customer_route(segmentation_id, metadata_addr, gw, rdid_uuid)
def _provision_network(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.info(_LI("Provisioning network %s"), net_uuid) vswitch_name = self._get_vswitch_name(network_type, physical_network) if network_type == constants.TYPE_VLAN: # Nothing to do pass elif network_type == constants.TYPE_NVGRE and self._nvgre_enabled: self._nvgre_ops.bind_nvgre_network( segmentation_id, net_uuid, vswitch_name) elif network_type == constants.TYPE_FLAT: # Nothing to do pass elif network_type == constants.TYPE_LOCAL: # TODO(alexpilotti): Check that the switch type is private # or create it if not existing pass else: raise exception.NetworkingHyperVException( (_("Cannot provision unknown network type %(network_type)s" " for network %(net_uuid)s") % dict(network_type=network_type, net_uuid=net_uuid))) map = { 'network_type': network_type, 'vswitch_name': vswitch_name, 'ports': [], 'vlan_id': segmentation_id} self._network_vswitch_map[net_uuid] = map
def _port_bound(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.debug("Binding port %s", port_id) if net_uuid not in self._network_vswitch_map: self._provision_network(port_id, net_uuid, network_type, physical_network, segmentation_id) map = self._network_vswitch_map[net_uuid] map["ports"].append(port_id) self._utils.connect_vnic_to_vswitch(map["vswitch_name"], port_id) if network_type == constants.TYPE_VLAN: LOG.info( _LI("Binding VLAN ID %(segmentation_id)s " "to switch port %(port_id)s"), dict(segmentation_id=segmentation_id, port_id=port_id), ) self._utils.set_vswitch_port_vlan_id(segmentation_id, port_id) elif network_type == constants.TYPE_NVGRE and self._nvgre_enabled: self._nvgre_ops.bind_nvgre_port(segmentation_id, map["vswitch_name"], port_id) elif network_type == constants.TYPE_FLAT: # Nothing to do pass elif network_type == constants.TYPE_LOCAL: # Nothing to do pass else: LOG.error(_LE("Unsupported network type %s"), network_type) if self.enable_metrics_collection: self._utils.enable_port_metrics_collection(port_id) self._port_metric_retries[port_id] = self._metrics_max_retries
def create_customer_routes(self, vsid, network_name, dest_prefix, gateway): cust_route_string = network_name + dest_prefix + str(vsid) rdid_uuid = uuid.uuid5(uuid.NAMESPACE_X500, cust_route_string) rdid_uuid = str(rdid_uuid) routes = self._scimv2.MSFT_NetVirtualizationCustomerRouteSettingData( VirtualSubnetID=vsid) for route in routes: route.Delete_() # TODO(claudiub): the logic should be moved to nvgre_ops. This should # create only one router per call. self._create_cust_route( vsid, dest_prefix, constants.IPV4_DEFAULT, rdid_uuid) if not gateway: LOG.info(_LI('Subnet does not have gateway configured. Skipping.')) return if gateway.split('.')[-1] == '1': LOG.error(_LE('Subnet has unsupported gateway IP ending in 1: %s. ' 'Any other gateway IP is supported.'), gateway) return # TODO(claudiub): what if there is no gateway? self._create_cust_route( vsid, '%s/0' % constants.IPV4_DEFAULT, gateway, rdid_uuid) # customer route for metadata is also necessary. self._create_cust_route( vsid, '%s/32' % CONF.AGENT.neutron_metadata_address, gateway, rdid_uuid)
def _provision_network(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.info(_LI("Provisioning network %s"), net_uuid) vswitch_name = self._get_vswitch_name(network_type, physical_network) if network_type == constants.TYPE_VLAN: self._utils.set_switch_external_port_trunk_vlan(vswitch_name, segmentation_id, constants.TRUNK_ENDPOINT_MODE) elif network_type == constants.TYPE_FLAT: #Nothing to do pass elif network_type == constants.TYPE_LOCAL: #TODO(alexpilotti): Check that the switch type is private #or create it if not existing pass else: raise utils.HyperVException( msg=(_("Cannot provision unknown network type %(network_type)s" " for network %(net_uuid)s") % dict(network_type=network_type, net_uuid=net_uuid))) map = { 'network_type': network_type, 'vswitch_name': vswitch_name, 'ports': [], 'vlan_id': segmentation_id} self._network_vswitch_map[net_uuid] = map
def _port_bound(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.debug("Binding port %s", port_id) if net_uuid not in self._network_vswitch_map: self._provision_network(port_id, net_uuid, network_type, physical_network, segmentation_id) map = self._network_vswitch_map[net_uuid] map['ports'].append(port_id) self._utils.connect_vnic_to_vswitch(map['vswitch_name'], port_id) if network_type == constants.TYPE_VLAN: LOG.info( _LI('Binding VLAN ID %(segmentation_id)s ' 'to switch port %(port_id)s'), dict(segmentation_id=segmentation_id, port_id=port_id)) self._utils.set_vswitch_port_vlan_id(segmentation_id, port_id) elif network_type == constants.TYPE_NVGRE and self._nvgre_enabled: self._nvgre_ops.bind_nvgre_port(segmentation_id, map['vswitch_name'], port_id) elif network_type == constants.TYPE_FLAT: # Nothing to do pass elif network_type == constants.TYPE_LOCAL: # Nothing to do pass else: LOG.error(_LE('Unsupported network type %s'), network_type) if self.enable_metrics_collection: self._utils.add_metrics_collection_acls(port_id) self._port_metric_retries[port_id] = self._metrics_max_retries
def _provision_network(self, port_id, net_uuid, network_type, physical_network, segmentation_id): LOG.info(_LI("Provisioning network %s"), net_uuid) vswitch_name = self._get_vswitch_name(network_type, physical_network) if network_type == constants.TYPE_VLAN: # Nothing to do pass elif network_type == constants.TYPE_NVGRE and self._nvgre_enabled: self._nvgre_ops.bind_nvgre_network(segmentation_id, net_uuid, vswitch_name) elif network_type == constants.TYPE_FLAT: # Nothing to do pass elif network_type == constants.TYPE_LOCAL: # TODO(alexpilotti): Check that the switch type is private # or create it if not existing pass else: raise exception.NetworkingHyperVException( (_("Cannot provision unknown network type %(network_type)s" " for network %(net_uuid)s") % dict(network_type=network_type, net_uuid=net_uuid))) map = { 'network_type': network_type, 'vswitch_name': vswitch_name, 'ports': [], 'vlan_id': segmentation_id } self._network_vswitch_map[net_uuid] = map
def bind_nvgre_port(self, segmentation_id, network_name, port_id): mac_addr = self._hyperv_utils.get_vnic_mac_address(port_id) provider_addr = self._nvgre_utils.get_network_iface_ip(network_name)[0] customer_addr = self._n_client.get_port_ip_address(port_id) if not provider_addr or not customer_addr: LOG.warning(_LW('Cannot bind NVGRE port. Could not determine ' 'provider address (%(prov_addr)s) or customer ' 'address (%(cust_addr)s).'), {'prov_addr': provider_addr, 'cust_addr': customer_addr}) return LOG.info(_LI('Binding VirtualSubnetID %(segmentation_id)s ' 'to switch port %(port_id)s'), dict(segmentation_id=segmentation_id, port_id=port_id)) self._hyperv_utils.set_vswitch_port_vsid(segmentation_id, port_id) # normal lookup record. self._register_lookup_record( provider_addr, customer_addr, mac_addr, segmentation_id) # lookup record for dhcp requests. self._register_lookup_record( self._vswitch_ips[network_name], constants.IPV4_DEFAULT, mac_addr, segmentation_id) LOG.info('Fanning out LookupRecord...') self._notifier.lookup_update(self.context, provider_addr, {'customer_addr': customer_addr, 'mac_addr': mac_addr, 'customer_vsid': segmentation_id})
def _init_nvgre(self, physical_networks): for network in physical_networks: LOG.info(_LI("Adding provider route and address for network: %s"), network) self._nvgre_utils.create_provider_route(network) self._nvgre_utils.create_provider_address( network, CONF.NVGRE.provider_vlan_id) ip_addr, length = self._nvgre_utils.get_network_iface_ip(network) self._vswitch_ips[network] = ip_addr
def main(): config.register_agent_state_opts_helper(cfg.CONF) common_config.init(sys.argv[1:]) config.setup_logging() hyperv_agent = HyperVNeutronAgent() # Start everything. LOG.info(_LI("Agent initialized successfully, now running... ")) hyperv_agent.daemon_loop()
def _register_lookup_record(self, prov_addr, cust_addr, mac_addr, vsid): LOG.info(_LI('Creating LookupRecord: VSID: %(vsid)s MAC: %(mac_addr)s ' 'Customer IP: %(cust_addr)s Provider IP: %(prov_addr)s'), dict(vsid=vsid, mac_addr=mac_addr, cust_addr=cust_addr, prov_addr=prov_addr)) self._nvgre_utils.create_lookup_record( prov_addr, cust_addr, mac_addr, vsid)
def delete(self, port, qos_policy=None): """Remove QoS rules from port. :param port: port object. :param qos_policy: the QoS policy to be removed from port. """ LOG.info(_LI("Deleting QoS policy %(qos_policy)s on " "port %(port)s"), dict(qos_policy=qos_policy, port=port)) self._utils.remove_port_qos_rule(port["port_id"])
def tunnel_update(self, context, **kwargs): LOG.info(_LI('tunnel_update received: kwargs: %s'), kwargs) tunnel_ip = kwargs.get('tunnel_ip') if tunnel_ip == CONF.NVGRE.provider_tunnel_ip: # the notification should be ignored if it originates from this # node. return tunnel_type = kwargs.get('tunnel_type') self._nvgre_ops.tunnel_update(context, tunnel_ip, tunnel_type)
def _register_lookup_record(self, prov_addr, cust_addr, mac_addr, vsid): LOG.info( _LI('Creating LookupRecord: VSID: %(vsid)s MAC: %(mac_addr)s ' 'Customer IP: %(cust_addr)s Provider IP: %(prov_addr)s'), dict(vsid=vsid, mac_addr=mac_addr, cust_addr=cust_addr, prov_addr=prov_addr)) self._nvgre_utils.create_lookup_record(prov_addr, cust_addr, mac_addr, vsid)
def update(self, port, qos_policy): """Apply QoS rules on port. :param port: port object. :param qos_policy: the QoS policy to be applied on port. """ LOG.info(_LI("Updating QoS policy %(qos_policy)s on " "port %(port)s"), dict(qos_policy=qos_policy, port=port)) policy_data = self._get_policy_values(qos_policy) self._utils.set_port_qos_rule(port["port_id"], policy_data)
def _treat_devices_added(self, devices): try: devices_details_list = self.plugin_rpc.get_devices_details_list( self.context, devices, self.agent_id) except Exception as e: LOG.debug( "Unable to get ports details for " "devices %(devices)s: %(e)s", { 'devices': devices, 'e': e }) # resync is needed return True for device_details in devices_details_list: device = device_details['device'] LOG.info(_LI("Adding port %s"), device) if 'port_id' in device_details: LOG.info( _LI("Port %(device)s updated. Details: " "%(device_details)s"), { 'device': device, 'device_details': device_details }) self._treat_vif_port(device_details['port_id'], device_details['network_id'], device_details['network_type'], device_details['physical_network'], device_details['segmentation_id'], device_details['admin_state_up']) # check if security groups is enabled. # if not, teardown the security group rules if self.enable_security_groups: self.sec_groups_agent.prepare_devices_filter([device]) else: self._utils.remove_all_security_rules( device_details['port_id']) self.plugin_rpc.update_device_up(self.context, device, self.agent_id, self._host) return False
def _set_port_vlan(self, port_id, vlan_id, vlan_trunk=None): LOG.info( _LI('Binding VLAN ID: %(vlan_id)s, VLAN trunk: ' '%(vlan_trunk)s to switch port %(port_id)s'), dict(vlan_id=vlan_id, vlan_trunk=vlan_trunk, port_id=port_id)) op_mode = (os_win_const.VLAN_MODE_TRUNK if vlan_trunk else os_win_const.VLAN_MODE_ACCESS) self._utils.set_vswitch_port_vlan_id(vlan_id, port_id, operation_mode=op_mode, vlan_trunk=vlan_trunk)
def _port_unbound(self, port_id, vnic_deleted=False): (net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id) if net_uuid not in self._network_vswitch_map: LOG.info(_LI('Network %s is not avalailable on this agent'), net_uuid) return LOG.debug("Unbinding port %s", port_id) self._utils.disconnect_switch_port(port_id, vnic_deleted, True) if not map['ports']: self._reclaim_local_network(net_uuid)
def _treat_devices_removed(self, devices): resync = False for device in devices: LOG.info(_LI("Removing port %s"), device) try: self.plugin_rpc.update_device_down(self.context, device, self.agent_id, self._host) except Exception as e: LOG.debug("Removing port failed for device %(device)s: %(e)s", dict(device=device, e=e)) resync = True continue self._port_unbound(device, vnic_deleted=True) return resync
def lookup_update(self, kwargs): lookup_ip = kwargs.get('lookup_ip') lookup_details = kwargs.get('lookup_details') LOG.info(_LI("Lookup Received: %(lookup_ip)s, %(lookup_details)s"), {'lookup_ip': lookup_ip, 'lookup_details': lookup_details}) if not lookup_ip or not lookup_details: return self._register_lookup_record(lookup_ip, lookup_details['customer_addr'], lookup_details['mac_addr'], lookup_details['customer_vsid'])
def update_port_filter(self, port): LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: self.prepare_port_filter(port) return old_port = self._security_ports[port['device']] rules = old_port['security_group_rules'] param_port_rules = port['security_group_rules'] new_rules = [r for r in param_port_rules if r not in rules] remove_rules = [r for r in rules if r not in param_port_rules] LOG.info(_LI("Creating %(new)s new rules, removing %(old)s " "old rules."), {'new': len(new_rules), 'old': len(remove_rules)}) self._remove_port_rules(old_port['id'], remove_rules) self._create_port_rules(port['id'], new_rules) self._security_ports[port['device']] = port
def _port_unbound(self, port_id, vnic_deleted=False): (net_uuid, map) = self._get_network_vswitch_map_by_port_id(port_id) if net_uuid not in self._network_vswitch_map: LOG.info(_LI('Network %s is not avalailable on this agent'), net_uuid) return LOG.debug("Unbinding port %s", port_id) self._utils.disconnect_switch_port(map['vswitch_name'], port_id, vnic_deleted, True) if not map['ports']: self._reclaim_local_network(net_uuid)
def update_port_filter(self, port): LOG.info(_LI('Updating port rules.')) if port['device'] not in self._security_ports: LOG.info(_LI("Device %(port)s not yet added. Adding."), {'port': port['id']}) self.prepare_port_filter(port) return old_port = self._security_ports[port['device']] old_provider_rules = old_port['security_group_rules'] added_provider_rules = port['security_group_rules'] # Generate the rules added_rules = self._generate_rules([port]) # Consider added provider rules (if any) new_rules = [r for r in added_provider_rules if r not in old_provider_rules] # Build new rules to add new_rules.extend([r for r in added_rules[port['id']] if r not in self._sec_group_rules[port['id']]]) # Remove non provider rules remove_rules = [r for r in self._sec_group_rules[port['id']] if r not in added_rules[port['id']]] # Remove for non provider rules remove_rules.extend([r for r in old_provider_rules if r not in added_provider_rules]) LOG.info(_("Creating %(new)s new rules, removing %(old)s " "old rules."), {'new': len(new_rules), 'old': len(remove_rules)}) self._create_port_rules(port['id'], new_rules) self._remove_port_rules(old_port['id'], remove_rules) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = added_rules[port['id']]
def lookup_update(self, kwargs): lookup_ip = kwargs.get('lookup_ip') lookup_details = kwargs.get('lookup_details') LOG.info(_LI("Lookup Received: %(lookup_ip)s, %(lookup_details)s"), { 'lookup_ip': lookup_ip, 'lookup_details': lookup_details }) if not lookup_ip or not lookup_details: return self._register_lookup_record(lookup_ip, lookup_details['customer_addr'], lookup_details['mac_addr'], lookup_details['customer_vsid'])
def _port_enable_control_metrics(self): if not self.enable_metrics_collection: return for port_id in self._port_metric_retries.keys(): if self._utils.can_enable_control_metrics(port_id): self._utils.enable_control_metrics(port_id) LOG.info(_LI("Port metrics enabled for port: %s"), port_id) del self._port_metric_retries[port_id] elif self._port_metric_retries[port_id] < 1: self._utils.enable_control_metrics(port_id) LOG.error(_LE("Port metrics raw enabling for port: %s"), port_id) del self._port_metric_retries[port_id] else: self._port_metric_retries[port_id] -= 1
def _port_enable_control_metrics(self): if not self.enable_metrics_collection: return for port_id in list(self._port_metric_retries.keys()): if self._utils.can_enable_control_metrics(port_id): self._utils.enable_control_metrics(port_id) LOG.info(_LI('Port metrics enabled for port: %s'), port_id) del self._port_metric_retries[port_id] elif self._port_metric_retries[port_id] < 1: self._utils.enable_control_metrics(port_id) LOG.error(_LE('Port metrics raw enabling for port: %s'), port_id) del self._port_metric_retries[port_id] else: self._port_metric_retries[port_id] -= 1
def _port_enable_control_metrics(self): if not self.enable_metrics_collection: return for port_id in list(self._port_metric_retries.keys()): if self._utils.is_metrics_collection_allowed(port_id): self._metricsutils.enable_port_metrics_collection(port_id) LOG.info(_LI('Port metrics enabled for port: %s'), port_id) del self._port_metric_retries[port_id] elif self._port_metric_retries[port_id] < 1: self._metricsutils.enable_port_metrics_collection(port_id) LOG.error(_LE('Port metrics raw enabling for port: %s'), port_id) del self._port_metric_retries[port_id] else: self._port_metric_retries[port_id] -= 1
def daemon_loop(self): # init NVGRE after the RPC connection and context is created. self._init_nvgre() sync = True ports = set() while True: try: start = time.time() if sync: LOG.info(_LI("Agent out of sync with plugin!")) ports.clear() sync = False port_info = self._update_ports(ports) # notify plugin about port deltas if port_info: LOG.debug("Agent loop has new devices!") # If treat devices fails - must resync with plugin sync = self._process_network_ports(port_info) ports = port_info['current'] if self._nvgre_enabled: self._nvgre_ops.refresh_nvgre_records() self._port_enable_control_metrics() except Exception: LOG.exception(_LE("Error in agent event loop")) # inconsistent cache might cause exceptions. for example, if a # port has been removed, it will be known in the next loop. # using the old switch port can cause exceptions. self._utils.update_cache() # sleep till end of polling interval elapsed = (time.time() - start) if (elapsed < self._polling_interval): time.sleep(self._polling_interval - elapsed) else: LOG.debug( "Loop iteration exceeded interval " "(%(polling_interval)s vs. %(elapsed)s)", { 'polling_interval': self._polling_interval, 'elapsed': elapsed })
def _treat_devices_removed(self): for device in list(self._removed_ports): LOG.info(_LI("Removing port %s"), device) try: self.plugin_rpc.update_device_down(self.context, device, self.agent_id, self._host) except Exception as e: LOG.debug("Removing port failed for device %(device)s: %(e)s", dict(device=device, e=e)) continue self._port_unbound(device, vnic_deleted=True) self.sec_groups_agent.remove_devices_filter([device]) # if the port unbind was successful, remove the port from removed # set, so it won't be reprocessed. self._removed_ports.discard(device)
def daemon_loop(self): # init NVGRE after the RPC connection and context is created. self._init_nvgre() sync = True ports = set() while True: try: start = time.time() if sync: LOG.info(_LI("Agent out of sync with plugin!")) ports.clear() sync = False port_info = self._update_ports(ports) # notify plugin about port deltas if port_info: LOG.debug("Agent loop has new devices!") # If treat devices fails - must resync with plugin sync = self._process_network_ports(port_info) ports = port_info['current'] if self._nvgre_enabled: self._nvgre_ops.refresh_nvgre_records() self._port_enable_control_metrics() except Exception: LOG.exception(_LE("Error in agent event loop")) # inconsistent cache might cause exceptions. for example, if a # port has been removed, it will be known in the next loop. # using the old switch port can cause exceptions. self._utils.update_cache() # sleep till end of polling interval elapsed = (time.time() - start) if (elapsed < self._polling_interval): time.sleep(self._polling_interval - elapsed) else: LOG.debug("Loop iteration exceeded interval " "(%(polling_interval)s vs. %(elapsed)s)", {'polling_interval': self._polling_interval, 'elapsed': elapsed})
def _setup_trunk(self, trunk, vlan_id=None): """Sets up VLAN trunk and updates the trunk status.""" LOG.info(_LI('Binding trunk port: %s.'), trunk) try: # bind sub_ports to host. self._trunk_rpc.update_subport_bindings(self._context, trunk.sub_ports) vlan_trunk = [s.segmentation_id for s in trunk.sub_ports] self._set_port_vlan(trunk.port_id, vlan_id, vlan_trunk) self._trunk_rpc.update_trunk_status(self._context, trunk.id, t_const.ACTIVE_STATUS) except Exception: # something broke LOG.exception(_LE("Failure setting up subports for %s"), trunk.port_id) self._trunk_rpc.update_trunk_status(self._context, trunk.id, t_const.DEGRADED_STATUS)
def daemon_loop(self): # init NVGRE after the RPC connection and context is created. self._init_nvgre() sync = True ports = set() while True: try: start = time.time() if sync: LOG.info(_LI("Agent out of sync with plugin!")) ports.clear() sync = False port_info = self._update_ports(ports) # notify plugin about port deltas if port_info: LOG.debug("Agent loop has new devices!") # If treat devices fails - must resync with plugin sync = self._process_network_ports(port_info) ports = port_info["current"] if self._nvgre_enabled: self._nvgre_ops.refresh_nvgre_records() self._port_enable_control_metrics() except Exception: LOG.exception(_LE("Error in agent event loop")) # sleep till end of polling interval elapsed = time.time() - start if elapsed < self._polling_interval: time.sleep(self._polling_interval - elapsed) else: LOG.debug( "Loop iteration exceeded interval " "(%(polling_interval)s vs. %(elapsed)s)", {"polling_interval": self._polling_interval, "elapsed": elapsed}, )
def _port_enable_control_metrics(self): if not self.enable_metrics_collection: return for port_id in list(self._port_metric_retries.keys()): try: if self._utils.is_metrics_collection_allowed(port_id): self._metricsutils.enable_port_metrics_collection(port_id) LOG.info(_LI('Port metrics enabled for port: %s'), port_id) del self._port_metric_retries[port_id] elif self._port_metric_retries[port_id] < 1: self._metricsutils.enable_port_metrics_collection(port_id) LOG.error(_LE('Port metrics raw enabling for port: %s'), port_id) del self._port_metric_retries[port_id] else: self._port_metric_retries[port_id] -= 1 except exceptions.NotFound: # the vNIC no longer exists. it might have been removed or # the VM it was attached to was destroyed. LOG.warning(_LW("Port %s no longer exists. Cannot enable " "metrics."), port_id) del self._port_metric_retries[port_id]
def prepare_port_filter(self, port): if not port['port_security_enabled']: LOG.info(_LI('Port %s does not have security enabled. ' 'Skipping rules creation.'), port['id']) return LOG.debug('Creating port %s rules', len(port['security_group_rules'])) # newly created port, add default rules. if port['device'] not in self._security_ports: LOG.debug('Creating default reject rules.') self._sec_group_rules[port['id']] = [] def_sg_rules = self._sg_gen.create_default_sg_rules() self._add_sg_port_rules(port['id'], def_sg_rules) # Add provider rules provider_rules = port['security_group_rules'] self._create_port_rules(port['id'], provider_rules) newrules = self._generate_rules([port]) self._create_port_rules(port['id'], newrules[port['id']]) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = newrules[port['id']]
def bind_nvgre_port(self, segmentation_id, network_name, port_id): mac_addr = self._hyperv_utils.get_vnic_mac_address(port_id) provider_addr = self._nvgre_utils.get_network_iface_ip(network_name)[0] customer_addr = self._n_client.get_port_ip_address(port_id) if not provider_addr or not customer_addr: LOG.warning( _LW('Cannot bind NVGRE port. Could not determine ' 'provider address (%(prov_addr)s) or customer ' 'address (%(cust_addr)s).'), { 'prov_addr': provider_addr, 'cust_addr': customer_addr }) return LOG.info( _LI('Binding VirtualSubnetID %(segmentation_id)s ' 'to switch port %(port_id)s'), dict(segmentation_id=segmentation_id, port_id=port_id)) self._hyperv_utils.set_vswitch_port_vsid(segmentation_id, port_id) # normal lookup record. self._register_lookup_record(provider_addr, customer_addr, mac_addr, segmentation_id) # lookup record for dhcp requests. self._register_lookup_record(self._vswitch_ips[network_name], constants.IPV4_DEFAULT, mac_addr, segmentation_id) LOG.info('Fanning out LookupRecord...') self._notifier.lookup_update( self.context, provider_addr, { 'customer_addr': customer_addr, 'mac_addr': mac_addr, 'customer_vsid': segmentation_id })
def prepare_port_filter(self, port): if not port.get('port_security_enabled'): LOG.info( _LI('Port %s does not have security enabled. ' 'Skipping rules creation.'), port['id']) return LOG.debug('Creating port %s rules', len(port['security_group_rules'])) # newly created port, add default rules. if port['device'] not in self._security_ports: LOG.debug('Creating default reject rules.') self._sec_group_rules[port['id']] = [] def_sg_rules = self._sg_gen.create_default_sg_rules() self._add_sg_port_rules(port['id'], def_sg_rules) # Add provider rules provider_rules = port['security_group_rules'] self._create_port_rules(port['id'], provider_rules) newrules = self._generate_rules([port]) self._create_port_rules(port['id'], newrules[port['id']]) self._security_ports[port['device']] = port self._sec_group_rules[port['id']] = newrules[port['id']]
def remove_port_filter(self, port): LOG.info(_LI('Removing port filter')) self._security_ports.pop(port['device'], None) self._sec_group_rules.pop(port['id'], None) self._utils.clear_port_sg_acls_cache(port['id'])
def remove_port_filter(self, port): LOG.info(_LI('Removing port filter')) self._security_ports.pop(port['device'], None)
def apply_port_filter(self, port): LOG.info(_LI('Aplying port filter.'))
def _process_removed_port_event(self, port_name): LOG.info(_LI("Hyper-V VM vNIC removed: %s"), port_name) self._removed_ports.add(port_name)
def _reclaim_local_network(self, net_uuid): LOG.info(_LI("Reclaiming local network %s"), net_uuid) del self._network_vswitch_map[net_uuid]