def _unbind_port(self, port_id): port_req_body = {'port': {'device_id': '', 'device_owner': ''}} port_req_body['port'][BINDING_HOST_ID] = None try: port = self.neutron_api.get_neutron_port(port_id) except exception.PortNotFound: LOG.debug('Unable to show port %s as it no longer ' 'exists.', port_id) return except Exception: # NOTE: In case we can't retrieve the binding:profile assume # that they are empty LOG.exception("Unable to get binding:profile for port '%s'", port_id) port_profile = {} else: port_profile = port.get(BINDING_PROFILE, {}) # NOTE: We're doing this to remove the binding information # for the physical device but don't want to overwrite the other # information in the binding profile. for profile_key in ('pci_vendor_info', 'pci_slot'): if profile_key in port_profile: del port_profile[profile_key] port_req_body['port'][BINDING_PROFILE] = port_profile try: # Requires admin creds to set port bindings admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) neutron_api.update_port(port_id, port_req_body) except exception.PortNotFound: LOG.debug('Unable to unbind port %s as it no longer ' 'exists.', port_id) except Exception: LOG.exception("Unable to clear device ID for port '%s'", port_id)
def _get_subnetpool(self, subnet): # NOTE(kiennt): Elevate admin privilege to list all subnetpools # across projects. admin_context = self.neutron_api.context.elevated() neutron_api = neutron.NeutronAPI(admin_context) subnetpool_id = subnet.get('subnetpool_id') if self._check_valid_subnetpool(neutron_api, subnetpool_id, subnet['cidr']): return subnetpool_id # NOTE(kiennt): Subnetpool which was created by Kuryr-libnetwork # will be tagged with subnet_id. kwargs = { 'tags': [subnet['id']], } subnetpools = \ neutron_api.list_subnetpools(**kwargs).get('subnetpools', []) if not subnetpools: return None elif len(subnetpools) > 1: raise exception.ZunException( _('Multiple Neutron subnetpools exist with prefixes %s'), subnet['cidr']) else: return subnetpools[0]['id']
def do_port_cleanup(self, addresses, port): preserve_flag = addresses[0].get('preserve_on_delete') port_id = port.get('id') if preserve_flag: port_req_body = {'port': {'device_id': '', 'device_owner': ''}} port_req_body['port'][BINDING_HOST_ID] = None port_req_body['port']['mac_address'] = port.get('mac_address') port_req_body['port'][BINDING_PROFILE] = \ port.get(BINDING_PROFILE, {}) try: # Requires admin creds to set port bindings admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) neutron_api.update_port(port_id, port_req_body) except exception.PortNotFound: LOG.debug( 'Unable to unbind port %s as it no longer ' 'exists.', port_id) except Exception: LOG.exception("Unable to clear device ID for port '%s'", port_id) else: try: self.neutron_api.delete_port(port_id) except exception.PortNotFound: LOG.debug( 'Unable to delete port %s as it no longer ' 'exists.', port_id)
def init(self, context, docker_api): self.docker = docker_api self.neutron_api = neutron.NeutronAPI(context) self.context = context self.pci_whitelist = pci_whitelist.Whitelist( CONF.pci.passthrough_whitelist) self.last_neutron_extension_sync = None self.extensions = {}
def build_requested_networks(context, nets): """Build requested networks by calling neutron client :param nets: The special network uuid when create container if none, will call neutron to create new network. :returns: available network and ports """ neutron_api = neutron.NeutronAPI(context) requested_networks = [] for net in nets: if net.get('port'): port = neutron_api.get_neutron_port(net['port']) neutron_api.ensure_neutron_port_usable(port) network = neutron_api.get_neutron_network(port['network_id']) requested_networks.append({ 'network': port['network_id'], 'port': port['id'], 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'fixed_ip': '', 'preserve_on_delete': True }) elif net.get('network'): network = neutron_api.get_neutron_network(net['network']) requested_networks.append({ 'network': network['id'], 'port': '', 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'fixed_ip': net.get('fixed_ip') or net.get('v4-fixed-ip', '') or net.get('v6-fixed-ip', ''), 'preserve_on_delete': False }) if not requested_networks: # Find an available neutron net and create docker network by # wrapping the neutron net. neutron_net = neutron_api.get_available_network() requested_networks.append({ 'network': neutron_net['id'], 'port': '', 'fixed_ip': '', 'preserve_on_delete': False }) check_external_network_attach(context, requested_networks) return requested_networks
def _build_requested_networks(self, context, nets): neutron_api = neutron.NeutronAPI(context) requested_networks = [] for net in nets: if net.get('port'): port = neutron_api.get_neutron_port(net['port']) neutron_api.ensure_neutron_port_usable(port) network = neutron_api.get_neutron_network(port['network_id']) requested_networks.append({ 'network': port['network_id'], 'port': port['id'], 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'preserve_on_delete': True }) elif net.get('network'): network = neutron_api.get_neutron_network(net['network']) requested_networks.append({ 'network': network['id'], 'port': '', 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'v4-fixed-ip': net.get('v4-fixed-ip', ''), 'v6-fixed-ip': net.get('v6-fixed-ip', ''), 'preserve_on_delete': False }) if not requested_networks: # Find an available neutron net and create docker network by # wrapping the neutron net. neutron_net = neutron_api.get_available_network() requested_networks.append({ 'network': neutron_net['id'], 'port': '', 'v4-fixed-ip': '', 'v6-fixed-ip': '', 'preserve_on_delete': False }) self._check_external_network_attach(context, requested_networks) return requested_networks
def __init__(self, worker_id, registry): super(CNIDaemonWatcherService, self).__init__(worker_id) self.registry = registry self.host = CONF.host self.context = zun_context.get_admin_context(all_projects=True) self.neutron_api = neutron.NeutronAPI(self.context) self.periodic = periodics.PeriodicWorker.create( [], executor_factory=lambda: futures.ThreadPoolExecutor(max_workers=1))
def _get_phynet_info(self, context, net_id): # NOTE(hongbin): Use admin context here because non-admin users are # unable to retrieve provider:* attributes. admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) network = neutron_api.show_network(net_id, fields='provider:physical_network') net = network.get('network') phynet_name = net.get('provider:physical_network') return phynet_name
def network_detach(self, container_id, **kwargs): container = _get_container(container_id) check_policy_on_container(container.as_dict(), "container:network_detach") context = pecan.request.context compute_api = pecan.request.compute_api neutron_api = neutron.NeutronAPI(context) neutron_net = neutron_api.get_neutron_network(kwargs.get('network')) compute_api.network_detach(context, container, neutron_net['id']) pecan.response.status = 202
def network_attach(self, container_ident, **kwargs): """Attach a network to the container. :param container_ident: UUID or Name of a container. """ container = utils.get_container(container_ident) check_policy_on_container(container.as_dict(), "container:network_attach") context = pecan.request.context compute_api = pecan.request.compute_api neutron_api = neutron.NeutronAPI(context) neutron_net = neutron_api.get_neutron_network(kwargs.get('network')) compute_api.network_attach(context, container, neutron_net['id'])
def _delete_neutron_ports(self, context, capsule): if not capsule.addresses: return neutron_ports = set() all_ports = set() for net_uuid, addrs_list in capsule.addresses.items(): for addr in addrs_list: all_ports.add(addr['port']) if not addr['preserve_on_delete']: port_id = addr['port'] neutron_ports.add(port_id) neutron_api = neutron.NeutronAPI(context) neutron_api.delete_or_unbind_ports(all_ports, neutron_ports)
def _show_port(self, context, port_id, neutron_client=None, fields=None): """Return the port for the client given the port id. :param context: Request context. :param port_id: The id of port to be queried. :param neutron_client: A neutron client. :param fields: The condition fields to query port data. :returns: A dict of port data. e.g. {'port_id': 'abcd', 'fixed_ip_address': '1.2.3.4'} """ if not neutron_client: neutron_client = neutron.NeutronAPI(context) if fields: result = neutron_client.show_port(port_id, fields=fields) else: result = neutron_client.show_port(port_id) return result.get('port')
def _check_security_group(self, context, security_group): neutron_api = neutron.NeutronAPI(context) try: return neutron_api.find_resourceid_by_name_or_id( 'security_group', security_group['name'], context.project_id) except n_exc.NeutronClientNoUniqueMatch as e: msg = _("Multiple security group matches found for name " "%(name)s, use an ID to be more specific.") % { 'name': security_group['name']} raise exception.Conflict(msg) except n_exc.NeutronClientException as e: if e.status_code == 404: msg = _("Security group %(name)s not found.") % { 'name': security_group['name']} raise exception.InvalidValue(msg) else: raise
def network_detach(self, container_ident, **kwargs): """Detach a network from the container. :param container_ident: UUID or Name of a container. """ container = utils.get_container(container_ident) check_policy_on_container(container.as_dict(), "container:network_detach") context = pecan.request.context compute_api = pecan.request.compute_api neutron_api = neutron.NeutronAPI(context) if kwargs.get('port'): port = neutron_api.get_neutron_port(kwargs['port']) net_id = port['network_id'] else: network = neutron_api.get_neutron_network(kwargs.get('network')) net_id = network['id'] compute_api.network_detach(context, container, net_id) pecan.response.status = 202
def process_networking_config(self, container, requested_network, host_config, container_kwargs, docker, security_group_ids=None): network_id = requested_network['network'] addresses, port = self.neutron_api.create_or_update_port( container, network_id, requested_network, consts.DEVICE_OWNER_ZUN, security_group_ids, set_binding_host=True) container.addresses = {network_id: addresses} admin_neutron_api = neutron.NeutronAPI(zun_context.get_admin_context()) network = admin_neutron_api.show_network(port['network_id'])['network'] subnets = {} for fixed_ip in port['fixed_ips']: subnet_id = fixed_ip['subnet_id'] subnets[subnet_id] = \ admin_neutron_api.show_subnet(subnet_id)['subnet'] vif_plugin = port.get('binding:vif_type') vif_obj = os_vif_util.neutron_to_osvif_vif(vif_plugin, port, network, subnets) state = objects.vif.VIFState(default_vif=vif_obj) state_dict = state.obj_to_primitive() container.cni_metadata = {consts.CNI_METADATA_VIF: state_dict} container.save(self.context) host_config['network_mode'] = 'none' container_kwargs['mac_address'] = port['mac_address'] # We manipulate entrypoint and command parameters in here. token = (container.entrypoint or []) + (container.command or []) new_command = ZUN_INIT + ' '.join(shlex.quote(t) for t in token) new_entrypoint = ['/bin/sh', '-c'] container_kwargs['entrypoint'] = new_entrypoint container_kwargs['command'] = [new_command]
def add_security_groups_to_ports(self, container, security_group_ids): container_id = container.get_sandbox_id() if not container_id: container_id = container.container_id port_ids = set() for addrs_list in container.addresses.values(): for addr in addrs_list: port_id = addr['port'] port_ids.add(port_id) search_opts = {'tenant_id': self.context.project_id} neutron_ports = self.neutron_api.list_ports(**search_opts).get( 'ports', []) neutron_ports = [p for p in neutron_ports if p['id'] in port_ids] for port in neutron_ports: if 'security_groups' not in port: port['security_groups'] = [] port['security_groups'].extend(security_group_ids) updated_port = {'security_groups': port['security_groups']} try: LOG.info( "Adding security group %(security_group_ids)s " "to port %(port_id)s", { 'security_group_ids': security_group_ids, 'port_id': port['id'] }) admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) neutron_api.update_port(port['id'], {'port': updated_port}) except exceptions.NeutronClientException as e: exc_info = sys.exc_info() if e.status_code == 400: raise exception.SecurityGroupCannotBeApplied( six.text_type(e)) else: six.reraise(*exc_info) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Neutron Error:")
def _build_requested_networks(self, context, nets): #LOG.debug('_build_requested_networks xxx context=%s,nets=%s' % (context.to_dict(), nets)) neutron_api = neutron.NeutronAPI(context) requested_networks = [] for net in nets: if net.get('port'): port = neutron_api.get_neutron_port(net['port']) neutron_api.ensure_neutron_port_usable(port) network = neutron_api.get_neutron_network(port['network_id']) requested_networks.append({'network': port['network_id'], 'port': port['id'], 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'v4-fixed-ip': '', 'v6-fixed-ip': ''}) elif net.get('network'): network = neutron_api.get_neutron_network(net['network']) requested_networks.append({'network': network['id'], 'port': '', 'router:external': network.get('router:external'), 'shared': network.get('shared'), 'v4-fixed-ip': '', 'v6-fixed-ip': ''}) #LOG.debug('_build_requested_networks xxx requested_networks=%s' % (requested_networks)) if not requested_networks: # Find an available neutron net and create docker network by # wrapping the neutron net. neutron_net = neutron_api.get_available_network() requested_networks.append({'network': neutron_net['id'], 'port': '', 'v4-fixed-ip': '', 'v6-fixed-ip': ''}) self._check_external_network_attach(context, requested_networks) return requested_networks
def init(self, context, docker_api): self.docker = docker_api self.neutron_api = neutron.NeutronAPI(context) self.context = context
def create_or_update_port(self, container, network_name, requested_network, security_groups=None): if requested_network.get('port'): neutron_port_id = requested_network.get('port') neutron_port = self.neutron_api.get_neutron_port(neutron_port_id) # update device_id in port port_req_body = {'port': {'device_id': container.uuid}} self.neutron_api.update_port(neutron_port_id, port_req_body) # If there is pci_request_id, it should be a sriov port. # populate pci related info. pci_request_id = requested_network.get('pci_request_id') if pci_request_id: self._populate_neutron_extension_values( container, pci_request_id, port_req_body) self._populate_pci_mac_address(container, pci_request_id, port_req_body) # NOTE(hongbin): Use admin context here because non-admin # context might not be able to update some attributes # (i.e. binding:profile). admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) neutron_api.update_port(neutron_port_id, port_req_body) else: network = self.inspect_network(network_name) neutron_net_id = network['Options']['neutron.net.uuid'] port_dict = { 'network_id': neutron_net_id, 'tenant_id': self.context.project_id, 'device_id': container.uuid, } ip_addr = requested_network.get("fixed_ip") if ip_addr: port_dict['fixed_ips'] = [{'ip_address': ip_addr}] if security_groups is not None: port_dict['security_groups'] = security_groups neutron_port = self.neutron_api.create_port({'port': port_dict}) neutron_port = neutron_port['port'] preserve_on_delete = requested_network['preserve_on_delete'] addresses = [] for fixed_ip in neutron_port['fixed_ips']: ip_address = fixed_ip['ip_address'] ip = ipaddress.ip_address(six.text_type(ip_address)) if ip.version == 4: addresses.append({ 'addr': ip_address, 'version': 4, 'port': neutron_port['id'], 'subnet_id': fixed_ip['subnet_id'], 'preserve_on_delete': preserve_on_delete }) else: addresses.append({ 'addr': ip_address, 'version': 6, 'port': neutron_port['id'], 'subnet_id': fixed_ip['subnet_id'], 'preserve_on_delete': preserve_on_delete }) return addresses, neutron_port
def create_or_update_port(self, container, network_name, requested_network, security_groups=None): if requested_network.get('port'): neutron_port_id = requested_network.get('port') neutron_port = self.neutron_api.get_neutron_port(neutron_port_id) # NOTE(hongbin): If existing port is specified, security_group_ids # is ignored because existing port already has security groups. # We might revisit this behaviour later. Alternatively, we could # either throw an exception or overwrite the port's security # groups. if not container.security_groups: container.security_groups = [] if neutron_port.get('security_groups'): for sg in neutron_port['security_groups']: if sg not in container.security_groups: container.security_groups += [sg] container.save(self.context) # update device_id in port port_req_body = {'port': {'device_id': container.uuid}} self.neutron_api.update_port(neutron_port_id, port_req_body) # If there is pci_request_id, it should be a sriov port. # populate pci related info. pci_request_id = requested_network.get('pci_request_id') if pci_request_id: self._populate_neutron_extension_values(container, pci_request_id, port_req_body) self._populate_pci_mac_address(container, pci_request_id, port_req_body) # NOTE(hongbin): Use admin context here because non-admin # context might not be able to update some attributes # (i.e. binding:profile). admin_context = zun_context.get_admin_context() neutron_api = neutron.NeutronAPI(admin_context) neutron_api.update_port(neutron_port_id, port_req_body) else: network = self.inspect_network(network_name) neutron_net_id = network['Options']['neutron.net.uuid'] port_dict = { 'network_id': neutron_net_id, 'tenant_id': self.context.project_id, 'device_id': container.uuid, } ip_addr = requested_network.get("v4-fixed-ip") or requested_network.\ get("v6-fixed-ip") if ip_addr: port_dict['fixed_ips'] = [{'ip_address': ip_addr}] if security_groups is not None: port_dict['security_groups'] = security_groups neutron_port = self.neutron_api.create_port({'port': port_dict}) neutron_port = neutron_port['port'] preserve_on_delete = requested_network['preserve_on_delete'] addresses = [] for fixed_ip in neutron_port['fixed_ips']: ip_address = fixed_ip['ip_address'] ip = ipaddress.ip_address(six.text_type(ip_address)) if ip.version == 4: addresses.append({ 'addr': ip_address, 'version': 4, 'port': neutron_port['id'], 'subnet_id': fixed_ip['subnet_id'], 'preserve_on_delete': preserve_on_delete }) else: addresses.append({ 'addr': ip_address, 'version': 6, 'port': neutron_port['id'], 'subnet_id': fixed_ip['subnet_id'], 'preserve_on_delete': preserve_on_delete }) return addresses, neutron_port
def __init__(self, registry): self.registry = registry self.host = CONF.host self.context = zun_context.get_admin_context(all_projects=True) self.neutron_api = neutron.NeutronAPI(self.context)