Exemple #1
0
def _validate_device_list(data, valid_values=None):
    """Validate the list of service definitions."""
    if not data:
        # Devices must be provided
        msg = _("Cannot create a gateway with an empty device list")
        return msg
    try:
        for device in data:
            key_specs = {DEVICE_ID_ATTR:
                         {'type:regex': attributes.UUID_PATTERN,
                          'required': True},
                         IFACE_NAME_ATTR:
                         {'type:string': None,
                          'required': False}}
            err_msg = attributes._validate_dict(
                device, key_specs=key_specs)
            if err_msg:
                return err_msg
            unexpected_keys = [key for key in device if key not in key_specs]
            if unexpected_keys:
                err_msg = (_("Unexpected keys found in device description:%s")
                           % ",".join(unexpected_keys))
                return err_msg
    except TypeError:
        return (_("%s: provided data are not iterable") %
                _validate_device_list.__name__)
Exemple #2
0
    def _check_lb_service_on_router(self, resource, event, trigger,
                                    payload=None):
        """Prevent removing a router GW or deleting a router used by LB"""
        router_id = payload.resource_id
        context = payload.context
        nsx_router_id = nsx_db.get_nsx_router_id(context.session,
                                                 router_id)
        if not nsx_router_id:
            # Skip non-v3 routers (could be a V router in case of TVD plugin)
            return
        nsxlib = self.loadbalancer.core_plugin.nsxlib
        service_client = nsxlib.load_balancer.service
        # Check if there is any lb service on nsx router
        lb_service = service_client.get_router_lb_service(nsx_router_id)
        if lb_service:
            msg = _('Cannot delete a %s as it still has lb service '
                    'attachment') % resource
            raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)

        # Also check if there are any loadbalancers attached to this router
        # subnets
        router_subnets = self.loadbalancer.core_plugin._find_router_subnets(
            context.elevated(), router_id)
        subnet_ids = [subnet['id'] for subnet in router_subnets]
        if subnet_ids and self._get_lb_ports(context.elevated(), subnet_ids):
            msg = (_('Cannot delete a %s as it used by a loadbalancer') %
                   resource)
            raise n_exc.BadRequest(resource='lbaas-lb', msg=msg)
Exemple #3
0
 def _create_ssl_cert(self, edge_id=None):
     # Create a self signed certificate in the backend if both Cert details
     # and private key are not supplied in nsx.ini
     if (not cfg.CONF.nsxv.metadata_nova_client_cert and
         not cfg.CONF.nsxv.metadata_nova_client_priv_key):
         h = self.nsxv_plugin.nsx_v.vcns.create_csr(edge_id)[0]
         # Extract the CSR ID from header
         csr_id = lbaas_common.extract_resource_id(h['location'])
         # Create a self signed certificate
         cert = self.nsxv_plugin.nsx_v.vcns.create_csr_cert(csr_id)[1]
         cert_id = cert['objectId']
     else:
         # Raise an error if either the Cert path or the private key is not
         # configured
         error = None
         if not cfg.CONF.nsxv.metadata_nova_client_cert:
             error = _('Metadata certificate path not configured')
         elif not cfg.CONF.nsxv.metadata_nova_client_priv_key:
             error = _('Metadata client private key not configured')
         if error:
             raise nsxv_exc.NsxPluginException(err_msg=error)
         pem_encoding = utils.read_file(
             cfg.CONF.nsxv.metadata_nova_client_cert)
         priv_key = utils.read_file(
             cfg.CONF.nsxv.metadata_nova_client_priv_key)
         request = {
             'pemEncoding': pem_encoding,
             'privateKey': priv_key}
         cert = self.nsxv_plugin.nsx_v.vcns.upload_edge_certificate(
             edge_id, request)[1]
         cert_id = cert.get('certificates')[0]['objectId']
     return cert_id
Exemple #4
0
def validate_session_persistence(pool, listener, completor, old_pool=None):
    sp = pool.get('session_persistence')
    if not listener or not sp:
        # safety first!
        return
    # L4 listeners only allow source IP persistence
    if (listener['protocol'] == lb_const.LB_PROTOCOL_TCP and
            sp['type'] != lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP):
        completor(success=False)
        msg = (_("Invalid session persistence type %(sp_type)s for "
                 "pool on listener %(lst_id)s with %(proto)s protocol") %
               {'sp_type': sp['type'],
                'lst_id': listener['id'],
                'proto': listener['protocol']})
        raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
    # Cannot switch (yet) on update from source IP to cookie based, and
    # vice versa
    cookie_pers_types = (lb_const.LB_SESSION_PERSISTENCE_HTTP_COOKIE,
                         lb_const.LB_SESSION_PERSISTENCE_APP_COOKIE)
    if old_pool:
        oldsp = old_pool.get('session_persistence')
        if not oldsp:
            return
        if ((sp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP and
             oldsp['type'] in cookie_pers_types) or
                (sp['type'] in cookie_pers_types and
                 oldsp['type'] == lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP)):
            completor(success=False)
            msg = (_("Cannot update session persistence type to "
                     "%(sp_type)s for pool on listener %(lst_id)s "
                     "from %(old_sp_type)s") %
                   {'sp_type': sp['type'],
                    'lst_id': listener['id'],
                    'old_sp_type': oldsp['type']})
            raise n_exc.BadRequest(resource='lbaas-pool', msg=msg)
Exemple #5
0
 def update_backend_pool(self, nsx_pool_id, subnet_request):
     update_args = {
         'cidr': self._get_cidr_from_request(subnet_request),
         'allocation_ranges': self._get_ranges_from_request(subnet_request),
         'gateway_ip': subnet_request.gateway_ip}
     try:
         self.nsxlib_ipam.update(
             nsx_pool_id, **update_args)
     except nsx_lib_exc.ManagerError as e:
         LOG.error("NSX IPAM failed to update pool %(id)s: "
                   " %(e)s; code %(code)s",
                   {'e': e,
                    'id': nsx_pool_id,
                    'code': e.error_code})
         if (e.error_code == error.ERR_CODE_IPAM_RANGE_MODIFY or
             e.error_code == error.ERR_CODE_IPAM_RANGE_DELETE or
             e.error_code == error.ERR_CODE_IPAM_RANGE_SHRUNK):
             # The change is not allowed: already allocated IPs out of
             # the new range
             raise ipam_exc.InvalidSubnetRequest(
                 reason=_("Already allocated IPs outside of the updated "
                          "pools"))
     except Exception as e:
         # unexpected error
         msg = _('Failed to update subnet IPAM: %s') % e
         raise ipam_exc.IpamValueInvalid(message=msg)
Exemple #6
0
 def _validate_device_list(self, devices, check_backend=True):
     # In NSXv3, one L2 gateway is mapped to one bridge endpoint profle.
     # So we expect only one device to be configured as part of
     # a L2 gateway resource. The name of the device must be the bridge
     # endpoint profile UUID.
     if len(devices) != 1:
         msg = _("Only a single device is supported by the NSX L2"
                 "gateway driver")
         raise n_exc.InvalidInput(error_message=msg)
     dev_name = devices[0]['device_name']
     if not uuidutils.is_uuid_like(dev_name):
         msg = _("Device name must be configured with a UUID")
         raise n_exc.InvalidInput(error_message=msg)
     # Ensure the L2GW device is a valid bridge endpoint profile in NSX
     if check_backend:
         try:
             self._core_plugin.nsxlib.bridge_endpoint_profile.get(
                 dev_name)
         except nsxlib_exc.ResourceNotFound:
             msg = _("Could not find Bridge Endpoint Profile for L2 "
                     "gateway device %s on NSX backend") % dev_name
             LOG.error(msg)
             raise n_exc.InvalidInput(error_message=msg)
     # One L2 gateway must have only one interface defined.
     interfaces = devices[0].get(l2gw_const.IFACE_NAME_ATTR)
     if len(interfaces) > 1:
         msg = _("Maximum of one interface is supported by the NSX L2 "
                 "gateway driver")
         raise n_exc.InvalidInput(error_message=msg)
Exemple #7
0
 def _validate_network(self, context, net_data):
     network_type = net_data.get(pnet.NETWORK_TYPE)
     segmentation_id = net_data.get(pnet.SEGMENTATION_ID)
     segmentation_id_set = attr.is_attr_set(segmentation_id)
     if not context.is_admin:
         err_msg = _("Only and admin can create a DVS provider "
                     "network")
         raise n_exc.InvalidInput(error_message=err_msg)
     err_msg = None
     if network_type == c_utils.NetworkTypes.FLAT:
         if segmentation_id_set:
             err_msg = _("Segmentation ID cannot be specified with "
                         "flat network type")
     elif network_type == c_utils.NetworkTypes.VLAN:
         if not segmentation_id_set:
             err_msg = _("Segmentation ID must be specified with "
                         "vlan network type")
         elif (segmentation_id_set and
               not utils.is_valid_vlan_tag(segmentation_id)):
             err_msg = (_("%(segmentation_id)s out of range "
                          "(%(min_id)s through %(max_id)s)") %
                        {'segmentation_id': segmentation_id,
                         'min_id': constants.MIN_VLAN_TAG,
                         'max_id': constants.MAX_VLAN_TAG})
     else:
         err_msg = (_("%(net_type_param)s %(net_type_value)s not "
                      "supported") %
                    {'net_type_param': pnet.NETWORK_TYPE,
                     'net_type_value': network_type})
     if err_msg:
         raise n_exc.InvalidInput(error_message=err_msg)
 def _validate_network_mapping_info(self, network_mapping_info):
     self._set_mapping_info_defaults(network_mapping_info)
     network_id = network_mapping_info.get(NETWORK_ID)
     if not network_id:
         raise exceptions.InvalidInput(
             error_message=_("A network identifier must be specified "
                             "when connecting a network to a network "
                             "gateway. Unable to complete operation"))
     connection_attrs = set(network_mapping_info.keys())
     if not connection_attrs.issubset(ALLOWED_CONNECTION_ATTRIBUTES):
         raise exceptions.InvalidInput(
             error_message=(_("Invalid keys found among the ones provided "
                              "in request body: %(connection_attrs)s."),
                            connection_attrs))
     seg_type = network_mapping_info.get(SEGMENTATION_TYPE)
     seg_id = network_mapping_info.get(SEGMENTATION_ID)
     # It is important to validate that the segmentation ID is actually an
     # integer value
     try:
         seg_id = int(seg_id)
     except ValueError:
         msg = _("An invalid segmentation ID was specified. The "
                 "segmentation ID must be a positive integer number")
         raise exceptions.InvalidInput(error_message=msg)
     # The NSX plugin accepts 0 as a valid vlan tag
     seg_id_valid = seg_id == 0 or utils.is_valid_vlan_tag(seg_id)
     if seg_type.lower() == 'flat' and seg_id:
         msg = _("Cannot specify a segmentation id when "
                 "the segmentation type is flat")
         raise exceptions.InvalidInput(error_message=msg)
     elif (seg_type.lower() == 'vlan' and not seg_id_valid):
         msg = _("Invalid segmentation id (%s) for "
                 "vlan segmentation type") % seg_id
         raise exceptions.InvalidInput(error_message=msg)
     return network_id
    def __init__(self, az_conf, az_class, default_availability_zones=None):
        self.availability_zones = {}

        # Add the configured availability zones
        for az in az_conf:
            obj = az_class(az)
            self.availability_zones[obj.name] = obj

        # add a default entry
        obj = az_class(None, default_name=self.default_name)
        self.availability_zones[obj.name] = obj

        # validate the default az:
        if default_availability_zones:
            # we support only 1 default az
            if len(default_availability_zones) > 1:
                raise nsx_exc.NsxInvalidConfiguration(
                    opt_name="default_availability_zones",
                    opt_value=default_availability_zones,
                    reason=_("The NSX plugin supports only 1 default AZ"))
            default_az_name = default_availability_zones[0]
            if (default_az_name not in self.availability_zones):
                raise nsx_exc.NsxInvalidConfiguration(
                    opt_name="default_availability_zones",
                    opt_value=default_availability_zones,
                    reason=_("The default AZ is not defined in the NSX "
                             "plugin"))
            else:
                self._default_az = self.availability_zones[default_az_name]
        else:
            self._default_az = self.availability_zones[self.default_name]
Exemple #10
0
def add_nsx_extensions_to_parser(parser, client_manager, is_create=True):
    allowed_extensions = utils.get_extensions(client_manager)
    # Provider security group (only for create action)
    if (is_create and
        'provider-security-group' in allowed_extensions):
        parser.add_argument(
            '--provider-security-group',
            metavar='<provider-security-group>',
            action='append',
            dest='provider_security_groups',
            help=_("Provider Security group to associate with this port "
                   "(name or ID) "
                   "(repeat option to set multiple security groups)")
        )
    if 'vnic-index' in allowed_extensions:
        # vnic index
        parser.add_argument(
            '--vnic-index',
            type=int,
            metavar='<vnic-index>',
            help=_("Vnic index")
        )
    if 'mac-learning' in allowed_extensions:
        # mac-learning-enabled
        mac_learning_group = parser.add_mutually_exclusive_group()
        mac_learning_group.add_argument(
            '--enable-mac-learning',
            action='store_true',
            help=_("Enable MAC learning")
        )
        mac_learning_group.add_argument(
            '--disable-mac-learning',
            action='store_true',
            help=_("Disable MAC learning (Default")
        )
Exemple #11
0
    def create_ipsec_site_connection(self, context, ipsec_site_connection):
        LOG.debug('Creating ipsec site connection %(conn_info)s.',
                  {"conn_info": ipsec_site_connection})
        new_ipsec = self._convert_ipsec_conn(context, ipsec_site_connection)
        vpnservice_id = ipsec_site_connection['vpnservice_id']
        edge_id = self._get_router_edge_id(context, vpnservice_id)[1]
        with locking.LockManager.get_lock(edge_id):
            vse_sites = self._generate_new_sites(edge_id, new_ipsec)
            ipsec_id = ipsec_site_connection["id"]
            try:
                LOG.debug('Updating ipsec vpn configuration %(vse_sites)s.',
                          {'vse_sites': vse_sites})
                self._update_ipsec_config(edge_id, vse_sites, enabled=True)
            except vcns_exc.VcnsApiException:
                self._update_status(context, vpnservice_id, ipsec_id,
                                    "ERROR")
                msg = (_("Failed to create ipsec site connection "
                         "configuration with %(edge_id)s.") %
                       {'edge_id': edge_id})
                raise nsxv_exc.NsxPluginException(err_msg=msg)

            LOG.debug('Updating ipsec vpn firewall')
            try:
                self._update_firewall_rules(context, vpnservice_id)
            except vcns_exc.VcnsApiException:
                self._update_status(context, vpnservice_id, ipsec_id, "ERROR")
                msg = (_("Failed to update firewall rule for ipsec vpn "
                         "with %(edge_id)s.") % {'edge_id': edge_id})
                raise nsxv_exc.NsxPluginException(err_msg=msg)
            self._update_status(context, vpnservice_id, ipsec_id, "ACTIVE")
Exemple #12
0
def update_lrouter_port_ips(cluster, lrouter_id, lport_id,
                            ips_to_add, ips_to_remove):
    uri = nsxlib._build_uri_path(LROUTERPORT_RESOURCE, lport_id, lrouter_id)
    try:
        port = nsxlib.do_request(HTTP_GET, uri, cluster=cluster)
        # TODO(salvatore-orlando): Enforce ips_to_add intersection with
        # ips_to_remove is empty
        ip_address_set = set(port['ip_addresses'])
        ip_address_set = ip_address_set - set(ips_to_remove)
        ip_address_set = ip_address_set | set(ips_to_add)
        # Set is not JSON serializable - convert to list
        port['ip_addresses'] = list(ip_address_set)
        nsxlib.do_request(HTTP_PUT, uri, jsonutils.dumps(port),
                          cluster=cluster)
    except exception.NotFound:
        # FIXME(salv-orlando):avoid raising different exception
        data = {'lport_id': lport_id, 'lrouter_id': lrouter_id}
        msg = (_("Router Port %(lport_id)s not found on router "
                 "%(lrouter_id)s") % data)
        LOG.exception(msg)
        raise nsx_exc.NsxPluginException(err_msg=msg)
    except api_exc.NsxApiException as e:
        msg = _("An exception occurred while updating IP addresses on a "
                "router logical port:%s") % e
        LOG.exception(msg)
        raise nsx_exc.NsxPluginException(err_msg=msg)
Exemple #13
0
    def get_details(self):
        """Return subnet data as a SpecificSubnetRequest"""
        # get the pool from the backend
        try:
            pool_details = self.nsxlib_ipam.get(self._nsx_pool_id)
        except Exception as e:
            msg = _('Failed to get details for nsx pool: %(id)s: '
                    '%(e)s') % {'id': self._nsx_pool_id, 'e': e}
            raise ipam_exc.IpamValueInvalid(message=msg)

        first_range = pool_details.get('subnets', [None])[0]
        if not first_range:
            msg = _('Failed to get details for nsx pool: %(id)s') % {
                'id': self._nsx_pool_id}
            raise ipam_exc.IpamValueInvalid(message=msg)

        cidr = first_range.get('cidr')
        gateway_ip = first_range.get('gateway_ip')
        pools = []
        for subnet in pool_details.get('subnets', []):
            for ip_range in subnet.get('allocation_ranges', []):
                pools.append(netaddr.IPRange(ip_range.get('start'),
                                             ip_range.get('end')))
        return ipam_req.SpecificSubnetRequest(
            self._tenant_id, self._subnet_id,
            cidr, gateway_ip=gateway_ip, allocation_pools=pools)
Exemple #14
0
    def create_flow_classifier_precommit(self, context):
        """Validate the flow classifier data before committing the transaction

        The NSX-v redirect rules does not support:
        - logical ports
        - l7 parameters
        - source ports range / destination port range with more than 15 ports
        """
        flow_classifier = context.current

        # Logical source port
        logical_source_port = flow_classifier['logical_source_port']
        if logical_source_port is not None:
            msg = _('The NSXv driver does not support setting '
                    'logical source port in FlowClassifier')
            raise exc.FlowClassifierBadRequest(message=msg)

        # Logical destination port
        logical_destination_port = flow_classifier['logical_destination_port']
        if logical_destination_port is not None:
            msg = _('The NSXv driver does not support setting '
                    'logical destination port in FlowClassifier')
            raise exc.FlowClassifierBadRequest(message=msg)

        # L7 parameters
        l7_params = flow_classifier['l7_parameters']
        if l7_params is not None and len(l7_params.keys()) > 0:
            msg = _('The NSXv driver does not support setting '
                    'L7 parameters in FlowClassifier')
            raise exc.FlowClassifierBadRequest(message=msg)
Exemple #15
0
    def _extract_external_gw(self, context, router, is_extract=True):
        r = router['router']
        gw_info = constants.ATTR_NOT_SPECIFIED
        # First extract the gateway info in case of updating
        # gateway before edge is deployed.
        if 'external_gateway_info' in r:
            gw_info = r.get('external_gateway_info', {})
            if is_extract:
                del r['external_gateway_info']
            network_id = (gw_info.get('network_id') if gw_info
                          else None)
            if network_id:
                ext_net = self._get_network(context, network_id)
                if not ext_net.external:
                    msg = (_("Network '%s' is not a valid external network") %
                           network_id)
                    raise n_exc.BadRequest(resource='router', msg=msg)

                subnets = self._get_subnets_by_network(context.elevated(),
                                                       network_id)
                if not subnets:
                    msg = _("Cannot update gateway on Network '%s' "
                            "with no subnet") % network_id
                    raise n_exc.BadRequest(resource='router', msg=msg)
        return gw_info
Exemple #16
0
 def validate_tier0(self, tier0_groups_dict, tier0_uuid):
     err_msg = None
     try:
         lrouter = self._router_client.get(tier0_uuid)
     except nsx_exc.ResourceNotFound:
         err_msg = (_("Tier0 router %s not found at the backend. Either a "
                      "valid UUID must be specified or a default tier0 "
                      "router UUID must be configured in nsx.ini") %
                    tier0_uuid)
     else:
         edge_cluster_uuid = lrouter.get('edge_cluster_id')
         if not edge_cluster_uuid:
             err_msg = _("Failed to get edge cluster uuid from tier0 "
                         "router %s at the backend") % lrouter
         else:
             edge_cluster = nsxlib.get_edge_cluster(edge_cluster_uuid)
             member_index_list = [member['member_index']
                                  for member in edge_cluster['members']]
             if len(member_index_list) < MIN_EDGE_NODE_NUM:
                 err_msg = _("%(act_num)s edge members found in "
                             "edge_cluster %(cluster_id)s, however we "
                             "require at least %(exp_num)s edge nodes "
                             "in edge cluster for use.") % {
                     'act_num': len(member_index_list),
                     'exp_num': MIN_EDGE_NODE_NUM,
                     'cluster_id': edge_cluster_uuid}
     if err_msg:
         raise n_exc.InvalidInput(error_message=err_msg)
     else:
         tier0_groups_dict[tier0_uuid] = {
             'edge_cluster_uuid': edge_cluster_uuid,
             'member_index_list': member_index_list}
def _validate_dns_format(data):
    if not data:
        return
    try:
        # Allow values ending in period '.'
        trimmed = data if not data.endswith('.') else data[:-1]
        names = trimmed.split('.')
        for name in names:
            if not name:
                raise TypeError(_("Encountered an empty component"))
            if name.endswith('-') or name[0] == '-':
                raise TypeError(
                    _("Name '%s' must not start or end with a hyphen") % name)
            if not re.match(DNS_LABEL_REGEX, name):
                raise TypeError(
                    _("Name '%s' must be 1-63 characters long, each of "
                      "which can only be alphanumeric or a hyphen") % name)
        # RFC 1123 hints that a TLD can't be all numeric. last is a TLD if
        # it's an FQDN.
        if len(names) > 1 and re.match("^[0-9]+$", names[-1]):
            raise TypeError(_("TLD '%s' must not be all numeric") % names[-1])
    except TypeError as e:
        msg = _("'%(data)s' not a valid DNS search domain. Reason: "
                "%(reason)s") % {'data': data, 'reason': str(e)}
        return msg
Exemple #18
0
    def validate(self, context, network_id):
        """Validate and return subnet's dhcp info for migration."""
        network = self.plugin.get_network(context, network_id)

        if self.manager.lsn_exists(context, network_id):
            reason = _("LSN already exist")
            raise p_exc.LsnMigrationConflict(net_id=network_id, reason=reason)

        if network[external_net.EXTERNAL]:
            reason = _("Cannot migrate an external network")
            raise n_exc.BadRequest(resource='network', msg=reason)

        filters = {'network_id': [network_id]}
        subnets = self.plugin.get_subnets(context, filters=filters)
        count = len(subnets)
        if count == 0:
            return None
        elif count == 1 and subnets[0]['cidr'] == rpc.METADATA_SUBNET_CIDR:
            reason = _("Cannot migrate a 'metadata' network")
            raise n_exc.BadRequest(resource='network', msg=reason)
        elif count > 1:
            reason = _("Unable to support multiple subnets per network")
            raise p_exc.LsnMigrationConflict(net_id=network_id, reason=reason)
        else:
            return subnets[0]
Exemple #19
0
    def delete_ipsec_site_connection(self, context, ipsec_site_conn):
        LOG.debug('Deleting ipsec site connection %(site)s.',
                  {"site": ipsec_site_conn})
        ipsec_id = ipsec_site_conn['id']
        edge_id = self._get_router_edge_id(context,
                                           ipsec_site_conn['vpnservice_id'])[1]
        with locking.LockManager.get_lock(edge_id):
            del_site, vse_sites = self._find_vse_site(context, edge_id,
                                                      ipsec_site_conn)
            if not del_site:
                LOG.error("Failed to find ipsec_site_connection "
                          "%(ipsec_site_conn)s with %(edge_id)s.",
                          {'ipsec_site_conn': ipsec_site_conn,
                           'edge_id': edge_id})
                raise nsxv_exc.NsxIPsecVpnMappingNotFound(conn=ipsec_id)

            vse_sites.remove(del_site)
            enabled = True if vse_sites else False
            try:
                self._update_ipsec_config(edge_id, vse_sites, enabled)
            except vcns_exc.VcnsApiException:
                msg = (_("Failed to delete ipsec site connection "
                         "configuration with edge_id: %(edge_id)s.") %
                       {'egde_id': edge_id})
                raise nsxv_exc.NsxPluginException(err_msg=msg)
            try:
                self._update_firewall_rules(context,
                                            ipsec_site_conn['vpnservice_id'])
            except vcns_exc.VcnsApiException:
                msg = _("Failed to update firewall rule for ipsec vpn with "
                        "%(edge_id)s.") % {'edge_id': edge_id}
                raise nsxv_exc.NsxPluginException(err_msg=msg)
Exemple #20
0
    def create_l2_gateway_connection_precommit(self, context, gw_connection):
        """Validate the L2 gateway connection
        Do not allow another connection with the same bride cluster and seg_id
        """
        admin_ctx = context.elevated()
        nsxlib = self._core_plugin.nsxlib
        l2gw_id = gw_connection.get(l2gw_const.L2GATEWAY_ID)
        devices = self._get_l2_gateway_devices(context, l2gw_id)
        bep_id = devices[0].get('device_name')
        # Check for bridge endpoint profile existence
        # if bridge endpoint profile is not found, this is likely an old
        # connection, fail with error.
        try:
            nsxlib.bridge_endpoint_profile.get_id_by_name_or_id(bep_id)
        except nsxlib_exc.ManagerError as e:
            msg = (_("Error while retrieving bridge endpoint profile "
                     "%(bep_id)s from NSX backend. Check that the profile "
                     "exits and there are not multiple profiles with "
                     "the given name. Exception: %(exc)s") %
                   {'bep_id': bep_id, 'exc': e})
            raise n_exc.InvalidInput(error_message=msg)

        interface_name, seg_id = self._get_conn_parameters(
            admin_ctx, gw_connection)
        try:
            # Use search API for listing bridge endpoints on NSX for provided
            # VLAN id, transport zone id, and Bridge endpoint profile
            endpoints = nsxlib.search_all_resource_by_attributes(
                nsxlib.bridge_endpoint.resource_type,
                bridge_endpoint_profile_id=bep_id,
                vlan_transport_zone_id=interface_name,
                vlan=seg_id)
            endpoint_map = dict((endpoint['id'],
                                 endpoint['bridge_endpoint_profile_id'])
                            for endpoint in endpoints)
        except nsxlib_exc.ManagerError as e:
            msg = (_("Error while retrieving endpoints for bridge endpoint "
                     "profile %(bep_id)s s from NSX backend. "
                     "Exception: %(exc)s") % {'bep_id': bep_id, 'exc': e})
            raise n_exc.InvalidInput(error_message=msg)

        # get all bridge endpoint ports
        with db_api.CONTEXT_WRITER.using(admin_ctx):
            port_filters = {'device_owner': [nsx_constants.BRIDGE_ENDPOINT]}
            ports = self._core_plugin.get_ports(
                admin_ctx, filters=port_filters)
            for port in ports:
                device_id = port.get('device_id')
                if endpoint_map.get(device_id) == bep_id:
                    # This device is using the same vlan id and bridge endpoint
                    # profile as the one requested. Not ok.
                    msg = (_("Cannot create multiple connections with the "
                             "same segmentation id %(seg_id)s for bridge "
                             "endpoint profile %(bep_id)s") %
                           {'seg_id': seg_id,
                            'bep_id': bep_id})
                    raise n_exc.InvalidInput(error_message=msg)
Exemple #21
0
 def _validate_interface_list(self, interfaces):
     # In NSXv, interface is mapped to a vDS VLAN port group.
     # Since HA is not supported, only one interface is expected
     if len(interfaces) != 1:
         msg = _("Only a single interface is supported for one L2 gateway")
         raise n_exc.InvalidInput(error_message=msg)
     if not self._nsxv.vcns.validate_network(interfaces[0]['name']):
         msg = _("Configured interface not found")
         raise n_exc.InvalidInput(error_message=msg)
    def _check_advertisment_overlap(self, context, ipsec_site_conn):
        """Validate there is no overlapping advertisement of networks

        The plugin advertise all no-snat routers networks + vpn local
        networks.
        The NSX does not allow different Tier1 router to advertise the
        same subnets
        """
        admin_con = context.elevated()
        srv_id = ipsec_site_conn.get('vpnservice_id')
        srv = self.vpn_plugin._get_vpnservice(admin_con, srv_id)
        this_router = srv['router_id']
        this_cidr = srv['subnet']['cidr']

        # get all subnets of no-snat routers
        all_routers = self._core_plugin.get_routers(admin_con)
        nosnat_routers = [rtr for rtr in all_routers
                          if (rtr['id'] != this_router and
                              rtr.get('external_gateway_info') and
                              not rtr['external_gateway_info'].get(
                                  'enable_snat',
                                  cfg.CONF.enable_snat_by_default))]
        for rtr in nosnat_routers:
            if rtr['id'] == this_router:
                continue
            # go over the subnets of this router
            subnets = self._core_plugin._find_router_subnets_cidrs(
                admin_con, rtr['id'])
            if subnets and netaddr.IPSet(subnets) & netaddr.IPSet([this_cidr]):
                msg = (_("Cannot create connection with overlapping local "
                         "cidrs %(local)s which was already advertised by "
                         "no-snat router %(rtr)s") % {'local': subnets,
                                                      'rtr': rtr['id']})
                raise nsx_exc.NsxVpnValidationError(details=msg)

        # add all vpn local subnets
        connections = self.vpn_plugin.get_ipsec_site_connections(admin_con)
        for conn in connections:
            # skip this connection and connections in non active state
            if (conn['id'] == ipsec_site_conn.get('id') or
                conn['status'] != constants.ACTIVE):
                continue
            # check the service local address
            conn_srv_id = conn.get('vpnservice_id')
            conn_srv = self.vpn_plugin._get_vpnservice(admin_con, conn_srv_id)
            if conn_srv['router_id'] == this_router:
                continue
            conn_cidr = conn_srv['subnet']['cidr']
            if netaddr.IPSet([conn_cidr]) & netaddr.IPSet([this_cidr]):
                msg = (_("Cannot create connection with overlapping local "
                         "cidr %(local)s which was already advertised by "
                         "router %(rtr)s and connection %(conn)s") % {
                    'local': conn_cidr,
                    'rtr': conn_srv['router_id'],
                    'conn': conn['id']})
                raise nsx_exc.NsxVpnValidationError(details=msg)
Exemple #23
0
    def _get_proxy_edges(self, context):
        proxy_edge_ips = []

        db_edge_ips = get_db_internal_edge_ips(context, self.az.name)
        if len(db_edge_ips) > len(self.az.mgt_net_proxy_ips):
            error = (_('Number of configured metadata proxy IPs is smaller '
                      'than number of Edges which are already provisioned '
                      'for availability zone %s'), self.az.name)
            raise nsxv_exc.NsxPluginException(err_msg=error)

        pool = eventlet.GreenPool(min(MAX_INIT_THREADS,
                                      len(self.az.mgt_net_proxy_ips)))

        # Edge IPs that exist in both lists have to be validated that their
        # Edge appliance settings are valid
        for edge_inner_ip in pool.imap(
                self._setup_proxy_edge_route_and_connectivity,
                list(set(db_edge_ips) & set(self.az.mgt_net_proxy_ips))):
            proxy_edge_ips.append(edge_inner_ip)

        # Edges that exist only in the CFG list, should be paired with Edges
        # that exist only in the DB list. The existing Edge from the list will
        # be reconfigured to match the new config
        edge_to_convert_ips = (
            list(set(db_edge_ips) - set(self.az.mgt_net_proxy_ips)))
        edge_ip_to_set = (
            list(set(self.az.mgt_net_proxy_ips) - set(db_edge_ips)))

        if edge_to_convert_ips:
            if cfg.CONF.nsxv.metadata_initializer:
                for edge_inner_ip in pool.imap(
                        self._setup_proxy_edge_external_interface_ip,
                        zip(edge_to_convert_ips, edge_ip_to_set)):
                    proxy_edge_ips.append(edge_inner_ip)
            else:
                error = _('Metadata initialization is incomplete on '
                          'initializer node')
                raise nsxv_exc.NsxPluginException(err_msg=error)

        # Edges that exist in the CFG list but do not have a matching DB
        # element will be created.
        remaining_cfg_ips = edge_ip_to_set[len(edge_to_convert_ips):]
        if remaining_cfg_ips:
            if cfg.CONF.nsxv.metadata_initializer:
                for edge_inner_ip in pool.imap(
                        self._setup_new_proxy_edge, remaining_cfg_ips):
                    proxy_edge_ips.append(edge_inner_ip)

                pool.waitall()
            else:
                error = _('Metadata initialization is incomplete on '
                          'initializer node')
                raise nsxv_exc.NsxPluginException(err_msg=error)

        return proxy_edge_ips
Exemple #24
0
 def backend_allocate(self, address_request):
     try:
         # allocate a specific IP
         if isinstance(address_request, ipam_req.SpecificAddressRequest):
             # This handles both specific and automatic address requests
             ip_address = str(address_request.address)
             # If this is the subnet gateway IP - no need to allocate it
             subnet = self.get_details()
             if str(subnet.gateway_ip) == ip_address:
                 LOG.info("Skip allocation of gateway-ip for pool %s",
                          self._nsx_pool_id)
                 return ip_address
         else:
             # Allocate any free IP
             ip_address = None
         response = self.nsxlib_ipam.allocate(self._nsx_pool_id,
                                              ip_addr=ip_address)
         ip_address = response['allocation_id']
     except nsx_lib_exc.ManagerError as e:
         LOG.error("NSX IPAM failed to allocate ip %(ip)s of subnet "
                   "%(id)s: %(e)s; code %(code)s",
                   {'e': e,
                    'ip': ip_address,
                    'id': self._subnet_id,
                    'code': e.error_code})
         if e.error_code == error.ERR_CODE_IPAM_POOL_EXHAUSTED:
             # No more IP addresses available on the pool
             raise ipam_exc.IpAddressGenerationFailure(
                 subnet_id=self._subnet_id)
         if e.error_code == error.ERR_CODE_IPAM_SPECIFIC_IP:
             # The NSX backend  does not support allocation of specific IPs
             # prior to version 2.0.
             msg = (_("NSX-V3 IPAM driver does not support allocation of a "
                      "specific ip %s for port") % ip_address)
             raise NotImplementedError(msg)
         if e.error_code == error.ERR_CODE_IPAM_IP_ALLOCATED:
             # This IP is already in use
             raise ipam_exc.IpAddressAlreadyAllocated(
                 ip=ip_address, subnet_id=self._subnet_id)
         if e.error_code == error.ERR_CODE_OBJECT_NOT_FOUND:
             msg = (_("NSX-V3 IPAM failed to allocate: pool %s was not "
                      "found") % self._nsx_pool_id)
             raise ipam_exc.IpamValueInvalid(message=msg)
         else:
             # another backend error
             raise ipam_exc.IPAllocationFailed()
     except Exception as e:
         LOG.error("NSX IPAM failed to allocate ip %(ip)s of subnet "
                   "%(id)s: %(e)s",
                   {'e': e,
                    'ip': ip_address,
                    'id': self._subnet_id})
         # handle unexpected failures
         raise ipam_exc.IPAllocationFailed()
     return ip_address
Exemple #25
0
 def _validate_device_list(self, devices):
     # In NSXv3, one L2 gateway is mapped to one bridge cluster.
     # So we expect only one device to be configured as part of
     # a L2 gateway resource. The name of the device must be the bridge
     # cluster's UUID.
     if len(devices) != 1:
         msg = _("Only a single device is supported for one L2 gateway")
         raise n_exc.InvalidInput(error_message=msg)
     if not uuidutils.is_uuid_like(devices[0]['device_name']):
         msg = _("Device name must be configured with a UUID")
         raise n_exc.InvalidInput(error_message=msg)
    def init_from_config_section(self, az_name):
        az_info = self.get_az_opts()

        if self._has_native_dhcp_metadata():
            # The optional parameters will get the global values if not
            # defined for this AZ
            self.metadata_proxy = az_info.get('metadata_proxy')
            if not self.metadata_proxy:
                raise nsx_exc.NsxInvalidConfiguration(
                    opt_name="metadata_proxy",
                    opt_value='None',
                    reason=(_("metadata_proxy for availability zone %s "
                              "must be defined") % az_name))

            self.dhcp_profile = az_info.get('dhcp_profile')
            if not self.dhcp_profile:
                raise nsx_exc.NsxInvalidConfiguration(
                    opt_name="dhcp_profile",
                    opt_value='None',
                    reason=(_("dhcp_profile for availability zone %s "
                              "must be defined") % az_name))

            native_metadata_route = az_info.get('native_metadata_route')
            if native_metadata_route:
                self.native_metadata_route = native_metadata_route
        else:
            self.metadata_proxy = None
            self.dhcp_profile = None
            self.native_metadata_route = None

        default_overlay_tz = az_info.get('default_overlay_tz')
        if default_overlay_tz:
            self.default_overlay_tz = default_overlay_tz

        default_vlan_tz = az_info.get('default_vlan_tz')
        if default_vlan_tz:
            self.default_vlan_tz = default_vlan_tz

        default_tier0_router = az_info.get('default_tier0_router')
        if default_tier0_router:
            self.default_tier0_router = default_tier0_router

        dns_domain = az_info.get('dns_domain')
        if dns_domain:
            self.dns_domain = dns_domain

        nameservers = az_info.get('nameservers')
        if nameservers:
            self.nameservers = nameservers

        edge_cluster = az_info.get('edge_cluster')
        if edge_cluster:
            self.edge_cluster = edge_cluster
Exemple #27
0
    def create(self, context, pol, completor):
        # find out the edge to be updated, by the listener of this policy
        listener = pol['listener']
        lb_id = listener['loadbalancer_id']
        lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
            context.session, lb_id)
        if not lb_binding:
            msg = _(
                'No suitable Edge found for listener %s') % listener['id']
            raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)

        if (listener['protocol'] == lb_const.LB_PROTOCOL_HTTPS or
            listener['protocol'] == lb_const.LB_PROTOCOL_TERMINATED_HTTPS):
            msg = _(
                'L7 policy is not supported for %(prot)s listener %(ls)s') % {
                'prot': listener['protocol'], 'ls': pol['listener_id']}
            raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)

        edge_id = lb_binding['edge_id']
        app_rule = policy_to_application_rule(pol)
        app_rule_id = None
        try:
            with locking.LockManager.get_lock(edge_id):
                # create the backend application rule for this policy
                h = (self.vcns.create_app_rule(edge_id, app_rule))[0]
                app_rule_id = lb_common.extract_resource_id(h['location'])

                # add the nsx application rule (neutron policy) to the nsx
                # virtual server (neutron listener)
                vse_id = self._get_vse_id(context, pol)
                if vse_id:
                    self._add_app_rule_to_virtual_server(
                        edge_id, vse_id, app_rule_id, pol['position'])
        except Exception as e:
            with excutils.save_and_reraise_exception():
                completor(success=False)
                LOG.error('Failed to create L7policy on edge %(edge)s: '
                          '%(err)s',
                          {'edge': edge_id, 'err': e})
                if app_rule_id:
                    # Failed to add the rule to the vip: delete the rule
                    # from the backend.
                    try:
                        self.vcns.delete_app_rule(edge_id, app_rule_id)
                    except Exception:
                        pass

        # save the nsx application rule id in the DB
        nsxv_db.add_nsxv_lbaas_l7policy_binding(context.session, pol['id'],
                                                edge_id, app_rule_id)
        # complete the transaction
        completor(success=True)
Exemple #28
0
 def _check_services_requirements(self):
     try:
         error = None
         nsx_svc.check_services_requirements(self.cluster)
     except nsx_exc.InvalidVersion:
         error = _("Unable to run Neutron with config option '%s', as NSX "
                   "does not support it") % cfg.CONF.NSX.agent_mode
     except nsx_exc.ServiceClusterUnavailable:
         error = _("Unmet dependency for config option "
                   "'%s'") % cfg.CONF.NSX.agent_mode
     if error:
         LOG.exception(error)
         raise nsx_exc.NsxPluginException(err_msg=error)
    def init_from_config_line(self, config_line):
        values = config_line.split(':')
        if len(values) < 4 or len(values) > 5:
            raise nsx_exc.NsxInvalidConfiguration(
                opt_name="availability_zones",
                opt_value=config_line,
                reason=_("Expected 4 or 5 values per zone"))

        self.resource_pool = values[1]
        self.datastore_id = values[2]

        # validate the edge_ha
        if values[3].lower() == "true":
            self.edge_ha = True
        elif values[3].lower() == "false":
            self.edge_ha = False
        else:
            raise nsx_exc.NsxInvalidConfiguration(
                opt_name="availability_zones",
                opt_value=config_line,
                reason=_("Expected the 4th value to be true/false"))

        # HA datastore id is relevant only with edge_ha
        if not self.edge_ha and len(values) == 5:
            raise nsx_exc.NsxInvalidConfiguration(
                opt_name="availability_zones",
                opt_value=config_line,
                reason=_("Expected HA datastore ID only when edge_ha is "
                         "enabled"))

        self.ha_datastore_id = values[4] if len(values) == 5 else None

        # Some parameters are not supported in this format.
        # using the global ones instead.
        self.ha_placement_random = cfg.CONF.nsxv.ha_placement_random
        self.datacenter_moid = cfg.CONF.nsxv.datacenter_moid
        self.backup_edge_pool = cfg.CONF.nsxv.backup_edge_pool
        self.external_network = cfg.CONF.nsxv.external_network
        self.vdn_scope_id = cfg.CONF.nsxv.vdn_scope_id
        self.dvs_id = cfg.CONF.nsxv.dvs_id
        self.edge_host_groups = cfg.CONF.nsxv.edge_host_groups
        self.exclusive_dhcp_edge = cfg.CONF.nsxv.exclusive_dhcp_edge
        self.bind_floatingip_to_all_interfaces = (
            cfg.CONF.nsxv.bind_floatingip_to_all_interfaces)

        # No support for metadata per az
        self.az_metadata_support = False
        self.mgt_net_moid = None
        self.mgt_net_proxy_ips = []
        self.mgt_net_proxy_netmask = None
        self.mgt_net_default_gateway = None
Exemple #30
0
def _validate_connector_type(data, valid_values=None):
    if not data:
        # A connector type is compulsory
        msg = _("A connector type is required to create a gateway device")
        return msg
    connector_types = (valid_values if valid_values else
                       [NetworkTypes.GRE,
                        NetworkTypes.STT,
                        NetworkTypes.BRIDGE,
                        'ipsec%s' % NetworkTypes.GRE,
                        'ipsec%s' % NetworkTypes.STT])
    if data not in connector_types:
        msg = _("Unknown connector type: %s") % data
        return msg
Exemple #31
0
    def _validate_port_vnic_type(self, context, port_data, network_id):
        vnic_type = port_data.get(pbin.VNIC_TYPE)

        if vnic_type and vnic_type not in SUPPORTED_VNIC_TYPES:
            err_msg = _("Invalid port vnic-type '%(vnic_type)s'."
                        "Supported vnic-types are %(valid_types)s.") % {
                            'vnic_type': vnic_type,
                            'valid_types': SUPPORTED_VNIC_TYPES
                        }
            raise exceptions.InvalidInput(error_message=err_msg)
        direct_vnic_type = vnic_type in VNIC_TYPES_DIRECT_PASSTHROUGH
        if direct_vnic_type:
            self._validate_vnic_type_direct_passthrough_for_network(
                context, network_id)
        return direct_vnic_type
Exemple #32
0
 def delete(self, context, policy, completor):
     vs_client = self.core_plugin.nsxpolicy.load_balancer.virtual_server
     policy_name = utils.get_name_and_uuid(policy['name'] or 'policy',
                                           policy['id'])
     try:
         vs_client.remove_lb_rule(policy['listener_id'], policy_name)
     except nsx_exc.NsxResourceNotFound:
         pass
     except nsxlib_exc.ManagerError:
         completor(success=False)
         msg = (_('Failed to delete L7 policy: %(policy)s') % {
             'policy': policy['id']
         })
         raise n_exc.BadRequest(resource='lbaas-l7policy', msg=msg)
     completor(success=True)
Exemple #33
0
    def validate_ike_policy(self, context, ike_policy):
        # Call general validations
        super(IPsecV3Validator, self).validate_ike_policy(context, ike_policy)

        # Call specific NSX validations
        self._validate_policy_lifetime(ike_policy, "IKE")
        self._validate_policy_auth_algorithm(ike_policy, "IKE")
        self._validate_policy_encryption_algorithm(ike_policy, "IKE")
        self._validate_policy_pfs(ike_policy, "IKE")

        # 'aggressive' phase1-negotiation-mode is not supported
        if ike_policy.get('phase1-negotiation-mode', 'main') != 'main':
            msg = _("Unsupported phase1-negotiation-mode: %s! Only 'main' is "
                    "supported.") % ike_policy['phase1-negotiation-mode']
            raise nsx_exc.NsxVpnValidationError(details=msg)
Exemple #34
0
 def validate_tier0(self, tier0_groups_dict, tier0_uuid):
     err_msg = None
     try:
         lrouter = self._router_client.get(tier0_uuid)
     except exceptions.ResourceNotFound:
         err_msg = (_("Tier0 router %s not found at the backend. Either a "
                      "valid UUID must be specified or a default tier0 "
                      "router UUID must be configured in nsx.ini") %
                    tier0_uuid)
     else:
         edge_cluster_uuid = lrouter.get('edge_cluster_id')
         if not edge_cluster_uuid:
             err_msg = _("Failed to get edge cluster uuid from tier0 "
                         "router %s at the backend") % lrouter
         else:
             edge_cluster = self.nsxlib.get_edge_cluster(edge_cluster_uuid)
             member_index_list = [
                 member['member_index']
                 for member in edge_cluster['members']
             ]
             if len(member_index_list) < MIN_EDGE_NODE_NUM:
                 err_msg = _("%(act_num)s edge members found in "
                             "edge_cluster %(cluster_id)s, however we "
                             "require at least %(exp_num)s edge nodes "
                             "in edge cluster for use.") % {
                                 'act_num': len(member_index_list),
                                 'exp_num': MIN_EDGE_NODE_NUM,
                                 'cluster_id': edge_cluster_uuid
                             }
     if err_msg:
         raise n_exc.InvalidInput(error_message=err_msg)
     else:
         tier0_groups_dict[tier0_uuid] = {
             'edge_cluster_uuid': edge_cluster_uuid,
             'member_index_list': member_index_list
         }
Exemple #35
0
    def validate_ipsec_policy(self, context, ipsec_policy):
        # Call general validations
        super(IPsecV3Validator,
              self).validate_ipsec_policy(context, ipsec_policy)

        # Call specific NSX validations
        self._validate_policy_lifetime(ipsec_policy, "IPSec")
        self._validate_policy_auth_algorithm(ipsec_policy, "IPSec")
        self._validate_policy_encryption_algorithm(ipsec_policy, "IPSec")
        self._validate_policy_pfs(ipsec_policy, "IPSec")

        # Ensure IPSec policy encap mode is tunnel
        mode = ipsec_policy.get('encapsulation_mode')
        if mode and mode not in ipsec_utils.ENCAPSULATION_MODE_MAP.keys():
            msg = _("Unsupported encapsulation mode: %s. Only 'tunnel' mode "
                    "is supported.") % mode
            raise nsx_exc.NsxVpnValidationError(details=msg)

        # Ensure IPSec policy transform protocol is esp
        prot = ipsec_policy.get('transform_protocol')
        if prot and prot not in ipsec_utils.TRANSFORM_PROTOCOL_MAP.keys():
            msg = _("Unsupported transform protocol: %s. Only 'esp' protocol "
                    "is supported.") % prot
            raise nsx_exc.NsxVpnValidationError(details=msg)
Exemple #36
0
    def _extract_external_gw(self, context, router, is_extract=True):
        r = router['router']
        gw_info = constants.ATTR_NOT_SPECIFIED
        # First extract the gateway info in case of updating
        # gateway before edge is deployed.
        if 'external_gateway_info' in r:
            gw_info = r.get('external_gateway_info', {})
            if is_extract:
                del r['external_gateway_info']
            network_id = (gw_info.get('network_id') if gw_info else None)
            if network_id:
                ext_net = self._get_network(context.elevated(), network_id)
                if not ext_net.external:
                    msg = (_("Network '%s' is not a valid external network") %
                           network_id)
                    raise n_exc.BadRequest(resource='router', msg=msg)

                subnets = self._get_subnets_by_network(context.elevated(),
                                                       network_id)
                if not subnets:
                    msg = _("Cannot update gateway on Network '%s' "
                            "with no subnet") % network_id
                    raise n_exc.BadRequest(resource='router', msg=msg)
        return gw_info
Exemple #37
0
def get_lb_flavor_size(flavor_plugin, context, flavor_id):
    if not flavor_id:
        return lb_const.DEFAULT_LB_SIZE
    else:
        flavor = flavors_plugin.FlavorsPlugin.get_flavor(
            flavor_plugin, context, flavor_id)
        flavor_size = flavor['name']
        if flavor_size in lb_const.LB_FLAVOR_SIZES:
            return flavor_size.upper()
        else:
            err_msg = (_("Invalid flavor size %(flavor)s, only 'small', "
                         "'medium', or 'large' are supported") % {
                             'flavor': flavor_size
                         })
            raise n_exc.InvalidInput(error_message=err_msg)
Exemple #38
0
    def validate_obj_azs(self, availability_zones):
        """Verify that the availability zones exist, and only 1 hint
        was set.
        """
        # For now we support only 1 hint per network/router
        # TODO(asarfaty): support multiple hints
        if len(availability_zones) > 1:
            err_msg = _("Can't use multiple availability zone hints")
            raise n_exc.InvalidInput(error_message=err_msg)

        # check that all hints appear in the predefined list of availability
        # zones
        diff = (set(availability_zones) - set(self.get_azs_names()))
        if diff:
            raise az_exc.AvailabilityZoneNotFound(availability_zone=diff.pop())
Exemple #39
0
    def create_policy(self, context, policy):
        policy_id = policy.id
        tags = self._get_tags(context, policy)
        result = self._nsxlib_qos.create(
            tags=tags, name=policy.name,
            description=policy.description)
        if not result or not validators.is_attr_set(result.get('id')):
            msg = _("Unable to create QoS switching profile on the backend")
            raise nsx_exc.NsxPluginException(err_msg=msg)
        profile_id = result['id']

        # Add the mapping entry of the policy_id <-> profile_id
        nsx_db.add_qos_policy_profile_mapping(context.session,
                                              policy_id,
                                              profile_id)
Exemple #40
0
    def init_profile_id(self):
        """Init the service insertion profile ID

        Initialize the profile id that should be assigned to the redirect
        rules from the nsx configuration and verify that it exists on backend.
        """
        if not cfg.CONF.nsxv.service_insertion_profile_id:
            raise cfg.RequiredOptError("service_profile_id")
        self._profile_id = cfg.CONF.nsxv.service_insertion_profile_id

        # Verify that this moref exists
        if not self._nsxv.vcns.validate_inventory(self._profile_id):
            error = (_("Configured service profile ID: %s not found") %
                     self._profile_id)
            raise nsx_exc.NsxPluginException(err_msg=error)
Exemple #41
0
 def _get_lb_flavor_size(self, context, flavor_id):
     if not flavor_id:
         return vcns_const.SERVICE_SIZE_MAPPING['lb']
     else:
         flavor = flavors_plugin.FlavorsPlugin.get_flavor(
             self.flavor_plugin, context, flavor_id)
         flavor_size = flavor['name']
         if flavor_size.lower() in vcns_const.ALLOWED_EDGE_SIZES:
             return flavor_size.lower()
         else:
             err_msg = (_("Invalid flavor size %(flavor)s, only %(sizes)s "
                          "are supported") %
                        {'flavor': flavor_size,
                         'sizes': vcns_const.ALLOWED_EDGE_SIZES})
             raise n_exc.InvalidInput(error_message=err_msg)
Exemple #42
0
    def _get_internal_network_and_subnet(self, context):
        internal_net = None
        internal_subnet = None

        # Try to find internal net, internal subnet. If not found, create new
        net_list = nsxv_db.get_nsxv_internal_network(
            context.session,
            vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)

        if net_list:
            internal_net = net_list[0]['network_id']

        if internal_net:
            internal_subnet = self.nsxv_plugin.get_subnets(
                context, fields=['id'], filters={'network_id':
                                                 [internal_net]})[0]['id']

        if internal_net is None or internal_subnet is None:
            if cfg.CONF.nsxv.metadata_initializer:
                # Couldn't find net, subnet - create new
                try:
                    internal_net, internal_subnet = (
                        self._create_metadata_internal_network(
                            context, INTERNAL_SUBNET))
                except Exception as e:
                    nsxv_db.delete_nsxv_internal_network(
                        context.session,
                        vcns_const.InternalEdgePurposes.INTER_EDGE_PURPOSE)

                    # if network is created, clean up
                    if internal_net:
                        self.nsxv_plugin.delete_network(context, internal_net)

                    LOG.exception(
                        _LE("Exception %s while creating internal "
                            "network for metadata service"), e)
                    return

                # Update the new network_id in DB
                nsxv_db.create_nsxv_internal_network(
                    context.session, nsxv_constants.INTER_EDGE_PURPOSE,
                    internal_net)
            else:
                error = _('Metadata initialization is incomplete on '
                          'initializer node')
                raise nsxv_exc.NsxPluginException(err_msg=error)

        return internal_net, internal_subnet
Exemple #43
0
    def _validate_member_lb_connectivity(self, context, member, completor):
        lb = member['pool'].get('loadbalancer')

        if not lb:
            msg = (_('Member %s loadbalancer object is missing') %
                   member['id'])
            raise n_exc.BadRequest(resource='lbaas-vip', msg=msg)

        subnet_id = lb.get('vip_subnet_id')
        network = lb_utils.get_network_from_subnet(context, self.core_plugin,
                                                   subnet_id)

        if not network.get('router:external'):
            return

        # If VIP is attached to an external network, loadbalancer_mgr might not
        # attach it to a router. If not, set the LB service connectivity path
        # to the member subnet's router.
        service_client = self.core_plugin.nsxpolicy.load_balancer.lb_service
        service = service_client.get(lb['id'])
        if not service.get('connectivity_path'):
            router_id = lb_utils.get_router_from_network(
                context, self.core_plugin, member['subnet_id'])
            if not self.core_plugin.service_router_has_services(
                    context, router_id):
                self.core_plugin.create_service_router(context, router_id)

            connectivity_path = self.core_plugin.nsxpolicy.tier1.get_path(
                router_id)
            tags = lb_utils.get_tags(self.core_plugin, router_id,
                                     lb_const.LR_ROUTER_TYPE, lb['tenant_id'],
                                     context.project_name)
            try:
                service_client.update(lb['id'],
                                      tags=tags,
                                      connectivity_path=connectivity_path)
                p_utils.update_router_lb_vip_advertisement(
                    context, self.core_plugin, router_id)
            except Exception as e:
                with excutils.save_and_reraise_exception():
                    completor(success=False)
                    LOG.error(
                        'Failed to set connectivity for loadbalancer '
                        '%(lb)s on subnet %(sub)s with error %(err)s', {
                            'lb': lb['id'],
                            'sub': member['subnet_id'],
                            'err': e
                        })
    def _validate_vnic_type_direct_passthrough_for_network(
            self, context, network_id):
        supported_network_types = (c_utils.NsxVNetworkTypes.VLAN,
                                   c_utils.NsxVNetworkTypes.FLAT,
                                   c_utils.NsxVNetworkTypes.PORTGROUP)

        if not self._validate_network_type(context, network_id,
                                           supported_network_types):
            msg_info = {
                'vnic_types': VNIC_TYPES_DIRECT_PASSTHROUGH,
                'networks': supported_network_types
            }
            err_msg = _("%(vnic_types)s port vnic-types are only supported "
                        "for ports on networks of types "
                        "%(networks)s.") % msg_info
            raise exceptions.InvalidInput(error_message=err_msg)
 def add_nsgroup(self, nsgroup_id):
     for group in self._suggest_nested_group(nsgroup_id):
         try:
             LOG.debug("Adding NSGroup %s to nested group %s",
                       nsgroup_id, group)
             firewall.add_nsgroup_member(group,
                                         firewall.NSGROUP,
                                         nsgroup_id)
             break
         except firewall.NSGroupIsFull:
             LOG.debug("Nested group %(group_id)s is full, trying the "
                       "next group..", {'group_id': group})
     else:
         raise nsx_exc.NsxPluginException(
             err_msg=_("Reached the maximum supported amount of "
                       "security groups."))
Exemple #46
0
def allocate_edge_vnic(session, edge_id, network_id):
    """Allocate an available edge vnic to network."""

    with session.begin(subtransactions=True):
        bindings = (session.query(nsxv_models.NsxvEdgeVnicBinding).
                    filter_by(edge_id=edge_id, network_id=None).all())
        for binding in bindings:
            if binding['tunnel_index'] % constants.MAX_TUNNEL_NUM == 1:
                binding['network_id'] = network_id
                session.add(binding)
                return binding
    msg = (_("Edge VNIC: Failed to allocate one available vnic on edge_id: "
             ":%(edge_id)s to network_id: %(network_id)s") %
           {'edge_id': edge_id, 'network_id': network_id})
    LOG.error(msg)
    raise nsx_exc.NsxPluginException(err_msg=msg)
Exemple #47
0
    def validate_vpnservice(self, context, vpnservice):
        """Called upon create/update of a service"""

        self._validate_backend_version()

        # Call general validations
        super(IPsecV3Validator, self).validate_vpnservice(context, vpnservice)

        # Call specific NSX validations
        self._validate_router(context, vpnservice['router_id'])

        if not vpnservice['subnet_id']:
            # we currently do not support multiple subnets so a subnet must
            # be defined
            msg = _("Subnet must be defined in a service")
            raise nsx_exc.NsxVpnValidationError(details=msg)
Exemple #48
0
 def add_nsgroup(self, nsgroup_id):
     for group in self._suggest_nested_group(nsgroup_id):
         try:
             LOG.debug("Adding NSGroup %s to nested group %s",
                       nsgroup_id, group)
             self.nsx.add_nsgroup_members(group,
                                         firewall.NSGROUP,
                                         [nsgroup_id])
             break
         except exceptions.NSGroupIsFull:
             LOG.debug("Nested group %(group_id)s is full, trying the "
                       "next group..", {'group_id': group})
     else:
         raise exceptions.ManagerError(
             details=_("Reached the maximum supported amount of "
                       "security groups."))
 def _update_external_interface_on_routers(self, context, target_router_id,
                                           router_ids):
     ext_net_ids = self._get_ext_net_ids(context, router_ids)
     if len(ext_net_ids) > 1:
         LOG.error(
             "Can't configure external interface on multiple "
             "external networks %(networks)s for routers %(routers)s", {
                 'networks': ext_net_ids,
                 'routers': router_ids
             })
         msg = _("Can't configure external interface on multiple external "
                 "networks")
         raise nsx_exc.NsxPluginException(err_msg=msg)
     gateway_primary_addr = None
     gateway_mask = None
     gateway_nexthop = None
     secondary = []
     if not ext_net_ids:
         ext_net_id = None
     else:
         ext_net_id = ext_net_ids[0]
     for router_id in router_ids:
         router_qry = context.session.query(l3_db_models.Router)
         router = router_qry.filter_by(id=router_id).one()
         addr, mask, nexthop = self.plugin._get_external_attachment_info(
             context, router)
         if addr:
             if not gateway_primary_addr:
                 gateway_primary_addr = addr
             else:
                 secondary.append(addr)
         if mask and not gateway_mask:
             gateway_mask = mask
         if nexthop and not gateway_nexthop:
             gateway_nexthop = nexthop
         secondary.extend(
             self.plugin._get_floatingips_by_router(context, router_id))
     LOG.debug(
         'Configure ext interface as following, ext_net: %s, '
         'primaryAddress: %s, netmask: %s, nexthop: %s, secondary: '
         '%s.', ext_net_id, gateway_primary_addr, gateway_mask,
         gateway_nexthop, secondary)
     self.edge_manager.update_external_interface(self.nsx_v, context,
                                                 target_router_id,
                                                 ext_net_id,
                                                 gateway_primary_addr,
                                                 gateway_mask, secondary)
Exemple #50
0
 def _get_rule_match_conditions(self, rule):
     match_conditions = []
     # values in rule have already been validated in LBaaS API,
     # we won't need to valid anymore in driver, and just get
     # the LB rule mapping from the dict.
     match_type = lb_const.LB_RULE_MATCH_TYPE[rule.compare_type]
     if rule.type == lb_const.L7_RULE_TYPE_COOKIE:
         header_value = rule.key + '=' + rule.value
         match_conditions.append({
             'type': 'LbHttpRequestHeaderCondition',
             'match_type': match_type,
             'header_name': 'Cookie',
             'header_value': header_value
         })
     elif rule.type == lb_const.L7_RULE_TYPE_FILE_TYPE:
         match_conditions.append({
             'type': 'LbHttpRequestUriCondition',
             'match_type': match_type,
             'uri': '*.' + rule.value
         })
     elif rule.type == lb_const.L7_RULE_TYPE_HEADER:
         match_conditions.append({
             'type': 'LbHttpRequestHeaderCondition',
             'match_type': match_type,
             'header_name': rule.key,
             'header_value': rule.value
         })
     elif rule.type == lb_const.L7_RULE_TYPE_HOST_NAME:
         match_conditions.append({
             'type': 'LbHttpRequestHeaderCondition',
             'match_type': match_type,
             'header_name': 'Host',
             'header_value': rule.value
         })
     elif rule.type == lb_const.L7_RULE_TYPE_PATH:
         match_conditions.append({
             'type': 'LbHttpRequestUriCondition',
             'match_type': match_type,
             'uri': rule.value
         })
     else:
         msg = (_('l7rule type %(type)s is not supported in LBaaS') % {
             'type': rule.type
         })
         LOG.error(msg)
         raise n_exc.BadRequest(resource='lbaas-l7rule', msg=msg)
     return match_conditions
Exemple #51
0
    def validate_vpnservice(self, context, vpnservice):
        if not vpnservice.get('tenant_id'):
            # This will happen during update.
            # nothing significant like router or subnet can be changes
            # so we can skip it.
            return

        v = self._get_validator_for_project(vpnservice['tenant_id'])

        # first make sure the router&subnet plugin matches the vpnservice
        router_id = vpnservice['router_id']
        p = self.core_plugin._get_plugin_from_router_id(context, router_id)
        if self.validators.get(p.plugin_type()) != v:
            err_msg = _('Router & subnet should belong to the same plugin '
                        'as the VPN service')
            raise nsx_exc.NsxVpnValidationError(details=err_msg)
        return v.validate_vpnservice(context, vpnservice)
Exemple #52
0
    def _validate_vnic_type_direct_passthrough_for_network(self,
                                                           context,
                                                           network_id,
                                                           plugin_type):
        supported_network_types = SUPPORTED_V_NETWORK_TYPES
        if plugin_type == projectpluginmap.NsxPlugins.NSX_T:
            supported_network_types = SUPPORTED_T_NETWORK_TYPES

        if not self._validate_network_type(context, network_id,
                                           supported_network_types):
            msg_info = {
                'vnic_types': VNIC_TYPES_DIRECT_PASSTHROUGH,
                'networks': supported_network_types}
            err_msg = _("%(vnic_types)s port vnic-types are only supported "
                        "for ports on networks of types "
                        "%(networks)s") % msg_info
            raise exceptions.InvalidInput(error_message=err_msg)
Exemple #53
0
 def _get_monitor_policy_client(self, hm):
     lb_client = self.core_plugin.nsxpolicy.load_balancer
     if hm['type'] == lb_const.LB_HEALTH_MONITOR_TCP:
         return lb_client.lb_monitor_profile_tcp
     elif hm['type'] == lb_const.LB_HEALTH_MONITOR_HTTP:
         return lb_client.lb_monitor_profile_http
     elif hm['type'] == lb_const.LB_HEALTH_MONITOR_HTTPS:
         return lb_client.lb_monitor_profile_https
     elif hm['type'] == lb_const.LB_HEALTH_MONITOR_PING:
         return lb_client.lb_monitor_profile_icmp
     else:
         msg = (_('Cannot create health monitor %(monitor)s with '
                  'type %(type)s') % {
                      'monitor': hm['id'],
                      'type': hm['type']
                  })
         raise n_exc.InvalidInput(error_message=msg)
    def remove_router_interface(self, context, router_id, interface_info):

        # If a loadbalancer is attached to this Edge appliance, we cannot
        # detach the subnet from the exclusive router.
        subnet = interface_info.get('subnet_id')
        if not subnet and interface_info.get('port_id'):
            port = self.plugin.get_port(context, interface_info['port_id'])
            port_subnets = [
                fixed_ip['subnet_id']
                for fixed_ip in port.get('fixed_ips', [])
            ]
            subnet = port_subnets[0]

        if subnet and self._check_lb_on_subnet(context, subnet):
            error = _('Cannot delete router interface while loadbalancers are '
                      'provisioned on attached subnet')
            raise nsxv_exc.NsxPluginException(err_msg=error)

        info = super(nsx_v.NsxVPluginV2, self.plugin).remove_router_interface(
            context, router_id, interface_info)
        router_db = self.plugin._get_router(context, router_id)
        subnet = self.plugin.get_subnet(context, info['subnet_id'])
        network_id = subnet['network_id']

        with locking.LockManager.get_lock(
                self._get_router_edge_id(context, router_id)):
            if router_db.gw_port and router_db.enable_snat:
                # First update nat rules
                self.plugin._update_nat_rules(context, router_db)
            ports = self.plugin._get_router_interface_ports_by_network(
                context, router_id, network_id)
            self.plugin._update_subnets_and_dnat_firewall(context, router_db)
            # No subnet on the network connects to the edge vnic
            if not ports:
                edge_utils.delete_interface(self.nsx_v,
                                            context,
                                            router_id,
                                            network_id,
                                            dist=False)
            else:
                address_groups = self.plugin._get_address_groups(
                    context, router_id, network_id)
                edge_utils.update_internal_interface(self.nsx_v, context,
                                                     router_id, network_id,
                                                     address_groups)
        return info
 def get_nat_config(self, edge_id):
     if edge_id not in self._edges:
         raise Exception(_("Edge %s does not exist") % edge_id)
     edge = self._edges[edge_id]
     rules = edge['nat_rules']
     if rules is None:
         rules = {
             'rules': {
                 'natRulesDtos': []
             },
             'version': 1
         }
     header = {
         'status': 200
     }
     rules['version'] = 1
     return (header, rules)
Exemple #56
0
    def update(self,
               context,
               old_listener,
               new_listener,
               completor,
               certificate=None):
        nsxlib_lb = self.core_plugin.nsxlib.load_balancer
        vs_client = nsxlib_lb.virtual_server
        app_client = nsxlib_lb.application_profile
        vs_name = None
        tags = None
        if new_listener['name'] != old_listener['name']:
            vs_name = utils.get_name_and_uuid(
                new_listener['name'] or 'listener', new_listener['id'])
            tags = self._get_listener_tags(context, new_listener)

        binding = nsx_db.get_nsx_lbaas_listener_binding(
            context.session, old_listener['loadbalancer_id'],
            old_listener['id'])
        if not binding:
            msg = (_('Cannot find listener %(listener)s binding on NSX '
                     'backend'), {
                         'listener': old_listener['id']
                     })
            raise n_exc.BadRequest(resource='lbaas-listener', msg=msg)
        try:
            vs_id = binding['lb_vs_id']
            app_profile_id = binding['app_profile_id']
            updated_kwargs = self._get_virtual_server_kwargs(
                context, new_listener, vs_name, tags, app_profile_id,
                certificate)
            vs_client.update(vs_id, **updated_kwargs)
            if vs_name:
                app_client.update(app_profile_id,
                                  display_name=vs_name,
                                  tags=tags)
            completor(success=True)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                completor(success=False)
                LOG.error(
                    'Failed to update listener %(listener)s with '
                    'error %(error)s', {
                        'listener': old_listener['id'],
                        'error': e
                    })
Exemple #57
0
    def validate_ipsec_site_connection(self, context, ipsec_site_conn):
        if not ipsec_site_conn.get('tenant_id'):
            # nothing we can do here.
            return

        v = self._get_validator_for_project(ipsec_site_conn['tenant_id'])

        # first make sure the plugin is the same as the one of the vpnservice
        srv_id = ipsec_site_conn.get('vpnservice_id')
        srv = self.vpn_plugin._get_vpnservice(context, srv_id)
        srv_validator = self._get_validator_for_project(srv['tenant_id'])
        if v != srv_validator:
            err_msg = _('VPN service should belong to the same plugin '
                        'as the connection')
            raise nsx_exc.NsxVpnValidationError(details=err_msg)

        return v.validate_ipsec_site_connection(context, ipsec_site_conn)
Exemple #58
0
def add_vip_as_secondary_ip(vcns, edge_id, vip):
    """
    Edge appliance requires that a VIP will be configured as a primary
    or a secondary IP address on an interface.
    To do so, we locate an interface which is connected to the same subnet
    that vip belongs to.
    This can be a regular interface, on a sub-interface on a trunk.
    """
    if not vip_as_secondary_ip(vcns, edge_id, vip,
                               add_address_to_address_groups):

        msg = _('Failed to add VIP %(vip)s as secondary IP on '
                'Edge %(edge_id)s') % {
                    'vip': vip,
                    'edge_id': edge_id
                }
        raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
Exemple #59
0
    def create(self, context, pol):
        # find out the edge to be updated, by the listener of this policy
        lb_id = pol.listener.loadbalancer_id
        lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding(
            context.session, lb_id)
        if not lb_binding:
            msg = _('No suitable Edge found for listener %s') % pol.listener_id
            raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
        edge_id = lb_binding['edge_id']
        app_rule = policy_to_application_rule(pol)
        app_rule_id = None
        try:
            with locking.LockManager.get_lock(edge_id):
                # create the backend application rule for this policy
                h = (self.vcns.create_app_rule(edge_id, app_rule))[0]
                app_rule_id = lb_common.extract_resource_id(h['location'])

                # add the nsx application rule (neutron policy) to the nsx
                # virtual server (neutron listener)
                vse_id = self._get_vse_id(context, pol)
                if vse_id:
                    self._add_app_rule_to_virtual_server(
                        edge_id, vse_id, app_rule_id, pol.position)
        except Exception as e:
            with excutils.save_and_reraise_exception():
                self.lbv2_driver.l7policy.failed_completion(context, pol)
                LOG.error(
                    'Failed to create L7policy on edge %(edge)s: '
                    '%(err)s', {
                        'edge': edge_id,
                        'err': e
                    })
                if app_rule_id:
                    # Failed to add the rule to the vip: delete the rule
                    # from the backend.
                    try:
                        self.vcns.delete_app_rule(edge_id, app_rule_id)
                    except Exception:
                        pass

        # save the nsx application rule id in the DB
        nsxv_db.add_nsxv_lbaas_l7policy_binding(context.session, pol.id,
                                                edge_id, app_rule_id)
        # complete the transaction
        self.lbv2_driver.l7policy.successful_completion(context, pol)
def convert_lbaas_app_profile(name, sess_persist, protocol):
    """
    Create app profile dict for lbaas VIP.

    Neutron-lbaas VIP objects breaks into an application profile object, and
    a virtual server object in NSXv.
    """
    vcns_app_profile = {
        'insertXForwardedFor': False,
        'name': name,
        'serverSslEnabled': False,
        'sslPassthrough': False,
        'template': protocol,
    }
    # Since SSL Termination is not supported right now, so just use
    # sslPassthrough method if the protocol is HTTPS.
    if protocol == lb_const.LB_PROTOCOL_HTTPS:
        vcns_app_profile['sslPassthrough'] = True

    if sess_persist:
        persist_type = sess_persist.get('type')
        if persist_type:
            # If protocol is not HTTP, only source_ip is supported
            if (protocol != lb_const.LB_PROTOCOL_HTTP and
                    persist_type != lb_const.LB_SESSION_PERSISTENCE_SOURCE_IP):
                msg = (_('Invalid %(protocol)s persistence method: %(type)s') %
                       {
                           'protocol': protocol,
                           'type': persist_type
                       })
                raise n_exc.BadRequest(resource='edge-lbaas', msg=msg)
            persistence = {
                'method':
                lb_const.SESSION_PERSISTENCE_METHOD_MAP.get(persist_type)
            }
            if persist_type in lb_const.SESSION_PERSISTENCE_COOKIE_MAP:
                persistence.update({
                    'cookieName':
                    sess_persist.get('cookie_name', 'default_cookie_name'),
                    'cookieMode':
                    lb_const.SESSION_PERSISTENCE_COOKIE_MAP[persist_type]
                })

            vcns_app_profile['persistence'] = persistence
    return vcns_app_profile