예제 #1
0
 def delete_trunk(self, context, trunk_id):
     """Delete the trunk port."""
     LOG.debug("Deleting trunk_id %s", trunk_id)
     deleted_from_db = False
     with db_context_writer.using(context):
         trunk = self._get_trunk(context, trunk_id)
         rules.trunk_can_be_managed(context, trunk)
         trunk_port_validator = rules.TrunkPortValidator(trunk.port_id)
         if not trunk_port_validator.is_bound(context):
             trunk.delete()
             deleted_from_db = True
             payload = callbacks.TrunkPayload(context,
                                              trunk_id,
                                              original_trunk=trunk)
             registry.notify(trunk_const.TRUNK,
                             events.PRECOMMIT_DELETE,
                             self,
                             payload=payload)
         else:
             raise trunk_exc.TrunkInUse(trunk_id=trunk_id)
     if deleted_from_db:
         registry.notify(trunk_const.TRUNK,
                         events.AFTER_DELETE,
                         self,
                         payload=payload)
예제 #2
0
    def create_router(self, context, router):
        router_dict = super(VppL3RouterPlugin, self).create_router(
            context, router)
        with db_context_writer.using(context):
            # Allocate VRF for this router
            db.add_router_vrf(context.session, router_dict['id'])
            if router_dict.get('external_gateway_info', False):
                self._write_router_external_gw_journal(
                    context, router_dict['id'], router_dict)

        return router_dict
예제 #3
0
    def release_segment(self, context, segment):
        vni_id = segment[driver_api.SEGMENTATION_ID]
        LOG.debug('Releasing GPE segment %s', vni_id)

        info = {'type': self.get_type(), 'id': vni_id}
        with db_context_writer.using(context):
            query = (context.session.query(
                self.model).filter_by(**{self.segmentation_key: vni_id}))
            count = query.delete()
        if count:
            LOG.debug("Releasing %(type)s VNI %(id)s", info)
        else:
            LOG.warning("Released %(type)s VNI %(id)s was not allocated", info)
예제 #4
0
 def delete_router(self, context, router_id):
     router = self.get_router(context, router_id)
     super(VppL3RouterPlugin, self).delete_router(context, router_id)
     with db_context_writer.using(context):
         # Delete the external gateway key from etcd
         if router.get('external_gateway_info', False):
             self._write_router_external_gw_journal(context, router_id,
                                                    router, delete=True)
         # Delete the base <router_id> key from etcd, i.e.,
         # /networking-vpp/nodes/<node_name>/routers/<router_id>
         for l3_host in self.l3_hosts:
             etcd_key = self._get_router_intf_path(l3_host, router_id, '')
             db.journal_write(context.session, etcd_key, None)
         db.delete_router_vrf(context.session, router_id)
         self.communicator.kick()
예제 #5
0
 def add_subports(self, context, trunk_id, subports):
     """Add one or more subports to a trunk."""
     LOG.debug("Adding subports %s to trunk %s", subports, trunk_id)
     trunk = self._get_trunk(context, trunk_id)
     subports = subports['sub_ports']
     subports = self.validate_subports(context,
                                       subports,
                                       trunk,
                                       basic_validation=True)
     added_subports = []
     rules.trunk_can_be_managed(context, trunk)
     original_trunk = copy.deepcopy(trunk)
     # The trunk should not be in the ERROR_STATUS
     if trunk.status == trunk_const.ERROR_STATUS:
         raise trunk_exc.TrunkInErrorState(trunk_id=trunk_id)
     else:
         # The trunk will transition to DOWN and subsequently to ACTIVE
         # when a subport is added.
         trunk.update(status=trunk_const.DOWN_STATUS)
     with db_context_writer.using(context):
         for subport in subports:
             subport_obj = trunk_objects.SubPort(
                 context=context,
                 trunk_id=trunk_id,
                 port_id=subport['port_id'],
                 segmentation_type=subport['segmentation_type'],
                 segmentation_id=subport['segmentation_id'])
             subport_obj.create()
             trunk['sub_ports'].append(subport_obj)
             added_subports.append(subport_obj)
         payload = callbacks.TrunkPayload(context,
                                          trunk_id,
                                          current_trunk=trunk,
                                          original_trunk=original_trunk,
                                          subports=added_subports)
         if added_subports:
             registry.notify(trunk_const.SUBPORTS,
                             events.PRECOMMIT_CREATE,
                             self,
                             payload=payload)
             self.send_subport_update_to_etcd(context, trunk)
     if added_subports:
         registry.notify(trunk_const.SUBPORTS,
                         events.AFTER_CREATE,
                         self,
                         payload=payload)
     return trunk
예제 #6
0
    def allocate_partially_specified_segment(self, context, **filters):
        """Allocate a segment partially specified by the raw_segment.

        Allocate an ML2 GPE segment from the pool and save it in the
        database.
        If successful, return the allocated DB object.
        Return None if a segment cannot be allocated.
        """
        network_type = self.get_type()
        session = context.session
        LOG.debug('Allocating a partially specified GPE segment ' 'from pool')
        segmentation_id = self.gpe_vni_allocator.allocate()
        if segmentation_id is None:
            LOG.error('Failed to allocate a GPE segment ID')
            return

        with db_context_writer.using(context):
            raw_segment = {self.segmentation_key: segmentation_id}
            alloc = (session.query(
                self.model).filter_by(**raw_segment).first())
            # The VNI is present in the DB, update its allocation
            if alloc and not alloc.allocated:
                (session.query(self.model).filter_by(allocated=False,
                                                     **raw_segment).update(
                                                         {"allocated": True}))
            # Create a new allocation
            elif not alloc:
                alloc = self.model(allocated=True, **raw_segment)
                alloc.save(session)
                LOG.debug("%(type)s segment %(segment)s create done", {
                    "type": network_type,
                    "segment": raw_segment
                })
            # We should never run into this state
            else:
                LOG.error(
                    "Could not allocate segment %s as it is already "
                    "allocated in the DB", segmentation_id)
                alloc = None
            return alloc
예제 #7
0
 def update_trunk(self, context, trunk_id, trunk):
     """Update the trunk object."""
     LOG.debug("Updating trunk %s trunk_id %s", trunk, trunk_id)
     trunk_data = trunk['trunk']
     with db_context_writer.using(context):
         trunk_obj = self._get_trunk(context, trunk_id)
         original_trunk = copy.deepcopy(trunk_obj)
         trunk_obj.update_fields(trunk_data, reset_changes=True)
         trunk_obj.update()
         payload = callbacks.TrunkPayload(context,
                                          trunk_id,
                                          original_trunk=original_trunk,
                                          current_trunk=trunk_obj)
         registry.notify(trunk_const.TRUNK,
                         events.PRECOMMIT_UPDATE,
                         self,
                         payload=payload)
     registry.notify(trunk_const.TRUNK,
                     events.AFTER_UPDATE,
                     self,
                     payload=payload)
     return trunk_obj
예제 #8
0
 def create_trunk(self, context, trunk):
     """Create a trunk object."""
     LOG.debug("Creating trunk %s", trunk)
     trunk = self.validate_trunk(context, trunk['trunk'])
     sub_ports = [
         trunk_objects.SubPort(context=context,
                               port_id=p['port_id'],
                               segmentation_id=p['segmentation_id'],
                               segmentation_type=p['segmentation_type'])
         for p in trunk['sub_ports']
     ]
     trunk_obj = trunk_objects.Trunk(
         context=context,
         admin_state_up=trunk.get('admin_state_up', True),
         id=uuidutils.generate_uuid(),
         name=trunk.get('name', ""),
         description=trunk.get('description', ""),
         project_id=trunk['tenant_id'],
         port_id=trunk['port_id'],
         # Trunk will turn active only after it has been bound on a host
         status=trunk_const.DOWN_STATUS,
         sub_ports=sub_ports)
     with db_context_writer.using(context):
         trunk_obj.create()
         payload = callbacks.TrunkPayload(context,
                                          trunk_obj.id,
                                          current_trunk=trunk_obj)
         registry.notify(trunk_const.TRUNK,
                         events.PRECOMMIT_CREATE,
                         self,
                         payload=payload)
     registry.notify(trunk_const.TRUNK,
                     events.AFTER_CREATE,
                     self,
                     payload=payload)
     return trunk_obj
예제 #9
0
    def remove_subports(self, context, trunk_id, subports):
        """Remove one or more subports from the trunk.

        param: subports:
        {u'sub_ports': [{u'port_id': u'fa006724-dbca-4e7f-bb6b-ec70162eb681'}]}
        """
        LOG.debug("Removing subports %s from trunk %s", subports, trunk_id)
        trunk = self._get_trunk(context, trunk_id)
        original_trunk = copy.deepcopy(trunk)
        # key-value data corresponding to original trunk
        original_trunk_data = self._get_trunk_data(trunk)
        # ID's of subports to remove
        subports_to_remove = [pid['port_id'] for pid in subports['sub_ports']]
        LOG.debug('trunk subports to remove: %s', subports_to_remove)
        subports = subports['sub_ports']
        subports = self.validate_subports(context,
                                          subports,
                                          trunk,
                                          basic_validation=True,
                                          trunk_validation=False)
        removed_subports = []
        rules.trunk_can_be_managed(context, trunk)
        # The trunk should not be in the ERROR_STATUS
        if trunk.status == trunk_const.ERROR_STATUS:
            raise trunk_exc.TrunkInErrorState(trunk_id=trunk_id)
        else:
            # The trunk will transition to DOWN and subsequently to ACTIVE
            # when a subport is removed.
            trunk.update(status=trunk_const.DOWN_STATUS)
        current_subports = {p.port_id: p for p in trunk.sub_ports}
        # Ensure that all sub-ports to be removed are actually present
        for subport in subports:
            if subport['port_id'] not in current_subports:
                raise trunk_exc.SubPortNotFound(trunk_id=trunk_id,
                                                port_id=subport['port_id'])
        with db_context_writer.using(context):
            for subport in subports:
                subport_obj = current_subports.pop(subport['port_id'])
                subport_obj.delete()
                removed_subports.append(subport_obj)
            if removed_subports:
                del trunk.sub_ports[:]
                trunk.sub_ports.extend(current_subports.values())
                payload = callbacks.TrunkPayload(context,
                                                 trunk_id,
                                                 current_trunk=trunk,
                                                 original_trunk=original_trunk,
                                                 subports=removed_subports)
                registry.notify(trunk_const.SUBPORTS,
                                events.PRECOMMIT_DELETE,
                                self,
                                payload=payload)
                self.send_subport_update_to_etcd(context, trunk)
                # Subport data to remove
                subports = [
                    subport for subport in original_trunk_data['sub_ports']
                    if subport['port_id'] in subports_to_remove
                ]
                original_trunk_data['sub_ports'] = subports
                trunk_data = self.add_data_to_subports(context,
                                                       original_trunk_data)
                # Remove all remote-group subport keys from etcd
                LOG.debug('trunk data with subports to remove: %s', trunk_data)
                for subport_data in trunk_data['sub_ports']:
                    self._write_remote_group_journal(context,
                                                     subport_data,
                                                     remove_key=True)
        if removed_subports:
            registry.notify(trunk_const.SUBPORTS,
                            events.AFTER_DELETE,
                            self,
                            payload=payload)
        return trunk
예제 #10
0
    def allocate_fully_specified_segment(self, context, **raw_segment):
        """Allocate a segment fully specified by the raw_segment.

        Fetch the fully specified GPE segment (i.e. with a user
        specified GPE VNI_ID) from the allocation pool allocate it
        in the Neutron DB. If successful, return the DB allocation object.
        Else, return None.
        """
        network_type = self.get_type()
        session = context.session
        # Release segment from mem pool prior to allocating it in the DB
        gpe_vni = raw_segment['gpe_vni']
        seg_id = self.gpe_vni_allocator.allocate(gpe_vni)
        if seg_id is None:
            LOG.error('Failed to allocate the specified GPE segment ID %s ',
                      gpe_vni)
            return
        try:
            with db_context_writer.using(context):
                alloc = (session.query(
                    self.model).filter_by(**raw_segment).first())
                if alloc:
                    if alloc.allocated:
                        # Segment already allocated in the DB
                        return
                    else:
                        # Segment not allocated in the DB
                        LOG.debug(
                            "%(type)s segment %(segment)s allocate "
                            "started ", {
                                "type": network_type,
                                "segment": raw_segment
                            })

                        count = (session.query(self.model).filter_by(
                            allocated=False,
                            **raw_segment).update({"allocated": True}))
                        if count:
                            LOG.debug(
                                "%(type)s segment %(segment)s allocate "
                                "done ", {
                                    "type": network_type,
                                    "segment": raw_segment
                                })
                            return alloc

                        # Segment allocated or deleted since select
                        LOG.debug(
                            "%(type)s segment %(segment)s allocate "
                            "failed: segment has been allocated or "
                            "deleted", {
                                "type": network_type,
                                "segment": raw_segment
                            })

                # Segment to create in the DB
                LOG.debug("%(type)s segment %(segment)s create started", {
                    "type": network_type,
                    "segment": raw_segment
                })
                alloc = self.model(allocated=True, **raw_segment)
                alloc.save(session)
                LOG.debug("%(type)s segment %(segment)s create done", {
                    "type": network_type,
                    "segment": raw_segment
                })
                return alloc

        except db_exc.DBDuplicateEntry:
            # Segment already allocated (insert failure)
            alloc = None
            LOG.debug("%(type)s segment %(segment)s create failed", {
                "type": network_type,
                "segment": raw_segment
            })