def free_ip(self, res_id): neutron = clients.get_neutron_client() try: neutron.delete_floatingip(res_id) except n_exc.NeutronClientException as ex: LOG.error("Failed to delete floating_ip_id =%s !", res_id) raise ex
def release_vif(self, pod, vif): neutron = clients.get_neutron_client() try: container_port = neutron.list_ports( True, device_owner=pod['deviceOnwer']).get('ports')[0] except IndexError: LOG.error("Unable to find port with mac %s.", pod['macAddr']) return port_id = container_port.get('id') container_mac = container_port['mac_address'] container_ips = frozenset(entry['ip_address'] for entry in container_port['fixed_ips']) parent_port_ip = container_port['binding:host_id'] with self.lock: vm_port = self._get_parent_port_for_release( neutron, parent_port_ip) self._remove_from_allowed_address_pairs(neutron, vm_port, container_ips, container_mac) try: neutron.delete_port(port_id) except n_exc.PortNotFoundClient: LOG.warning("Unable to release port %s as it no longer exists.", port_id)
def request_vifs(self, pod, project_id, subnets, security_groups, num_ports): neutron = clients.get_neutron_client() rq = self._get_port_request(pod, project_id, subnets, security_groups, unbound=True) bulk_port_rq = {'ports': [rq for _ in range(num_ports)]} try: ports = neutron.create_port(bulk_port_rq).get('ports') except n_exc.NeutronClientException as ex: LOG.error("Error creating bulk ports: %s", bulk_port_rq) raise ex vif_plugin = self._get_vif_plugin(ports[0]) # NOTE(ltomasbo): Due to the bug (1696051) on neutron bulk port # creation request returning the port objects without binding # information, an additional (non-bulk) port creation is performed to # get the right vif binding information if vif_plugin == 'unbound': single_port = neutron.create_port(rq).get('port') vif_plugin = self._get_vif_plugin(single_port) ports.append(single_port) vifs = [] for port in ports: vif = ovu.neutron_to_osvif_vif(vif_plugin, port, subnets) vifs.append(vif) return vifs
def release_vif(self, pod, vif): neutron = clients.get_neutron_client() try: neutron.delete_port(vif.id) except n_exc.PortNotFoundClient: LOG.debug('Unable to release port %s as it no longer exists.', vif.id)
def request_vif(self, pod, project_id, subnets, security_groups): neutron = clients.get_neutron_client() rq = self._get_port_request(pod, project_id, subnets, security_groups) port = neutron.create_port(rq).get('port') vif_plugin = self._get_vif_plugin(port) return ovu.neutron_to_osvif_vif(vif_plugin, port, subnets)
def _get_in_use_vlan_ids_set(self, trunk_id): vlan_ids = set() neutron = clients.get_neutron_client() trunk = neutron.show_trunk(trunk_id) for port in trunk['trunk']['sub_ports']: vlan_ids.add(port['segmentation_id']) return vlan_ids
def _return_ports_to_pool(self): """Recycle ports to be reused by future pods. For each port in the recyclable_ports dict it reaplies security group if they have been changed and it changes the port name to available_port if the port_debug option is enabled. Then the port_id is included in the dict with the available_ports. If a maximun number of port per pool is set, the port will be deleted if the maximun has been already reached. """ neutron = clients.get_neutron_client() while True: sg_current = {} if not config.CONF.rancher.port_debug: kuryr_ports = self._get_ports_by_attrs( device_owner=kl_const.DEVICE_OWNER) for port in kuryr_ports: if port['id'] in self._recyclable_ports.keys(): sg_current[port['id']] = port['security_groups'] for port_id, pool_key in self._recyclable_ports.copy().items(): if (not oslo_cfg.CONF.vif_pool.ports_pool_max or self._get_pool_size(pool_key) < oslo_cfg.CONF.vif_pool.ports_pool_max): port_name = (constants.KURYR_PORT_NAME if config.CONF.rancher.port_debug else '') if (config.CONF.rancher.port_debug or list(pool_key[2]) != sg_current.get(port_id)): try: neutron.update_port( port_id, { "port": { 'name': port_name, 'device_id': '', 'security_groups': list(pool_key[2]) } }) except n_exc.NeutronClientException: LOG.warning( "Error preparing port %s to be " "reused, put back on the cleanable " "pool.", port_id) continue self._available_ports_pools.setdefault(pool_key, []).append(port_id) else: try: del self._existing_vifs[port_id] neutron.delete_port(port_id) except n_exc.PortNotFoundClient: LOG.debug( 'Unable to release port %s as it no longer ' 'exists.', port_id) except KeyError: LOG.debug('Port %s is not in the ports list.', port_id) del self._recyclable_ports[port_id] eventlet.sleep(oslo_cfg.CONF.vif_pool.ports_pool_update_frequency)
def request_vif(self, pod, project_id, subnets, security_groups): neutron = clients.get_neutron_client() parent_port = self._get_parent_port(neutron, pod) trunk_id = self._get_trunk_id(parent_port) rq = self._get_port_request(pod, project_id, subnets, security_groups) port = neutron.create_port(rq).get('port') vlan_id = self._add_subport(neutron, trunk_id, port['id']) return ovu.neutron_to_osvif_vif_nested_vlan(port, subnets, vlan_id)
def _create_listener(self, listener): neutron = clients.get_neutron_client() response = neutron.create_listener({'listener': { 'name': listener.name, 'project_id': listener.project_id, 'tenant_id': listener.project_id, 'loadbalancer_id': listener.loadbalancer_id, 'protocol': listener.protocol, 'protocol_port': listener.port}}) listener.id = response['listener']['id'] return listener
def release_vif(self, pod, vif): neutron = clients.get_neutron_client() parent_port = self._get_parent_port(neutron, pod) trunk_id = self._get_trunk_id(parent_port) self._remove_subport(neutron, trunk_id, vif.id) self._release_vlan_id(vif.vlan_id) try: neutron.delete_port(vif.id) except n_exc.PortNotFoundClient: LOG.debug('Unable to release port %s as it no longer exists.', vif.id)
def _create_loadbalancer(self, loadbalancer): neutron = clients.get_neutron_client() response = neutron.create_loadbalancer({'loadbalancer': { 'name': loadbalancer.name, 'project_id': loadbalancer.project_id, 'tenant_id': loadbalancer.project_id, 'vip_address': str(loadbalancer.ip), 'vip_subnet_id': loadbalancer.subnet_id}}) loadbalancer.id = response['loadbalancer']['id'] loadbalancer.port_id = self._get_vip_port_id(loadbalancer) return loadbalancer
def _create_member(self, member): neutron = clients.get_neutron_client() response = neutron.create_lbaas_member(member.pool_id, {'member': { 'name': member.name, 'project_id': member.project_id, 'tenant_id': member.project_id, 'subnet_id': member.subnet_id, 'address': str(member.ip), 'protocol_port': member.port}}) member.id = response['member']['id'] return member
def activate_vif(self, pod, vif): if vif.active: return neutron = clients.get_neutron_client() port = neutron.show_port(vif.id).get('port') if port['status'] != kl_const.PORT_STATUS_ACTIVE: raise k_exc.ResourceNotReady(vif) vif.active = True
def _get_subnet(subnet_id): # TODO(ivc): add caching (e.g. oslo.cache with dict backend) neutron = clients.get_neutron_client() n_subnet = neutron.show_subnet(subnet_id).get('subnet') network_id = n_subnet['network_id'] n_network = neutron.show_network(network_id).get('network') subnet = os_vif_util.neutron_to_osvif_subnet(n_subnet) network = os_vif_util.neutron_to_osvif_network(n_network) network.subnets.objects.append(subnet) return network
def _update(self, res_id, vip_port_id): response = None neutron = clients.get_neutron_client() try: response = neutron.update_floatingip( res_id, {'floatingip': { 'port_id': vip_port_id, }}) except n_exc.NeutronClientException as ex: LOG.error( "Failed to update_floatingip ,floating_ip_id=%s," "response=%s!", res_id, response) raise ex
def _get_vip_port_id(self, loadbalancer): neutron = clients.get_neutron_client() try: fixed_ips = ['subnet_id=%s' % str(loadbalancer.subnet_id), 'ip_address=%s' % str(loadbalancer.ip)] ports = neutron.list_ports(fixed_ips=fixed_ips) except n_exc.NeutronClientException as ex: LOG.error("Port with fixed ips %s not found!", fixed_ips) raise ex if ports['ports']: return ports['ports'][0].get("id") return None
def request_vif(self, pod, project_id, subnets, security_groups): neutron = clients.get_neutron_client() req = self._get_port_request(pod, project_id, subnets, security_groups) container_port = neutron.create_port(req).get('port') container_mac = container_port['mac_address'] container_ips = frozenset(entry['ip_address'] for entry in container_port['fixed_ips']) with self.lock: vm_port = self._get_parent_port_for_request(neutron, pod) self._add_to_allowed_address_pairs(neutron, vm_port, container_ips, container_mac) return ovu.neutron_to_osvif_vif_nested_macvlan(container_port, subnets)
def test_setup_clients(self, m_neutron, m_k8s, m_cfg): k8s_api_root = 'http://127.0.0.1:1234' neutron_dummy = object() k8s_dummy = object() m_cfg.kubernetes.api_root = k8s_api_root m_neutron.return_value = neutron_dummy m_k8s.return_value = k8s_dummy clients.setup_clients() m_k8s.assert_called_with(k8s_api_root) self.assertIs(k8s_dummy, clients.get_kubernetes_client()) self.assertIs(neutron_dummy, clients.get_neutron_client())
def _get_port_from_pool(self, pool_key, pod, subnets): try: port_id = self._available_ports_pools[pool_key].pop() except IndexError: raise exceptions.ResourceNotReady(pod) if config.CONF.rancher.port_debug: neutron = clients.get_neutron_client() neutron.update_port(port_id, {"port": { 'name': pod['name'], }}) # check if the pool needs to be populated if (self._get_pool_size(pool_key) < oslo_cfg.CONF.vif_pool.ports_pool_min): eventlet.spawn(self._populate_pool, pool_key, pod, subnets) return self._existing_vifs[port_id]
def acquire_service_pub_ip_info(self, spec_type, spec_lb_ip, project_id): if spec_type != 'LoadBalancer': return None if spec_lb_ip: user_specified_ip = spec_lb_ip.format() res_id = self._drv_pub_ip.is_ip_available(user_specified_ip) if res_id: service_pub_ip_info = (obj_lbaas.LBaaSPubIp( ip_id=res_id, ip_addr=str(user_specified_ip), alloc_method='user')) return service_pub_ip_info else: # user specified IP is not valid LOG.error("IP=%s is not available", user_specified_ip) return None else: LOG.debug("Trying to allocate public ip from pool") # get public subnet id from kuryr.conf external_svc_subnet = config.CONF.neutron_defaults.external_svc_subnet if not external_svc_subnet: raise cfg.RequiredOptError('external_svc_subnet', cfg.OptGroup('neutron_defaults')) neutron = clients.get_neutron_client() n_subnet = neutron.show_subnet(external_svc_subnet).get('subnet') if not n_subnet: LOG.error( "No subnet found for external_svc_subnet=%s", external_svc_subnet) raise kl_exc.NoResourceException public_network_id = n_subnet['network_id'] res_id, alloc_ip_addr = (self._drv_pub_ip.allocate_ip (public_network_id, external_svc_subnet, project_id, 'kuryr_lb')) service_pub_ip_info = obj_lbaas.LBaaSPubIp(ip_id=res_id, ip_addr=alloc_ip_addr, alloc_method='pool') return service_pub_ip_info
def is_ip_available(self, ip_addr): if ip_addr: neutron = clients.get_neutron_client() floating_ips_list = neutron.list_floatingips( floating_ip_address=ip_addr) for entry in floating_ips_list['floatingips']: if not entry: continue if (entry['floating_ip_address'] == ip_addr and not entry['port_id']): return entry['id'] # floating IP not available LOG.error("Floating IP=%s not available", ip_addr) else: LOG.error("Invalid parameter ip_addr=%s", ip_addr) return None
def _find_loadbalancer(self, loadbalancer): neutron = clients.get_neutron_client() response = neutron.list_loadbalancers( name=loadbalancer.name, project_id=loadbalancer.project_id, tenant_id=loadbalancer.project_id, vip_address=str(loadbalancer.ip), vip_subnet_id=loadbalancer.subnet_id) try: loadbalancer.id = response['loadbalancers'][0]['id'] loadbalancer.port_id = self._get_vip_port_id(loadbalancer) except (KeyError, IndexError): return None return loadbalancer
def _find_listener(self, listener): neutron = clients.get_neutron_client() response = neutron.list_listeners( name=listener.name, project_id=listener.project_id, tenant_id=listener.project_id, loadbalancer_id=listener.loadbalancer_id, protocol=listener.protocol, protocol_port=listener.port) try: listener.id = response['listeners'][0]['id'] except (KeyError, IndexError): return None return listener
def _find_pool(self, pool): neutron = clients.get_neutron_client() response = neutron.list_lbaas_pools( name=pool.name, project_id=pool.project_id, tenant_id=pool.project_id, loadbalancer_id=pool.loadbalancer_id, protocol=pool.protocol) try: pools = [p for p in response['pools'] if pool.listener_id in {l['id'] for l in p['listeners']}] pool.id = pools[0]['id'] except (KeyError, IndexError): return None return pool
def _find_member(self, member): neutron = clients.get_neutron_client() response = neutron.list_lbaas_members( member.pool_id, name=member.name, project_id=member.project_id, tenant_id=member.project_id, subnet_id=member.subnet_id, address=member.ip, protocol_port=member.port) try: member.id = response['members'][0]['id'] except (KeyError, IndexError): return None return member
def _wait_for_provisioning(self, loadbalancer, timeout): neutron = clients.get_neutron_client() for remaining in self._provisioning_timer(timeout): response = neutron.show_loadbalancer(loadbalancer.id) status = response['loadbalancer']['provisioning_status'] if status == 'ACTIVE': LOG.debug("Provisioning complete for %(lb)s", { 'lb': loadbalancer}) return else: LOG.debug("Provisioning status %(status)s for %(lb)s, " "%(rem).3gs remaining until timeout", {'status': status, 'lb': loadbalancer, 'rem': remaining}) raise k_exc.ResourceNotReady(loadbalancer)
def _create_pool(self, pool): # TODO(ivc): make lb_algorithm configurable lb_algorithm = 'ROUND_ROBIN' neutron = clients.get_neutron_client() try: response = neutron.create_lbaas_pool({'pool': { 'name': pool.name, 'project_id': pool.project_id, 'tenant_id': pool.project_id, 'listener_id': pool.listener_id, 'loadbalancer_id': pool.loadbalancer_id, 'protocol': pool.protocol, 'lb_algorithm': lb_algorithm}}) pool.id = response['pool']['id'] return pool except n_exc.StateInvalidClient: with excutils.save_and_reraise_exception(): self._cleanup_bogus_pool(neutron, pool, lb_algorithm)
def allocate_ip(self, pub_net_id, pub_subnet_id, project_id, description): neutron = clients.get_neutron_client() try: response = neutron.create_floatingip({ 'floatingip': { 'tenant_id': project_id, 'project_id': project_id, 'floating_network_id': pub_net_id, 'subnet_id': pub_subnet_id, 'description': description } }) except n_exc.NeutronClientException as ex: LOG.error("Failed to create floating IP - subnetid=%s ", pub_subnet_id) raise ex return response['floatingip']['id'], response['floatingip'][ 'floating_ip_address']
def request_vifs(self, pod, project_id, subnets, security_groups, num_ports, trunk_ip=None): """This method creates subports and returns a list with their vifs. It creates up to num_ports subports and attaches them to the trunk port. If not enough vlan ids are available for all the subports to create, it creates as much as available vlan ids. Note the neutron trunk_add_subports is an atomic operation that will either attach all or none of the subports. Therefore, if there is a vlan id collision, all the created ports will be deleted and the exception is raised. """ neutron = clients.get_neutron_client() if trunk_ip: parent_port = self._get_parent_port_by_host_ip(neutron, trunk_ip) else: parent_port = self._get_parent_port(neutron, pod) trunk_id = self._get_trunk_id(parent_port) port_rq, subports_info = self._create_subports_info(pod, project_id, subnets, security_groups, trunk_id, num_ports, unbound=True) if not subports_info: LOG.error("There are no vlan ids available to create subports") return [] bulk_port_rq = {'ports': [port_rq for _ in range(len(subports_info))]} try: ports = neutron.create_port(bulk_port_rq).get('ports') except n_exc.NeutronClientException as ex: LOG.error("Error creating bulk ports: %s", bulk_port_rq) raise ex for index, port in enumerate(ports): subports_info[index]['port_id'] = port['id'] try: try: neutron.trunk_add_subports(trunk_id, {'sub_ports': subports_info}) except n_exc.Conflict as ex: LOG.error("vlan ids already in use on trunk") for port in ports: neutron.delete_port(port['id']) raise ex except n_exc.NeutronClientException as ex: LOG.error("Error happened during subport addition to trunk") raise ex vifs = [] for index, port in enumerate(ports): vlan_id = subports_info[index]['segmentation_id'] vif = ovu.neutron_to_osvif_vif_nested_vlan(port, subnets, vlan_id) vifs.append(vif) return vifs
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.rancher.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'])