コード例 #1
0
ファイル: test_ml2_plugin.py プロジェクト: zanailhan/neutron
 def raise_mechanism_exc(*args, **kwargs):
     raise ml2_exc.MechanismDriverError(
         method='create_network_postcommit')
コード例 #2
0
ファイル: test_ml2_plugin.py プロジェクト: zanailhan/neutron
 def mock_update_network_postcommit(self, context):
     raise ml2_exc.MechanismDriverError(
         method='update_network_postcommit')
コード例 #3
0
 def create_network(self, vlan_id, ports):
     if self.error:
         raise ml2_exc.MechanismDriverError(method='create_network')
     vlan_map = {}
     vlan_map.update({vlan_id: ports})
     config_map.update({self.address: vlan_map})
コード例 #4
0
 def delete_network(self, vlan_id):
     vlan_map = config_map.pop(self.address, None)
     if vlan_map is None:
         raise ml2_exc.MechanismDriverError(method='delete_network')
     else:
         vlan_map.pop(vlan_id, None)
コード例 #5
0
    def update_port_postcommit(self, context):
        """Update the name of a given port in EOS.

        At the moment we only support port name change
        Any other change to port is not supported at this time.
        """
        port = context.current
        orig_port = context.original

        device_id = port['device_id']
        device_owner = port['device_owner']
        host = context.host
        is_vm_boot = device_id and device_owner

        vnic_type = port['binding:vnic_type']
        binding_profile = port['binding:profile']
        bindings = []
        if binding_profile:
            bindings = binding_profile['local_link_information']

        port_id = port['id']
        port_name = port['name']
        network_id = port['network_id']
        tenant_id = port['tenant_id'] or INTERNAL_TENANT_ID
        # Ensure that we use tenant Id for the network owner
        tenant_id = self._network_owner_tenant(context, network_id, tenant_id)
        sg = port['security_groups']
        orig_sg = orig_port['security_groups']

        pretty_log("update_port_postcommit: new", port)
        pretty_log("update_port_postcommit: orig", orig_port)

        # Check if it is port migration case
        if self._handle_port_migration_postcommit(context):
            # Return from here as port migration is already handled.
            return

        seg_info = self._bound_segments(context)
        if not seg_info:
            LOG.debug("Ignoring the update as the port is not managed by "
                      "Arista switches.")
            return

        with self.eos_sync_lock:
            hostname = self._host_name(host)
            segmentation_id = seg_info[driver_api.SEGMENTATION_ID]
            port_host_filter = None
            if (port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE):
                # <port, host> uniquely identifies a DVR port. Other
                # ports are identified by just the port id
                port_host_filter = host

            port_provisioned = db_lib.is_port_provisioned(
                port_id, port_host_filter)
            # If network does not exist under this tenant,
            # it may be a shared network. Get shared network owner Id
            net_provisioned = self._network_provisioned(
                tenant_id, network_id, segmentation_id=segmentation_id)
            segments = []
            if net_provisioned:
                if self.rpc.hpb_supported():
                    for binding_level in context.binding_levels:
                        bound_segment = binding_level.get(
                            driver_api.BOUND_SEGMENT)
                        if bound_segment:
                            segments.append(bound_segment)
                    all_segments = self.ndb.get_all_network_segments(
                        network_id, context=context._plugin_context)
                    try:
                        self.rpc.create_network_segments(
                            tenant_id, network_id,
                            context.network.current['name'], all_segments)
                    except arista_exc.AristaRpcError:
                        LOG.error(_LE("Failed to create network segments"))
                        raise ml2_exc.MechanismDriverError()
                else:
                    # For non HPB cases, the port is bound to the static
                    # segment
                    segments = self.ndb.get_network_segments(network_id)

            try:
                orig_host = context.original_host
                port_down = False
                if (port['device_owner'] == n_const.DEVICE_OWNER_DVR_INTERFACE
                    ):
                    # We care about port status only for DVR ports
                    port_down = context.status == n_const.PORT_STATUS_DOWN

                if orig_host and (port_down or host != orig_host):
                    try:
                        LOG.info("Deleting the port %s" % str(orig_port))
                        # The port moved to a different host or the VM
                        # connected to the port was deleted or its in DOWN
                        # state. So delete the old port on the old host.
                        self._delete_port(orig_port, orig_host, tenant_id)
                    except ml2_exc.MechanismDriverError:
                        # If deleting a port fails, then not much can be done
                        # about it. Log a warning and move on.
                        LOG.warning(UNABLE_TO_DELETE_PORT_MSG)
                if (port_provisioned and net_provisioned and hostname
                        and is_vm_boot and not port_down):
                    LOG.info(_LI("Port plugged into network"))
                    # Plug port into the network only if it exists in the db
                    # and is bound to a host and the port is up.
                    self.rpc.plug_port_into_network(device_id,
                                                    hostname,
                                                    port_id,
                                                    network_id,
                                                    tenant_id,
                                                    port_name,
                                                    device_owner,
                                                    sg,
                                                    orig_sg,
                                                    vnic_type,
                                                    segments=segments,
                                                    switch_bindings=bindings)
                else:
                    LOG.info(_LI("Port not plugged into network"))
            except arista_exc.AristaRpcError as err:
                LOG.error(
                    _LE('update_port_postcommit: Did not update '
                        'port %(port_id)s. Reason: %(err)s'), {
                            'port_id': port_id,
                            'err': err
                        })
コード例 #6
0
 def _raise_ml2_error(self, err_type, method_name):
     base.FAULT_MAP.update({ml2_exc.MechanismDriverError: err_type})
     raise ml2_exc.MechanismDriverError(method=method_name)
コード例 #7
0
    def create_network_postcommit(self, mech_context):
        """Create VLAN on the switch.

        :param:mech_context: Details about the network to be created
        :raise: Exception
        """

        LOG.debug("create_network_postcommit: called")
        network = mech_context.current
        network_id = network['id']
        tenant_id = network['tenant_id']
        segments = mech_context.network_segments
        network_type = segments[0]['network_type']
        vlan_id = segments[0]['segmentation_id']
        physical_network = segments[0]['physical_network']
        if physical_network not in self._physical_networks:
            LOG.exception(_LE("BrocadeFiNiMechanism: Failed to create network."
                              " Network cannot be created in the configured "
                              "physical network %(physnet)s"),
                          {'physnet': physical_network})
            raise ml2_exc.MechanismDriverError(method='create_network_postcomm'
                                               'it')
        if network_type != 'vlan':
            LOG.exception(_LE("BrocadeFiNiMechanism: Failed to create network "
                              "for network type %(nw_type)s. Only network type"
                              " vlan is supported"), {'nw_type': network_type})
            raise ml2_exc.MechanismDriverError(method='create_network_postcomm'
                                               'it')
        try:
            devices = self._physical_networks.get(physical_network)
            for device in devices:
                device_info = self._devices.get(device)
                address = device_info.get('address')
                driver = None
                try:
                    driver = self._get_driver(device)
                except Exception as e:
                    LOG.exception(_LE("BrocadeFiNiMechanism: create_network"
                                      "_postcommit failed while configuring "
                                      "device %(host)s exception=%(error)s"),
                                  {'host': address,
                                   'error': e.args})
                    raise ml2_exc.MechanismDriverError(method='create_network_'
                                                       'postcommit')
                # Proceed only if the driver is not None
                if driver is not None:
                    driver.create_network(
                        vlan_id,
                        device_info.get("ports").split(","))
        except Exception as e:
            LOG.exception(
                _LE("Brocade FI/NI driver: create_network_postcommit failed"
                    "Error = %(error)s"), {'error': e.args})
            raise ml2_exc.MechanismDriverError(method='create_network_postcomm'
                                               'it')
        LOG.info(_LI("BrocadeFiNiMechanism:created_network_postcommit: "
                     "%(network_id)s of network type = %(network_type)s with "
                     "vlan = %(vlan_id)s for tenant %(tenant_id)s"),
                 {'network_id': network_id,
                  'network_type': network_type,
                  'vlan_id': vlan_id,
                  'tenant_id': tenant_id})
コード例 #8
0
 def __restRequestError__(self, errorCode, reason):
     LOG.error("----------restRequest error")
     LOG.debug(("----------the reason is: %s"), reason)
     LOG.debug(("----------the errorCode is: %s"), errorCode)
     raise ml2_exc.MechanismDriverError()
コード例 #9
0
    def create_subnet_postcommit(self, mech_context, update=False):
        if not update:
            # log the context for debugging
            LOG.debug("create_subnetwork_postcommit: called, context %(ctx)s",
                      {'ctx': mech_context.current})
        gateway = mech_context.current['gateway_ip']
        network_id = mech_context.current['network_id']
        subnet_id = mech_context.current['id']
        tenant_id = mech_context.current['tenant_id']
        context = mech_context._plugin_context
        dns_nameservers = mech_context.current.setdefault(
            'dns_nameservers', [])
        if update:
            router_func = utils.set_routerstatic
            dhcp_func = utils.set_dhcpserver
        else:
            router_func = utils.add_routerstatic
            dhcp_func = utils.add_dhcpserver
        try:
            if fortinet_db.query_record(context,
                                        ext_db.ExternalNetwork,
                                        network_id=network_id):

                router_func(self,
                            context,
                            subnet_id=subnet_id,
                            vdom=const.EXT_VDOM,
                            dst=const.EXT_DEF_DST,
                            device=self._fortigate['ext_interface'],
                            gateway=gateway)
            else:
                namespace = fortinet_db.query_record(
                    context,
                    fortinet_db.Fortinet_ML2_Namespace,
                    tenant_id=tenant_id)
                interface = utils.get_intf(context,
                                           mech_context.current['network_id'])
                netmask = str(
                    netaddr.IPNetwork(mech_context.current['cidr']).netmask)
                start_ip = mech_context.current['allocation_pools'][0]['start']
                end_ip = mech_context.current['allocation_pools'][0]['end']
                dhcp_func(self,
                          context,
                          subnet_id=subnet_id,
                          vdom=namespace.vdom,
                          interface=interface,
                          dns_nameservers=dns_nameservers,
                          gateway=gateway,
                          netmask=netmask,
                          start_ip=start_ip,
                          end_ip=end_ip)

                # TODO(samsu): need to add rollback for the update and set
                cls = fortinet_db.Fortinet_Interface
                record = fortinet_db.query_record(context,
                                                  cls,
                                                  name=interface,
                                                  vdom=namespace.vdom)
                if gateway:
                    cls.update_record(context,
                                      record,
                                      ip="%s %s" % (gateway, netmask))
                    utils.op(self,
                             context,
                             resources.VlanInterface.set,
                             name=interface,
                             vdom=namespace.vdom,
                             ip="%s %s" % (gateway, netmask))
        except Exception as e:
            utils._rollback_on_err(self, context, e)
            raise ml2_exc.MechanismDriverError(
                method=sys._getframe().f_code.co_name)
        if not update:
            utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
コード例 #10
0
    def create_subnet_postcommit(self, mech_context):
        """Noop now, it is left here for future."""
        #LOG.debug(_("create_subnetwork_postcommit: called"))
        gateway = mech_context.current['gateway_ip']
        network_id = mech_context.current['network_id']
        subnet_id = mech_context.current['id']
        tenant_id = mech_context.current['tenant_id']
        context = mech_context._plugin_context
        try:
            if fortinet_db.query_record(context,
                                        ExternalNetwork,
                                        network_id=network_id):
                utils.add_routerstatic(self,
                                       context,
                                       subnet_id=subnet_id,
                                       vdom=const.EXT_VDOM,
                                       dst=const.EXT_DEF_DST,
                                       device=self._fortigate['ext_interface'],
                                       gateway=gateway)
            else:
                namespace = fortinet_db.query_record(
                    context,
                    fortinet_db.Fortinet_ML2_Namespace,
                    tenant_id=tenant_id)
                interface = utils.get_intf(context,
                                           mech_context.current['network_id'])
                netmask = str(netaddr.\
                            IPNetwork(mech_context.current['cidr']).netmask)
                start_ip = mech_context.current['allocation_pools'][0]['start']
                end_ip = mech_context.current['allocation_pools'][0]['end']

                utils.add_dhcpserver(self,
                                     context,
                                     subnet_id=subnet_id,
                                     vdom=namespace.vdom,
                                     interface=interface,
                                     gateway=gateway,
                                     netmask=netmask,
                                     start_ip=start_ip,
                                     end_ip=end_ip)

                # TODO: need to add rollback for the update and set
                cls = fortinet_db.Fortinet_Interface
                record = fortinet_db.query_record(context,
                                                  cls,
                                                  name=interface,
                                                  vdom=namespace.vdom)
                if gateway:
                    cls.update_record(context,
                                      record,
                                      ip="%s %s" % (gateway, netmask))
                    utils.op(self,
                             context,
                             resources.VlanInterface.set,
                             name=interface,
                             vdom=namespace.vdom,
                             ip="%s %s" % (gateway, netmask))
        except Exception as e:
            utils._rollback_on_err(self, context, e)
            raise ml2_exc.MechanismDriverError(
                method=sys._getframe().f_code.co_name)
        utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
コード例 #11
0
    def bind_port(self, context):
        """Attempt to bind a port.

        :param context: PortContext instance describing the port

        This method is called outside any transaction to attempt to
        establish a port binding using this mechanism driver. Bindings
        may be created at each of multiple levels of a hierarchical
        network, and are established from the top level downward. At
        each level, the mechanism driver determines whether it can
        bind to any of the network segments in the
        context.segments_to_bind property, based on the value of the
        context.host property, any relevant port or network
        attributes, and its own knowledge of the network topology. At
        the top level, context.segments_to_bind contains the static
        segments of the port's network. At each lower level of
        binding, it contains static or dynamic segments supplied by
        the driver that bound at the level above. If the driver is
        able to complete the binding of the port to any segment in
        context.segments_to_bind, it must call context.set_binding
        with the binding details. If it can partially bind the port,
        it must call context.continue_binding with the network
        segments to be used to bind at the next lower level.

        If the binding results are committed after bind_port returns,
        they will be seen by all mechanism drivers as
        update_port_precommit and update_port_postcommit calls. But if
        some other thread or process concurrently binds or updates the
        port, these binding results will not be committed, and
        update_port_precommit and update_port_postcommit will not be
        called on the mechanism drivers with these results. Because
        binding results can be discarded rather than committed,
        drivers should avoid making persistent state changes in
        bind_port, or else must ensure that such state changes are
        eventually cleaned up.

        Implementing this method explicitly declares the mechanism
        driver as having the intention to bind ports. This is inspected
        by the QoS service to identify the available QoS rules you
        can use with ports.
        """
        port = context.current
        network = context.network.current
        switch_name, switch_port, segmentation_id = \
            self._link_info_from_port(port, network)
        if not self._is_port_supported(port):
            LOG.debug('Port {} has vnic_type set to %s which is not correct '
                      'to work with networking-ansible driver.'.format(
                          port['id'], port[portbindings.VNIC_TYPE]))
            return

        segments = context.segments_to_bind

        LOG.debug('Plugging in port {switch_port} on '
                  '{switch_name} to vlan: {segmentation_id}'.format(
                      switch_port=switch_port,
                      switch_name=switch_name,
                      segmentation_id=segmentation_id))

        provisioning_blocks.add_provisioning_component(
            context._plugin_context, port['id'], resources.PORT,
            ANSIBLE_NETWORKING_ENTITY)

        # Assign port to network
        try:
            self.ansnet.update_access_port(switch_name, switch_port,
                                           segmentation_id)
            context.set_binding(segments[0][ml2api.ID],
                                portbindings.VIF_TYPE_OTHER, {})
            LOG.info('Port {neutron_port} has been plugged into '
                     'network {net_id} on device {switch_name}'.format(
                         neutron_port=port['id'],
                         net_id=network['id'],
                         switch_name=switch_name))
        except Exception as e:
            LOG.error('Failed to plug in port {neutron_port} on '
                      'device: {switch_name} from network {net_id} '
                      'reason: {exc}'.format(neutron_port=port['id'],
                                             net_id=network['id'],
                                             switch_name=switch_name,
                                             exc=e))
            raise ml2_exc.MechanismDriverError(e)
コード例 #12
0
    def create_network_postcommit(self, context):
        """Create a network.

        :param context: NetworkContext instance describing the new
        network.

        Called after the transaction commits. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance. Raising an exception will
        cause the deletion of the resource.
        """

        # assuming all hosts
        # TODO(radez): can we filter by physnets?
        # TODO(michchap): we should be able to do each switch in parallel
        # if it becomes a performance issue. switch topology might also
        # open up options for filtering.
        for host_name in self.ml2config.inventory:
            host = self.ml2config.inventory[host_name]
            if host.get('manage_vlans', True):

                network = context.current
                network_id = network['id']
                provider_type = network['provider:network_type']
                segmentation_id = network['provider:segmentation_id']

                lock = self.coordinator.get_lock(host_name)
                with lock:
                    if provider_type == 'vlan' and segmentation_id:

                        # re-request network info in case it's stale
                        net = Network.get_object(context._plugin_context,
                                                 id=network_id)
                        LOG.debug('network create object: {}'.format(net))

                        # network was since deleted by user and we can discard
                        # this request
                        if not net:
                            return

                        # check the vlan for this request is still associated
                        # with this network. We don't currently allow updating
                        # the segment on a network - it's disallowed at the
                        # neutron level for provider networks - but that could
                        # change in the future
                        s_ids = [s.segmentation_id for s in net.segments]
                        if segmentation_id not in s_ids:
                            return

                        # Create VLAN on the switch
                        try:
                            self.net_runr.create_vlan(
                                host_name, segmentation_id,
                                **self.extra_params[host_name])
                            LOG.info('Network {net_id}, segmentation '
                                     '{seg} has been added on '
                                     'ansible host {host}'.format(
                                         net_id=network['id'],
                                         seg=segmentation_id,
                                         host=host_name))

                        except Exception as e:
                            # TODO(radez) I don't think there is a message
                            #             returned from ansible runner's
                            #             exceptions
                            LOG.error('Failed to create network {net_id} '
                                      'on ansible host: {host}, '
                                      'reason: {err}'.format(net_id=network_id,
                                                             host=host_name,
                                                             err=e))
                            raise ml2_exc.MechanismDriverError(e)
コード例 #13
0
    def delete_network_postcommit(self, context):
        """Delete a network.

        :param context: NetworkContext instance describing the current
        state of the network, prior to the call to delete it.

        Called after the transaction commits. Call can block, though
        will block the entire process so care should be taken to not
        drastically affect performance. Runtime errors are not
        expected, and will not prevent the resource from being
        deleted.
        """

        # assuming all hosts
        # TODO(radez): can we filter by physnets?
        LOG.debug('ansnet:network delete')
        for host_name in self.ml2config.inventory:
            host = self.ml2config.inventory[host_name]

            network = context.current
            provider_type = network['provider:network_type']
            segmentation_id = network['provider:segmentation_id']
            physnet = network['provider:physical_network']

            if provider_type == 'vlan' and segmentation_id:
                if host.get('manage_vlans', True):
                    lock = self.coordinator.get_lock(host_name)
                    with lock:
                        # Find out if this segment is active.
                        # We need to find out if this segment is being used
                        # by another network before deleting it from the switch
                        # since reordering could mean that a vlan is recycled
                        # by the time this request is satisfied. Getting
                        # the current network is not enough
                        db = context._plugin_context

                        segments = NetworkSegment.get_objects(
                            db, segmentation_id=segmentation_id)

                        for segment in segments:
                            if (segment.segmentation_id == segmentation_id
                                    and segment.physical_network == physnet
                                    and segment.network_type == 'vlan'):
                                LOG.debug('Not deleting segment {} from {}'
                                          'because it was recreated'.format(
                                              segmentation_id, physnet))
                                return

                        # Delete VLAN on the switch
                        try:
                            self.net_runr.delete_vlan(
                                host_name, segmentation_id,
                                **self.extra_params[host_name])
                            LOG.info('Network {net_id} has been deleted on '
                                     'ansible host {host}'.format(
                                         net_id=network['id'], host=host_name))

                        except Exception as e:
                            LOG.error('Failed to delete network {net} '
                                      'on ansible host: {host}, '
                                      'reason: {err}'.format(net=network['id'],
                                                             host=host_name,
                                                             err=e))
                            raise ml2_exc.MechanismDriverError(e)