Example #1
0
    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)
Example #2
0
    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']
Example #3
0
    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)
Example #4
0
 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 = {}
Example #5
0
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
Example #6
0
    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
Example #7
0
 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
Example #9
0
 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'])
Example #11
0
    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')
Example #13
0
 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
Example #14
0
    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
Example #15
0
    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]
Example #16
0
    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:")
Example #17
0
    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
Example #18
0
 def init(self, context, docker_api):
     self.docker = docker_api
     self.neutron_api = neutron.NeutronAPI(context)
     self.context = context
Example #19
0
    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
Example #20
0
    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
Example #21
0
 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)