signature:
def update_subnet ( context , id , subnet ) :
    """Update values of a subnet .
 : param context : neutron api request context
 : param id : UUID representing the subnet to update .
 : param subnet : dictionary with keys indicating fields to update .
 valid keys are those that have a value of True for ' allow _ put '
 as listed in the RESOURCE _ ATTRIBUTE _ MAP object in
 neutron / api / v2 / attributes . py ."""

implementation:
LOG . info ( "update_subnet %s for tenant %s" % ( id , context . tenant_id ) )
with context . session . begin ( ) :
    subnet_db = db_api . subnet_find ( context = context , limit = None , page_reverse = False , sorts = [ 'id' ] , marker_obj = None , fields = None , id = id , scope = db_api . ONE )
    if not subnet_db :
        raise n_exc . SubnetNotFound ( subnet_id = id )
    s = subnet [ "subnet" ]
    always_pop = [ "_cidr" , "cidr" , "first_ip" , "last_ip" , "ip_version" , "segment_id" , "network_id" ]
    admin_only = [ "do_not_use" , "created_at" , "tenant_id" , "next_auto_assign_ip" , "enable_dhcp" ]
    utils . filter_body ( context , s , admin_only , always_pop )
    dns_ips = utils . pop_param ( s , "dns_nameservers" , [ ] )
    host_routes = utils . pop_param ( s , "host_routes" , [ ] )
    gateway_ip = utils . pop_param ( s , "gateway_ip" , None )
    allocation_pools = utils . pop_param ( s , "allocation_pools" , None )
    if not CONF . QUARK . allow_allocation_pool_update :
        if allocation_pools :
            raise n_exc . BadRequest ( resource = "subnets" , msg = "Allocation pools cannot be updated." )
        if subnet_db [ "ip_policy" ] is not None :
            ip_policy_cidrs = subnet_db [ "ip_policy" ] . get_cidrs_ip_set ( )
        else :
            ip_policy_cidrs = netaddr . IPSet ( [ ] )
        alloc_pools = allocation_pool . AllocationPools ( subnet_db [ "cidr" ] , policies = ip_policy_cidrs )
    else :
        alloc_pools = allocation_pool . AllocationPools ( subnet_db [ "cidr" ] , allocation_pools )
        original_pools = subnet_db . allocation_pools
        ori_pools = allocation_pool . AllocationPools ( subnet_db [ "cidr" ] , original_pools )
        # Check if the pools are growing or shrinking
        is_growing = _pool_is_growing ( ori_pools , alloc_pools )
        if not CONF . QUARK . allow_allocation_pool_growth and is_growing :
            raise n_exc . BadRequest ( resource = "subnets" , msg = "Allocation pools may not be updated to be larger " "do to configuration settings" )
    quota . QUOTAS . limit_check ( context , context . tenant_id , alloc_pools_per_subnet = len ( alloc_pools ) )
    if gateway_ip :
        alloc_pools . validate_gateway_excluded ( gateway_ip )
        default_route = None
        for route in host_routes :
            netaddr_route = netaddr . IPNetwork ( route [ "destination" ] )
            if netaddr_route . value == routes . DEFAULT_ROUTE . value :
                default_route = route
                break
        if default_route is None :
            route_model = db_api . route_find ( context , cidr = str ( routes . DEFAULT_ROUTE ) , subnet_id = id , scope = db_api . ONE )
            if route_model :
                db_api . route_update ( context , route_model , gateway = gateway_ip )
            else :
                db_api . route_create ( context , cidr = str ( routes . DEFAULT_ROUTE ) , gateway = gateway_ip , subnet_id = id )
    if dns_ips :
        subnet_db [ "dns_nameservers" ] = [ ]
        quota . QUOTAS . limit_check ( context , context . tenant_id , dns_nameservers_per_subnet = len ( dns_ips ) )
    for dns_ip in dns_ips :
        subnet_db [ "dns_nameservers" ] . append ( db_api . dns_create ( context , ip = netaddr . IPAddress ( dns_ip ) ) )
    if host_routes :
        subnet_db [ "routes" ] = [ ]
        quota . QUOTAS . limit_check ( context , context . tenant_id , routes_per_subnet = len ( host_routes ) )
    for route in host_routes :
        subnet_db [ "routes" ] . append ( db_api . route_create ( context , cidr = route [ "destination" ] , gateway = route [ "nexthop" ] ) )
    if CONF . QUARK . allow_allocation_pool_update :
        if isinstance ( allocation_pools , list ) :
            cidrs = alloc_pools . get_policy_cidrs ( )
            ip_policies . ensure_default_policy ( cidrs , [ subnet_db ] )
            subnet_db [ "ip_policy" ] = db_api . ip_policy_update ( context , subnet_db [ "ip_policy" ] , exclude = cidrs )
            # invalidate the cache
            db_api . subnet_update_set_alloc_pool_cache ( context , subnet_db )
    subnet = db_api . subnet_update ( context , subnet_db , ** s )
return v . _make_subnet_dict ( subnet )


signature:
def get_subnet ( context , id , fields = None ) :
    """Retrieve a subnet .
 : param context : neutron api request context
 : param id : UUID representing the subnet to fetch .
 : param fields : a list of strings that are valid keys in a
 subnet dictionary as listed in the RESOURCE _ ATTRIBUTE _ MAP
 object in neutron / api / v2 / attributes . py . Only these fields
 will be returned ."""

implementation:
LOG . info ( "get_subnet %s for tenant %s with fields %s" % ( id , context . tenant_id , fields ) )
subnet = db_api . subnet_find ( context = context , limit = None , page_reverse = False , sorts = [ 'id' ] , marker_obj = None , fields = None , id = id , join_dns = True , join_routes = True , scope = db_api . ONE )
if not subnet :
    raise n_exc . SubnetNotFound ( subnet_id = id )
cache = subnet . get ( "_allocation_pool_cache" )
if not cache :
    new_cache = subnet . allocation_pools
    db_api . subnet_update_set_alloc_pool_cache ( context , subnet , new_cache )
return v . _make_subnet_dict ( subnet )


signature:
def get_subnets ( context , limit = None , page_reverse = False , sorts = [ 'id' ] , marker = None , filters = None , fields = None ) :
    """Retrieve a list of subnets .
 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 subnet as listed in the RESOURCE _ ATTRIBUTE _ MAP object
 in neutron / api / v2 / attributes . py . Values in this dictiontary
 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
 subnet dictionary as listed in the RESOURCE _ ATTRIBUTE _ MAP
 object in neutron / api / v2 / attributes . py . Only these fields
 will be returned ."""

implementation:
LOG . info ( "get_subnets for tenant %s with filters %s fields %s" % ( context . tenant_id , filters , fields ) )
filters = filters or { }
subnets = db_api . subnet_find ( context , limit = limit , page_reverse = page_reverse , sorts = sorts , marker_obj = marker , join_dns = True , join_routes = True , join_pool = True , ** filters )
for subnet in subnets :
    cache = subnet . get ( "_allocation_pool_cache" )
    if not cache :
        db_api . subnet_update_set_alloc_pool_cache ( context , subnet , subnet . allocation_pools )
return v . _make_subnets_list ( subnets , fields = fields )


signature:
def get_subnets_count ( context , filters = None ) :
    """Return the number of subnets .
 The result 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 network as listed in the RESOURCE _ ATTRIBUTE _ MAP object
 in neutron / api / v2 / attributes . py . Values in this dictiontary
 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 .
 NOTE : this method is optional , as it was not part of the originally
 defined plugin API ."""

implementation:
LOG . info ( "get_subnets_count for tenant %s with filters %s" % ( context . tenant_id , filters ) )
return db_api . subnet_count_all ( context , ** filters )


signature:
def delete_subnet ( context , id ) :
    """Delete a subnet .
 : param context : neutron api request context
 : param id : UUID representing the subnet to delete ."""

implementation:
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 )


signature:
def get_resources ( cls ) :
    """Returns Ext Resources ."""

implementation:
plugin = directory . get_plugin ( )
controller = MacAddressRangesController ( plugin )
return [ extensions . ResourceExtension ( Mac_address_ranges . get_alias ( ) , controller ) ]


signature:
def _filter_update_security_group_rule ( rule ) :
    '''Only two fields are allowed for modification :
 external _ service and external _ service _ id'''

implementation:
allowed = [ 'external_service' , 'external_service_id' ]
filtered = { }
for k , val in rule . iteritems ( ) :
    if k in allowed :
        if isinstance ( val , basestring ) and len ( val ) <= GROUP_NAME_MAX_LENGTH :
            filtered [ k ] = val
return filtered


signature:
def _perform_async_update_rule ( context , id , db_sg_group , rule_id , action ) :
    """Updates a SG rule async and return the job information .
 Only happens if the security group has associated ports . If the async
 connection fails the update continues ( legacy mode ) ."""

implementation:
rpc_reply = None
sg_rpc = sg_rpc_api . QuarkSGAsyncProcessClient ( )
ports = db_api . sg_gather_associated_ports ( context , db_sg_group )
if len ( ports ) > 0 :
    rpc_reply = sg_rpc . start_update ( context , id , rule_id , action )
    if rpc_reply :
        job_id = rpc_reply [ 'job_id' ]
        job_api . add_job_to_context ( context , job_id )
    else :
        LOG . error ( "Async update failed. Is the worker running?" )


signature:
def create_security_group_rule ( context , security_group_rule ) :
    """Creates a rule and updates the ports ( async ) if enabled ."""

implementation:
LOG . info ( "create_security_group for tenant %s" % ( context . tenant_id ) )
with context . session . begin ( ) :
    rule = _validate_security_group_rule ( context , security_group_rule [ "security_group_rule" ] )
    rule [ "id" ] = uuidutils . generate_uuid ( )
    group_id = rule [ "security_group_id" ]
    group = db_api . security_group_find ( context , id = group_id , scope = db_api . ONE )
    if not group :
        raise sg_ext . SecurityGroupNotFound ( id = group_id )
    quota . QUOTAS . limit_check ( context , context . tenant_id , security_rules_per_group = len ( group . get ( "rules" , [ ] ) ) + 1 )
    new_rule = db_api . security_group_rule_create ( context , ** rule )
if group :
    _perform_async_update_rule ( context , group_id , group , new_rule . id , RULE_CREATE )
return v . _make_security_group_rule_dict ( new_rule )


signature:
def update_security_group_rule ( context , id , security_group_rule ) :
    '''Updates a rule and updates the ports'''

implementation:
LOG . info ( "update_security_group_rule for tenant %s" % ( context . tenant_id ) )
new_rule = security_group_rule [ "security_group_rule" ]
# Only allow updatable fields
new_rule = _filter_update_security_group_rule ( new_rule )
with context . session . begin ( ) :
    rule = db_api . security_group_rule_find ( context , id = id , scope = db_api . ONE )
    if not rule :
        raise sg_ext . SecurityGroupRuleNotFound ( id = id )
    db_rule = db_api . security_group_rule_update ( context , rule , ** new_rule )
    group_id = db_rule . group_id
    group = db_api . security_group_find ( context , id = group_id , scope = db_api . ONE )
    if not group :
        raise sg_ext . SecurityGroupNotFound ( id = group_id )
if group :
    _perform_async_update_rule ( context , group_id , group , rule . id , RULE_UPDATE )
return v . _make_security_group_rule_dict ( db_rule )


signature:
def delete_security_group_rule ( context , id ) :
    """Deletes a rule and updates the ports ( async ) if enabled ."""

implementation:
LOG . info ( "delete_security_group %s for tenant %s" % ( id , context . tenant_id ) )
with context . session . begin ( ) :
    rule = db_api . security_group_rule_find ( context , id = id , scope = db_api . ONE )
    if not rule :
        raise sg_ext . SecurityGroupRuleNotFound ( id = id )
    group = db_api . security_group_find ( context , id = rule [ "group_id" ] , scope = db_api . ONE )
    if not group :
        raise sg_ext . SecurityGroupNotFound ( id = id )
    rule [ "id" ] = id
    db_api . security_group_rule_delete ( context , rule )
if group :
    _perform_async_update_rule ( context , group . id , group , id , RULE_DELETE )


signature:
def get_data ( ) :
    """Returns combined list of tuples : [ ( table , column ) ] .
 List is built , based on retrieved tables , where column with name
 ` ` tenant _ id ` ` exists ."""

implementation:
output = [ ]
tables = get_tables ( )
for table in tables :
    try :
        columns = get_columns ( table )
    except sa . exc . NoSuchTableError :
        continue
    for column in columns :
        if column [ 'name' ] == 'tenant_id' :
            output . append ( ( table , column ) )
return output


signature:
def get_public_net_id ( self ) :
    """Returns the public net id"""

implementation:
for id , net_params in self . strategy . iteritems ( ) :
    if id == CONF . QUARK . public_net_id :
        return id
return None


signature:
def opt_args_decorator ( func ) :
    """A decorator to be used on another decorator
 This is done to allow separate handling on the basis of argument values"""

implementation:
@ wraps ( func )
def wrapped_dec ( * args , ** kwargs ) :
    if len ( args ) == 1 and len ( kwargs ) == 0 and callable ( args [ 0 ] ) : # actual decorated function
        return func ( args [ 0 ] )
    else : # decorator arguments
        return lambda realf : func ( realf , * args , ** kwargs )
return wrapped_dec


signature:
def _fix_missing_tenant_id ( self , context , body , key ) :
    """Will add the tenant _ id to the context from body .
 It is assumed that the body must have a tenant _ id because neutron
 core could never have gotten here otherwise ."""

implementation:
if not body :
    raise n_exc . BadRequest ( resource = key , msg = "Body malformed" )
resource = body . get ( key )
if not resource :
    raise n_exc . BadRequest ( resource = key , msg = "Body malformed" )
if context . tenant_id is None :
    context . tenant_id = resource . get ( "tenant_id" )
if context . tenant_id is None :
    msg = _ ( "Running without keystone AuthN requires " "that tenant_id is specified" )
    raise n_exc . BadRequest ( resource = key , msg = msg )


signature:
def _validate_allocation_pools ( self ) :
    """Validate IP allocation pools .
 Verify start and end address for each allocation pool are valid ,
 ie : constituted by valid and appropriately ordered IP addresses .
 Also , verify pools do not overlap among themselves .
 Finally , verify that each range fall within the subnet ' s CIDR ."""

implementation:
ip_pools = self . _alloc_pools
subnet_cidr = self . _subnet_cidr
LOG . debug ( _ ( "Performing IP validity checks on allocation pools" ) )
ip_sets = [ ]
for ip_pool in ip_pools :
    try :
        start_ip = netaddr . IPAddress ( ip_pool [ 'start' ] )
        end_ip = netaddr . IPAddress ( ip_pool [ 'end' ] )
    except netaddr . AddrFormatError :
        LOG . info ( _ ( "Found invalid IP address in pool: " "%(start)s - %(end)s:" ) , { 'start' : ip_pool [ 'start' ] , 'end' : ip_pool [ 'end' ] } )
        raise n_exc_ext . InvalidAllocationPool ( pool = ip_pool )
    if ( start_ip . version != self . _subnet_cidr . version or end_ip . version != self . _subnet_cidr . version ) :
        LOG . info ( _ ( "Specified IP addresses do not match " "the subnet IP version" ) )
        raise n_exc_ext . InvalidAllocationPool ( pool = ip_pool )
    if end_ip < start_ip :
        LOG . info ( _ ( "Start IP (%(start)s) is greater than end IP " "(%(end)s)" ) , { 'start' : ip_pool [ 'start' ] , 'end' : ip_pool [ 'end' ] } )
        raise n_exc_ext . InvalidAllocationPool ( pool = ip_pool )
    if ( start_ip < self . _subnet_first_ip or end_ip > self . _subnet_last_ip ) :
        LOG . info ( _ ( "Found pool larger than subnet " "CIDR:%(start)s - %(end)s" ) , { 'start' : ip_pool [ 'start' ] , 'end' : ip_pool [ 'end' ] } )
        raise n_exc_ext . OutOfBoundsAllocationPool ( pool = ip_pool , subnet_cidr = subnet_cidr )
    # Valid allocation pool
    # Create an IPSet for it for easily verifying overlaps
    ip_sets . append ( netaddr . IPSet ( netaddr . IPRange ( ip_pool [ 'start' ] , ip_pool [ 'end' ] ) . cidrs ( ) ) )
LOG . debug ( _ ( "Checking for overlaps among allocation pools " "and gateway ip" ) )
ip_ranges = ip_pools [ : ]
# Use integer cursors as an efficient way for implementing
# comparison and avoiding comparing the same pair twice
for l_cursor in xrange ( len ( ip_sets ) ) :
    for r_cursor in xrange ( l_cursor + 1 , len ( ip_sets ) ) :
        if ip_sets [ l_cursor ] & ip_sets [ r_cursor ] :
            l_range = ip_ranges [ l_cursor ]
            r_range = ip_ranges [ r_cursor ]
            LOG . info ( _ ( "Found overlapping ranges: %(l_range)s and " "%(r_range)s" ) , { 'l_range' : l_range , 'r_range' : r_range } )
            raise n_exc_ext . OverlappingAllocationPools ( pool_1 = l_range , pool_2 = r_range , subnet_cidr = subnet_cidr )


signature:
def add_job_to_context ( context , job_id ) :
    """Adds job to neutron context for use later ."""

implementation:
db_job = db_api . async_transaction_find ( context , id = job_id , scope = db_api . ONE )
if not db_job :
    return
context . async_job = { "job" : v . _make_job_dict ( db_job ) }


signature:
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"""

implementation:
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 )


signature:
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 ."""

implementation:
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 )


implementation:
plugin = directory . get_plugin ( )
controller = IPPoliciesController ( plugin )
return [ extensions . ResourceExtension ( Ip_policies . get_alias ( ) , controller ) ]


signature:
def _lswitch_select_open ( self , context , switches = None , ** kwargs ) :
    """Selects an open lswitch for a network .
 Note that it does not select the most full switch , but merely one with
 ports available ."""

implementation:
if switches is not None :
    for res in switches [ "results" ] :
        count = res [ "_relations" ] [ "LogicalSwitchStatus" ] [ "lport_count" ]
        if ( self . limits [ 'max_ports_per_switch' ] == 0 or count < self . limits [ 'max_ports_per_switch' ] ) :
            return res [ "uuid" ]
return None


signature:
def _add_default_tz_bindings ( self , context , switch , network_id ) :
    """Configure any additional default transport zone bindings ."""

implementation:
default_tz = CONF . NVP . default_tz
# If there is no default tz specified it ' s pointless to try
# and add any additional default tz bindings .
if not default_tz :
    LOG . warn ( "additional_default_tz_types specified, " "but no default_tz. Skipping " "_add_default_tz_bindings()." )
    return
# This should never be called without a neutron network uuid ,
# we require it to bind some segment allocations .
if not network_id :
    LOG . warn ( "neutron network_id not specified, skipping " "_add_default_tz_bindings()" )
    return
for net_type in CONF . NVP . additional_default_tz_types :
    if net_type in TZ_BINDINGS :
        binding = TZ_BINDINGS [ net_type ]
        binding . add ( context , switch , default_tz , network_id )
    else :
        LOG . warn ( "Unknown default tz type %s" % ( net_type ) )


signature:
def _remove_default_tz_bindings ( self , context , network_id ) :
    """Deconfigure any additional default transport zone bindings ."""

implementation:
default_tz = CONF . NVP . default_tz
if not default_tz :
    LOG . warn ( "additional_default_tz_types specified, " "but no default_tz. Skipping " "_remove_default_tz_bindings()." )
    return
if not network_id :
    LOG . warn ( "neutron network_id not specified, skipping " "_remove_default_tz_bindings()" )
    return
for net_type in CONF . NVP . additional_default_tz_types :
    if net_type in TZ_BINDINGS :
        binding = TZ_BINDINGS [ net_type ]
        binding . remove ( context , default_tz , network_id )
    else :
        LOG . warn ( "Unknown default tz type %s" % ( net_type ) )


signature:
def get_lswitch_ids_for_network ( self , context , network_id ) :
    """Public interface for fetching lswitch ids for a given network .
 NOTE ( morgabra ) This is here because calling private methods
 from outside the class feels wrong , and we need to be able to
 fetch lswitch ids for use in other drivers ."""

implementation:
lswitches = self . _lswitches_for_network ( context , network_id ) . results ( )
return [ s [ 'uuid' ] for s in lswitches [ "results" ] ]


signature:
def register_floating_ip ( self , floating_ip , port_fixed_ips ) :
    """Register a floating ip with Unicorn
 : param floating _ ip : The quark . db . models . IPAddress to register
 : param port _ fixed _ ips : A dictionary containing the port and fixed ips
 to associate the floating IP with . Has the structure of :
 { " < id of port > " : { " port " : < quark . db . models . Port > ,
 " fixed _ ip " : " < fixed ip address > " } }
 : return : None"""

implementation:
url = CONF . QUARK . floating_ip_base_url
timeout = CONF . QUARK . unicorn_api_timeout_seconds
req = self . _build_request_body ( floating_ip , port_fixed_ips )
try :
    LOG . info ( "Calling unicorn to register floating ip: %s %s" % ( url , req ) )
    r = requests . post ( url , data = json . dumps ( req ) , timeout = timeout )
except Exception as e :
    LOG . error ( "Unhandled Exception caught when trying to register " "floating ip %s with the unicorn API.  Error: %s" % ( floating_ip . id , e . message ) )
    raise ex . RegisterFloatingIpFailure ( id = floating_ip . id )
if r . status_code != 200 and r . status_code != 201 :
    msg = "Unexpected status from unicorn API: Status Code %s, " "Message: %s" % ( r . status_code , r . json ( ) )
    LOG . error ( "register_floating_ip: %s" % msg )
    raise ex . RegisterFloatingIpFailure ( id = floating_ip . id )


signature:
def remove_floating_ip ( self , floating_ip ) :
    """Register a floating ip with Unicorn
 : param floating _ ip : The quark . db . models . IPAddress to remove
 : return : None"""

implementation:
url = "%s/%s" % ( CONF . QUARK . floating_ip_base_url , floating_ip . address_readable )
timeout = CONF . QUARK . unicorn_api_timeout_seconds
try :
    LOG . info ( "Calling unicorn to remove floating ip: %s" % url )
    r = requests . delete ( url , timeout = timeout )
except Exception as e :
    LOG . error ( "Unhandled Exception caught when trying to un-register " "floating ip %s with the unicorn API.  Error: %s" % ( floating_ip . id , e . message ) )
    raise ex . RemoveFloatingIpFailure ( id = floating_ip . id )
if r . status_code == 404 :
    LOG . warn ( "The floating IP %s does not exist in the unicorn system." % floating_ip . address_readable )
elif r . status_code != 204 :
    msg = "Unexpected status from unicorn API: Status Code %s, " "Message: %s" % ( r . status_code , r . json ( ) )
    LOG . error ( "remove_floating_ip: %s" % msg )
    raise ex . RemoveFloatingIpFailure ( id = floating_ip . id )


signature:
def _load_worker_plugin_with_module ( self , module , version ) :
    """Instantiates worker plugins that have requsite properties .
 The required properties are :
 * must have PLUGIN _ EP entrypoint registered ( or it wouldn ' t be in the
 list )
 * must have class attribute versions ( list ) of supported RPC versions
 * must subclass QuarkAsyncPluginBase"""

implementation:
classes = inspect . getmembers ( module , inspect . isclass )
loaded = 0
for cls_name , cls in classes :
    if hasattr ( cls , 'versions' ) :
        if version not in cls . versions :
            continue
    else :
        continue
    if issubclass ( cls , base_worker . QuarkAsyncPluginBase ) :
        LOG . debug ( "Loading plugin %s" % cls_name )
        plugin = cls ( )
        self . plugins . append ( plugin )
        loaded += 1
LOG . debug ( "Found %d possible plugins and loaded %d" % ( len ( classes ) , loaded ) )


signature:
def _discover_via_entrypoints ( self ) :
    """Looks for modules with amtching entry points ."""

implementation:
emgr = extension . ExtensionManager ( PLUGIN_EP , invoke_on_load = False )
return ( ( ext . name , ext . plugin ) for ext in emgr )


signature:
def serve_rpc ( self ) :
    """Launches configured # of workers per loaded plugin ."""

implementation:
if cfg . CONF . QUARK_ASYNC . rpc_workers < 1 :
    cfg . CONF . set_override ( 'rpc_workers' , 1 , "QUARK_ASYNC" )
try :
    rpc = service . RpcWorker ( self . plugins )
    launcher = common_service . ProcessLauncher ( CONF , wait_interval = 1.0 )
    launcher . launch_service ( rpc , workers = CONF . QUARK_ASYNC . rpc_workers )
    return launcher
except Exception :
    with excutils . save_and_reraise_exception ( ) :
        LOG . exception ( _LE ( 'Unrecoverable error: please check log for ' 'details.' ) )


signature:
def start_api_and_rpc_workers ( self ) :
    """Initializes eventlet and starts wait for workers to exit .
 Spawns the workers returned from serve _ rpc"""

implementation:
pool = eventlet . GreenPool ( )
quark_rpc = self . serve_rpc ( )
pool . spawn ( quark_rpc . wait )
pool . waitall ( )


signature:
def get_resources ( cls ) :
    """Returns Ext Resources ."""

implementation:
plural_mappings = resource_helper . build_plural_mappings ( { } , RESOURCE_ATTRIBUTE_MAP )
# attr . PLURALS . update ( plural _ mappings )
return resource_helper . build_resource_info ( plural_mappings , RESOURCE_ATTRIBUTE_MAP , None , register_quota = True )


signature:
def _chunks ( self , iterable , chunk_size ) :
    """Chunks data into chunk with size < = chunk _ size ."""

implementation:
iterator = iter ( iterable )
chunk = list ( itertools . islice ( iterator , 0 , chunk_size ) )
while chunk :
    yield chunk
    chunk = list ( itertools . islice ( iterator , 0 , chunk_size ) )


signature:
def _check_collisions ( self , new_range , existing_ranges ) :
    """Check for overlapping ranges ."""

implementation:
def _contains ( num , r1 ) :
    return ( num >= r1 [ 0 ] and num <= r1 [ 1 ] )
def _is_overlap ( r1 , r2 ) :
    return ( _contains ( r1 [ 0 ] , r2 ) or _contains ( r1 [ 1 ] , r2 ) or _contains ( r2 [ 0 ] , r1 ) or _contains ( r2 [ 1 ] , r1 ) )
for existing_range in existing_ranges :
    if _is_overlap ( new_range , existing_range ) :
        return True
return False


signature:
def _try_allocate ( self , context , segment_id , network_id ) :
    """Find a deallocated network segment id and reallocate it .
 NOTE ( morgabra ) This locks the segment table , but only the rows
 in use by the segment , which is pretty handy if we ever have
 more than 1 segment or segment type ."""

implementation:
LOG . info ( "Attempting to allocate segment for network %s " "segment_id %s segment_type %s" % ( network_id , segment_id , self . segment_type ) )
filter_dict = { "segment_id" : segment_id , "segment_type" : self . segment_type , "do_not_use" : False }
available_ranges = db_api . segment_allocation_range_find ( context , scope = db_api . ALL , ** filter_dict )
available_range_ids = [ r [ "id" ] for r in available_ranges ]
try :
    with context . session . begin ( subtransactions = True ) : # Search for any deallocated segment ids for the
    # given segment .
        filter_dict = { "deallocated" : True , "segment_id" : segment_id , "segment_type" : self . segment_type , "segment_allocation_range_ids" : available_range_ids }
        # NOTE ( morgabra ) We select 100 deallocated segment ids from
        # the table here , and then choose 1 randomly . This is to help
        # alleviate the case where an uncaught exception might leave
        # an allocation active on a remote service but we do not have
        # a record of it locally . If we * do * end up choosing a
        # conflicted id , the caller should simply allocate another one
        # and mark them all as reserved . If a single object has
        # multiple reservations on the same segment , they will not be
        # deallocated , and the operator must resolve the conficts
        # manually .
        allocations = db_api . segment_allocation_find ( context , lock_mode = True , ** filter_dict ) . limit ( 100 ) . all ( )
        if allocations :
            allocation = random . choice ( allocations )
            # Allocate the chosen segment .
            update_dict = { "deallocated" : False , "deallocated_at" : None , "network_id" : network_id }
            allocation = db_api . segment_allocation_update ( context , allocation , ** update_dict )
            LOG . info ( "Allocated segment %s for network %s " "segment_id %s segment_type %s" % ( allocation [ "id" ] , network_id , segment_id , self . segment_type ) )
            return allocation
except Exception :
    LOG . exception ( "Error in segment reallocation." )
LOG . info ( "Cannot find reallocatable segment for network %s " "segment_id %s segment_type %s" % ( network_id , segment_id , self . segment_type ) )


signature:
def delete_locks ( context , network_ids , addresses ) :
    """Deletes locks for each IP address that is no longer null - routed ."""

implementation:
addresses_no_longer_null_routed = _find_addresses_to_be_unlocked ( context , network_ids , addresses )
LOG . info ( "Deleting %s lock holders on IPAddress with ids: %s" , len ( addresses_no_longer_null_routed ) , [ addr . id for addr in addresses_no_longer_null_routed ] )
for address in addresses_no_longer_null_routed :
    lock_holder = None
    try :
        lock_holder = db_api . lock_holder_find ( context , lock_id = address . lock_id , name = LOCK_NAME , scope = db_api . ONE )
        if lock_holder :
            db_api . lock_holder_delete ( context , address , lock_holder )
    except Exception :
        LOG . exception ( "Failed to delete lock holder %s" , lock_holder )
        continue
context . session . flush ( )


signature:
def create_locks ( context , network_ids , addresses ) :
    """Creates locks for each IP address that is null - routed .
 The function creates the IP address if it is not present in the database ."""

implementation:
for address in addresses :
    address_model = None
    try :
        address_model = _find_or_create_address ( context , network_ids , address )
        lock_holder = None
        if address_model . lock_id :
            lock_holder = db_api . lock_holder_find ( context , lock_id = address_model . lock_id , name = LOCK_NAME , scope = db_api . ONE )
        if not lock_holder :
            LOG . info ( "Creating lock holder on IPAddress %s with id %s" , address_model . address_readable , address_model . id )
            db_api . lock_holder_create ( context , address_model , name = LOCK_NAME , type = "ip_address" )
    except Exception :
        LOG . exception ( "Failed to create lock holder on IPAddress %s" , address_model )
        continue
context . session . flush ( )


signature:
def select_ipam_strategy ( self , network_id , network_strategy , ** kwargs ) :
    """Return relevant IPAM strategy name .
 : param network _ id : neutron network id .
 : param network _ strategy : default strategy for the network .
 NOTE ( morgabra ) This feels like a hack but I can ' t think of a better
 idea . The root problem is we can now attach ports to networks with
 a different backend driver / ipam strategy than the network speficies .
 We handle the the backend driver part with allowing network _ plugin to
 be specified for port objects . This works pretty well because nova or
 whatever knows when we are hooking up an Ironic node so it can pass
 along that key during port _ create ( ) .
 IPAM is a little trickier , especially in Ironic ' s case , because we
 * must * use a specific IPAM for provider networks . There isn ' t really
 much of an option other than involve the backend driver when selecting
 the IPAM strategy ."""

implementation:
LOG . info ( "Selecting IPAM strategy for network_id:%s " "network_strategy:%s" % ( network_id , network_strategy ) )
net_type = "tenant"
if STRATEGY . is_provider_network ( network_id ) :
    net_type = "provider"
strategy = self . _ipam_strategies . get ( net_type , { } )
default = strategy . get ( "default" )
overrides = strategy . get ( "overrides" , { } )
# If we override a particular strategy explicitly , we use it .
if network_strategy in overrides :
    LOG . info ( "Selected overridden IPAM strategy: %s" % ( overrides [ network_strategy ] ) )
    return overrides [ network_strategy ]
# Otherwise , we are free to use an explicit default .
if default :
    LOG . info ( "Selected default IPAM strategy for tenant " "network: %s" % ( default ) )
    return default
# Fallback to the network - specified IPAM strategy
LOG . info ( "Selected network strategy for tenant " "network: %s" % ( network_strategy ) )
return network_strategy


signature:
def _get_base_network_info ( self , context , network_id , base_net_driver ) :
    """Return a dict of extra network information .
 : param context : neutron request context .
 : param network _ id : neturon network id .
 : param net _ driver : network driver associated with network _ id .
 : raises IronicException : Any unexpected data fetching failures will
 be logged and IronicException raised .
 This driver can attach to networks managed by other drivers . We may
 need some information from these drivers , or otherwise inform
 downstream about the type of network we are attaching to . We can
 make these decisions here ."""

implementation:
driver_name = base_net_driver . get_name ( )
net_info = { "network_type" : driver_name }
LOG . debug ( '_get_base_network_info: %s %s' % ( driver_name , network_id ) )
# If the driver is NVP , we need to look up the lswitch id we should
# be attaching to .
if driver_name == 'NVP' :
    LOG . debug ( 'looking up lswitch ids for network %s' % ( network_id ) )
    lswitch_ids = base_net_driver . get_lswitch_ids_for_network ( context , network_id )
    if not lswitch_ids or len ( lswitch_ids ) > 1 :
        msg = ( 'lswitch id lookup failed, %s ids found.' % ( len ( lswitch_ids ) ) )
        LOG . error ( msg )
        raise IronicException ( msg )
    lswitch_id = lswitch_ids . pop ( )
    LOG . info ( 'found lswitch for network %s: %s' % ( network_id , lswitch_id ) )
    net_info [ 'lswitch_id' ] = lswitch_id
LOG . debug ( '_get_base_network_info finished: %s %s %s' % ( driver_name , network_id , net_info ) )
return net_info


signature:
def create_port ( self , context , network_id , port_id , ** kwargs ) :
    """Create a port .
 : param context : neutron api request context .
 : param network _ id : neutron network id .
 : param port _ id : neutron port id .
 : param kwargs :
 required keys - device _ id : neutron port device _ id ( instance _ id )
 instance _ node _ id : nova hypervisor host id
 mac _ address : neutron port mac address
 base _ net _ driver : the base network driver
 optional keys - addresses : list of allocated IPAddress models
 security _ groups : list of associated security groups
 : raises IronicException : If the client is unable to create the
 downstream port for any reason , the exception will be logged
 and IronicException raised ."""

implementation:
LOG . info ( "create_port %s %s %s" % ( context . tenant_id , network_id , port_id ) )
# sanity check
if not kwargs . get ( 'base_net_driver' ) :
    raise IronicException ( msg = 'base_net_driver required.' )
base_net_driver = kwargs [ 'base_net_driver' ]
if not kwargs . get ( 'device_id' ) :
    raise IronicException ( msg = 'device_id required.' )
device_id = kwargs [ 'device_id' ]
if not kwargs . get ( 'instance_node_id' ) :
    raise IronicException ( msg = 'instance_node_id required.' )
instance_node_id = kwargs [ 'instance_node_id' ]
if not kwargs . get ( 'mac_address' ) :
    raise IronicException ( msg = 'mac_address is required.' )
mac_address = str ( netaddr . EUI ( kwargs [ "mac_address" ] [ "address" ] ) )
mac_address = mac_address . replace ( '-' , ':' )
# TODO ( morgabra ) : Change this when we enable security groups .
if kwargs . get ( 'security_groups' ) :
    msg = 'ironic driver does not support security group operations.'
    raise IronicException ( msg = msg )
# unroll the given address models into a fixed _ ips list we can
# pass downstream
fixed_ips = [ ]
addresses = kwargs . get ( 'addresses' )
if not isinstance ( addresses , list ) :
    addresses = [ addresses ]
for address in addresses :
    fixed_ips . append ( self . _make_fixed_ip_dict ( context , address ) )
body = { "id" : port_id , "network_id" : network_id , "device_id" : device_id , "device_owner" : kwargs . get ( 'device_owner' , '' ) , "tenant_id" : context . tenant_id or "quark" , "roles" : context . roles , "mac_address" : mac_address , "fixed_ips" : fixed_ips , "switch:hardware_id" : instance_node_id , "dynamic_network" : not STRATEGY . is_provider_network ( network_id ) }
net_info = self . _get_base_network_info ( context , network_id , base_net_driver )
body . update ( net_info )
try :
    LOG . info ( "creating downstream port: %s" % ( body ) )
    port = self . _create_port ( context , body )
    LOG . info ( "created downstream port: %s" % ( port ) )
    return { "uuid" : port [ 'port' ] [ 'id' ] , "vlan_id" : port [ 'port' ] [ 'vlan_id' ] }
except Exception as e :
    msg = "failed to create downstream port. Exception: %s" % ( e )
    raise IronicException ( msg = msg )


signature:
def update_port ( self , context , port_id , ** kwargs ) :
    """Update a port .
 : param context : neutron api request context .
 : param port _ id : neutron port id .
 : param kwargs : optional kwargs .
 : raises IronicException : If the client is unable to update the
 downstream port for any reason , the exception will be logged
 and IronicException raised .
 TODO ( morgabra ) It does not really make sense in the context of Ironic
 to allow updating ports . fixed _ ips and mac _ address are burned in the
 configdrive on the host , and we otherwise cannot migrate a port between
 instances . Eventually we will need to support security groups , but for
 now it ' s a no - op on port data changes , and we need to rely on the
 API / Nova to not allow updating data on active ports ."""

implementation:
LOG . info ( "update_port %s %s" % ( context . tenant_id , port_id ) )
# TODO ( morgabra ) : Change this when we enable security groups .
if kwargs . get ( "security_groups" ) :
    msg = 'ironic driver does not support security group operations.'
    raise IronicException ( msg = msg )
return { "uuid" : port_id }


signature:
def delete_port ( self , context , port_id , ** kwargs ) :
    """Delete a port .
 : param context : neutron api request context .
 : param port _ id : neutron port id .
 : param kwargs : optional kwargs .
 : raises IronicException : If the client is unable to delete the
 downstream port for any reason , the exception will be logged
 and IronicException raised ."""

implementation:
LOG . info ( "delete_port %s %s" % ( context . tenant_id , port_id ) )
try :
    self . _delete_port ( context , port_id )
    LOG . info ( "deleted downstream port: %s" % ( port_id ) )
except Exception :
    LOG . error ( "failed deleting downstream port, it is now " "orphaned! port_id: %s" % ( port_id ) )


signature:
def diag_port ( self , context , port_id , ** kwargs ) :
    """Diagnose a port .
 : param context : neutron api request context .
 : param port _ id : neutron port id .
 : param kwargs : optional kwargs .
 : raises IronicException : If the client is unable to fetch the
 downstream port for any reason , the exception will be
 logged and IronicException raised ."""

implementation:
LOG . info ( "diag_port %s" % port_id )
try :
    port = self . _client . show_port ( port_id )
except Exception as e :
    msg = "failed fetching downstream port: %s" % ( str ( e ) )
    LOG . exception ( msg )
    raise IronicException ( msg = msg )
return { "downstream_port" : port }


signature:
def set ( self , model , value ) :
    """Set tag on model object ."""

implementation:
self . validate ( value )
self . _pop ( model )
value = self . serialize ( value )
model . tags . append ( value )


signature:
def get ( self , model ) :
    """Get a matching valid tag off the model ."""

implementation:
for tag in model . tags :
    if self . is_tag ( tag ) :
        value = self . deserialize ( tag )
        try :
            self . validate ( value )
            return value
        except TagValidationError :
            continue
return None


signature:
def _pop ( self , model ) :
    """Pop all matching tags off the model and return them ."""

implementation:
tags = [ ]
# collect any exsiting tags with matching prefix
for tag in model . tags :
    if self . is_tag ( tag ) :
        tags . append ( tag )
# remove collected tags from model
if tags :
    for tag in tags :
        model . tags . remove ( tag )
return tags


signature:
def pop ( self , model ) :
    """Pop all matching tags off the port , return a valid one ."""

implementation:
tags = self . _pop ( model )
if tags :
    for tag in tags :
        value = self . deserialize ( tag )
        try :
            self . validate ( value )
            return value
        except TagValidationError :
            continue


signature:
def has_tag ( self , model ) :
    """Does the given port have this tag ?"""

implementation:
for tag in model . tags :
    if self . is_tag ( tag ) :
        return True
return False


signature:
def validate ( self , value ) :
    """Validates a VLAN ID .
 : param value : The VLAN ID to validate against .
 : raises TagValidationError : Raised if the VLAN ID is invalid ."""

implementation:
try :
    vlan_id_int = int ( value )
    assert vlan_id_int >= self . MIN_VLAN_ID
    assert vlan_id_int <= self . MAX_VLAN_ID
except Exception :
    msg = ( "Invalid vlan_id. Got '%(vlan_id)s'. " "vlan_id should be an integer between %(min)d and %(max)d " "inclusive." % { 'vlan_id' : value , 'min' : self . MIN_VLAN_ID , 'max' : self . MAX_VLAN_ID } )
    raise TagValidationError ( value , msg )
return True


signature:
def get_all ( self , model ) :
    """Get all known tags from a model .
 Returns a dict of { < tag _ name > : < tag _ value > } ."""

implementation:
tags = { }
for name , tag in self . tags . items ( ) :
    for mtag in model . tags :
        if tag . is_tag ( mtag ) :
            tags [ name ] = tag . get ( model )
return tags


signature:
def set_all ( self , model , ** tags ) :
    """Validate and set all known tags on a port ."""

implementation:
for name , tag in self . tags . items ( ) :
    if name in tags :
        value = tags . pop ( name )
        if value :
            try :
                tag . set ( model , value )
            except TagValidationError as e :
                raise n_exc . BadRequest ( resource = "tags" , msg = "%s" % ( e . message ) )


signature:
def serialize_rules ( self , rules ) :
    """Creates a payload for the redis server ."""

implementation:
# TODO ( mdietz ) : If / when we support other rule types , this comment
# will have to be revised .
# Action and direction are static , for now . The implementation may
# support ' deny ' and ' egress ' respectively in the future . We allow
# the direction to be set to something else , technically , but current
# plugin level call actually raises . It ' s supported here for unit
# test purposes at this time
serialized = [ ]
for rule in rules :
    direction = rule [ "direction" ]
    source = ''
    destination = ''
    if rule . get ( "remote_ip_prefix" ) :
        prefix = rule [ "remote_ip_prefix" ]
        if direction == "ingress" :
            source = self . _convert_remote_network ( prefix )
        else :
            if ( Capabilities . EGRESS not in CONF . QUARK . environment_capabilities ) :
                raise q_exc . EgressSecurityGroupRulesNotEnabled ( )
            else :
                destination = self . _convert_remote_network ( prefix )
    optional_fields = { }
    # NOTE ( mdietz ) : this will expand as we add more protocols
    protocol_map = protocols . PROTOCOL_MAP [ rule [ "ethertype" ] ]
    if rule [ "protocol" ] == protocol_map [ "icmp" ] :
        optional_fields [ "icmp type" ] = rule [ "port_range_min" ]
        optional_fields [ "icmp code" ] = rule [ "port_range_max" ]
    else :
        optional_fields [ "port start" ] = rule [ "port_range_min" ]
        optional_fields [ "port end" ] = rule [ "port_range_max" ]
    payload = { "ethertype" : rule [ "ethertype" ] , "protocol" : rule [ "protocol" ] , "source network" : source , "destination network" : destination , "action" : "allow" , "direction" : direction }
    payload . update ( optional_fields )
    serialized . append ( payload )
return serialized


signature:
def serialize_groups ( self , groups ) :
    """Creates a payload for the redis server
 The rule schema is the following :
 REDIS KEY - port _ device _ id . port _ mac _ address / sg
 REDIS VALUE - A JSON dump of the following :
 port _ mac _ address must be lower - cased and stripped of non - alphanumeric
 characters
 { " id " : " < arbitrary uuid > " ,
 " rules " : [
 { " ethertype " : < hexademical integer > ,
 " protocol " : < integer > ,
 " port start " : < integer > , # optional
 " port end " : < integer > , # optional
 " icmp type " : < integer > , # optional
 " icmp code " : < integer > , # optional
 " source network " : < string > ,
 " destination network " : < string > ,
 " action " : < string > ,
 " direction " : < string > } ,
 " security groups ack " : < boolean >
 Example :
 { " id " : " 004c6369-9f3d - 4d33 - b8f5-9416bf3567dd " ,
 " rules " : [
 { " ethertype " : 0x800,
 " protocol " : " tcp " ,
 " port start " : 1000,
 " port end " : 1999,
 " source network " : " 10.10.10.0/24 " ,
 " destination network " : " " ,
 " action " : " allow " ,
 " direction " : " ingress " } ,
 " security groups ack " : " true "
 port start / end and icmp type / code are mutually exclusive pairs ."""

implementation:
rules = [ ]
for group in groups :
    rules . extend ( self . serialize_rules ( group . rules ) )
return rules


signature:
def apply_rules ( self , device_id , mac_address , rules ) :
    """Writes a series of security group rules to a redis server ."""

implementation:
LOG . info ( "Applying security group rules for device %s with MAC %s" % ( device_id , mac_address ) )
rule_dict = { SECURITY_GROUP_RULE_KEY : rules }
redis_key = self . vif_key ( device_id , mac_address )
# TODO ( mdietz ) : Pipeline these . Requires some rewriting
self . set_field ( redis_key , SECURITY_GROUP_HASH_ATTR , rule_dict )
self . set_field_raw ( redis_key , SECURITY_GROUP_ACK , False )


signature:
def get_security_group_states ( self , interfaces ) :
    """Gets security groups for interfaces from Redis
 Returns a dictionary of xapi . VIFs with values of the current
 acknowledged status in Redis .
 States not explicitly handled :
 * ack key , no rules - This is the same as just tagging the VIF ,
 the instance will be inaccessible
 * rules key , no ack - Nothing will happen , the VIF will
 not be tagged ."""

implementation:
LOG . debug ( "Getting security groups from Redis for {0}" . format ( interfaces ) )
interfaces = tuple ( interfaces )
vif_keys = [ self . vif_key ( vif . device_id , vif . mac_address ) for vif in interfaces ]
# Retrieve all fields associated with this key , which should be
# ' security groups ack ' and ' security group rules ' .
sec_grp_all = self . get_fields_all ( vif_keys )
ret = { }
# Associate the vif with the fields in a dictionary
for vif , group in zip ( interfaces , sec_grp_all ) :
    if group :
        ret [ vif ] = { SECURITY_GROUP_ACK : None , SECURITY_GROUP_HASH_ATTR : [ ] }
        temp_ack = group [ SECURITY_GROUP_ACK ] . lower ( )
        temp_rules = group [ SECURITY_GROUP_HASH_ATTR ]
        if temp_rules :
            temp_rules = json . loads ( temp_rules )
            ret [ vif ] [ SECURITY_GROUP_HASH_ATTR ] = temp_rules [ "rules" ]
        if "true" in temp_ack :
            ret [ vif ] [ SECURITY_GROUP_ACK ] = True
        elif "false" in temp_ack :
            ret [ vif ] [ SECURITY_GROUP_ACK ] = False
        else :
            ret . pop ( vif , None )
            LOG . debug ( "Skipping bad ack value %s" % temp_ack )
return ret


signature:
def update_group_states_for_vifs ( self , vifs , ack ) :
    """Updates security groups by setting the ack field"""

implementation:
vif_keys = [ self . vif_key ( vif . device_id , vif . mac_address ) for vif in vifs ]
self . set_fields ( vif_keys , SECURITY_GROUP_ACK , ack )


signature:
def run_migrations_offline ( ) :
    """Run migrations in ' offline ' mode .
 This configures the context with just a URL
 and not an Engine , though an Engine is acceptable
 here as well . By skipping the Engine creation
 we don ' t even need a DBAPI to be available .
 Calls to context . execute ( ) here emit the given string to the
 script output ."""

implementation:
context . configure ( url = neutron_config . database . connection )
with context . begin_transaction ( ) :
    context . run_migrations ( )


signature:
def run_migrations_online ( ) :
    """Run migrations in ' online ' mode .
 In this scenario we need to create an Engine
 and associate a connection with the context ."""

implementation:
engine = create_engine ( neutron_config . database . connection , poolclass = pool . NullPool )
connection = engine . connect ( )
context . configure ( connection = connection , target_metadata = target_metadata )
try :
    with context . begin_transaction ( ) :
        context . run_migrations ( )
finally :
    connection . close ( )


signature:
def do_notify ( context , event_type , payload ) :
    """Generic Notifier .
 Parameters :
 - ` context ` : session context
 - ` event _ type ` : the event type to report , i . e . ip . usage
 - ` payload ` : dict containing the payload to send"""

implementation:
LOG . debug ( 'IP_BILL: notifying {}' . format ( payload ) )
notifier = n_rpc . get_notifier ( 'network' )
notifier . info ( context , event_type , payload )


signature:
def notify ( context , event_type , ipaddress , send_usage = False , * args , ** kwargs ) :
    """Method to send notifications .
 We must send USAGE when a public IPv4 address is deallocated or a FLIP is
 associated .
 Parameters :
 - ` context ` : the context for notifier
 - ` event _ type ` : the event type for IP allocate , deallocate , associate ,
 disassociate
 - ` ipaddress ` : the ipaddress object to notify about
 Returns :
 nothing
 Notes : this may live in the billing module"""

implementation:
if ( event_type == IP_ADD and not CONF . QUARK . notify_ip_add ) or ( event_type == IP_DEL and not CONF . QUARK . notify_ip_delete ) or ( event_type == IP_ASSOC and not CONF . QUARK . notify_flip_associate ) or ( event_type == IP_DISASSOC and not CONF . QUARK . notify_flip_disassociate ) or ( event_type == IP_EXISTS and not CONF . QUARK . notify_ip_exists ) :
    LOG . debug ( 'IP_BILL: notification {} is disabled by config' . format ( event_type ) )
    return
# Do not send notifications when we are undoing due to an error
if 'rollback' in kwargs and kwargs [ 'rollback' ] :
    LOG . debug ( 'IP_BILL: not sending notification because we are in undo' )
    return
# ip . add needs the allocated _ at time .
# All other events need the current time .
ts = ipaddress . allocated_at if event_type == IP_ADD else _now ( )
payload = build_payload ( ipaddress , event_type , event_time = ts )
# Send the notification with the payload
do_notify ( context , event_type , payload )
# When we deallocate an IP or associate a FLIP we must send
# a usage message to billing .
# In other words when we supply end _ time we must send USAGE to billing
# immediately .
# Our billing period is 24 hrs . If the address was allocated after midnight
# send the start _ time as as . If the address was allocated yesterday , then
# send midnight as the start _ time .
# Note : if allocated _ at is empty we assume today ' s midnight .
if send_usage :
    if ipaddress . allocated_at is not None and ipaddress . allocated_at >= _midnight_today ( ) :
        start_time = ipaddress . allocated_at
    else :
        start_time = _midnight_today ( )
    payload = build_payload ( ipaddress , IP_EXISTS , start_time = start_time , end_time = ts )
    do_notify ( context , IP_EXISTS , payload )


signature:
def build_payload ( ipaddress , event_type , event_time = None , start_time = None , end_time = None ) :
    """Method builds a payload out of the passed arguments .
 Parameters :
 ` ipaddress ` : the models . IPAddress object
 ` event _ type ` : USAGE , CREATE , DELETE , SUSPEND , or UNSUSPEND
 ` start _ time ` : startTime for cloudfeeds
 ` end _ time ` : endTime for cloudfeeds
 Returns a dictionary suitable to notify billing .
 Message types mapping to cloud feeds for references :
 ip . exists - USAGE
 ip . add - CREATE
 ip . delete - DELETE
 ip . associate - UP
 ip . disassociate - DOWN
 Refer to : http : / / rax . io / cf - api for more details ."""

implementation:
# This is the common part of all message types
payload = { 'event_type' : unicode ( event_type ) , 'tenant_id' : unicode ( ipaddress . used_by_tenant_id ) , 'ip_address' : unicode ( ipaddress . address_readable ) , 'ip_version' : int ( ipaddress . version ) , 'ip_type' : unicode ( ipaddress . address_type ) , 'id' : unicode ( ipaddress . id ) }
# Depending on the message type add the appropriate fields
if event_type == IP_EXISTS :
    if start_time is None or end_time is None :
        raise ValueError ( 'IP_BILL: {} start_time/end_time cannot be empty' . format ( event_type ) )
    payload . update ( { 'startTime' : unicode ( convert_timestamp ( start_time ) ) , 'endTime' : unicode ( convert_timestamp ( end_time ) ) } )
elif event_type in [ IP_ADD , IP_DEL , IP_ASSOC , IP_DISASSOC ] :
    if event_time is None :
        raise ValueError ( 'IP_BILL: {}: event_time cannot be NULL' . format ( event_type ) )
    payload . update ( { 'eventTime' : unicode ( convert_timestamp ( event_time ) ) , 'subnet_id' : unicode ( ipaddress . subnet_id ) , 'network_id' : unicode ( ipaddress . network_id ) , 'public' : True if ipaddress . network_id == PUBLIC_NETWORK_ID else False , } )
else :
    raise ValueError ( 'IP_BILL: bad event_type: {}' . format ( event_type ) )
return payload


signature:
def build_full_day_ips ( query , period_start , period_end ) :
    """Method to build an IP list for the case 1
 when the IP was allocated before the period start
 and is still allocated after the period end .
 This method only looks at public IPv4 addresses ."""

implementation:
# Filter out only IPv4 that have not been deallocated
ip_list = query . filter ( models . IPAddress . version == 4L ) . filter ( models . IPAddress . network_id == PUBLIC_NETWORK_ID ) . filter ( models . IPAddress . used_by_tenant_id is not None ) . filter ( models . IPAddress . allocated_at != null ( ) ) . filter ( models . IPAddress . allocated_at < period_start ) . filter ( or_ ( models . IPAddress . _deallocated is False , models . IPAddress . deallocated_at == null ( ) , models . IPAddress . deallocated_at >= period_end ) ) . all ( )
return ip_list


signature:
def calc_periods ( hour = 0 , minute = 0 ) :
    """Returns a tuple of start _ period and end _ period .
 Assumes that the period is 24 - hrs .
 Parameters :
 - ` hour ` : the hour from 0 to 23 when the period ends
 - ` minute ` : the minute from 0 to 59 when the period ends
 This method will calculate the end of the period as the closest hour / minute
 going backwards .
 It will also calculate the start of the period as the passed hour / minute
 but 24 hrs ago .
 Example , if we pass 0 , 0 - we will get the events from 0:00 midnight of the
 day before yesterday until today ' s midnight .
 If we pass 2,0 - we will get the start time as 2am of the previous morning
 till 2am of today ' s morning .
 By default it ' s midnight ."""

implementation:
# Calculate the time intervals in a usable form
period_end = datetime . datetime . utcnow ( ) . replace ( hour = hour , minute = minute , second = 0 , microsecond = 0 )
period_start = period_end - datetime . timedelta ( days = 1 )
# period end should be slightly before the midnight .
# hence , we subtract a second
# this will force period _ end to store something like :
# datetime . datetime ( 2016 , 5 , 19 , 23 , 59 , 59 , 99999)
# instead of :
# datetime . datetime ( 2016 , 5 , 20 , 0 , 0 , 0 , 0)
period_end -= datetime . timedelta ( seconds = 1 )
return ( period_start , period_end )


signature:
def _make_job_dict ( job ) :
    """Creates the view for a job while calculating progress .
 Since a root job does not have a transaction id ( TID ) it will return its
 id as the TID ."""

implementation:
body = { "id" : job . get ( 'id' ) , "action" : job . get ( 'action' ) , "completed" : job . get ( 'completed' ) , "tenant_id" : job . get ( 'tenant_id' ) , "created_at" : job . get ( 'created_at' ) , "transaction_id" : job . get ( 'transaction_id' ) , "parent_id" : job . get ( 'parent_id' , None ) }
if not body [ 'transaction_id' ] :
    body [ 'transaction_id' ] = job . get ( 'id' )
completed = 0
for sub in job . subtransactions :
    if sub . get ( 'completed' ) :
        completed += 1
pct = 100 if job . get ( 'completed' ) else 0
if len ( job . subtransactions ) > 0 :
    pct = float ( completed ) / len ( job . subtransactions ) * 100.0
body [ 'transaction_percent' ] = int ( pct )
body [ 'completed_subtransactions' ] = completed
body [ 'subtransactions' ] = len ( job . subtransactions )
return body


signature:
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 ."""

implementation:
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 )


signature:
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 ."""

implementation:
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 )


signature:
def get_resources ( cls ) :
    """Returns Ext Resources ."""

implementation:
job_controller = JobsController ( directory . get_plugin ( ) )
resources = [ ]
resources . append ( extensions . ResourceExtension ( Jobs . get_alias ( ) , job_controller ) )
return resources


signature:
def downgrade ( ) :
    """alexm : i believe this method is never called"""

implementation:
with op . batch_alter_table ( t2_name ) as batch_op :
    batch_op . drop_column ( 'do_not_use' )
with op . batch_alter_table ( t1_name ) as batch_op :
    batch_op . drop_column ( 'enabled' )


signature:
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 ."""

implementation:
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 )


signature:
def filter_factory ( global_conf , ** local_conf ) :
    """Returns a WSGI filter app for use with paste . deploy ."""

implementation:
conf = global_conf . copy ( )
conf . update ( local_conf )
def wrapper ( app ) :
    return ResponseAsyncIdAdder ( app , conf )
return wrapper


signature:
def get_used_ips ( session , ** kwargs ) :
    """Returns dictionary with keys segment _ id and value used IPs count .
 Used IP address count is determined by :
 - allocated IPs
 - deallocated IPs whose ` deallocated _ at ` is within the ` reuse _ after `
 window compared to the present time , excluding IPs that are accounted for
 in the current IP policy ( because IP policy is mutable and deallocated IPs
 are not checked nor deleted on IP policy creation , thus deallocated IPs
 that don ' t fit the current IP policy can exist in the neutron database ) ."""

implementation:
LOG . debug ( "Getting used IPs..." )
with session . begin ( ) :
    query = session . query ( models . Subnet . segment_id , func . count ( models . IPAddress . address ) )
    query = query . group_by ( models . Subnet . segment_id )
    query = _filter ( query , ** kwargs )
    reuse_window = timeutils . utcnow ( ) - datetime . timedelta ( seconds = cfg . CONF . QUARK . ipam_reuse_after )
    # NOTE ( asadoughi ) : This is an outer join instead of a regular join
    # to include subnets with zero IP addresses in the database .
    query = query . outerjoin ( models . IPAddress , and_ ( models . Subnet . id == models . IPAddress . subnet_id , or_ ( not_ ( models . IPAddress . lock_id . is_ ( None ) ) , models . IPAddress . _deallocated . is_ ( None ) , models . IPAddress . _deallocated == 0 , models . IPAddress . deallocated_at > reuse_window ) ) )
    query = query . outerjoin ( models . IPPolicyCIDR , and_ ( models . Subnet . ip_policy_id == models . IPPolicyCIDR . ip_policy_id , models . IPAddress . address >= models . IPPolicyCIDR . first_ip , models . IPAddress . address <= models . IPPolicyCIDR . last_ip ) )
    # NOTE ( asadoughi ) : ( address is allocated ) OR
    # ( address is deallocated and not inside subnet ' s IP policy )
    query = query . filter ( or_ ( models . IPAddress . _deallocated . is_ ( None ) , models . IPAddress . _deallocated == 0 , models . IPPolicyCIDR . id . is_ ( None ) ) )
    ret = ( ( segment_id , address_count ) for segment_id , address_count in query . all ( ) )
    return dict ( ret )


signature:
def get_unused_ips ( session , used_ips_counts , ** kwargs ) :
    """Returns dictionary with key segment _ id , and value unused IPs count .
 Unused IP address count is determined by :
 - adding subnet ' s cidr ' s size
 - subtracting IP policy exclusions on subnet
 - subtracting used ips per segment"""

implementation:
LOG . debug ( "Getting unused IPs..." )
with session . begin ( ) :
    query = session . query ( models . Subnet . segment_id , models . Subnet )
    query = _filter ( query , ** kwargs )
    query = query . group_by ( models . Subnet . segment_id , models . Subnet . id )
    ret = defaultdict ( int )
    for segment_id , subnet in query . all ( ) :
        net_size = netaddr . IPNetwork ( subnet . _cidr ) . size
        ip_policy = subnet [ "ip_policy" ] or { "size" : 0 }
        ret [ segment_id ] += net_size - ip_policy [ "size" ]
    for segment_id in used_ips_counts :
        ret [ segment_id ] -= used_ips_counts [ segment_id ]
    return ret


signature:
def get_instances ( self , session ) :
    """Returns a dict of ` VM OpaqueRef ` ( str ) - > ` xapi . VM ` ."""

implementation:
LOG . debug ( "Getting instances from Xapi" )
recs = session . xenapi . VM . get_all_records ( )
# NOTE ( asadoughi ) : Copied from xen - networking - scripts / utils . py
is_inst = lambda r : ( r [ 'power_state' ] . lower ( ) == 'running' and not r [ 'is_a_template' ] and not r [ 'is_control_domain' ] and ( 'nova_uuid' in r [ 'other_config' ] or r [ 'name_label' ] . startswith ( 'instance-' ) ) )
instances = dict ( )
for vm_ref , rec in recs . iteritems ( ) :
    if not is_inst ( rec ) :
        continue
    instances [ vm_ref ] = VM ( ref = vm_ref , uuid = rec [ "other_config" ] [ "nova_uuid" ] , vifs = rec [ "VIFs" ] , dom_id = rec [ "domid" ] )
return instances


signature:
def get_interfaces ( self ) :
    """Returns a set of VIFs from ` get _ instances ` return value ."""

implementation:
LOG . debug ( "Getting interfaces from Xapi" )
with self . sessioned ( ) as session :
    instances = self . get_instances ( session )
    recs = session . xenapi . VIF . get_all_records ( )
interfaces = set ( )
for vif_ref , rec in recs . iteritems ( ) :
    vm = instances . get ( rec [ "VM" ] )
    if not vm :
        continue
    device_id = vm . uuid
    interfaces . add ( VIF ( device_id , rec , vif_ref ) )
return interfaces


signature:
def update_interfaces ( self , added_sg , updated_sg , removed_sg ) :
    """Handles changes to interfaces ' security groups
 Calls refresh _ interfaces on argument VIFs . Set security groups on
 added _ sg ' s VIFs . Unsets security groups on removed _ sg ' s VIFs ."""

implementation:
if not ( added_sg or updated_sg or removed_sg ) :
    return
with self . sessioned ( ) as session :
    self . _set_security_groups ( session , added_sg )
    self . _unset_security_groups ( session , removed_sg )
    combined = added_sg + updated_sg + removed_sg
    self . _refresh_interfaces ( session , combined )


signature:
def create_network ( context , network ) :
    """Create a network .
 Create a network which represents an L2 network segment which
 can have a set of subnets and ports associated with it .
 : param context : neutron api request context
 : param network : dictionary describing the network , with keys
 as listed in the RESOURCE _ ATTRIBUTE _ MAP object in
 neutron / api / v2 / attributes . py . All keys will be populated ."""

implementation:
LOG . info ( "create_network for tenant %s" % context . tenant_id )
with context . session . begin ( ) :
    net_attrs = network [ "network" ]
    subs = net_attrs . pop ( "subnets" , [ ] )
    # Enforce subnet quotas
    if not context . is_admin :
        if len ( subs ) > 0 :
            v4_count , v6_count = 0 , 0
            for s in subs :
                version = netaddr . IPNetwork ( s [ 'subnet' ] [ 'cidr' ] ) . version
                if version == 6 :
                    v6_count += 1
                else :
                    v4_count += 1
            if v4_count > 0 :
                tenant_q_v4 = context . session . query ( qdv . Quota ) . filter_by ( tenant_id = context . tenant_id , resource = 'v4_subnets_per_network' ) . first ( )
                if tenant_q_v4 != - 1 :
                    quota . QUOTAS . limit_check ( context , context . tenant_id , v4_subnets_per_network = v4_count )
            if v6_count > 0 :
                tenant_q_v6 = context . session . query ( qdv . Quota ) . filter_by ( tenant_id = context . tenant_id , resource = 'v6_subnets_per_network' ) . first ( )
                if tenant_q_v6 != - 1 :
                    quota . QUOTAS . limit_check ( context , context . tenant_id , v6_subnets_per_network = v6_count )
    # Generate a uuid that we ' re going to hand to the backend and db
    net_uuid = utils . pop_param ( net_attrs , "id" , None )
    net_type = None
    if net_uuid and context . is_admin :
        net = db_api . network_find ( context = context , limit = None , sorts = [ 'id' ] , marker = None , page_reverse = False , id = net_uuid , scope = db_api . ONE )
        net_type = utils . pop_param ( net_attrs , "network_plugin" , None )
        if net :
            raise q_exc . NetworkAlreadyExists ( id = net_uuid )
    else :
        net_uuid = uuidutils . generate_uuid ( )
    # TODO ( mdietz ) this will be the first component registry hook , but
    # lets make it work first
    pnet_type , phys_net , seg_id = _adapt_provider_nets ( context , network )
    ipam_strategy = utils . pop_param ( net_attrs , "ipam_strategy" , None )
    if not ipam_strategy or not context . is_admin :
        ipam_strategy = CONF . QUARK . default_ipam_strategy
    if not ipam . IPAM_REGISTRY . is_valid_strategy ( ipam_strategy ) :
        raise q_exc . InvalidIpamStrategy ( strat = ipam_strategy )
    net_attrs [ "ipam_strategy" ] = ipam_strategy
    # NOTE ( mdietz ) I think ideally we would create the providernet
    # elsewhere as a separate driver step that could be
    # kept in a plugin and completely removed if desired . We could
    # have a pre - callback / observer on the netdriver create _ network
    # that gathers any additional parameters from the network dict
    default_net_type = net_type or CONF . QUARK . default_network_type
    net_driver = registry . DRIVER_REGISTRY . get_driver ( default_net_type )
    net_driver . create_network ( context , net_attrs [ "name" ] , network_id = net_uuid , phys_type = pnet_type , phys_net = phys_net , segment_id = seg_id )
    net_attrs [ "id" ] = net_uuid
    net_attrs [ "tenant_id" ] = context . tenant_id
    net_attrs [ "network_plugin" ] = default_net_type
    new_net = db_api . network_create ( context , ** net_attrs )
    new_subnets = [ ]
    for sub in subs :
        sub [ "subnet" ] [ "network_id" ] = new_net [ "id" ]
        sub [ "subnet" ] [ "tenant_id" ] = context . tenant_id
        s = db_api . subnet_create ( context , ** sub [ "subnet" ] )
        new_subnets . append ( s )
    new_net [ "subnets" ] = new_subnets
    # if not security _ groups . get _ security _ groups (
    # context ,
    # filters = { " id " : security _ groups . DEFAULT _ SG _ UUID } ) :
    # security _ groups . _ create _ default _ security _ group ( context )
return v . _make_network_dict ( new_net )


signature:
def update_network ( context , id , network ) :
    """Update values of a network .
 : param context : neutron api request context
 : param id : UUID representing the network to update .
 : param network : dictionary with keys indicating fields to update .
 valid keys are those that have a value of True for ' allow _ put '
 as listed in the RESOURCE _ ATTRIBUTE _ MAP object in
 neutron / api / v2 / attributes . py ."""

implementation:
LOG . info ( "update_network %s for tenant %s" % ( id , context . tenant_id ) )
with context . session . begin ( ) :
    net = db_api . network_find ( context , id = id , scope = db_api . ONE )
    if not net :
        raise n_exc . NetworkNotFound ( net_id = id )
    net_dict = network [ "network" ]
    utils . pop_param ( net_dict , "network_plugin" )
    if not context . is_admin and "ipam_strategy" in net_dict :
        utils . pop_param ( net_dict , "ipam_strategy" )
    net = db_api . network_update ( context , net , ** net_dict )
return v . _make_network_dict ( net )


signature:
def get_network ( context , id , fields = None ) :
    """Retrieve a network .
 : 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 ."""

implementation:
LOG . info ( "get_network %s for tenant %s fields %s" % ( id , context . tenant_id , fields ) )
network = db_api . network_find ( context = context , limit = None , sorts = [ 'id' ] , marker = None , page_reverse = False , id = id , join_subnets = True , scope = db_api . ONE )
if not network :
    raise n_exc . NetworkNotFound ( net_id = id )
return v . _make_network_dict ( network , fields = fields )


signature:
def get_networks ( context , limit = None , sorts = [ 'id' ] , marker = None , page_reverse = False , filters = None , fields = None ) :
    """Retrieve a list of networks .
 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 network as listed in the RESOURCE _ ATTRIBUTE _ MAP object
 in neutron / api / v2 / attributes . py . Values in this dictiontary
 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
 network dictionary as listed in the RESOURCE _ ATTRIBUTE _ MAP
 object in neutron / api / v2 / attributes . py . Only these fields
 will be returned ."""

implementation:
LOG . info ( "get_networks for tenant %s with filters %s, fields %s" % ( context . tenant_id , filters , fields ) )
filters = filters or { }
nets = db_api . network_find ( context , limit , sorts , marker , page_reverse , join_subnets = True , ** filters ) or [ ]
nets = [ v . _make_network_dict ( net , fields = fields ) for net in nets ]
return nets


signature:
def get_networks_count ( context , filters = None ) :
    """Return the number of networks .
 The result 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 network as listed in the RESOURCE _ ATTRIBUTE _ MAP object
 in neutron / api / v2 / attributes . py . Values in this dictiontary
 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 .
 NOTE : this method is optional , as it was not part of the originally
 defined plugin API ."""

implementation:
LOG . info ( "get_networks_count for tenant %s filters %s" % ( context . tenant_id , filters ) )
return db_api . network_count_all ( context )


signature:
def delete_network ( context , id ) :
    """Delete a network .
 : param context : neutron api request context
 : param id : UUID representing the network to delete ."""

implementation:
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 )


signature:
def make_case2 ( context ) :
    """This is a helper method for testing .
 When run with the current context , it will create a case 2 entries
 in the database . See top of file for what case 2 is ."""

implementation:
query = context . session . query ( models . IPAddress )
period_start , period_end = billing . calc_periods ( )
ip_list = billing . build_full_day_ips ( query , period_start , period_end )
import random
ind = random . randint ( 0 , len ( ip_list ) - 1 )
address = ip_list [ ind ]
address . allocated_at = datetime . datetime . utcnow ( ) - datetime . timedelta ( days = 1 )
context . session . add ( address )
context . session . flush ( )


signature:
def main ( notify , hour , minute ) :
    """Runs billing report . Optionally sends notifications to billing"""

implementation:
# Read the config file and get the admin context
config_opts = [ '--config-file' , '/etc/neutron/neutron.conf' ]
config . init ( config_opts )
# Have to load the billing module _ after _ config is parsed so
# that we get the right network strategy
network_strategy . STRATEGY . load ( )
billing . PUBLIC_NETWORK_ID = network_strategy . STRATEGY . get_public_net_id ( )
config . setup_logging ( )
context = neutron_context . get_admin_context ( )
# A query to get all IPAddress objects from the db
query = context . session . query ( models . IPAddress )
( period_start , period_end ) = billing . calc_periods ( hour , minute )
full_day_ips = billing . build_full_day_ips ( query , period_start , period_end )
partial_day_ips = billing . build_partial_day_ips ( query , period_start , period_end )
if notify : # ' = = = = = Full Day = = = = = '
    for ipaddress in full_day_ips :
        click . echo ( 'start: {}, end: {}' . format ( period_start , period_end ) )
        payload = billing . build_payload ( ipaddress , billing . IP_EXISTS , start_time = period_start , end_time = period_end )
        billing . do_notify ( context , billing . IP_EXISTS , payload )
    # ' = = = = = Part Day = = = = = '
    for ipaddress in partial_day_ips :
        click . echo ( 'start: {}, end: {}' . format ( period_start , period_end ) )
        payload = billing . build_payload ( ipaddress , billing . IP_EXISTS , start_time = ipaddress . allocated_at , end_time = period_end )
        billing . do_notify ( context , billing . IP_EXISTS , payload )
else :
    click . echo ( 'Case 1 ({}):\n' . format ( len ( full_day_ips ) ) )
    for ipaddress in full_day_ips :
        pp ( billing . build_payload ( ipaddress , billing . IP_EXISTS , start_time = period_start , end_time = period_end ) )
    click . echo ( '\n===============================================\n' )
    click . echo ( 'Case 2 ({}):\n' . format ( len ( partial_day_ips ) ) )
    for ipaddress in partial_day_ips :
        pp ( billing . build_payload ( ipaddress , billing . IP_EXISTS , start_time = ipaddress . allocated_at , end_time = period_end ) )


signature:
def start_rpc_listeners ( self ) :
    """Configure all listeners here"""

implementation:
self . _setup_rpc ( )
if not self . endpoints :
    return [ ]
self . conn = n_rpc . create_connection ( )
self . conn . create_consumer ( self . topic , self . endpoints , fanout = False )
return self . conn . consume_in_threads ( )


signature:
def context ( self ) :
    """Provides an admin context for workers ."""

implementation:
if not self . _context :
    self . _context = context . get_admin_context ( )
return self . _context


signature:
def update_sg ( self , context , sg , rule_id , action ) :
    """Begins the async update process ."""

implementation:
db_sg = db_api . security_group_find ( context , id = sg , scope = db_api . ONE )
if not db_sg :
    return None
with context . session . begin ( ) :
    job_body = dict ( action = "%s sg rule %s" % ( action , rule_id ) , resource_id = rule_id , tenant_id = db_sg [ 'tenant_id' ] )
    job_body = dict ( job = job_body )
    job = job_api . create_job ( context . elevated ( ) , job_body )
    rpc_client = QuarkSGAsyncProducerClient ( )
    try :
        rpc_client . populate_subtasks ( context , sg , job [ 'id' ] )
    except om_exc . MessagingTimeout :
        LOG . error ( "Failed to create subtasks. Rabbit running?" )
        return None
return { "job_id" : job [ 'id' ] }


signature:
def populate_subtasks ( self , context , sg , parent_job_id ) :
    """Produces a list of ports to be updated async ."""

implementation:
db_sg = db_api . security_group_find ( context , id = sg , scope = db_api . ONE )
if not db_sg :
    return None
ports = db_api . sg_gather_associated_ports ( context , db_sg )
if len ( ports ) == 0 :
    return { "ports" : 0 }
for port in ports :
    job_body = dict ( action = "update port %s" % port [ 'id' ] , tenant_id = db_sg [ 'tenant_id' ] , resource_id = port [ 'id' ] , parent_id = parent_job_id )
    job_body = dict ( job = job_body )
    job = job_api . create_job ( context . elevated ( ) , job_body )
    rpc_consumer = QuarkSGAsyncConsumerClient ( )
    try :
        rpc_consumer . update_port ( context , port [ 'id' ] , job [ 'id' ] )
    except om_exc . MessagingTimeout : # TODO ( roaet ) : Not too sure what can be done here other than
    # updating the job as a failure ?
        LOG . error ( "Failed to update port. Rabbit running?" )
return None


signature:
def update_ports_for_sg ( self , context , portid , jobid ) :
    """Updates the ports through redis ."""

implementation:
port = db_api . port_find ( context , id = portid , scope = db_api . ONE )
if not port :
    LOG . warning ( "Port not found" )
    return
net_driver = port_api . _get_net_driver ( port . network , port = port )
base_net_driver = port_api . _get_net_driver ( port . network )
sg_list = [ sg for sg in port . security_groups ]
success = False
error = None
retries = 3
retry_delay = 2
for retry in xrange ( retries ) :
    try :
        net_driver . update_port ( context , port_id = port [ "backend_key" ] , mac_address = port [ "mac_address" ] , device_id = port [ "device_id" ] , base_net_driver = base_net_driver , security_groups = sg_list )
        success = True
        error = None
        break
    except Exception as error :
        LOG . warning ( "Could not connect to redis, but retrying soon" )
        time . sleep ( retry_delay )
status_str = ""
if not success :
    status_str = "Port %s update failed after %d tries. Error: %s" % ( portid , retries , error )
update_body = dict ( completed = True , status = status_str )
update_body = dict ( job = update_body )
job_api . update_job ( context . elevated ( ) , jobid , update_body )


signature:
def sg_gather_associated_ports ( context , group ) :
    """Gather all ports associated to security group .
 Returns :
 * list , or None"""

implementation:
if not group :
    return None
if not hasattr ( group , "ports" ) or len ( group . ports ) <= 0 :
    return [ ]
return group . ports


signature:
def security_group_rule_update ( context , rule , ** kwargs ) :
    '''Updates a security group rule .
 NOTE ( alexm ) this is non - standard functionality .'''

implementation:
rule . update ( kwargs )
context . session . add ( rule )
return rule


signature:
def segment_allocation_find ( context , lock_mode = False , ** filters ) :
    """Query for segment allocations ."""

implementation:
range_ids = filters . pop ( "segment_allocation_range_ids" , None )
query = context . session . query ( models . SegmentAllocation )
if lock_mode :
    query = query . with_lockmode ( "update" )
query = query . filter_by ( ** filters )
# Optionally filter by given list of range ids
if range_ids :
    query . filter ( models . SegmentAllocation . segment_allocation_range_id . in_ ( range_ids ) )
return query


signature:
def get_resources ( cls ) :
    """Returns Ext Resources ."""

implementation:
controller = RoutesController ( directory . get_plugin ( ) )
return [ extensions . ResourceExtension ( Routes . get_alias ( ) , controller ) ]


signature:
def send ( self , s ) :
    """Sends the given command to Niko Home Control and returns the output of
 the system .
 Aliases : write , put , sendall , send _ all"""

implementation:
self . _socket . send ( s . encode ( ) )
return self . read ( )


signature:
def if_ ( * args ) :
    """Implements the ' if ' operator with support for multiple elseif - s ."""

implementation:
for i in range ( 0 , len ( args ) - 1 , 2 ) :
    if args [ i ] :
        return args [ i + 1 ]
if len ( args ) % 2 :
    return args [ - 1 ]
else :
    return None


signature:
def soft_equals ( a , b ) :
    """Implements the ' = = ' operator , which does type JS - style coertion ."""

implementation:
if isinstance ( a , str ) or isinstance ( b , str ) :
    return str ( a ) == str ( b )
if isinstance ( a , bool ) or isinstance ( b , bool ) :
    return bool ( a ) is bool ( b )
return a == b


signature:
def hard_equals ( a , b ) :
    """Implements the ' = = = ' operator ."""

implementation:
if type ( a ) != type ( b ) :
    return False
return a == b


signature:
def less ( a , b , * args ) :
    """Implements the ' < ' operator with JS - style type coertion ."""

implementation:
types = set ( [ type ( a ) , type ( b ) ] )
if float in types or int in types :
    try :
        a , b = float ( a ) , float ( b )
    except TypeError : # NaN
        return False
return a < b and ( not args or less ( b , * args ) )


signature:
def less_or_equal ( a , b , * args ) :
    """Implements the ' < = ' operator with JS - style type coertion ."""

implementation: return ( less ( a , b ) or soft_equals ( a , b ) ) and ( not args or less_or_equal ( b , * args ) )


signature:
def to_numeric ( arg ) :
    """Converts a string either to int or to float .
 This is important , because e . g . { " ! = = " : [ { " + " : " 0 " } , 0.0 ] }"""

implementation:
if isinstance ( arg , str ) :
    if '.' in arg :
        return float ( arg )
    else :
        return int ( arg )
return arg


signature:
def minus ( * args ) :
    """Also , converts either to ints or to floats ."""

implementation:
if len ( args ) == 1 :
    return - to_numeric ( args [ 0 ] )
return to_numeric ( args [ 0 ] ) - to_numeric ( args [ 1 ] )


signature:
def merge ( * args ) :
    """Implements the ' merge ' operator for merging lists ."""

implementation:
ret = [ ]
for arg in args :
    if isinstance ( arg , list ) or isinstance ( arg , tuple ) :
        ret += list ( arg )
    else :
        ret . append ( arg )
return ret


signature:
def get_var ( data , var_name , not_found = None ) :
    """Gets variable value from data dictionary ."""

implementation:
try :
    for key in str ( var_name ) . split ( '.' ) :
        try :
            data = data [ key ]
        except TypeError :
            data = data [ int ( key ) ]
except ( KeyError , TypeError , ValueError ) :
    return not_found
else :
    return data


signature:
def missing ( data , * args ) :
    """Implements the missing operator for finding missing variables ."""

implementation:
not_found = object ( )
if args and isinstance ( args [ 0 ] , list ) :
    args = args [ 0 ]
ret = [ ]
for arg in args :
    if get_var ( data , arg , not_found ) is not_found :
        ret . append ( arg )
return ret


signature:
def missing_some ( data , min_required , args ) :
    """Implements the missing _ some operator for finding missing variables ."""

implementation:
if min_required < 1 :
    return [ ]
found = 0
not_found = object ( )
ret = [ ]
for arg in args :
    if get_var ( data , arg , not_found ) is not_found :
        ret . append ( arg )
    else :
        found += 1
        if found >= min_required :
            return [ ]
return ret


signature:
def jsonLogic ( tests , data = None ) :
    """Executes the json - logic with given data ."""

implementation:
# You ' ve recursed to a primitive , stop !
if tests is None or not isinstance ( tests , dict ) :
    return tests
data = data or { }
operator = list ( tests . keys ( ) ) [ 0 ]
values = tests [ operator ]
# Easy syntax for unary operators , like { " var " : " x " } instead of strict
# { " var " : [ " x " ] }
if not isinstance ( values , list ) and not isinstance ( values , tuple ) :
    values = [ values ]
# Recursion !
values = [ jsonLogic ( val , data ) for val in values ]
if operator == 'var' :
    return get_var ( data , * values )
if operator == 'missing' :
    return missing ( data , * values )
if operator == 'missing_some' :
    return missing_some ( data , * values )
if operator not in operations :
    raise ValueError ( "Unrecognized operation %s" % operator )
return operations [ operator ] ( * values )


signature:
def indent ( self ) :
    """Performs an indentation"""

implementation:
if not self . tab_always_indent :
    super ( PyIndenterMode , self ) . indent ( )
else :
    cursor = self . editor . textCursor ( )
    assert isinstance ( cursor , QtGui . QTextCursor )
    if cursor . hasSelection ( ) :
        self . indent_selection ( cursor )
    else : # simply insert indentation at the cursor position
        tab_len = self . editor . tab_length
        cursor . beginEditBlock ( )
        if self . editor . use_spaces_instead_of_tabs :
            cursor . insertText ( tab_len * " " )
        else :
            cursor . insertText ( '\t' )
        cursor . endEditBlock ( )
        self . editor . setTextCursor ( cursor )


signature:
def unindent ( self ) :
    """Performs an un - indentation"""

implementation:
if self . tab_always_indent :
    cursor = self . editor . textCursor ( )
    if not cursor . hasSelection ( ) :
        cursor . select ( cursor . LineUnderCursor )
    self . unindent_selection ( cursor )
else :
    super ( PyIndenterMode , self ) . unindent ( )


signature:
def _handle_indent_between_paren ( self , column , line , parent_impl , tc ) :
    """Handle indent between symbols such as parenthesis , braces , . . ."""

implementation:
pre , post = parent_impl
next_char = self . _get_next_char ( tc )
prev_char = self . _get_prev_char ( tc )
prev_open = prev_char in [ '[' , '(' , '{' ]
next_close = next_char in [ ']' , ')' , '}' ]
( open_line , open_symbol_col ) , ( close_line , close_col ) = self . _get_paren_pos ( tc , column )
open_line_txt = self . _helper . line_text ( open_line )
open_line_indent = len ( open_line_txt ) - len ( open_line_txt . lstrip ( ) )
if prev_open :
    post = ( open_line_indent + self . editor . tab_length ) * ' '
elif next_close and prev_char != ',' :
    post = open_line_indent * ' '
elif tc . block ( ) . blockNumber ( ) == open_line :
    post = open_symbol_col * ' '
# adapt indent if cursor on closing line and next line have same
# indent - > PEP8 compliance
if close_line and close_col :
    txt = self . _helper . line_text ( close_line )
    bn = tc . block ( ) . blockNumber ( )
    flg = bn == close_line
    next_indent = self . _helper . line_indent ( bn + 1 ) * ' '
    if flg and txt . strip ( ) . endswith ( ':' ) and next_indent == post : # | look at how the previous line ( ` ` ' : ' ) : ` ` ) was
    # over - indented , this is actually what we are trying to
    # achieve here
        post += self . editor . tab_length * ' '
# breaking string
if next_char in [ '"' , "'" ] :
    tc . movePosition ( tc . Left )
is_string = self . _helper . is_comment_or_string ( tc , formats = [ 'string' ] )
if next_char in [ '"' , "'" ] :
    tc . movePosition ( tc . Right )
if is_string :
    trav = QTextCursor ( tc )
    while self . _helper . is_comment_or_string ( trav , formats = [ 'string' ] ) :
        trav . movePosition ( trav . Left )
    trav . movePosition ( trav . Right )
    symbol = '%s' % self . _get_next_char ( trav )
    pre += symbol
    post += symbol
return pre , post


signature:
def _at_block_start ( tc , line ) :
    """Improve QTextCursor . atBlockStart to ignore spaces"""

implementation:
if tc . atBlockStart ( ) :
    return True
column = tc . columnNumber ( )
indentation = len ( line ) - len ( line . lstrip ( ) )
return column <= indentation


signature:
def detect_encoding ( self , path ) :
    """For the implementation of encoding definitions in Python , look at :
 - http : / / www . python . org / dev / peps / pep - 0263/
 . . note : : code taken and adapted from
 ` ` ` jedi . common . source _ to _ unicode . detect _ encoding ` ` `"""

implementation:
with open ( path , 'rb' ) as file :
    source = file . read ( )
    # take care of line encodings ( not in jedi )
    source = source . replace ( b'\r' , b'' )
    source_str = str ( source ) . replace ( '\\n' , '\n' )
byte_mark = ast . literal_eval ( r"b'\xef\xbb\xbf'" )
if source . startswith ( byte_mark ) : # UTF - 8 byte - order mark
    return 'utf-8'
first_two_lines = re . match ( r'(?:[^\n]*\n){0,2}' , source_str ) . group ( 0 )
possible_encoding = re . search ( r"coding[=:]\s*([-\w.]+)" , first_two_lines )
if possible_encoding :
    return possible_encoding . group ( 1 )
return 'UTF-8'


signature:
def on_state_changed ( self , state ) :
    """Called when the mode is activated / deactivated"""

implementation:
if state :
    self . action . triggered . connect ( self . comment )
    self . editor . add_action ( self . action , sub_menu = 'Python' )
    if 'pyqt5' in os . environ [ 'QT_API' ] . lower ( ) :
        self . editor . key_pressed . connect ( self . on_key_pressed )
else :
    self . editor . remove_action ( self . action , sub_menu = 'Python' )
    self . action . triggered . disconnect ( self . comment )
    if 'pyqt5' in os . environ [ 'QT_API' ] . lower ( ) :
        self . editor . key_pressed . disconnect ( self . on_key_pressed )


signature:
def comment ( self ) :
    """Comments / Uncomments the selected lines or the current lines if there
 is no selection ."""

implementation:
cursor = self . editor . textCursor ( )
# get the indent at which comment should be inserted and whether to
# comment or uncomment the selected text
indent , comment , nb_lines = self . get_operation ( )
has_selection = cursor . hasSelection ( )
if nb_lines > 1 :
    self . _move_cursor_to_selection_start ( cursor )
    cursor . beginEditBlock ( )
    for i in range ( nb_lines ) :
        self . comment_line ( indent , cursor , comment )
        cursor . movePosition ( cursor . NextBlock )
    cursor . endEditBlock ( )
else : # comment a single line
    cursor . beginEditBlock ( )
    self . comment_line ( indent , cursor , comment )
    if not has_selection : # move to the first non - whitespace character of the next line
        cursor . movePosition ( cursor . NextBlock )
        text = cursor . block ( ) . text ( )
        indent = len ( text ) - len ( text . lstrip ( ) )
        cursor . movePosition ( cursor . Right , cursor . MoveAnchor , indent )
        cursor . endEditBlock ( )
        self . editor . setTextCursor ( cursor )
    else :
        cursor . endEditBlock ( )


signature:
def setPlainText ( self , txt , mimetype = 'text/x-python' , encoding = 'utf-8' ) :
    """Extends QCodeEdit . setPlainText to allow user to setPlainText without
 mimetype ( since the python syntax highlighter does not use it ) ."""

implementation:
try :
    self . syntax_highlighter . docstrings [ : ] = [ ]
    self . syntax_highlighter . import_statements [ : ] = [ ]
except AttributeError :
    pass
super ( PyCodeEditBase , self ) . setPlainText ( txt , mimetype , encoding )


signature:
def update_terminal_colors ( self ) :
    """Update terminal color scheme based on the pygments color scheme colors"""

implementation: self . color_scheme = self . create_color_scheme ( background = self . syntax_highlighter . color_scheme . background , foreground = self . syntax_highlighter . color_scheme . formats [ 'normal' ] . foreground ( ) . color ( ) )


signature:
def mouseMoveEvent ( self , e ) :
    """Extends mouseMoveEvent to display a pointing hand cursor when the
 mouse cursor is over a file location"""

implementation:
super ( PyInteractiveConsole , self ) . mouseMoveEvent ( e )
cursor = self . cursorForPosition ( e . pos ( ) )
assert isinstance ( cursor , QtGui . QTextCursor )
p = cursor . positionInBlock ( )
usd = cursor . block ( ) . userData ( )
if usd and usd . start_pos_in_block <= p <= usd . end_pos_in_block :
    if QtWidgets . QApplication . overrideCursor ( ) is None :
        QtWidgets . QApplication . setOverrideCursor ( QtGui . QCursor ( QtCore . Qt . PointingHandCursor ) )
else :
    if QtWidgets . QApplication . overrideCursor ( ) is not None :
        QtWidgets . QApplication . restoreOverrideCursor ( )


signature:
def mousePressEvent ( self , e ) :
    """Emits open _ file _ requested if the press event occured over
 a file location string ."""

implementation:
super ( PyInteractiveConsole , self ) . mousePressEvent ( e )
cursor = self . cursorForPosition ( e . pos ( ) )
p = cursor . positionInBlock ( )
usd = cursor . block ( ) . userData ( )
if usd and usd . start_pos_in_block <= p <= usd . end_pos_in_block :
    if e . button ( ) == QtCore . Qt . LeftButton :
        self . open_file_requested . emit ( usd . filename , usd . line )