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
예제 #2
0
    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})
예제 #10
0
    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)
예제 #11
0
    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 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 _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
예제 #15
0
    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
예제 #17
0
    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
예제 #18
0
    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
예제 #19
0
    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})
예제 #20
0
 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
예제 #21
0
 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
예제 #22
0
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()
예제 #23
0
    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)
예제 #24
0
    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)
예제 #26
0
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()
예제 #27
0
    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)
예제 #28
0
    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)
예제 #29
0
    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)
예제 #30
0
    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
예제 #34
0
    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)
예제 #37
0
 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 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']]
예제 #39
0
    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
예제 #41
0
    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
예제 #43
0
    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
                    })
예제 #44
0
    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 _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 _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},
                )
예제 #49
0
    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 _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']]
예제 #52
0
    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 apply_port_filter(self, port):
     LOG.info(_LI('Aplying port filter.'))
 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 _reclaim_local_network(self, net_uuid):
     LOG.info(_LI("Reclaiming local network %s"), net_uuid)
     del self._network_vswitch_map[net_uuid]