Ejemplo n.º 1
0
    def _recover_precreated_ports(self):
        if config.CONF.kubernetes.port_debug:
            available_ports = self._get_ports_by_attrs(
                name=constants.KURYR_PORT_NAME,
                device_owner=[kl_const.DEVICE_OWNER])
        else:
            kuryr_ports = self._get_ports_by_attrs(
                device_owner=kl_const.DEVICE_OWNER)
            in_use_ports = self._get_in_use_ports()
            available_ports = [
                port for port in kuryr_ports if port['id'] not in in_use_ports
            ]

        for port in available_ports:
            subnet_id = port['fixed_ips'][0]['subnet_id']
            subnet = {subnet_id: default_subnet._get_subnet(subnet_id)}
            vif_plugin = self._drv_vif._get_vif_plugin(port)
            vif = ovu.neutron_to_osvif_vif(vif_plugin, port, subnet)
            net_obj = subnet[subnet_id]
            pool_key = self._get_pool_key(port['binding:host_id'],
                                          port['project_id'],
                                          port['security_groups'], net_obj.id,
                                          None)

            self._existing_vifs[port['id']] = vif
            self._available_ports_pools.setdefault(pool_key,
                                                   []).append(port['id'])

        LOG.info("PORTS POOL: pools updated with pre-created ports")
        self._create_healthcheck_file()
    def test_get_subnet(self, m_osv_subnet, m_osv_network):
        neutron = self.useFixture(k_fix.MockNeutronClient()).client

        subnet = mock.MagicMock()
        network = mock.MagicMock()
        subnet_id = mock.sentinel.subnet_id
        network_id = mock.sentinel.network_id

        neutron_subnet = {'network_id': network_id}
        neutron_network = mock.sentinel.neutron_network

        neutron.show_subnet.return_value = {'subnet': neutron_subnet}
        neutron.show_network.return_value = {'network': neutron_network}

        m_osv_subnet.return_value = subnet
        m_osv_network.return_value = network

        ret = default_subnet._get_subnet(subnet_id)

        self.assertEqual(network, ret)
        neutron.show_subnet.assert_called_once_with(subnet_id)
        neutron.show_network.assert_called_once_with(network_id)
        m_osv_subnet.assert_called_once_with(neutron_subnet)
        m_osv_network.assert_called_once_with(neutron_network)
        network.subnets.objects.append.assert_called_once_with(subnet)
Ejemplo n.º 3
0
    def _recover_precreated_ports(self):
        neutron = clients.get_neutron_client()
        available_ports = self._get_ports_by_attrs(
            name='available-port', device_owner='trunk:subport')

        if not available_ports:
            return

        trunk_ports = neutron.list_trunks().get('trunks')
        for trunk in trunk_ports:
            try:
                host_addr = self._get_parent_port_ip(trunk['port_id'])
            except n_exc.PortNotFoundClient:
                LOG.debug('Unable to find parent port for trunk port %s.',
                          trunk['port_id'])
                continue

            for subport in trunk.get('sub_ports'):
                kuryr_subport = None
                for port in available_ports:
                    if port['id'] == subport['port_id']:
                        kuryr_subport = port
                        break

                if kuryr_subport:
                    pool_key = (host_addr, kuryr_subport['project_id'],
                                tuple(kuryr_subport['security_groups']))
                    subnet_id = kuryr_subport['fixed_ips'][0]['subnet_id']
                    subnet = {subnet_id: default_subnet._get_subnet(subnet_id)}
                    vif = ovu.neutron_to_osvif_vif_nested_vlan(
                        kuryr_subport, subnet, subport['segmentation_id'])

                    self._existing_vifs[subport['port_id']] = vif
                    self._available_ports_pools.setdefault(
                        pool_key, []).append(subport['port_id'])
Ejemplo n.º 4
0
    def _get_trunks_info(self):
        """Returns information about trunks and their subports.

        This method searches for parent ports and subports among the active
        neutron ports.
        To find the parent ports it filters the ones that have trunk_details,
        i.e., the ones that are the parent port of a trunk.
        To find the subports to recover, it filters out the ports that are
        already in used by running kubernetes pods. It also filters out the
        ports whose device_owner is not related to subports, i.e., the ports
        that are not attached to trunks, such as active ports allocated to
        running VMs.
        At the same time it collects information about ports subnets to
        minimize the number of interaction with Neutron API.

        It returns three dictionaries with the needed information about the
        parent ports, subports and subnets

        :return: 3 dicts with the trunk details (Key: trunk_id; Value: dict
        containing ip and subports), subport details (Key: port_id; Value:
        port_object), and subnet details (Key: subnet_id; Value: subnet dict)
        """
        # REVISIT(ltomasbo): there is no need to recover the subports
        # belonging to trunk ports whose parent port is DOWN as that means no
        # pods can be scheduled there. We may need to update this if we allow
        # lively extending the kubernetes cluster with VMs that already have
        # precreated subports. For instance by shutting down and up a
        # kubernetes Worker VM with subports already attached, and the
        # controller is restarted in between.
        parent_ports = {}
        subports = {}
        subnets = {}

        all_active_ports = self._get_ports_by_attrs(status='ACTIVE')
        in_use_ports = self._get_in_use_ports()

        for port in all_active_ports:
            trunk_details = port.get('trunk_details')
            # Parent port
            if trunk_details:
                parent_ports[trunk_details['trunk_id']] = {
                    'ip': port['fixed_ips'][0]['ip_address'],
                    'subports': trunk_details['sub_ports']
                }
            else:
                # Filter to only get subports that are not in use
                if (port['id'] not in in_use_ports and port['device_owner']
                        in ['trunk:subport', kl_const.DEVICE_OWNER]):
                    subports[port['id']] = port
                    # NOTE(ltomasbo): _get_subnet can be costly as it
                    # needs to call neutron to get network and subnet
                    # information. This ensures it is only called once
                    # per subnet in use
                    subnet_id = port['fixed_ips'][0]['subnet_id']
                    if not subnets.get(subnet_id):
                        subnets[subnet_id] = {
                            subnet_id: default_subnet._get_subnet(subnet_id)
                        }
        return parent_ports, subports, subnets
Ejemplo n.º 5
0
    def get_subnets(self, pod, project_id):
        pod_namespace = pod['metadata']['namespace']
        subnet_id = self._get_namespace_subnet(pod_namespace)

        return {subnet_id: default_subnet._get_subnet(subnet_id)}
Ejemplo n.º 6
0
    def _precreated_ports(self, action, trunk_ips=None):
        """Removes or recovers pre-created subports at given pools

        This function handles the pre-created ports based on the given action:
        - If action is `free` it will remove all the subport from the given
        trunk ports, or from all the trunk ports if no trunk_ips are passed.
        - If action is `recover` it will discover the existing subports in the
        given trunk ports (or in all of them if none are passed) and will add
        them (and the needed information) to the respective pools.
        """
        neutron = clients.get_neutron_client()
        # Note(ltomasbo): ML2/OVS changes the device_owner to trunk:subport
        # when a port is attached to a trunk. However, that is not the case
        # for other ML2 drivers, such as ODL. So we also need to look for
        # compute:kuryr
        if config.CONF.kubernetes.port_debug:
            available_ports = self._get_ports_by_attrs(
                name=constants.KURYR_PORT_NAME, device_owner=[
                    'trunk:subport', kl_const.DEVICE_OWNER])
        else:
            kuryr_subports = self._get_ports_by_attrs(
                device_owner=['trunk:subport', kl_const.DEVICE_OWNER])
            in_use_ports = self._get_in_use_ports()
            available_ports = [subport for subport in kuryr_subports
                               if subport['id'] not in in_use_ports]

        if not available_ports:
            return

        trunk_ports = neutron.list_trunks().get('trunks')
        for trunk in trunk_ports:
            try:
                host_addr = self._get_parent_port_ip(trunk['port_id'])
            except n_exc.PortNotFoundClient:
                LOG.debug('Unable to find parent port for trunk port %s.',
                          trunk['port_id'])
                continue

            if trunk_ips and host_addr not in trunk_ips:
                continue

            for subport in trunk.get('sub_ports'):
                kuryr_subport = None
                for port in available_ports:
                    if port['id'] == subport['port_id']:
                        kuryr_subport = port
                        break

                if kuryr_subport:
                    pool_key = (host_addr, kuryr_subport['project_id'],
                                tuple(kuryr_subport['security_groups']))

                    if action == 'recover':
                        subnet_id = kuryr_subport['fixed_ips'][0]['subnet_id']
                        subnet = {
                            subnet_id: default_subnet._get_subnet(subnet_id)}
                        vif = ovu.neutron_to_osvif_vif_nested_vlan(
                            kuryr_subport, subnet, subport['segmentation_id'])

                        self._existing_vifs[subport['port_id']] = vif
                        self._available_ports_pools.setdefault(
                            pool_key, []).append(subport['port_id'])
                    elif action == 'free':
                        try:
                            self._drv_vif._remove_subport(neutron, trunk['id'],
                                                          subport['port_id'])
                            neutron.delete_port(subport['port_id'])
                            self._drv_vif._release_vlan_id(
                                subport['segmentation_id'])
                            del self._existing_vifs[subport['port_id']]
                            self._available_ports_pools[pool_key].remove(
                                subport['port_id'])
                        except n_exc.PortNotFoundClient:
                            LOG.debug('Unable to release port %s as it no '
                                      'longer exists.', subport['port_id'])
                        except KeyError:
                            LOG.debug('Port %s is not in the ports list.',
                                      subport['port_id'])
                        except n_exc.NeutronClientException:
                            LOG.warning('Error removing the subport %s',
                                        subport['port_id'])
                        except ValueError:
                            LOG.debug('Port %s is not in the available ports '
                                      'pool.', subport['port_id'])