Example #1
0
    def create_port(self, context, port):
        # If PORTSECURITY is not the default value ATTR_NOT_SPECIFIED
        # then we pass the port to the policy engine. The reason why we don't
        # pass the value to the policy engine when the port is
        # ATTR_NOT_SPECIFIED is for the case where a port is created on a
        # shared network that is not owned by the tenant.
        port_data = port['port']

        with context.session.begin(subtransactions=True):
            # First we allocate port in neutron database
            neutron_db = super(NsxDvsV2, self).create_port(context, port)
            port_security = self._get_network_security_binding(
                context, neutron_db['network_id'])
            port_data[psec.PORTSECURITY] = port_security
            self._process_port_port_security_create(context, port_data,
                                                    neutron_db)
            # Update fields obtained from neutron db (eg: MAC address)
            port["port"].update(neutron_db)
            has_ip = self._ip_on_port(neutron_db)

            # security group extension checks
            if has_ip:
                self._ensure_default_security_group_on_port(context, port)
            elif validators.is_attr_set(port_data.get(ext_sg.SECURITYGROUPS)):
                raise psec.PortSecurityAndIPRequiredForSecurityGroups()
            port_data[ext_sg.SECURITYGROUPS] = (
                self._get_security_groups_on_port(context, port))
            self._process_port_create_security_group(
                context, port_data, port_data[ext_sg.SECURITYGROUPS])
            self._process_portbindings_create_and_update(
                context, port['port'], port_data)

            # allowed address pair checks
            if validators.is_attr_set(port_data.get(addr_pair.ADDRESS_PAIRS)):
                if not port_security:
                    raise addr_pair.AddressPairAndPortSecurityRequired()
                else:
                    self._process_create_allowed_address_pairs(
                        context, neutron_db,
                        port_data[addr_pair.ADDRESS_PAIRS])
            else:
                # remove ATTR_NOT_SPECIFIED
                port_data[addr_pair.ADDRESS_PAIRS] = []

            LOG.debug(
                "create_port completed on NSX for tenant "
                "%(tenant_id)s: (%(id)s)", port_data)

            self._process_portbindings_create_and_update(
                context, port['port'], port_data)
        # DB Operation is complete, perform DVS operation
        port_data = port['port']

        # this extra lookup is necessary to get the
        # latest db model for the extension functions
        port_model = self._get_port(context, port_data['id'])
        self._apply_dict_extend_functions('ports', port_data, port_model)

        self.handle_port_dhcp_access(context, port_data, action='create_port')
        return port_data
Example #2
0
    def update_port(self, context, id, port):
        delete_addr_pairs = self._check_update_deletes_allowed_address_pairs(
            port)
        has_addr_pairs = self._check_update_has_allowed_address_pairs(port)

        with context.session.begin(subtransactions=True):
            ret_port = super(NsxDvsV2, self).update_port(
                context, id, port)
            # Save current mac learning state to check whether it's
            # being updated or not
            # copy values over - except fixed_ips as
            # they've already been processed
            port['port'].pop('fixed_ips', None)
            ret_port.update(port['port'])

            # populate port_security setting
            if psec.PORTSECURITY not in port['port']:
                ret_port[psec.PORTSECURITY] = self._get_port_security_binding(
                    context, id)
            # validate port security and allowed address pairs
            if not ret_port[psec.PORTSECURITY]:
                #  has address pairs in request
                if has_addr_pairs:
                    raise addr_pair.AddressPairAndPortSecurityRequired()
                elif not delete_addr_pairs:
                    # check if address pairs are in db
                    ret_port[addr_pair.ADDRESS_PAIRS] = (
                        self.get_allowed_address_pairs(context, id))
                    if ret_port[addr_pair.ADDRESS_PAIRS]:
                        raise addr_pair.AddressPairAndPortSecurityRequired()

            if delete_addr_pairs or has_addr_pairs:
                # delete address pairs and read them in
                self._delete_allowed_address_pairs(context, id)
                self._process_create_allowed_address_pairs(
                    context, ret_port, ret_port[addr_pair.ADDRESS_PAIRS])

            if psec.PORTSECURITY in port['port']:
                self._process_port_port_security_update(
                    context, port['port'], ret_port)

            LOG.debug("Updating port: %s", port)
            self._process_portbindings_create_and_update(context,
                                                         port['port'],
                                                         ret_port)
        return ret_port
Example #3
0
    def update_port(self, context, id, port):
        LOG.debug(
            "MidonetPluginV2.update_port called: id=%(id)s "
            "port=%(port)r", {
                'id': id,
                'port': port
            })

        with context.session.begin(subtransactions=True):

            # update the port DB
            original_port = super(MidonetPluginV2, self).get_port(context, id)
            p = super(MidonetPluginV2, self).update_port(context, id, port)
            c_utils.check_update_port(original_port, p)
            self.extension_manager.process_update_port(context, port['port'],
                                                       p)

            has_sg = self._check_update_has_security_groups(port)
            delete_sg = self._check_update_deletes_security_groups(port)

            if delete_sg or has_sg:
                # delete the port binding and read it with the new rules.
                self._delete_port_security_group_bindings(context, id)
                sg_ids = self._get_security_groups_on_port(context, port)
                self._process_port_create_security_group(context, p, sg_ids)
            self._update_extra_dhcp_opts_on_port(context, id, port, p)

            self._process_portbindings_create_and_update(
                context, port['port'], p)
            self._process_mido_portbindings_create_and_update(
                context, port['port'], p)
            self.update_address_pairs_on_port(context, id, port, original_port,
                                              p)

            self._process_port_port_security_update(context, port['port'], p)

            port_psec = p.get(psec.PORTSECURITY)
            if port_psec is False:
                if p.get(ext_sg.SECURITYGROUPS):
                    raise psec.PortSecurityPortHasSecurityGroup()
                if p.get(addr_pair.ADDRESS_PAIRS):
                    raise addr_pair.AddressPairAndPortSecurityRequired()
            # NOTE(yamamoto): Retrieve the db object to get the correct
            # revision
            context.session.flush()
            context.session.expire_all()
            p = self.get_port(context, id)
            self.client.update_port_precommit(context, id, p)

        # Set status along admin_state_up to update.
        if p['admin_state_up']:
            update_status = n_const.PORT_STATUS_ACTIVE
        else:
            update_status = n_const.PORT_STATUS_DOWN

        try:
            self.client.update_port_postcommit(id, p)
            data = {'port': {'status': update_status}}
            new_port = super(MidonetPluginV2,
                             self).update_port(context, id, data)
            # prevent binding:profile information from lacking
            p['status'] = new_port['status']
            if 'revision_number' in new_port:
                p['revision_number'] = new_port['revision_number']
        except Exception as ex:
            with excutils.save_and_reraise_exception():
                LOG.error(
                    _LE("Failed to update a port %(port_id)s in "
                        "MidoNet: %(err)s"), {
                            "port_id": id,
                            "err": ex
                        })
                try:
                    data = {'port': {'status': n_const.PORT_STATUS_ERROR}}
                    super(MidonetPluginV2, self).update_port(context, id, data)
                except Exception:
                    LOG.exception(_LE("Failed to update port status %s"), id)

        LOG.debug("MidonetPluginV2.update_port exiting: p=%r", p)
        return p
Example #4
0
    def create_port(self, context, port):
        LOG.debug("MidonetPluginV2.create_port called: port=%r", port)

        port_data = port['port']
        # REVISIT(yamamoto): this nested transaction is a workaround
        # for bug #1490917.
        with db_api.autonested_transaction(context.session):
            # Set status along admin_state_up if the parameter is specified.
            if port['port'].get('admin_state_up') is not None:
                if not port['port']['admin_state_up']:
                    port['port']['status'] = n_const.PORT_STATUS_DOWN
            # Create a Neutron port
            port_db = self.create_port_db(context, port)
            new_port = self._make_port_dict(port_db, process_extensions=False)
            self.extension_manager.process_create_port(context, port_data,
                                                       new_port)

            # Do not create a gateway port if it has no IP address assigned as
            # MidoNet does not yet handle this case.
            if (new_port.get('device_owner') == n_const.DEVICE_OWNER_ROUTER_GW
                    and not new_port['fixed_ips']):
                msg = (_("No IPs assigned to the gateway port for"
                         " router %s") % port_data['device_id'])
                raise n_exc.BadRequest(resource='router', msg=msg)

            dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])

            # Make sure that the port created is valid
            if "id" not in new_port:
                raise n_exc.BadRequest(resource='port',
                                       msg="Invalid port created")

            # Update fields
            port_data.update(new_port)

            port_psec, has_ip = self._determine_port_security_and_has_ip(
                context, port['port'])
            port['port'][psec.PORTSECURITY] = port_psec
            self._process_port_port_security_create(context, port['port'],
                                                    new_port)

            if port_psec is False:
                if self._check_update_has_security_groups(port):
                    raise psec.PortSecurityAndIPRequiredForSecurityGroups()
                if self._check_update_has_allowed_address_pairs(port):
                    raise addr_pair.AddressPairAndPortSecurityRequired()
            else:
                # Bind security groups to the port
                self._ensure_default_security_group_on_port(context, port)

            sg_ids = self._get_security_groups_on_port(context, port)
            self._process_port_create_security_group(context, new_port, sg_ids)

            # Process port bindings
            self._process_portbindings_create_and_update(
                context, port_data, new_port)
            self._process_mido_portbindings_create_and_update(
                context, port_data, new_port)

            self._process_port_create_extra_dhcp_opts(context, new_port,
                                                      dhcp_opts)

            new_port[addr_pair.ADDRESS_PAIRS] = (
                self._process_create_allowed_address_pairs(
                    context, new_port, port_data.get(addr_pair.ADDRESS_PAIRS)))

            self.client.create_port_precommit(context, new_port)

        try:
            self.client.create_port_postcommit(new_port)
        except Exception as ex:
            with excutils.save_and_reraise_exception():
                LOG.error(_LE("Failed to create a port %(new_port)s: %(err)s"),
                          {
                              "new_port": new_port,
                              "err": ex
                          })
                try:
                    self.delete_port(context,
                                     new_port['id'],
                                     l3_port_check=False)
                except Exception:
                    LOG.exception(_LE("Failed to delete port %s"),
                                  new_port['id'])

        self._apply_dict_extend_functions('ports', new_port, port_db)

        LOG.debug("MidonetPluginV2.create_port exiting: port=%r", new_port)
        return new_port