Exemple #1
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 #2
0
 def _validate_with_subnet(self, subnet_cidr):
     if self.allocation_pools:
         if subnet_cidr.version != self.allocation_pools[0].version:
             raise ipam_exc.IpamValueInvalid(
                 _("allocation_pools use the wrong ip version"))
         for pool in self.allocation_pools:
             if pool not in subnet_cidr:
                 raise ipam_exc.IpamValueInvalid(
                     _("allocation_pools are not in the subnet"))
Exemple #3
0
    def allocate_backend_pool(self, subnet_request):
        """Create a pool on the NSX backend and return its ID"""
        if subnet_request.allocation_pools:
            ranges = [
                {'ipRangeDto':
                    {'startAddress': netaddr.IPAddress(pool.first),
                     'endAddress': netaddr.IPAddress(pool.last)}}
                for pool in subnet_request.allocation_pools]
        else:
            ranges = []

        request = {'ipamAddressPool':
            # max name length on backend is 255, so there is no problem here
            {'name': 'subnet_' + subnet_request.subnet_id,
             'prefixLength': subnet_request.prefixlen,
             'gateway': subnet_request.gateway_ip,
             'ipRanges': ranges}}

        try:
            response = self._vcns.create_ipam_ip_pool(request)
            nsx_pool_id = response[1]
        except vc_exc.VcnsApiException as e:
            msg = _('Failed to create subnet IPAM: %s') % e
            raise ipam_exc.IpamValueInvalid(message=msg)

        return nsx_pool_id
Exemple #4
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 #5
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 #6
0
    def _validate_with_subnet(self, subnet_cidr):
        if self.gateway_ip and cfg.CONF.force_gateway_on_subnet:
            gw_ip = netaddr.IPAddress(self.gateway_ip)
            if (gw_ip.version == 4
                    or (gw_ip.version == 6 and not gw_ip.is_link_local())):
                if self.gateway_ip not in subnet_cidr:
                    raise ipam_exc.IpamValueInvalid(
                        _("gateway_ip %s is not in the subnet") %
                        self.gateway_ip)

        if self.allocation_pools:
            if subnet_cidr.version != self.allocation_pools[0].version:
                raise ipam_exc.IpamValueInvalid(
                    _("allocation_pools use the wrong ip version"))
            for pool in self.allocation_pools:
                if pool not in subnet_cidr:
                    raise ipam_exc.IpamValueInvalid(
                        _("allocation_pools are not in the subnet"))
Exemple #7
0
    def _validate_gateway_ip_in_subnet(subnet_cidr, gateway_ip):
        if not gateway_ip:
            return

        if ipam_utils.check_gateway_invalid_in_subnet(subnet_cidr, gateway_ip):
            raise ipam_exc.IpamValueInvalid(
                _('Gateway IP %(gateway_ip)s cannot be allocated in CIDR '
                  '%(subnet_cidr)s' % {
                      'gateway_ip': gateway_ip,
                      'subnet_cidr': subnet_cidr
                  }))
Exemple #8
0
 def _get_driver_for_project(self, project):
     plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project)
     if not self.drivers.get(plugin_type):
         LOG.error(
             "Project %(project)s with plugin %(plugin)s has no "
             "support for IPAM", {
                 'project': project,
                 'plugin': plugin_type
             })
         raise ipam_exc.IpamValueInvalid(message="IPAM driver not found")
     return self.drivers[plugin_type]
Exemple #9
0
 def allocate_backend_pool(self, subnet_request):
     """Create a pool on the NSX backend and return its ID"""
     # name/description length on backend is long, so there is no problem
     name = 'subnet_' + subnet_request.subnet_id
     description = 'OS IP pool for subnet ' + subnet_request.subnet_id
     try:
         response = self.nsxlib_ipam.create(
             self._get_cidr_from_request(subnet_request),
             allocation_ranges=self._get_ranges_from_request(
                 subnet_request),
             display_name=name,
             description=description,
             gateway_ip=subnet_request.gateway_ip)
         nsx_pool_id = response['id']
     except Exception as e:
         #TODO(asarfaty): handle specific errors
         msg = _('Failed to create subnet IPAM: %s') % e
         raise ipam_exc.IpamValueInvalid(message=msg)
     return nsx_pool_id
Exemple #10
0
 def _raise_update_not_supported(self):
     msg = _('Changing the subnet range or gateway is not supported')
     raise ipam_exc.IpamValueInvalid(message=msg)