def update_ip_address(context, id, ip_address): LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) address = db_api.ip_address_find( context, id=id, tenant_id=context.tenant_id, scope=db_api.ONE) if not address: raise exceptions.NotFound( message="No IP address found with id=%s" % id) old_ports = address['ports'] port_ids = ip_address['ip_address'].get('port_ids') if port_ids is None: return v._make_ip_dict(address) for port in old_ports: port['ip_addresses'].remove(address) if port_ids: ports = db_api.port_find( context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE: could be considered inefficient because we're converting # to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise exceptions.NotFound( message="No ports not found with ids=%s" % port_ids) for port in ports: port['ip_addresses'].extend([address]) else: address["deallocated"] = 1 return v._make_ip_dict(address)
def update_ip_address(context, id, ip_address): LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) ports = [] with context.session.begin(): address = db_api.ip_address_find( context, id=id, tenant_id=context.tenant_id, scope=db_api.ONE) if not address: raise exceptions.NotFound( message="No IP address found with id=%s" % id) reset = ip_address['ip_address'].get('reset_allocation_time', False) if reset and address['deallocated'] == 1: if context.is_admin: LOG.info("IP's deallocated time being manually reset") address['deallocated_at'] = _get_deallocated_override() else: msg = "Modification of reset_allocation_time requires admin" raise webob.exc.HTTPForbidden(detail=msg) port_ids = ip_address['ip_address'].get('port_ids') if port_ids: _raise_if_shared_and_enabled(ip_address, address) ports = db_api.port_find(context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE(name): could be considered inefficient because we're # converting to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise exceptions.NotFound( message="No ports not found with ids=%s" % port_ids) validate_ports_on_network_and_same_segment(ports, address["network_id"]) validate_port_ip_quotas(context, ports) LOG.info("Updating IP address, %s, to only be used by the" "following ports: %s" % (address.address_readable, [p.id for p in ports])) new_address = db_api.update_port_associations_for_ip(context, ports, address) else: if port_ids is not None: ipam_driver.deallocate_ip_address( context, address) return v._make_ip_dict(address) return v._make_ip_dict(new_address)
def get_ip_addresses(context, **filters): LOG.info("get_ip_addresses for tenant %s" % context.tenant_id) if not filters: filters = {} if 'type' in filters: filters['address_type'] = filters['type'] if context.is_admin: if 'deallocated' in filters: if filters['deallocated'] == 'True': filters["_deallocated"] = True elif filters['deallocated'] == 'False': filters["_deallocated"] = False elif filters['deallocated'].lower() == 'both': pass else: filters['_deallocated'] = False else: filters['_deallocated'] = False else: filters["_deallocated"] = False if 'deallocated' in filters: # this needs to be removed or it corrupts the filters passed to the db # model. Only _deallocated needs to be present del filters['deallocated'] addrs = db_api.ip_address_find(context, scope=db_api.ALL, **filters) return [v._make_ip_dict(ip, context.is_admin) for ip in addrs]
def get_ip_address(context, id): LOG.info("get_ip_address %s for tenant %s" % (id, context.tenant_id)) addr = db_api.ip_address_find(context, id=id, scope=db_api.ONE) if not addr: raise quark_exceptions.IpAddressNotFound(addr_id=id) return v._make_ip_dict(addr)
def update_ip_address(context, id, ip_address): LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): address = db_api.ip_address_find(context, id=id, tenant_id=context.tenant_id, scope=db_api.ONE) if not address: raise exceptions.NotFound( message="No IP address found with id=%s" % id) reset = ip_address['ip_address'].get('reset_allocation_time', False) if reset and address['deallocated'] == 1: if context.is_admin: LOG.info("IP's deallocated time being manually reset") address['deallocated_at'] = _get_deallocated_override() else: msg = "Modification of reset_allocation_time requires admin" raise webob.exc.HTTPForbidden(detail=msg) old_ports = address['ports'] port_ids = ip_address['ip_address'].get('port_ids') if port_ids is None: return v._make_ip_dict(address) for port in old_ports: port['ip_addresses'].remove(address) if port_ids: ports = db_api.port_find(context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE: could be considered inefficient because we're converting # to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise exceptions.NotFound( message="No ports not found with ids=%s" % port_ids) for port in ports: port['ip_addresses'].extend([address]) else: address["deallocated"] = 1 return v._make_ip_dict(address)
def get_ip_address(context, id): LOG.info("get_ip_address %s for tenant %s" % (id, context.tenant_id)) filters = {} filters["_deallocated"] = False addr = db_api.ip_address_find(context, id=id, scope=db_api.ONE, **filters) if not addr: raise q_exc.IpAddressNotFound(addr_id=id) return v._make_ip_dict(addr)
def update_ip_address(context, id, ip_address): LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) with context.session.begin(): address = db_api.ip_address_find( context, id=id, tenant_id=context.tenant_id, scope=db_api.ONE) if not address: raise exceptions.NotFound( message="No IP address found with id=%s" % id) reset = ip_address['ip_address'].get('reset_allocation_time', False) if reset and address['deallocated'] == 1: if context.is_admin: LOG.info("IP's deallocated time being manually reset") address['deallocated_at'] = _get_deallocated_override() else: msg = "Modification of reset_allocation_time requires admin" raise webob.exc.HTTPForbidden(detail=msg) old_ports = address['ports'] port_ids = ip_address['ip_address'].get('port_ids') if port_ids is None: return v._make_ip_dict(address) for port in old_ports: port['ip_addresses'].remove(address) if port_ids: ports = db_api.port_find( context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE: could be considered inefficient because we're converting # to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise exceptions.NotFound( message="No ports not found with ids=%s" % port_ids) for port in ports: port['ip_addresses'].extend([address]) else: address["deallocated"] = 1 return v._make_ip_dict(address)
def get_ip_addresses(context, **filters): LOG.info("get_ip_addresses for tenant %s" % context.tenant_id) if not filters: filters = {} if 'type' in filters: filters['address_type'] = filters['type'] filters["_deallocated"] = False addrs = db_api.ip_address_find(context, scope=db_api.ALL, **filters) return [v._make_ip_dict(ip) for ip in addrs]
def create_ip_address(context, ip_address): LOG.info("create_ip_address for tenant %s" % context.tenant_id) port = None ip_dict = ip_address["ip_address"] port_ids = ip_dict.get('port_ids') network_id = ip_dict.get('network_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') ports = [] if device_ids and not network_id: raise exceptions.BadRequest( resource="ip_addresses", msg="network_id is required if device_ids are supplied.") with context.session.begin(): if network_id and device_ids: for device_id in device_ids: port = db_api.port_find( context, network_id=network_id, device_id=device_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) if not ports: raise exceptions.PortNotFound(port_id=port_ids, net_id=network_id) address = ipam_driver.allocate_ip_address( context, port['network_id'], port['id'], CONF.QUARK.ipam_reuse_after, ip_version, ip_addresses=[ip_address]) for port in ports: port["ip_addresses"].append(address) return v._make_ip_dict(address)
def update_ip_address(context, id, ip_address): """Due to NCP-1592 ensure that address_type cannot change after update.""" LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) ports = [] if 'ip_address' not in ip_address: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") with context.session.begin(): address = db_api.ip_address_find(context, id=id, scope=db_api.ONE) if not address: raise q_exc.IpAddressNotFound(addr_id=id) iptype = address.address_type if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest( resource="ip_addresses", msg="Fixed ips cannot be updated using this interface.") reset = ip_address['ip_address'].get('reset_allocation_time', False) if reset and address['deallocated'] == 1: if context.is_admin: LOG.info("IP's deallocated time being manually reset") address['deallocated_at'] = _get_deallocated_override() else: msg = "Modification of reset_allocation_time requires admin" raise webob.exc.HTTPForbidden(detail=msg) port_ids = ip_address['ip_address'].get('port_ids', None) if port_ids is not None and not port_ids: raise n_exc.BadRequest( resource="ip_addresses", msg="Cannot be updated with empty port_id list") if iptype == ip_types.SHARED: has_owner = address.has_any_shared_owner() if port_ids: if iptype == ip_types.FIXED and len(port_ids) > 1: raise n_exc.BadRequest( resource="ip_addresses", msg="Fixed ips cannot be updated with more than one port.") _raise_if_shared_and_enabled(ip_address, address) ports = db_api.port_find(context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE(name): could be considered inefficient because we're # converting to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise n_exc.PortNotFound(port_id=port_ids) validate_and_fetch_segment(ports, address["network_id"]) validate_port_ip_quotas(context, address.network_id, ports) if iptype == ip_types.SHARED and has_owner: for assoc in address.associations: pid = assoc.port_id if pid not in port_ids and 'none' != assoc.service: raise q_exc.PortRequiresDisassociation() LOG.info("Updating IP address, %s, to only be used by the" "following ports: %s" % (address.address_readable, [p.id for p in ports])) new_address = db_api.update_port_associations_for_ip( context, ports, address) elif iptype == ip_types.SHARED and has_owner: raise q_exc.PortRequiresDisassociation() else: ipam_driver.deallocate_ip_address(context, address) return v._make_ip_dict(address) return v._make_ip_dict(new_address)
def create_ip_address(context, body): LOG.info("create_ip_address for tenant %s" % context.tenant_id) iptype = (ip_types.SHARED if _shared_ip_request(body) else ip_types.FIXED) if 'ip_address' not in body: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest(resource="ip_addresses", msg="Only shared IPs may be made with " "this resource.") ip_dict = body.get("ip_address") port_ids = ip_dict.get('port_ids', []) network_id = ip_dict.get('network_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') # If no version is passed, you would get what the network provides, # which could be both v4 and v6 addresses. Rather than allow for such # an ambiguous outcome, we'll raise instead if not ip_version: raise n_exc.BadRequest(resource="ip_addresses", msg="version is required.") if network_id is None: raise n_exc.BadRequest(resource="ip_addresses", msg="network_id is required.") if network_id == "": raise n_exc.NetworkNotFound(net_id=network_id) net = db_api.network_find(context, None, None, None, False, id=network_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=network_id) if not port_ids and not device_ids: raise n_exc.BadRequest(resource="ip_addresses", msg="port_ids or device_ids required.") new_addresses = [] ports = [] by_device = False with context.session.begin(): if network_id and device_ids: by_device = True for device_id in device_ids: port = db_api.port_find(context, network_id=network_id, device_id=device_id, tenant_id=context.tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=context.tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) if not ports: raise n_exc.PortNotFoundOnNetwork(port_id=port_ids, net_id=network_id) if ((by_device and len(device_ids) != len(ports)) or (not by_device and len(port_ids) != len(ports))): raise q_exc.NotAllPortOrDeviceFound() segment_id = validate_and_fetch_segment(ports, network_id) if iptype == ip_types.SHARED: old_addresses = db_api.ip_address_find(context, network_id=network_id, address_type=ip_types.SHARED, scope=db_api.ALL) validate_shared_ips_quotas(context, network_id, old_addresses) validate_port_ip_quotas(context, network_id, ports) # Shared Ips are only new IPs. Two use cases: if we got device_id # or if we got port_ids. We should check the case where we got port_ids # and device_ids. The device_id must have a port on the network, # and any port_ids must also be on that network already. If we have # more than one port by this step, it's considered a shared IP, # and therefore will be marked as unconfigured (enabled=False) # for all ports. ipam_driver.allocate_ip_address( context, new_addresses, network_id, None, CONF.QUARK.ipam_reuse_after, version=ip_version, ip_addresses=[ip_address] if ip_address else [], segment_id=segment_id, address_type=iptype) with context.session.begin(): address = new_addresses[0] new_address = db_api.port_associate_ip(context, ports, address) return v._make_ip_dict(new_address)
def update_ip_address(context, id, ip_address): """Due to NCP-1592 ensure that address_type cannot change after update.""" LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id)) ports = [] if 'ip_address' not in ip_address: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") with context.session.begin(): address = db_api.ip_address_find(context, id=id, scope=db_api.ONE) if not address: raise q_exc.IpAddressNotFound(addr_id=id) iptype = address.address_type if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest( resource="ip_addresses", msg="Fixed ips cannot be updated using this interface.") reset = ip_address['ip_address'].get('reset_allocation_time', False) if reset and address['deallocated'] == 1: if context.is_admin: LOG.info("IP's deallocated time being manually reset") address['deallocated_at'] = _get_deallocated_override() else: msg = "Modification of reset_allocation_time requires admin" raise webob.exc.HTTPForbidden(detail=msg) port_ids = ip_address['ip_address'].get('port_ids', None) if port_ids is not None and not port_ids: raise n_exc.BadRequest( resource="ip_addresses", msg="Cannot be updated with empty port_id list") if iptype == ip_types.SHARED: has_owner = address.has_any_shared_owner() if port_ids: if iptype == ip_types.FIXED and len(port_ids) > 1: raise n_exc.BadRequest( resource="ip_addresses", msg="Fixed ips cannot be updated with more than one port.") _raise_if_shared_and_enabled(ip_address, address) ports = db_api.port_find(context, tenant_id=context.tenant_id, id=port_ids, scope=db_api.ALL) # NOTE(name): could be considered inefficient because we're # converting to a list to check length. Maybe revisit if len(ports) != len(port_ids): raise n_exc.PortNotFound(port_id=port_ids) validate_and_fetch_segment(ports, address["network_id"]) validate_port_ip_quotas(context, address.network_id, ports) if iptype == ip_types.SHARED and has_owner: for assoc in address.associations: pid = assoc.port_id if pid not in port_ids and 'none' != assoc.service: raise q_exc.PortRequiresDisassociation() LOG.info("Updating IP address, %s, to only be used by the" "following ports: %s" % (address.address_readable, [p.id for p in ports])) new_address = db_api.update_port_associations_for_ip(context, ports, address) elif iptype == ip_types.SHARED and has_owner: raise q_exc.PortRequiresDisassociation() else: ipam_driver.deallocate_ip_address(context, address) return v._make_ip_dict(address) return v._make_ip_dict(new_address)
def create_ip_address(context, body): LOG.info("create_ip_address for tenant %s" % context.tenant_id) iptype = (ip_types.SHARED if _shared_ip_request(body) else ip_types.FIXED) if 'ip_address' not in body: raise n_exc.BadRequest(resource="ip_addresses", msg="Invalid request body.") if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip: raise n_exc.BadRequest(resource="ip_addresses", msg="Only shared IPs may be made with " "this resource.") ip_dict = body.get("ip_address") port_ids = ip_dict.get('port_ids', []) network_id = ip_dict.get('network_id') tenant_id = ip_dict.get('tenant_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') # If no version is passed, you would get what the network provides, # which could be both v4 and v6 addresses. Rather than allow for such # an ambiguous outcome, we'll raise instead if not ip_version: raise n_exc.BadRequest(resource="ip_addresses", msg="version is required.") if network_id is None: raise n_exc.BadRequest(resource="ip_addresses", msg="network_id is required.") if network_id == "": raise n_exc.NetworkNotFound(net_id=network_id) net = db_api.network_find(context, None, None, None, False, id=network_id, scope=db_api.ONE) if not net: raise n_exc.NetworkNotFound(net_id=network_id) if not port_ids and not device_ids: raise n_exc.BadRequest(resource="ip_addresses", msg="port_ids or device_ids required.") new_addresses = [] ports = [] by_device = False with context.session.begin(): if network_id and device_ids: by_device = True for device_id in device_ids: port = db_api.port_find( context, network_id=network_id, device_id=device_id, tenant_id=tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=tenant_id, scope=db_api.ONE) if port is not None: ports.append(port) if not ports: raise n_exc.PortNotFoundOnNetwork(port_id=port_ids, net_id=network_id) if ((by_device and len(device_ids) != len(ports)) or (not by_device and len(port_ids) != len(ports))): raise q_exc.NotAllPortOrDeviceFound() segment_id = validate_and_fetch_segment(ports, network_id) if iptype == ip_types.SHARED: old_addresses = db_api.ip_address_find(context, network_id=network_id, tenant_id=tenant_id, address_type=ip_types.SHARED, scope=db_api.ALL) validate_shared_ips_quotas(context, network_id, old_addresses) validate_port_ip_quotas(context, network_id, ports) # Shared Ips are only new IPs. Two use cases: if we got device_id # or if we got port_ids. We should check the case where we got port_ids # and device_ids. The device_id must have a port on the network, # and any port_ids must also be on that network already. If we have # more than one port by this step, it's considered a shared IP, # and therefore will be marked as unconfigured (enabled=False) # for all ports. ipam_driver.allocate_ip_address(context, new_addresses, network_id, None, CONF.QUARK.ipam_reuse_after, version=ip_version, ip_addresses=[ip_address] if ip_address else [], segment_id=segment_id, address_type=iptype) with context.session.begin(): address = new_addresses[0] new_address = db_api.port_associate_ip(context, ports, address) return v._make_ip_dict(new_address)
def create_ip_address(context, body): LOG.info("create_ip_address for tenant %s" % context.tenant_id) address_type = (ip_types.SHARED if _shared_ip_request(body) else ip_types.FIXED) ip_dict = body.get("ip_address") port_ids = ip_dict.get('port_ids', []) network_id = ip_dict.get('network_id') device_ids = ip_dict.get('device_ids') ip_version = ip_dict.get('version') ip_address = ip_dict.get('ip_address') # If no version is passed, you would get what the network provides, # which could be both v4 and v6 addresses. Rather than allow for such # an ambiguous outcome, we'll raise instead if not ip_version: raise exceptions.BadRequest(resource="ip_addresses", msg="version is required.") if not network_id: raise exceptions.BadRequest(resource="ip_addresses", msg="network_id is required.") new_addresses = [] ports = [] with context.session.begin(): if network_id and device_ids: for device_id in device_ids: port = db_api.port_find( context, network_id=network_id, device_id=device_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) elif port_ids: for port_id in port_ids: port = db_api.port_find(context, id=port_id, tenant_id=context.tenant_id, scope=db_api.ONE) ports.append(port) if not ports: raise exceptions.PortNotFound(port_id=port_ids, net_id=network_id) validate_ports_on_network_and_same_segment(ports, network_id) validate_port_ip_quotas(context, ports) # Shared Ips are only new IPs. Two use cases: if we got device_id # or if we got port_ids. We should check the case where we got port_ids # and device_ids. The device_id must have a port on the network, # and any port_ids must also be on that network already. If we have # more than one port by this step, it's considered a shared IP, # and therefore will be marked as unconfigured (enabled=False) # for all ports. ipam_driver.allocate_ip_address(context, new_addresses, network_id, None, CONF.QUARK.ipam_reuse_after, version=ip_version, ip_addresses=[ip_address] if ip_address else [], address_type=address_type) with context.session.begin(): new_address = db_api.port_associate_ip(context, ports, new_addresses[0]) return v._make_ip_dict(new_address)