feedback from jk0's review, including removing a lot of spaces from docstrings
This commit is contained in:
@@ -779,8 +779,7 @@ class NetworkCommands(object):
|
|||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""List all created networks"""
|
"""List all created networks"""
|
||||||
_fmt = "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s"\
|
_fmt = "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s"
|
||||||
"\t%-15s\t%-15s"
|
|
||||||
print _fmt % (_('id'),
|
print _fmt % (_('id'),
|
||||||
_('IPv4'),
|
_('IPv4'),
|
||||||
_('IPv6'),
|
_('IPv6'),
|
||||||
|
|||||||
@@ -946,7 +946,7 @@ def virtual_interface_get_by_address(context, address):
|
|||||||
def virtual_interface_get_by_uuid(context, vif_uuid):
|
def virtual_interface_get_by_uuid(context, vif_uuid):
|
||||||
"""Gets a virtual interface from the table.
|
"""Gets a virtual interface from the table.
|
||||||
|
|
||||||
:param vif_uuid: = the uuid of the interface you're looking to get
|
:param vif_uuid: the uuid of the interface you're looking to get
|
||||||
"""
|
"""
|
||||||
session = get_session()
|
session = get_session()
|
||||||
vif_ref = session.query(models.VirtualInterface).\
|
vif_ref = session.query(models.VirtualInterface).\
|
||||||
|
|||||||
@@ -547,7 +547,7 @@ class NetworkManager(manager.SchedulerDependentManager):
|
|||||||
'network_id': network_id,
|
'network_id': network_id,
|
||||||
'uuid': str(utils.gen_uuid())}
|
'uuid': str(utils.gen_uuid())}
|
||||||
# try FLAG times to create a vif record with a unique mac_address
|
# try FLAG times to create a vif record with a unique mac_address
|
||||||
for i in xrange(FLAGS.create_unique_mac_address_attempts):
|
for _ in xrange(FLAGS.create_unique_mac_address_attempts):
|
||||||
try:
|
try:
|
||||||
return self.db.virtual_interface_create(context, vif)
|
return self.db.virtual_interface_create(context, vif)
|
||||||
except exception.VirtualInterfaceCreateException:
|
except exception.VirtualInterfaceCreateException:
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import socket
|
|||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
|
|
||||||
#FIXME(danwent): All content in this file should be removed once the
|
# FIXME(danwent): All content in this file should be removed once the
|
||||||
# packaging work for the quantum client libraries is complete.
|
# packaging work for the quantum client libraries is complete.
|
||||||
# At that point, we will be able to just install the libraries as a
|
# At that point, we will be able to just install the libraries as a
|
||||||
# dependency and import from quantum.client.* and quantum.common.*
|
# dependency and import from quantum.client.* and quantum.common.*
|
||||||
# Until then, we have simplified versions of these classes in this file.
|
# Until then, we have simplified versions of these classes in this file.
|
||||||
|
|
||||||
class JSONSerializer(object):
|
class JSONSerializer(object):
|
||||||
""" This is a simple json-only serializer to use until we can just grab
|
"""This is a simple json-only serializer to use until we can just grab
|
||||||
the standard serializer from the quantum library.
|
the standard serializer from the quantum library.
|
||||||
"""
|
"""
|
||||||
def serialize(self, data, content_type):
|
def serialize(self, data, content_type):
|
||||||
@@ -47,17 +47,17 @@ class JSONSerializer(object):
|
|||||||
# granular exceptions, for now, just try to distinguish
|
# granular exceptions, for now, just try to distinguish
|
||||||
# between the cases we care about.
|
# between the cases we care about.
|
||||||
class QuantumNotFoundException(Exception):
|
class QuantumNotFoundException(Exception):
|
||||||
""" Indicates that Quantum Server returned 404"""
|
"""Indicates that Quantum Server returned 404"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class QuantumServerException(Exception):
|
class QuantumServerException(Exception):
|
||||||
""" Indicates any non-404 error from Quantum Server"""
|
"""Indicates any non-404 error from Quantum Server"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class QuantumIOException(Exception):
|
class QuantumIOException(Exception):
|
||||||
""" Indicates network IO trouble reaching Quantum Server"""
|
"""Indicates network IO trouble reaching Quantum Server"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ class Client(object):
|
|||||||
def __init__(self, host="127.0.0.1", port=9696, use_ssl=False, tenant=None,
|
def __init__(self, host="127.0.0.1", port=9696, use_ssl=False, tenant=None,
|
||||||
format="xml", testing_stub=None, key_file=None,
|
format="xml", testing_stub=None, key_file=None,
|
||||||
cert_file=None, logger=None):
|
cert_file=None, logger=None):
|
||||||
""" Creates a new client to some service.
|
"""Creates a new client to some service.
|
||||||
|
|
||||||
:param host: The host where service resides
|
:param host: The host where service resides
|
||||||
:param port: The port where service resides
|
:param port: The port where service resides
|
||||||
@@ -123,7 +123,7 @@ class Client(object):
|
|||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
def get_connection_type(self):
|
def get_connection_type(self):
|
||||||
""" Returns the proper connection type """
|
"""Returns the proper connection type"""
|
||||||
if self.testing_stub:
|
if self.testing_stub:
|
||||||
return self.testing_stub
|
return self.testing_stub
|
||||||
elif self.use_ssl:
|
elif self.use_ssl:
|
||||||
@@ -133,7 +133,7 @@ class Client(object):
|
|||||||
|
|
||||||
def do_request(self, method, action, body=None,
|
def do_request(self, method, action, body=None,
|
||||||
headers=None, params=None):
|
headers=None, params=None):
|
||||||
""" Connects to the server and issues a request.
|
"""Connects to the server and issues a request.
|
||||||
Returns the result data, or raises an appropriate exception if
|
Returns the result data, or raises an appropriate exception if
|
||||||
HTTP status code is not 2xx
|
HTTP status code is not 2xx
|
||||||
|
|
||||||
@@ -142,7 +142,6 @@ class Client(object):
|
|||||||
:param headers: mapping of key/value pairs to add as headers
|
:param headers: mapping of key/value pairs to add as headers
|
||||||
:param params: dictionary of key/value pairs to add to append
|
:param params: dictionary of key/value pairs to add to append
|
||||||
to action
|
to action
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Ensure we have a tenant id
|
# Ensure we have a tenant id
|
||||||
@@ -207,7 +206,7 @@ class Client(object):
|
|||||||
"server. Got error: %s" % e))
|
"server. Got error: %s" % e))
|
||||||
|
|
||||||
def get_status_code(self, response):
|
def get_status_code(self, response):
|
||||||
""" Returns the integer status code from the response, which
|
"""Returns the integer status code from the response, which
|
||||||
can be either a Webob.Response (used in testing) or httplib.Response
|
can be either a Webob.Response (used in testing) or httplib.Response
|
||||||
"""
|
"""
|
||||||
if hasattr(response, 'status_int'):
|
if hasattr(response, 'status_int'):
|
||||||
@@ -236,73 +235,73 @@ class Client(object):
|
|||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def list_networks(self):
|
def list_networks(self):
|
||||||
""" Fetches a list of all networks for a tenant """
|
"""Fetches a list of all networks for a tenant"""
|
||||||
return self.do_request("GET", self.networks_path)
|
return self.do_request("GET", self.networks_path)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def show_network_details(self, network):
|
def show_network_details(self, network):
|
||||||
""" Fetches the details of a certain network """
|
"""Fetches the details of a certain network"""
|
||||||
return self.do_request("GET", self.network_path % (network))
|
return self.do_request("GET", self.network_path % (network))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def create_network(self, body=None):
|
def create_network(self, body=None):
|
||||||
""" Creates a new network """
|
"""Creates a new network"""
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
return self.do_request("POST", self.networks_path, body=body)
|
return self.do_request("POST", self.networks_path, body=body)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def update_network(self, network, body=None):
|
def update_network(self, network, body=None):
|
||||||
""" Updates a network """
|
"""Updates a network"""
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
return self.do_request("PUT", self.network_path % (network), body=body)
|
return self.do_request("PUT", self.network_path % (network), body=body)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def delete_network(self, network):
|
def delete_network(self, network):
|
||||||
""" Deletes the specified network """
|
"""Deletes the specified network"""
|
||||||
return self.do_request("DELETE", self.network_path % (network))
|
return self.do_request("DELETE", self.network_path % (network))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def list_ports(self, network):
|
def list_ports(self, network):
|
||||||
""" Fetches a list of ports on a given network """
|
"""Fetches a list of ports on a given network"""
|
||||||
return self.do_request("GET", self.ports_path % (network))
|
return self.do_request("GET", self.ports_path % (network))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def show_port_details(self, network, port):
|
def show_port_details(self, network, port):
|
||||||
""" Fetches the details of a certain port """
|
"""Fetches the details of a certain port"""
|
||||||
return self.do_request("GET", self.port_path % (network, port))
|
return self.do_request("GET", self.port_path % (network, port))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def create_port(self, network, body=None):
|
def create_port(self, network, body=None):
|
||||||
""" Creates a new port on a given network """
|
"""Creates a new port on a given network"""
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
return self.do_request("POST", self.ports_path % (network), body=body)
|
return self.do_request("POST", self.ports_path % (network), body=body)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def delete_port(self, network, port):
|
def delete_port(self, network, port):
|
||||||
""" Deletes the specified port from a network """
|
"""Deletes the specified port from a network"""
|
||||||
return self.do_request("DELETE", self.port_path % (network, port))
|
return self.do_request("DELETE", self.port_path % (network, port))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def set_port_state(self, network, port, body=None):
|
def set_port_state(self, network, port, body=None):
|
||||||
""" Sets the state of the specified port """
|
"""Sets the state of the specified port"""
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
return self.do_request("PUT",
|
return self.do_request("PUT",
|
||||||
self.port_path % (network, port), body=body)
|
self.port_path % (network, port), body=body)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def show_port_attachment(self, network, port):
|
def show_port_attachment(self, network, port):
|
||||||
""" Fetches the attachment-id associated with the specified port """
|
"""Fetches the attachment-id associated with the specified port"""
|
||||||
return self.do_request("GET", self.attachment_path % (network, port))
|
return self.do_request("GET", self.attachment_path % (network, port))
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def attach_resource(self, network, port, body=None):
|
def attach_resource(self, network, port, body=None):
|
||||||
""" Sets the attachment-id of the specified port """
|
"""Sets the attachment-id of the specified port"""
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
return self.do_request("PUT",
|
return self.do_request("PUT",
|
||||||
self.attachment_path % (network, port), body=body)
|
self.attachment_path % (network, port), body=body)
|
||||||
|
|
||||||
@api_call
|
@api_call
|
||||||
def detach_resource(self, network, port):
|
def detach_resource(self, network, port):
|
||||||
""" Removes the attachment-id of the specified port """
|
"""Removes the attachment-id of the specified port"""
|
||||||
return self.do_request("DELETE",
|
return self.do_request("DELETE",
|
||||||
self.attachment_path % (network, port))
|
self.attachment_path % (network, port))
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from nova.network import manager
|
|||||||
from nova.network.quantum import quantum_connection
|
from nova.network.quantum import quantum_connection
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
LOG = logging.getLogger("quantum_manager")
|
LOG = logging.getLogger("nova.network.quantum.manager")
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
@@ -34,26 +34,26 @@ flags.DEFINE_string('quantum_ipam_lib',
|
|||||||
|
|
||||||
|
|
||||||
class QuantumManager(manager.FlatManager):
|
class QuantumManager(manager.FlatManager):
|
||||||
""" NetworkManager class that communicates with a Quantum service
|
"""NetworkManager class that communicates with a Quantum service
|
||||||
via a web services API to provision VM network connectivity.
|
via a web services API to provision VM network connectivity.
|
||||||
|
|
||||||
For IP Address management, QuantumManager can be configured to
|
For IP Address management, QuantumManager can be configured to
|
||||||
use either Nova's local DB or the Melange IPAM service.
|
use either Nova's local DB or the Melange IPAM service.
|
||||||
|
|
||||||
Currently, the QuantumManager does NOT support any of the 'gateway'
|
Currently, the QuantumManager does NOT support any of the 'gateway'
|
||||||
functionality implemented by the Nova VlanManager, including:
|
functionality implemented by the Nova VlanManager, including:
|
||||||
* floating IPs
|
* floating IPs
|
||||||
* DHCP
|
* DHCP
|
||||||
* NAT gateway
|
* NAT gateway
|
||||||
|
|
||||||
Support for these capabilities are targted for future releases.
|
Support for these capabilities are targted for future releases.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, q_conn=None, ipam_lib=None, *args, **kwargs):
|
def __init__(self, q_conn=None, ipam_lib=None, *args, **kwargs):
|
||||||
""" Initialize two key libraries, the connection to a
|
"""Initialize two key libraries, the connection to a
|
||||||
Quantum service, and the library for implementing IPAM.
|
Quantum service, and the library for implementing IPAM.
|
||||||
|
|
||||||
Calls inherited FlatManager constructor.
|
Calls inherited FlatManager constructor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not q_conn:
|
if not q_conn:
|
||||||
@@ -70,16 +70,16 @@ class QuantumManager(manager.FlatManager):
|
|||||||
network_size, cidr_v6, gateway_v6, bridge,
|
network_size, cidr_v6, gateway_v6, bridge,
|
||||||
bridge_interface, dns1=None, dns2=None, uuid=None,
|
bridge_interface, dns1=None, dns2=None, uuid=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
""" Unlike other NetworkManagers, with QuantumManager, each
|
"""Unlike other NetworkManagers, with QuantumManager, each
|
||||||
create_networks calls should create only a single network.
|
create_networks calls should create only a single network.
|
||||||
|
|
||||||
Two scenarios exist:
|
Two scenarios exist:
|
||||||
- no 'uuid' is specified, in which case we contact
|
- no 'uuid' is specified, in which case we contact
|
||||||
Quantum and create a new network.
|
Quantum and create a new network.
|
||||||
- an existing 'uuid' is specified, corresponding to
|
- an existing 'uuid' is specified, corresponding to
|
||||||
a Quantum network created out of band.
|
a Quantum network created out of band.
|
||||||
|
|
||||||
In both cases, we initialize a subnet using the IPAM lib.
|
In both cases, we initialize a subnet using the IPAM lib.
|
||||||
"""
|
"""
|
||||||
if num_networks != 1:
|
if num_networks != 1:
|
||||||
raise Exception(_("QuantumManager requires that only one"
|
raise Exception(_("QuantumManager requires that only one"
|
||||||
@@ -101,8 +101,8 @@ class QuantumManager(manager.FlatManager):
|
|||||||
priority, cidr, gateway_v6, cidr_v6, dns1, dns2)
|
priority, cidr, gateway_v6, cidr_v6, dns1, dns2)
|
||||||
|
|
||||||
def delete_network(self, context, fixed_range):
|
def delete_network(self, context, fixed_range):
|
||||||
""" Lookup network by IPv4 cidr, delete both the IPAM
|
"""Lookup network by IPv4 cidr, delete both the IPAM
|
||||||
subnet and the corresponding Quantum network.
|
subnet and the corresponding Quantum network.
|
||||||
"""
|
"""
|
||||||
project_id = context.project_id
|
project_id = context.project_id
|
||||||
quantum_net_id = self.ipam.get_network_id_by_cidr(
|
quantum_net_id = self.ipam.get_network_id_by_cidr(
|
||||||
@@ -113,14 +113,14 @@ class QuantumManager(manager.FlatManager):
|
|||||||
self.q_conn.delete_network(q_tenant_id, quantum_net_id)
|
self.q_conn.delete_network(q_tenant_id, quantum_net_id)
|
||||||
|
|
||||||
def allocate_for_instance(self, context, **kwargs):
|
def allocate_for_instance(self, context, **kwargs):
|
||||||
""" Called by compute when it is creating a new VM.
|
"""Called by compute when it is creating a new VM.
|
||||||
|
|
||||||
There are three key tasks:
|
There are three key tasks:
|
||||||
- Determine the number and order of vNICs to create
|
- Determine the number and order of vNICs to create
|
||||||
- Allocate IP addresses
|
- Allocate IP addresses
|
||||||
- Create ports on a Quantum network and attach vNICs.
|
- Create ports on a Quantum network and attach vNICs.
|
||||||
|
|
||||||
We support two approaches to determining vNICs:
|
We support two approaches to determining vNICs:
|
||||||
- By default, a VM gets a vNIC for any network belonging
|
- By default, a VM gets a vNIC for any network belonging
|
||||||
to the VM's project, and a vNIC for any "global" network
|
to the VM's project, and a vNIC for any "global" network
|
||||||
that has a NULL project_id. vNIC order is determined
|
that has a NULL project_id. vNIC order is determined
|
||||||
@@ -130,10 +130,10 @@ class QuantumManager(manager.FlatManager):
|
|||||||
create vNICs, and the vNIC order is determiend by the
|
create vNICs, and the vNIC order is determiend by the
|
||||||
order in the requested_networks array.
|
order in the requested_networks array.
|
||||||
|
|
||||||
For each vNIC, use the FlatManager to create the entries
|
For each vNIC, use the FlatManager to create the entries
|
||||||
in the virtual_interfaces table, contact Quantum to
|
in the virtual_interfaces table, contact Quantum to
|
||||||
create a port and attachment the vNIC, and use the IPAM
|
create a port and attachment the vNIC, and use the IPAM
|
||||||
lib to allocate IP addresses.
|
lib to allocate IP addresses.
|
||||||
"""
|
"""
|
||||||
instance_id = kwargs.pop('instance_id')
|
instance_id = kwargs.pop('instance_id')
|
||||||
instance_type_id = kwargs['instance_type_id']
|
instance_type_id = kwargs['instance_type_id']
|
||||||
@@ -181,17 +181,17 @@ class QuantumManager(manager.FlatManager):
|
|||||||
|
|
||||||
def get_instance_nw_info(self, context, instance_id,
|
def get_instance_nw_info(self, context, instance_id,
|
||||||
instance_type_id, host):
|
instance_type_id, host):
|
||||||
""" This method is used by compute to fetch all network data
|
"""This method is used by compute to fetch all network data
|
||||||
that should be used when creating the VM.
|
that should be used when creating the VM.
|
||||||
|
|
||||||
The method simply loops through all virtual interfaces
|
The method simply loops through all virtual interfaces
|
||||||
stored in the nova DB and queries the IPAM lib to get
|
stored in the nova DB and queries the IPAM lib to get
|
||||||
the associated IP data.
|
the associated IP data.
|
||||||
|
|
||||||
The format of returned data is 'defined' by the initial
|
The format of returned data is 'defined' by the initial
|
||||||
set of NetworkManagers found in nova/network/manager.py .
|
set of NetworkManagers found in nova/network/manager.py .
|
||||||
Ideally this 'interface' will be more formally defined
|
Ideally this 'interface' will be more formally defined
|
||||||
in the future.
|
in the future.
|
||||||
"""
|
"""
|
||||||
network_info = []
|
network_info = []
|
||||||
instance = db.instance_get(context, instance_id)
|
instance = db.instance_get(context, instance_id)
|
||||||
@@ -269,10 +269,10 @@ class QuantumManager(manager.FlatManager):
|
|||||||
return network_info
|
return network_info
|
||||||
|
|
||||||
def deallocate_for_instance(self, context, **kwargs):
|
def deallocate_for_instance(self, context, **kwargs):
|
||||||
""" Called when a VM is terminated. Loop through each virtual
|
"""Called when a VM is terminated. Loop through each virtual
|
||||||
interface in the Nova DB and remove the Quantum port and
|
interface in the Nova DB and remove the Quantum port and
|
||||||
clear the IP allocation using the IPAM. Finally, remove
|
clear the IP allocation using the IPAM. Finally, remove
|
||||||
the virtual interfaces from the Nova DB.
|
the virtual interfaces from the Nova DB.
|
||||||
"""
|
"""
|
||||||
instance_id = kwargs.get('instance_id')
|
instance_id = kwargs.get('instance_id')
|
||||||
project_id = kwargs.pop('project_id', None)
|
project_id = kwargs.pop('project_id', None)
|
||||||
@@ -309,7 +309,7 @@ class QuantumManager(manager.FlatManager):
|
|||||||
(instance_id)))
|
(instance_id)))
|
||||||
|
|
||||||
def validate_networks(self, context, networks):
|
def validate_networks(self, context, networks):
|
||||||
""" Validates that this tenant has quantum networks with the associated
|
"""Validates that this tenant has quantum networks with the associated
|
||||||
UUIDs. This is called by the 'os-create-server-ext' API extension
|
UUIDs. This is called by the 'os-create-server-ext' API extension
|
||||||
code so that we can return an API error code to the caller if they
|
code so that we can return an API error code to the caller if they
|
||||||
request an invalid network.
|
request an invalid network.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ flags.DEFINE_string('melange_port',
|
|||||||
|
|
||||||
json_content_type = {'Content-type': "application/json"}
|
json_content_type = {'Content-type': "application/json"}
|
||||||
|
|
||||||
#FIXME(danwent): talk to the Melange folks about creating a
|
# FIXME(danwent): talk to the Melange folks about creating a
|
||||||
# client lib that we can import as a library, instead of
|
# client lib that we can import as a library, instead of
|
||||||
# have to have all of the client code in here.
|
# have to have all of the client code in here.
|
||||||
class MelangeConnection(object):
|
class MelangeConnection(object):
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from nova import log as logging
|
|||||||
from nova.network.quantum import melange_connection
|
from nova.network.quantum import melange_connection
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("quantum_melange_ipam")
|
LOG = logging.getLogger("nova.network.quantum.melange_ipam_lib")
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
@@ -34,26 +34,26 @@ def get_ipam_lib(net_man):
|
|||||||
|
|
||||||
|
|
||||||
class QuantumMelangeIPAMLib(object):
|
class QuantumMelangeIPAMLib(object):
|
||||||
""" Implements Quantum IP Address Management (IPAM) interface
|
"""Implements Quantum IP Address Management (IPAM) interface
|
||||||
using the Melange service, which is access using the Melange
|
using the Melange service, which is access using the Melange
|
||||||
web services API.
|
web services API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
""" Initialize class used to connect to Melange server"""
|
"""Initialize class used to connect to Melange server"""
|
||||||
self.m_conn = melange_connection.MelangeConnection()
|
self.m_conn = melange_connection.MelangeConnection()
|
||||||
|
|
||||||
def create_subnet(self, context, label, project_id,
|
def create_subnet(self, context, label, project_id,
|
||||||
quantum_net_id, priority, cidr=None,
|
quantum_net_id, priority, cidr=None,
|
||||||
gateway_v6=None, cidr_v6=None,
|
gateway_v6=None, cidr_v6=None,
|
||||||
dns1=None, dns2=None):
|
dns1=None, dns2=None):
|
||||||
""" Contact Melange and create a subnet for any non-NULL
|
"""Contact Melange and create a subnet for any non-NULL
|
||||||
IPv4 or IPv6 subnets.
|
IPv4 or IPv6 subnets.
|
||||||
|
|
||||||
Also create a entry in the Nova networks DB, but only
|
Also create a entry in the Nova networks DB, but only
|
||||||
to store values not represented in Melange or to
|
to store values not represented in Melange or to
|
||||||
temporarily provide compatibility with Nova code that
|
temporarily provide compatibility with Nova code that
|
||||||
accesses IPAM data directly via the DB (e.g., nova-api)
|
accesses IPAM data directly via the DB (e.g., nova-api)
|
||||||
"""
|
"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
if cidr:
|
if cidr:
|
||||||
@@ -73,15 +73,15 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
network = db.network_create_safe(admin_context, net)
|
network = db.network_create_safe(admin_context, net)
|
||||||
|
|
||||||
def allocate_fixed_ip(self, context, project_id, quantum_net_id, vif_ref):
|
def allocate_fixed_ip(self, context, project_id, quantum_net_id, vif_ref):
|
||||||
""" Pass call to allocate fixed IP on to Melange"""
|
"""Pass call to allocate fixed IP on to Melange"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
self.m_conn.allocate_ip(quantum_net_id,
|
self.m_conn.allocate_ip(quantum_net_id,
|
||||||
vif_ref['uuid'], project_id=tenant_id,
|
vif_ref['uuid'], project_id=tenant_id,
|
||||||
mac_address=vif_ref['address'])
|
mac_address=vif_ref['address'])
|
||||||
|
|
||||||
def get_network_id_by_cidr(self, context, cidr, project_id):
|
def get_network_id_by_cidr(self, context, cidr, project_id):
|
||||||
""" Find the Quantum UUID associated with a IPv4 CIDR
|
"""Find the Quantum UUID associated with a IPv4 CIDR
|
||||||
address for the specified tenant.
|
address for the specified tenant.
|
||||||
"""
|
"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
all_blocks = self.m_conn.get_blocks(tenant_id)
|
all_blocks = self.m_conn.get_blocks(tenant_id)
|
||||||
@@ -91,8 +91,8 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
raise exception.NotFound(_("No network found for cidr %s" % cidr))
|
raise exception.NotFound(_("No network found for cidr %s" % cidr))
|
||||||
|
|
||||||
def delete_subnets_by_net_id(self, context, net_id, project_id):
|
def delete_subnets_by_net_id(self, context, net_id, project_id):
|
||||||
""" Find Melange block associated with the Quantum UUID,
|
"""Find Melange block associated with the Quantum UUID,
|
||||||
then tell Melange to delete that block.
|
then tell Melange to delete that block.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
@@ -105,9 +105,10 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
db.network_delete_safe(context, network['id'])
|
db.network_delete_safe(context, network['id'])
|
||||||
|
|
||||||
def get_project_and_global_net_ids(self, context, project_id):
|
def get_project_and_global_net_ids(self, context, project_id):
|
||||||
""" Fetches all networks associated with this project, or
|
"""Fetches all networks associated with this project, or
|
||||||
that are "global" (i.e., have no project set).
|
that are "global" (i.e., have no project set).
|
||||||
Returns list sorted by 'priority'.
|
Returns list sorted by 'priority' (lowest integer value
|
||||||
|
is highest priority).
|
||||||
"""
|
"""
|
||||||
if project_id is None:
|
if project_id is None:
|
||||||
raise Exception(_("get_project_and_global_net_ids must be called"
|
raise Exception(_("get_project_and_global_net_ids must be called"
|
||||||
@@ -134,8 +135,8 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
for priority, network_id, tenant_id in priority_nets]
|
for priority, network_id, tenant_id in priority_nets]
|
||||||
|
|
||||||
def get_subnets_by_net_id(self, context, project_id, net_id):
|
def get_subnets_by_net_id(self, context, project_id, net_id):
|
||||||
""" Returns information about the IPv4 and IPv6 subnets
|
"""Returns information about the IPv4 and IPv6 subnets
|
||||||
associated with a Quantum Network UUID.
|
associated with a Quantum Network UUID.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# FIXME(danwent): Melange actually returns the subnet info
|
# FIXME(danwent): Melange actually returns the subnet info
|
||||||
@@ -164,23 +165,23 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
return (subnet_v4, subnet_v6)
|
return (subnet_v4, subnet_v6)
|
||||||
|
|
||||||
def get_v4_ips_by_interface(self, context, net_id, vif_id, project_id):
|
def get_v4_ips_by_interface(self, context, net_id, vif_id, project_id):
|
||||||
""" Returns a list of IPv4 address strings associated with
|
"""Returns a list of IPv4 address strings associated with
|
||||||
the specified virtual interface.
|
the specified virtual interface.
|
||||||
"""
|
"""
|
||||||
return self._get_ips_by_interface(context, net_id, vif_id,
|
return self._get_ips_by_interface(context, net_id, vif_id,
|
||||||
project_id, 4)
|
project_id, 4)
|
||||||
|
|
||||||
def get_v6_ips_by_interface(self, context, net_id, vif_id, project_id):
|
def get_v6_ips_by_interface(self, context, net_id, vif_id, project_id):
|
||||||
""" Returns a list of IPv6 address strings associated with
|
"""Returns a list of IPv6 address strings associated with
|
||||||
the specified virtual interface.
|
the specified virtual interface.
|
||||||
"""
|
"""
|
||||||
return self._get_ips_by_interface(context, net_id, vif_id,
|
return self._get_ips_by_interface(context, net_id, vif_id,
|
||||||
project_id, 6)
|
project_id, 6)
|
||||||
|
|
||||||
def _get_ips_by_interface(self, context, net_id, vif_id, project_id,
|
def _get_ips_by_interface(self, context, net_id, vif_id, project_id,
|
||||||
ip_version):
|
ip_version):
|
||||||
""" Helper method to fetch v4 or v6 addresses for a particular
|
"""Helper method to fetch v4 or v6 addresses for a particular
|
||||||
virtual interface.
|
virtual interface.
|
||||||
"""
|
"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
ip_list = self.m_conn.get_allocated_ips(net_id, vif_id, tenant_id)
|
ip_list = self.m_conn.get_allocated_ips(net_id, vif_id, tenant_id)
|
||||||
@@ -188,8 +189,8 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
if IPNetwork(ip['address']).version == ip_version]
|
if IPNetwork(ip['address']).version == ip_version]
|
||||||
|
|
||||||
def verify_subnet_exists(self, context, project_id, quantum_net_id):
|
def verify_subnet_exists(self, context, project_id, quantum_net_id):
|
||||||
""" Confirms that a subnet exists that is associated with the
|
"""Confirms that a subnet exists that is associated with the
|
||||||
specified Quantum Network UUID.
|
specified Quantum Network UUID.
|
||||||
"""
|
"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
v4_subnet, v6_subnet = self.get_subnets_by_net_id(context, tenant_id,
|
v4_subnet, v6_subnet = self.get_subnets_by_net_id(context, tenant_id,
|
||||||
@@ -197,8 +198,8 @@ class QuantumMelangeIPAMLib(object):
|
|||||||
return v4_subnet is not None
|
return v4_subnet is not None
|
||||||
|
|
||||||
def deallocate_ips_by_vif(self, context, project_id, net_id, vif_ref):
|
def deallocate_ips_by_vif(self, context, project_id, net_id, vif_ref):
|
||||||
""" Deallocate all fixed IPs associated with the specified
|
"""Deallocate all fixed IPs associated with the specified
|
||||||
virtual interface.
|
virtual interface.
|
||||||
"""
|
"""
|
||||||
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
tenant_id = project_id or FLAGS.quantum_default_tenant_id
|
||||||
self.m_conn.deallocate_ips(net_id, vif_ref['uuid'], tenant_id)
|
self.m_conn.deallocate_ips(net_id, vif_ref['uuid'], tenant_id)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from nova.network.quantum import melange_connection as melange
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("quantum_nova_ipam_lib")
|
LOG = logging.getLogger("nova.network.quantum.nova_ipam_lib")
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
@@ -37,15 +37,15 @@ def get_ipam_lib(net_man):
|
|||||||
|
|
||||||
|
|
||||||
class QuantumNovaIPAMLib(object):
|
class QuantumNovaIPAMLib(object):
|
||||||
""" Implements Quantum IP Address Management (IPAM) interface
|
"""Implements Quantum IP Address Management (IPAM) interface
|
||||||
using the local Nova database. This implementation is inline
|
using the local Nova database. This implementation is inline
|
||||||
with how IPAM is used by other NetworkManagers.
|
with how IPAM is used by other NetworkManagers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, net_manager):
|
def __init__(self, net_manager):
|
||||||
""" Holds a reference to the "parent" network manager, used
|
"""Holds a reference to the "parent" network manager, used
|
||||||
to take advantage of various FlatManager methods to avoid
|
to take advantage of various FlatManager methods to avoid
|
||||||
code duplication.
|
code duplication.
|
||||||
"""
|
"""
|
||||||
self.net_manager = net_manager
|
self.net_manager = net_manager
|
||||||
|
|
||||||
@@ -53,11 +53,11 @@ class QuantumNovaIPAMLib(object):
|
|||||||
quantum_net_id, priority, cidr=None,
|
quantum_net_id, priority, cidr=None,
|
||||||
gateway_v6=None, cidr_v6=None,
|
gateway_v6=None, cidr_v6=None,
|
||||||
dns1=None, dns2=None):
|
dns1=None, dns2=None):
|
||||||
""" Re-use the basic FlatManager create_networks method to
|
"""Re-use the basic FlatManager create_networks method to
|
||||||
initialize the networks and fixed_ips tables in Nova DB.
|
initialize the networks and fixed_ips tables in Nova DB.
|
||||||
|
|
||||||
Also stores a few more fields in the networks table that
|
Also stores a few more fields in the networks table that
|
||||||
are needed by Quantum but not the FlatManager.
|
are needed by Quantum but not the FlatManager.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
subnet_size = len(netaddr.IPNetwork(cidr))
|
subnet_size = len(netaddr.IPNetwork(cidr))
|
||||||
@@ -85,8 +85,8 @@ class QuantumNovaIPAMLib(object):
|
|||||||
return network['uuid']
|
return network['uuid']
|
||||||
|
|
||||||
def delete_subnets_by_net_id(self, context, net_id, project_id):
|
def delete_subnets_by_net_id(self, context, net_id, project_id):
|
||||||
""" Deletes a network based on Quantum UUID. Uses FlatManager
|
"""Deletes a network based on Quantum UUID. Uses FlatManager
|
||||||
delete_network to avoid duplication.
|
delete_network to avoid duplication.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
network = db.network_get_by_uuid(admin_context, net_id)
|
network = db.network_get_by_uuid(admin_context, net_id)
|
||||||
@@ -97,9 +97,9 @@ class QuantumNovaIPAMLib(object):
|
|||||||
require_disassociated=False)
|
require_disassociated=False)
|
||||||
|
|
||||||
def get_project_and_global_net_ids(self, context, project_id):
|
def get_project_and_global_net_ids(self, context, project_id):
|
||||||
""" Fetches all networks associated with this project, or
|
"""Fetches all networks associated with this project, or
|
||||||
that are "global" (i.e., have no project set).
|
that are "global" (i.e., have no project set).
|
||||||
Returns list sorted by 'priority'.
|
Returns list sorted by 'priority'.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
networks = db.project_get_networks(admin_context, project_id, False)
|
networks = db.project_get_networks(admin_context, project_id, False)
|
||||||
@@ -113,7 +113,7 @@ class QuantumNovaIPAMLib(object):
|
|||||||
return sorted(net_list, key=lambda x: id_priority_map[x[0]])
|
return sorted(net_list, key=lambda x: id_priority_map[x[0]])
|
||||||
|
|
||||||
def allocate_fixed_ip(self, context, tenant_id, quantum_net_id, vif_rec):
|
def allocate_fixed_ip(self, context, tenant_id, quantum_net_id, vif_rec):
|
||||||
""" Allocates a single fixed IPv4 address for a virtual interface."""
|
"""Allocates a single fixed IPv4 address for a virtual interface."""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
network = db.network_get_by_uuid(admin_context, quantum_net_id)
|
network = db.network_get_by_uuid(admin_context, quantum_net_id)
|
||||||
if network['cidr']:
|
if network['cidr']:
|
||||||
@@ -125,8 +125,8 @@ class QuantumNovaIPAMLib(object):
|
|||||||
db.fixed_ip_update(admin_context, address, values)
|
db.fixed_ip_update(admin_context, address, values)
|
||||||
|
|
||||||
def get_subnets_by_net_id(self, context, tenant_id, net_id):
|
def get_subnets_by_net_id(self, context, tenant_id, net_id):
|
||||||
""" Returns information about the IPv4 and IPv6 subnets
|
"""Returns information about the IPv4 and IPv6 subnets
|
||||||
associated with a Quantum Network UUID.
|
associated with a Quantum Network UUID.
|
||||||
"""
|
"""
|
||||||
n = db.network_get_by_uuid(context.elevated(), net_id)
|
n = db.network_get_by_uuid(context.elevated(), net_id)
|
||||||
subnet_data_v4 = {
|
subnet_data_v4 = {
|
||||||
@@ -148,8 +148,8 @@ class QuantumNovaIPAMLib(object):
|
|||||||
return (subnet_data_v4, subnet_data_v6)
|
return (subnet_data_v4, subnet_data_v6)
|
||||||
|
|
||||||
def get_v4_ips_by_interface(self, context, net_id, vif_id, project_id):
|
def get_v4_ips_by_interface(self, context, net_id, vif_id, project_id):
|
||||||
""" Returns a list of IPv4 address strings associated with
|
"""Returns a list of IPv4 address strings associated with
|
||||||
the specified virtual interface, based on the fixed_ips table.
|
the specified virtual interface, based on the fixed_ips table.
|
||||||
"""
|
"""
|
||||||
vif_rec = db.virtual_interface_get_by_uuid(context, vif_id)
|
vif_rec = db.virtual_interface_get_by_uuid(context, vif_id)
|
||||||
fixed_ips = db.fixed_ip_get_by_virtual_interface(context,
|
fixed_ips = db.fixed_ip_get_by_virtual_interface(context,
|
||||||
@@ -157,8 +157,8 @@ class QuantumNovaIPAMLib(object):
|
|||||||
return [fixed_ip['address'] for fixed_ip in fixed_ips]
|
return [fixed_ip['address'] for fixed_ip in fixed_ips]
|
||||||
|
|
||||||
def get_v6_ips_by_interface(self, context, net_id, vif_id, project_id):
|
def get_v6_ips_by_interface(self, context, net_id, vif_id, project_id):
|
||||||
""" Returns a list containing a single IPv6 address strings
|
"""Returns a list containing a single IPv6 address strings
|
||||||
associated with the specified virtual interface.
|
associated with the specified virtual interface.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
network = db.network_get_by_uuid(admin_context, net_id)
|
network = db.network_get_by_uuid(admin_context, net_id)
|
||||||
@@ -171,16 +171,16 @@ class QuantumNovaIPAMLib(object):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def verify_subnet_exists(self, context, tenant_id, quantum_net_id):
|
def verify_subnet_exists(self, context, tenant_id, quantum_net_id):
|
||||||
""" Confirms that a subnet exists that is associated with the
|
"""Confirms that a subnet exists that is associated with the
|
||||||
specified Quantum Network UUID. Raises an exception if no
|
specified Quantum Network UUID. Raises an exception if no
|
||||||
such subnet exists.
|
such subnet exists.
|
||||||
"""
|
"""
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
db.network_get_by_uuid(admin_context, quantum_net_id)
|
db.network_get_by_uuid(admin_context, quantum_net_id)
|
||||||
|
|
||||||
def deallocate_ips_by_vif(self, context, tenant_id, net_id, vif_ref):
|
def deallocate_ips_by_vif(self, context, tenant_id, net_id, vif_ref):
|
||||||
""" Deallocate all fixed IPs associated with the specified
|
"""Deallocate all fixed IPs associated with the specified
|
||||||
virtual interface.
|
virtual interface.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
admin_context = context.elevated()
|
admin_context = context.elevated()
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from nova.network.quantum import client as quantum_client
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("nova.network.quantum")
|
LOG = logging.getLogger("nova.network.quantum.quantum_connection")
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
|
|
||||||
flags.DEFINE_string('quantum_connection_host',
|
flags.DEFINE_string('quantum_connection_host',
|
||||||
@@ -38,35 +38,35 @@ flags.DEFINE_string('quantum_default_tenant_id',
|
|||||||
|
|
||||||
|
|
||||||
class QuantumClientConnection(object):
|
class QuantumClientConnection(object):
|
||||||
""" Abstracts connection to Quantum service into higher level
|
"""Abstracts connection to Quantum service into higher level
|
||||||
operations performed by the QuantumManager.
|
operations performed by the QuantumManager.
|
||||||
|
|
||||||
Separating this out as a class also let's us create a 'fake'
|
Separating this out as a class also let's us create a 'fake'
|
||||||
version of this class for unit tests.
|
version of this class for unit tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
""" Initialize Quantum client class based on flags. """
|
"""Initialize Quantum client class based on flags."""
|
||||||
self.client = quantum_client.Client(FLAGS.quantum_connection_host,
|
self.client = quantum_client.Client(FLAGS.quantum_connection_host,
|
||||||
FLAGS.quantum_connection_port,
|
FLAGS.quantum_connection_port,
|
||||||
format="json",
|
format="json",
|
||||||
logger=LOG)
|
logger=LOG)
|
||||||
|
|
||||||
def create_network(self, tenant_id, network_name):
|
def create_network(self, tenant_id, network_name):
|
||||||
""" Create network using specified name, return Quantum
|
"""Create network using specified name, return Quantum
|
||||||
network UUID.
|
network UUID.
|
||||||
"""
|
"""
|
||||||
data = {'network': {'name': network_name}}
|
data = {'network': {'name': network_name}}
|
||||||
resdict = self.client.create_network(data, tenant=tenant_id)
|
resdict = self.client.create_network(data, tenant=tenant_id)
|
||||||
return resdict["network"]["id"]
|
return resdict["network"]["id"]
|
||||||
|
|
||||||
def delete_network(self, tenant_id, net_id):
|
def delete_network(self, tenant_id, net_id):
|
||||||
""" Deletes Quantum network with specified UUID. """
|
"""Deletes Quantum network with specified UUID."""
|
||||||
self.client.delete_network(net_id, tenant=tenant_id)
|
self.client.delete_network(net_id, tenant=tenant_id)
|
||||||
|
|
||||||
def network_exists(self, tenant_id, net_id):
|
def network_exists(self, tenant_id, net_id):
|
||||||
""" Determine if a Quantum network exists for the
|
"""Determine if a Quantum network exists for the
|
||||||
specified tenant.
|
specified tenant.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.client.show_network_details(net_id, tenant=tenant_id)
|
self.client.show_network_details(net_id, tenant=tenant_id)
|
||||||
@@ -76,9 +76,9 @@ class QuantumClientConnection(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def create_and_attach_port(self, tenant_id, net_id, interface_id):
|
def create_and_attach_port(self, tenant_id, net_id, interface_id):
|
||||||
""" Creates a Quantum port on the specified network, sets
|
"""Creates a Quantum port on the specified network, sets
|
||||||
status to ACTIVE to enable traffic, and attaches the
|
status to ACTIVE to enable traffic, and attaches the
|
||||||
vNIC with the specified interface-id.
|
vNIC with the specified interface-id.
|
||||||
"""
|
"""
|
||||||
LOG.debug(_("Connecting interface %(interface_id)s to "
|
LOG.debug(_("Connecting interface %(interface_id)s to "
|
||||||
"net %(net_id)s for %(tenant_id)s" % locals()))
|
"net %(net_id)s for %(tenant_id)s" % locals()))
|
||||||
@@ -91,7 +91,7 @@ class QuantumClientConnection(object):
|
|||||||
tenant=tenant_id)
|
tenant=tenant_id)
|
||||||
|
|
||||||
def detach_and_delete_port(self, tenant_id, net_id, port_id):
|
def detach_and_delete_port(self, tenant_id, net_id, port_id):
|
||||||
""" Detach and delete the specified Quantum port. """
|
"""Detach and delete the specified Quantum port."""
|
||||||
LOG.debug(_("Deleting port %(port_id)s on net %(net_id)s"
|
LOG.debug(_("Deleting port %(port_id)s on net %(net_id)s"
|
||||||
" for %(tenant_id)s" % locals()))
|
" for %(tenant_id)s" % locals()))
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ class QuantumClientConnection(object):
|
|||||||
self.client.delete_port(net_id, port_id, tenant=tenant_id)
|
self.client.delete_port(net_id, port_id, tenant=tenant_id)
|
||||||
|
|
||||||
def get_port_by_attachment(self, tenant_id, attachment_id):
|
def get_port_by_attachment(self, tenant_id, attachment_id):
|
||||||
""" Given a tenant, search for the Quantum network and port
|
"""Given a tenant, search for the Quantum network and port
|
||||||
UUID that has the specified interface-id attachment.
|
UUID that has the specified interface-id attachment.
|
||||||
"""
|
"""
|
||||||
# FIXME(danwent): this will be inefficient until the Quantum
|
# FIXME(danwent): this will be inefficient until the Quantum
|
||||||
# API implements querying a port by the interface-id
|
# API implements querying a port by the interface-id
|
||||||
|
|||||||
Reference in New Issue
Block a user