def create_bgpvpn_network_association(self, context, bgpvpn_id, network_association): net_assoc = network_association['network_association'] # check net exists net = self._validate_network(context, net_assoc['network_id']) # check every resource belong to the same tenant bgpvpn = self.get_bgpvpn(context, bgpvpn_id) if net['tenant_id'] != bgpvpn['tenant_id']: msg = 'network doesn\'t belong to the bgpvpn owner' raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) if net_assoc['tenant_id'] != bgpvpn['tenant_id']: msg = 'network association and bgpvpn should belong to\ the same tenant' raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) return self.driver.create_net_assoc(context, bgpvpn_id, net_assoc)
def diagnose_subnet(context, id, fields): if not context.is_admin: raise n_exc.NotAuthorized() if id == "*": return {'subnets': get_subnets(context, filters={})} return {'subnets': get_subnet(context, id)}
def get_mac_address_ranges(context): LOG.info("get_mac_address_ranges for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() ranges = db_api.mac_address_range_find(context) return [v._make_mac_range_dict(m) for m in ranges]
def request(self, method, url, token=None, args=None, headers=None, accepted_codes=[200, 201, 202, 204]): params = {} if args: # extract filter and fields if 'filters' in args: params = args.pop('filters') if 'fields' in args: params['fields'] = args.pop('fields') args = jsonutils.dumps(args) if not headers: headers = { 'Content-type': 'application/json', 'X-Auth-Token': token } headers['User-Agent'] = OCTAVIA_PROXY_CLIENT url = '{}/{}'.format(self.base_url, str(url)) LOG.debug("url = %s", url) LOG.debug("args = %s", args) LOG.debug("params = %s", str(params)) r = requests.request(method, url, data=args, params=params, headers=headers) LOG.debug("Octavia Response Code: {0}".format(r.status_code)) LOG.debug("Octavia Response Body: {0}".format(r.content)) LOG.debug("Octavia Response Headers: {0}".format(r.headers)) if r.status_code in accepted_codes: if method != 'DELETE': return r.json() elif r.status_code == 413: e = lib_exc.OverQuota() e.msg = str(r.content) raise e elif r.status_code == 409: e = lib_exc.Conflict() e.msg = str(r.content) raise e elif r.status_code == 401: e = lib_exc.NotAuthorized() e.msg = str(r.content) raise e elif r.status_code == 404: e = lib_exc.NotFound() e.msg = str(r.content) raise e elif r.status_code == 400: e = lib_exc.BadRequest(resource="", msg="") e.msg = str(r.content) raise e else: raise loadbalancerv2.DriverError(msg=str(r.content))
def delete_network(context, id): """Delete a network. : param context: neutron api request context : param id: UUID representing the network to delete. """ LOG.info("delete_network %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): net = db_api.network_find(context=context, limit=None, sorts=['id'], marker=None, page_reverse=False, id=id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=id) if not context.is_admin: if STRATEGY.is_provider_network(net.id): raise n_exc.NotAuthorized(net_id=id) if net.ports: raise n_exc.NetworkInUse(net_id=id) net_driver = registry.DRIVER_REGISTRY.get_driver(net["network_plugin"]) net_driver.delete_network(context, id) for subnet in net["subnets"]: subnets._delete_subnet(context, subnet) db_api.network_delete(context, net)
def create_bgpvpn_port_association(self, context, bgpvpn_id, port_association): port_association = port_association['port_association'] port = self._validate_port(context, port_association['port_id']) bgpvpn = self.get_bgpvpn(context, bgpvpn_id) if not port['tenant_id'] == bgpvpn['project_id']: msg = "port doesn't belong to the bgpvpn owner" raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) if not (port_association['project_id'] == bgpvpn['project_id']): msg = "port association and bgpvpn should " \ "belong to the same tenant" raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) self._validate_port_association_routes_bgpvpn(context, port_association, bgpvpn_id) return self.driver.create_port_assoc(context, bgpvpn_id, port_association)
def get_segment_allocation_ranges(context, **filters): LOG.info("get_segment_allocation_ranges for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() sa_ranges = db_api.segment_allocation_range_find( context, scope=db_api.ALL, **filters) return [v._make_segment_allocation_range_dict(m) for m in sa_ranges]
def create_bgpvpn_router_association(self, context, bgpvpn_id, router_association): router_assoc = router_association['router_association'] router = self._validate_router(context, router_assoc['router_id']) bgpvpn = self.get_bgpvpn(context, bgpvpn_id) if not bgpvpn['type'] == constants.BGPVPN_L3: msg = ("Router associations require the bgpvpn to be of type %s" % constants.BGPVPN_L3) raise n_exc.BadRequest(resource='bgpvpn', msg=msg) if not router['tenant_id'] == bgpvpn['tenant_id']: msg = "router doesn't belong to the bgpvpn owner" raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) if not (router_assoc['tenant_id'] == bgpvpn['tenant_id']): msg = "router association and bgpvpn should " \ "belong to the same tenant" raise n_exc.NotAuthorized(resource='bgpvpn', msg=msg) return self.driver.create_router_assoc(context, bgpvpn_id, router_assoc)
def get_ports(context, limit=None, sorts=['id'], marker=None, page_reverse=False, filters=None, fields=None): """Retrieve a list of ports. The contents of the list depends on the identity of the user making the request (as indicated by the context) as well as any filters. : param context: neutron api request context : param filters: a dictionary with keys that are valid keys for a port as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Values in this dictionary are an iterable containing values that will be used for an exact match comparison for that value. Each result returned by this function will have matched one of the values for each key in filters. : param fields: a list of strings that are valid keys in a port dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_ports for tenant %s filters %s fields %s" % (context.tenant_id, filters, fields)) if filters is None: filters = {} if "ip_address" in filters: if not context.is_admin: raise n_exc.NotAuthorized() ips = [] try: ips = [netaddr.IPAddress(ip) for ip in filters.pop("ip_address")] except netaddr.AddrFormatError: raise n_exc.InvalidInput( error_message="Invalid format provided for ip_address") query = db_api.port_find_by_ip_address(context, ip_address=ips, scope=db_api.ALL, **filters) ports = [] for ip in query: ports.extend(ip.ports) else: ports = db_api.port_find(context, limit, sorts, marker, fields=fields, join_security_groups=True, **filters) return v._make_ports_list(ports, fields)
def update_vip(self, context, id, vip): v = vip['vip'] sess_persist = v.pop('session_persistence', None) with context.session.begin(subtransactions=True): vip_db = self._get_resource(context, Vip, id) self.assert_modification_allowed(vip_db) if sess_persist: self._update_vip_session_persistence(context, id, sess_persist) else: self._delete_session_persistence(context, id) if v: try: # in case new pool already has a vip # update will raise integrity error at first query old_pool_id = vip_db['pool_id'] vip_db.update(v) # If the pool_id is changed, we need to update # the associated pools if 'pool_id' in v: new_pool = self._get_resource(context, Pool, v['pool_id']) self.assert_modification_allowed(new_pool) # check that the pool matches the tenant_id if new_pool['tenant_id'] != vip_db['tenant_id']: raise n_exc.NotAuthorized() # validate that the pool has same protocol if new_pool['protocol'] != vip_db['protocol']: raise loadbalancer.ProtocolMismatch( vip_proto=vip_db['protocol'], pool_proto=new_pool['protocol']) if new_pool['status'] == constants.PENDING_DELETE: raise loadbalancer.StateInvalid( state=new_pool['status'], id=new_pool['id']) if old_pool_id: old_pool = self._get_resource( context, Pool, old_pool_id ) old_pool['vip_id'] = None new_pool['vip_id'] = vip_db['id'] except exception.DBDuplicateEntry: raise loadbalancer.VipExists(pool_id=v['pool_id']) return self._make_vip_dict(vip_db)
def _validate(self, context, tenant_id): """Validate and return the tenant to be associated to the topology.""" if tenant_id == 'None': # NOTE(HenryG): the client might be sending us astray by # passing no tenant; this is really meant to be the tenant # issuing the request, therefore let's get it from the context tenant_id = context.tenant_id if not context.is_admin and tenant_id != context.tenant_id: raise n_exc.NotAuthorized() return tenant_id
def update_job(context, id, body): LOG.info("update_job %s for tenant %s" % (id, context.tenant_id)) if not context.is_admin: raise n_exc.NotAuthorized() job_update = body.get('job') if not job_update: raise n_exc.BadRequest(resource="job", msg="Invalid request body.") job = db_api.async_transaction_find(context, id=id, scope=db_api.ONE) if not job: raise q_exc.JobNotFound(job_id=id) job_mod = db_api.async_transaction_update(context, job, **job_update) return v._make_job_dict(job_mod)
def create_mac_address_range(context, mac_range): LOG.info("create_mac_address_range for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() cidr = mac_range["mac_address_range"]["cidr"] do_not_use = mac_range["mac_address_range"].get("do_not_use", "0") cidr, first_address, last_address = _to_mac_range(cidr) with context.session.begin(): new_range = db_api.mac_address_range_create( context, cidr=cidr, first_address=first_address, last_address=last_address, next_auto_assign_mac=first_address, do_not_use=do_not_use) return v._make_mac_range_dict(new_range)
def create_segment_allocation_range(context, sa_range): LOG.info("create_segment_allocation_range for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() sa_range = sa_range.get("segment_allocation_range") if not sa_range: raise n_exc.BadRequest(resource="segment_allocation_range", msg=("segment_allocation_range not in " "request body.")) # TODO(morgabra) Figure out how to get the api extension to validate this # for us. # parse required fields for k in ["first_id", "last_id", "segment_id", "segment_type"]: sa_range[k] = sa_range.get(k, None) if sa_range[k] is None: raise n_exc.BadRequest( resource="segment_allocation_range", msg=("Missing required key %s in request body." % (k))) # parse optional fields for k in ["do_not_use"]: sa_range[k] = sa_range.get(k, None) # use the segment registry to validate and create/populate the range if not SA_REGISTRY.is_valid_strategy(sa_range["segment_type"]): raise n_exc.BadRequest( resource="segment_allocation_range", msg=("Unknown segment type '%s'" % (k))) strategy = SA_REGISTRY.get_strategy(sa_range["segment_type"]) # Create the new range with context.session.begin(): new_range = strategy.create_range(context, sa_range) # Bulk-populate the range, this could take a while for huge ranges # (millions) so we do this in chunks outside the transaction. That # means we need to rollback the range creation if it fails for # whatever reason (and it will cascade delete any added allocations) try: strategy.populate_range(context, new_range) except Exception: LOG.exception("Failed to populate segment allocation range.") delete_segment_allocation_range(context, new_range["id"]) raise return v._make_segment_allocation_range_dict(new_range)
def diagnose_port(context, id, fields): if not context.is_admin: raise n_exc.NotAuthorized() if id == "*": return { 'ports': [ _diag_port(context, port, fields) for port in db_api.port_find(context).all() ] } db_port = db_api.port_find(context, id=id, scope=db_api.ONE) if not db_port: raise n_exc.PortNotFound(port_id=id) port = _diag_port(context, db_port, fields) return {'ports': port}
def diagnose_network(context, id, fields): if not context.is_admin: raise n_exc.NotAuthorized() if id == "*": return { 'networks': [ _diag_network(context, net, fields) for net in db_api.network_find(context, scope=db_api.ALL) ] } db_net = db_api.network_find(context, id=id, scope=db_api.ONE) if not db_net: raise n_exc.NetworkNotFound(net_id=id) net = _diag_network(context, db_net, fields) return {'networks': net}
def delete_mac_address_range(context, id): """Delete a mac_address_range. : param context: neutron api request context : param id: UUID representing the mac_address_range to delete. """ LOG.info("delete_mac_address_range %s for tenant %s" % (id, context.tenant_id)) if not context.is_admin: raise n_exc.NotAuthorized() with context.session.begin(): mar = db_api.mac_address_range_find(context, id=id, scope=db_api.ONE) if not mar: raise q_exc.MacAddressRangeNotFound( mac_address_range_id=id) _delete_mac_address_range(context, mar)
def delete_job(context, id, **filters): """Delete an ip address. : param context: neutron api request context : param id: UUID representing the ip address to delete. """ LOG.info("delete_ip_address %s for tenant %s" % (id, context.tenant_id)) if not context.is_admin: raise n_exc.NotAuthorized() with context.session.begin(): job = db_api.async_transaction_find(context, id=id, scope=db_api.ONE, **filters) if not job: raise q_exc.JobNotFound(job_id=id) db_api.async_transaction_delete(context, job)
def delete_segment_allocation_range(context, sa_id): """Delete a segment_allocation_range. : param context: neutron api request context : param id: UUID representing the segment_allocation_range to delete. """ LOG.info("delete_segment_allocation_range %s for tenant %s" % (sa_id, context.tenant_id)) if not context.is_admin: raise n_exc.NotAuthorized() with context.session.begin(): sa_range = db_api.segment_allocation_range_find( context, id=sa_id, scope=db_api.ONE) if not sa_range: raise q_exc.SegmentAllocationRangeNotFound( segment_allocation_range_id=sa_id) _delete_segment_allocation_range(context, sa_range)
def _allocate_ips(fixed_ips, net, port_id, segment_id, mac, **kwargs): if fixed_ips: if (STRATEGY.is_provider_network(net_id) and not context.is_admin): raise n_exc.NotAuthorized() ips, subnets = split_and_validate_requested_subnets( context, net_id, segment_id, fixed_ips) kwargs["ip_addresses"] = ips kwargs["subnets"] = subnets ipam_driver.allocate_ip_address(context, addresses, net["id"], port_id, CONF.QUARK.ipam_reuse_after, segment_id=segment_id, mac_address=mac, **kwargs)
def get_segment_allocation_range(context, id, fields=None): LOG.info("get_segment_allocation_range %s for tenant %s fields %s" % (id, context.tenant_id, fields)) if not context.is_admin: raise n_exc.NotAuthorized() sa_range = db_api.segment_allocation_range_find(context, id=id, scope=db_api.ONE) if not sa_range: raise q_exc.SegmentAllocationRangeNotFound( segment_allocation_range_id=id) # Count up allocations so we can calculate how many are free. allocs = db_api.segment_allocation_find( context, segment_allocation_range_id=sa_range["id"], deallocated=False).count() return v._make_segment_allocation_range_dict(sa_range, allocations=allocs)
def create_job(context, body): """Creates a job with support for subjobs. If parent_id is not in the body: * the job is considered a parent job * it will have a NULL transaction id * its transaction id == its id * all subjobs will use its transaction id as theirs Else: * the job is a sub job * the parent id is the id passed in * the transaction id is the root of the job tree """ LOG.info("create_job for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() job = body.get('job') if 'parent_id' in job: parent_id = job['parent_id'] if not parent_id: raise q_exc.JobNotFound(job_id=parent_id) parent_job = db_api.async_transaction_find(context, id=parent_id, scope=db_api.ONE) if not parent_job: raise q_exc.JobNotFound(job_id=parent_id) tid = parent_id if parent_job.get('transaction_id'): tid = parent_job.get('transaction_id') job['transaction_id'] = tid if not job: raise n_exc.BadRequest(resource="job", msg="Invalid request body.") with context.session.begin(subtransactions=True): new_job = db_api.async_transaction_create(context, **job) return v._make_job_dict(new_job)
def create_mac_address_range(context, mac_range): LOG.info("create_mac_address_range for tenant %s" % context.tenant_id) if not context.is_admin: raise n_exc.NotAuthorized() if not mac_range or "mac_address_range" not in mac_range: raise n_exc.BadRequest(resource="mac_address_range", msg="Malformed body") rng = mac_range.get("mac_address_range") cidr = rng.get("cidr") if not cidr: raise n_exc.BadRequest(resource="mac_address_range", msg="Missing cidr") do_not_use = rng.get("do_not_use", "0") cidr, first_address, last_address = _to_mac_range(cidr) with context.session.begin(): new_range = db_api.mac_address_range_create( context, cidr=cidr, first_address=first_address, last_address=last_address, next_auto_assign_mac=first_address, do_not_use=do_not_use) return v._make_mac_range_dict(new_range)
def get_mac_address_range(context, id, fields=None): """Retrieve a mac_address_range. : param context: neutron api request context : param id: UUID representing the network to fetch. : param fields: a list of strings that are valid keys in a network dictionary as listed in the RESOURCE_ATTRIBUTE_MAP object in neutron/api/v2/attributes.py. Only these fields will be returned. """ LOG.info("get_mac_address_range %s for tenant %s fields %s" % (id, context.tenant_id, fields)) if not context.is_admin: raise n_exc.NotAuthorized() mac_address_range = db_api.mac_address_range_find( context, id=id, scope=db_api.ONE) if not mac_address_range: raise q_exc.MacAddressRangeNotFound( mac_address_range_id=id) return v._make_mac_range_dict(mac_address_range)
def delete_subnet(context, id): """Delete a subnet. : param context: neutron api request context : param id: UUID representing the subnet to delete. """ LOG.info("delete_subnet %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): subnet = db_api.subnet_find(context, id=id, scope=db_api.ONE) if not subnet: raise n_exc.SubnetNotFound(subnet_id=id) if not context.is_admin: if STRATEGY.is_provider_network(subnet.network_id): if subnet.tenant_id == context.tenant_id: # A tenant can't delete subnets on provider network raise n_exc.NotAuthorized(subnet_id=id) else: # Raise a NotFound here because the foreign tenant # does not have to know about other tenant's subnet # existence. raise n_exc.SubnetNotFound(subnet_id=id) _delete_subnet(context, subnet)
def get_rule_type(self, context, rule_type_name, fields=None): if not context.is_admin: raise lib_exc.NotAuthorized() return rule_type_object.QosRuleType.get_object(rule_type_name)
def index(self, request): context = request.context if not context.is_admin: raise n_exc.NotAuthorized() return self._plugin.get_ip_availability(**request.GET)
def create_vip(self, context, vip): v = vip['vip'] tenant_id = v['tenant_id'] with context.session.begin(subtransactions=True): if v['pool_id']: pool = self._get_resource(context, Pool, v['pool_id']) # validate that the pool has same tenant if pool['tenant_id'] != tenant_id: raise n_exc.NotAuthorized() # validate that the pool has same protocol if pool['protocol'] != v['protocol']: raise loadbalancer.ProtocolMismatch( vip_proto=v['protocol'], pool_proto=pool['protocol']) if pool['status'] == constants.PENDING_DELETE: raise loadbalancer.StateInvalid(state=pool['status'], id=pool['id']) vip_db = Vip(id=uuidutils.generate_uuid(), tenant_id=tenant_id, name=v['name'], description=v['description'], port_id=None, protocol_port=v['protocol_port'], protocol=v['protocol'], pool_id=v['pool_id'], connection_limit=v['connection_limit'], admin_state_up=v['admin_state_up'], status=constants.PENDING_CREATE) session_info = v['session_persistence'] if session_info: s_p = self._create_session_persistence_db( session_info, vip_db['id']) vip_db.session_persistence = s_p try: context.session.add(vip_db) context.session.flush() except exception.DBDuplicateEntry: raise loadbalancer.VipExists(pool_id=v['pool_id']) try: # create a port to reserve address for IPAM # do it outside the transaction to avoid rpc calls self._create_port_for_vip(context, vip_db, v['subnet_id'], v.get('address')) except Exception: # catch any kind of exceptions with excutils.save_and_reraise_exception(): context.session.delete(vip_db) context.session.flush() if v['pool_id']: # fetching pool again pool = self._get_resource(context, Pool, v['pool_id']) # (NOTE): we rely on the fact that pool didn't change between # above block and here vip_db['pool_id'] = v['pool_id'] pool['vip_id'] = vip_db['id'] # explicitly flush changes as we're outside any transaction context.session.flush() return self._make_vip_dict(vip_db)
def _raise_if_unauthorized(context, net): if (not STRATEGY.is_provider_network(net["id"]) and net["tenant_id"] != context.tenant_id and not context.is_advsvc): raise n_exc.NotAuthorized()