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)
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'])
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
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)}
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'])