1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2011 Nicira Networks
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may
7
# not use this file except in compliance with the License. You may obtain
8
# a copy of the License at
10
# http://www.apache.org/licenses/LICENSE-2.0
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
# License for the specific language governing permissions and limitations
18
from nova import flags
19
from nova.network.quantum import client as quantum_client
20
from nova.openstack.common import cfg
21
from nova.openstack.common import log as logging
24
LOG = logging.getLogger(__name__)
27
cfg.StrOpt('quantum_connection_host',
29
help='HOST for connecting to quantum'),
30
cfg.IntOpt('quantum_connection_port',
32
help='PORT for connecting to quantum'),
33
cfg.StrOpt('quantum_default_tenant_id',
35
help='Default tenant id when creating quantum networks'),
36
cfg.IntOpt('quantum_request_timeout',
38
help='Maximum amount of time to wait for quantum request'),
42
FLAGS.register_opts(quantum_opts)
45
class QuantumClientConnection(object):
46
"""Abstracts connection to Quantum service into higher level
47
operations performed by the QuantumManager.
49
Separating this out as a class also let's us create a 'fake'
50
version of this class for unit tests.
53
def __init__(self, client=None):
54
"""Initialize Quantum client class based on flags."""
58
self.client = quantum_client.Client(FLAGS.quantum_connection_host,
59
FLAGS.quantum_connection_port,
60
timeout=FLAGS.quantum_request_timeout,
64
def create_network(self, tenant_id, network_name, **kwargs):
65
"""Create network using specified name, return Quantum
68
data = {'network': {'name': network_name}}
70
data['network'][kw] = kwargs[kw]
71
resdict = self.client.create_network(data, tenant=tenant_id)
72
return resdict["network"]["id"]
74
def get_network_name(self, tenant_id, network_id):
75
net = self.client.show_network_details(network_id, tenant=tenant_id)
76
return net["network"]["name"]
78
def delete_network(self, tenant_id, net_id):
79
"""Deletes Quantum network with specified UUID."""
80
self.client.delete_network(net_id, tenant=tenant_id)
82
def network_exists(self, tenant_id, net_id):
83
"""Determine if a Quantum network exists for the
87
self.client.show_network_details(net_id, tenant=tenant_id)
89
except quantum_client.QuantumNotFoundException:
90
# Not really an error. Real errors will be propogated to caller
93
def get_networks(self, tenant_id):
94
"""Retrieve all networks for this tenant"""
95
return self.client.list_networks(tenant=tenant_id)
97
def create_and_attach_port(self, tenant_id, net_id, interface_id,
99
"""Creates a Quantum port on the specified network, sets
100
status to ACTIVE to enable traffic, and attaches the
101
vNIC with the specified interface-id.
103
LOG.debug(_("Connecting interface %(interface_id)s to "
104
"net %(net_id)s for %(tenant_id)s"), locals())
105
port_data = {'port': {'state': 'ACTIVE'}}
107
port_data['port'][kw] = kwargs[kw]
108
resdict = self.client.create_port(net_id, port_data, tenant=tenant_id)
109
port_id = resdict["port"]["id"]
111
attach_data = {'attachment': {'id': interface_id}}
112
self.client.attach_resource(net_id, port_id, attach_data,
115
def detach_and_delete_port(self, tenant_id, net_id, port_id):
116
"""Detach and delete the specified Quantum port."""
117
LOG.debug(_("Deleting port %(port_id)s on net %(net_id)s"
118
" for %(tenant_id)s"), locals())
120
self.client.detach_resource(net_id, port_id, tenant=tenant_id)
121
self.client.delete_port(net_id, port_id, tenant=tenant_id)
123
def get_port_by_attachment(self, tenant_id, net_id, attachment_id):
124
"""Given a tenant and network, search for the port UUID that
125
has the specified interface-id attachment.
129
port_list_resdict = self.client.list_ports(net_id,
131
filter_ops={'attachment': attachment_id})
132
port_list = port_list_resdict["ports"]
133
except quantum_client.QuantumNotFoundException:
136
port_list_len = len(port_list)
137
if port_list_len == 1:
138
return port_list[0]['id']
139
elif port_list_len > 1:
140
raise Exception("Expected single port with attachment "
141
"%(attachment_id)s, found %(port_list_len)s" % locals())
144
def get_attached_ports(self, tenant_id, network_id):
146
port_list = self.client.list_ports(network_id, tenant=tenant_id)
147
for p in port_list["ports"]:
150
port = self.client.show_port_attachment(network_id,
151
port_id, tenant=tenant_id)
152
# Skip ports without an attachment
153
if "id" not in port["attachment"]:
155
rv.append({'port-id': port_id,
156
'attachment': port["attachment"]["id"]})
157
except quantum_client.QuantumNotFoundException: