2.1.16
by Chuck Short
Import upstream version 2013.1~g1 |
1 |
#!/usr/bin/env python
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
2 |
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
3 |
#
|
|
4 |
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
|
|
5 |
#
|
|
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
|
|
9 |
#
|
|
10 |
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11 |
#
|
|
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
|
|
16 |
# under the License.
|
|
17 |
#
|
|
18 |
# @author: Edgar Magana, Cisco Systems
|
|
19 |
#
|
|
20 |
"""
|
|
21 |
Network Library to insert services using Quantum APIs
|
|
22 |
Currently has four functionalities:
|
|
23 |
1. insert_inpath_service <tenant_id> <service_image_id>
|
|
24 |
<management_net_name> <northbound_net_name> <southbound_net_name>
|
|
25 |
2. delete_service <tenant_id> <service_instance_id>
|
|
26 |
3. connect_vm <tenant_id> <vm_image_id> <service_instance_id>
|
|
27 |
4. disconnect_vm <vm_instance_id>
|
|
28 |
"""
|
|
29 |
||
30 |
import logging |
|
31 |
import logging.handlers |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
32 |
from optparse import OptionParser |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
33 |
import os |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
34 |
import re |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
35 |
import subprocess |
36 |
import sys |
|
37 |
||
2.1.11
by Chuck Short
Import upstream version 2012.2~rc1~20120907.1154 |
38 |
from quantum.common import constants |
2.1.16
by Chuck Short
Import upstream version 2013.1~g1 |
39 |
from quantum.common import utils |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
40 |
from quantum.plugins.cisco.common import cisco_constants as const |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
41 |
from quantum.plugins.cisco.db import api as db |
42 |
from quantum.plugins.cisco.db import l2network_db as l2db |
|
43 |
from quantum.plugins.cisco.db import services_db as sdb |
|
44 |
from quantum.plugins.cisco.services import services_constants as servconts |
|
45 |
from quantum.plugins.cisco.services import services_logistics as servlogcs |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
46 |
from quantumclient import Client |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
47 |
|
48 |
||
49 |
LOG = logging.getLogger(__name__) |
|
50 |
||
51 |
||
52 |
def insert_inpath_service(tenant_id, service_image_id, |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
53 |
management_net_name, northbound_net_name, |
54 |
southbound_net_name, *args): |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
55 |
"""Inserting a network service between two networks"""
|
56 |
print ("Creating Network for Services and Servers") |
|
57 |
service_logic = servlogcs.ServicesLogistics() |
|
58 |
net_list = {} |
|
59 |
multiport_net_list = [] |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
60 |
networks_name_list = [management_net_name, northbound_net_name, |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
61 |
southbound_net_name] |
62 |
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id) |
|
63 |
for net in networks_name_list: |
|
64 |
data = {servconts.NETWORK: {servconts.NAME: net}} |
|
65 |
net_list[net] = client.create_network(data) |
|
66 |
net_list[net][servconts.PORTS] = [] |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
67 |
LOG.debug("Network %s Created with ID: %s " % ( |
68 |
net, net_list[net][servconts.NETWORK][servconts.ID])) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
69 |
print "Completed" |
70 |
print ("Creating Ports on Services and Server Networks") |
|
71 |
LOG.debug("Operation 'create_port' executed.") |
|
72 |
if not service_logic.verify_plugin(const.UCS_PLUGIN): |
|
73 |
for net in networks_name_list: |
|
74 |
net_list[net][servconts.PORTS].append |
|
75 |
(client.create_port |
|
76 |
(net_list[net][servconts.NETWORK][servconts.ID])) |
|
77 |
LOG.debug("Operation 'create_port' executed.") |
|
78 |
else: |
|
79 |
for net in networks_name_list: |
|
80 |
nets = net_list[net][servconts.NETWORK][servconts.ID] |
|
81 |
multiport_net_list.append(nets) |
|
82 |
data = create_multiport(tenant_id, multiport_net_list) |
|
83 |
net_idx = 0 |
|
84 |
for net in networks_name_list: |
|
85 |
port_id = data[servconts.PORTS][net_idx][servconts.ID] |
|
86 |
net_list[net][servconts.PORTS].append(port_id) |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
87 |
LOG.debug("Port UUID: %s on network: %s" % |
88 |
(data[servconts.PORTS][net_idx][servconts.ID], net)) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
89 |
net_idx = net_idx + 1 |
90 |
print "Completed" |
|
91 |
try: |
|
92 |
create_vm_args = [] |
|
93 |
create_vm_args.append(servconts.CREATE_VM_CMD) |
|
94 |
create_vm_args.append(service_image_id) |
|
95 |
print ("Creating VM with image: %s" % (service_image_id)) |
|
2.1.16
by Chuck Short
Import upstream version 2013.1~g1 |
96 |
process = utils.subprocess_popen(create_vm_args, |
97 |
stdout=subprocess.PIPE) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
98 |
result = process.stdout.readlines() |
99 |
tokens = re.search("i-[a-f0-9]*", str(result[1])) |
|
100 |
service_vm_name = tokens.group(0) |
|
101 |
print ("Image: %s instantiated successfully" % (service_vm_name)) |
|
102 |
||
103 |
except Exception as exc: |
|
104 |
print exc |
|
105 |
||
106 |
service_logic.image_status(service_vm_name) |
|
107 |
print "Completed" |
|
108 |
print "Attaching Ports To VM Service interfaces" |
|
109 |
try: |
|
110 |
idx = 0 |
|
111 |
for net in networks_name_list: |
|
112 |
network_id = net_list[net][servconts.NETWORK][servconts.ID] |
|
113 |
port_id = net_list[net][servconts.PORTS][idx] |
|
114 |
attachment = client.show_port_attachment(network_id, port_id) |
|
115 |
attachment = attachment[servconts.ATTACHMENT][servconts.ID][:36] |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
116 |
LOG.debug(("Plugging virtual interface: %s of VM %s" |
117 |
"into port: %s on network: %s") % |
|
118 |
(attachment, service_vm_name, port_id, net)) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
119 |
attach_data = {servconts.ATTACHMENT: {servconts.ID: '%s' % |
120 |
attachment}} |
|
121 |
client.attach_resource(network_id, port_id, attach_data) |
|
122 |
except Exception as exc: |
|
123 |
print exc |
|
124 |
print "Completed" |
|
125 |
try: |
|
126 |
LOG.debug("Registering Service in DB") |
|
127 |
l2db.initialize() |
|
128 |
for uuid_net in db.network_id(networks_name_list[0]): |
|
129 |
mngnet_id = str(uuid_net.uuid) |
|
130 |
for uuid_net in db.network_id(networks_name_list[1]): |
|
131 |
nbnet_id = str(uuid_net.uuid) |
|
132 |
for uuid_net in db.network_id(networks_name_list[2]): |
|
133 |
sbnet_id = str(uuid_net.uuid) |
|
134 |
sdb.add_services_binding(service_vm_name, mngnet_id, nbnet_id, |
|
135 |
sbnet_id) |
|
136 |
except Exception as exc: |
|
137 |
print exc |
|
138 |
||
139 |
||
140 |
def delete_service(tenant_id, service_instance_id, *args): |
|
141 |
"""
|
|
142 |
Removes a service and all the network configuration
|
|
143 |
"""
|
|
144 |
l2db.initialize() |
|
145 |
print ("Terminating Service VM") |
|
146 |
service_logic = servlogcs.ServicesLogistics() |
|
147 |
vms_list = [] |
|
148 |
vms_list.append(servconts.DELETE_VM_CMD) |
|
149 |
vms_list.append(service_instance_id) |
|
150 |
||
151 |
if not service_logic.image_exist(service_instance_id): |
|
152 |
print ("Service VM does not exist") |
|
153 |
sys.exit() |
|
154 |
||
155 |
result = subprocess.call(vms_list) |
|
156 |
service_logic.image_shutdown_verification(service_instance_id) |
|
157 |
||
158 |
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id) |
|
159 |
service_nets = sdb.get_service_bindings(service_instance_id) |
|
160 |
print ("Terminating Ports and Networks") |
|
161 |
network_name = db.network_get(service_nets.mngnet_id) |
|
162 |
port_id_net = db.port_list(service_nets.mngnet_id) |
|
163 |
for ports_uuid in port_id_net: |
|
164 |
client.delete_port(service_nets.mngnet_id, ports_uuid.uuid) |
|
165 |
client.delete_network(service_nets.mngnet_id) |
|
166 |
network_name = db.network_get(service_nets.nbnet_id) |
|
167 |
port_id_net = db.port_list(service_nets.nbnet_id) |
|
168 |
for ports_uuid in port_id_net: |
|
169 |
client.delete_port(service_nets.nbnet_id, ports_uuid.uuid) |
|
170 |
client.delete_network(service_nets.nbnet_id) |
|
171 |
network_name = db.network_get(service_nets.sbnet_id) |
|
172 |
port_id_net = db.port_list(service_nets.sbnet_id) |
|
173 |
for ports_uuid in port_id_net: |
|
174 |
client.delete_port(service_nets.sbnet_id, ports_uuid.uuid) |
|
175 |
client.delete_network(service_nets.sbnet_id) |
|
176 |
service_list = sdb.remove_services_binding(service_instance_id) |
|
177 |
print ("Configuration Removed Successfully") |
|
178 |
||
179 |
||
180 |
def disconnect_vm(vm_instance_id, *args): |
|
181 |
"""
|
|
182 |
Deletes VMs and Port connection
|
|
183 |
"""
|
|
184 |
l2db.initialize() |
|
185 |
print ("Terminating Service VM") |
|
186 |
service_logic = servlogcs.ServicesLogistics() |
|
187 |
vms_list = [] |
|
188 |
vms_list.append(servconts.DELETE_VM_CMD) |
|
189 |
vms_list.append(vm_instance_id) |
|
190 |
result = subprocess.call(vms_list) |
|
191 |
service_logic.image_shutdown_verification(vm_instance_id) |
|
192 |
print ("VM Server Off") |
|
193 |
||
194 |
||
195 |
def connect_vm(tenant_id, vm_image_id, service_instance_id, *args): |
|
196 |
"""
|
|
197 |
Starts a VMs and is connected to southbound network
|
|
198 |
"""
|
|
199 |
l2db.initialize() |
|
200 |
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id) |
|
201 |
print ("Connecting %s to Service %s " % (vm_image_id, service_instance_id)) |
|
202 |
service_logic = servlogcs.ServicesLogistics() |
|
203 |
service_nets = sdb.get_service_bindings(service_instance_id) |
|
204 |
client.create_port(service_nets.mngnet_id) |
|
205 |
client.create_port(service_nets.nbnet_id) |
|
206 |
sb_port_id = client.create_port(service_nets.sbnet_id) |
|
207 |
LOG.debug("Operation 'create_port' executed.") |
|
208 |
new_port_id = sb_port_id[servconts.PORT][servconts.ID] |
|
209 |
try: |
|
210 |
create_vm_args = [] |
|
211 |
create_vm_args.append(servconts.CREATE_VM_CMD) |
|
212 |
create_vm_args.append(vm_image_id) |
|
213 |
print ("Creating VM with image: %s" % (vm_image_id)) |
|
2.1.16
by Chuck Short
Import upstream version 2013.1~g1 |
214 |
process = utils.subprocess_popen(create_vm_args, |
215 |
stdout=subprocess.PIPE) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
216 |
result = process.stdout.readlines() |
217 |
tokens = re.search("i-[a-f0-9]*", str(result[1])) |
|
218 |
vm_name = tokens.group(0) |
|
219 |
print ("Image: %s instantiated successfully" % (vm_name)) |
|
220 |
except Exception as exc: |
|
221 |
print exc |
|
222 |
||
223 |
service_logic.image_status(vm_name) |
|
224 |
print "Completed" |
|
225 |
print "Attaching Ports To VM Service interfaces" |
|
226 |
south_net = service_nets.sbnet_id |
|
227 |
attachment = client.show_port_attachment(south_net, new_port_id) |
|
228 |
attachment = attachment[servconts.ATTACHMENT][servconts.ID][:36] |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
229 |
LOG.debug(("Plugging virtual interface: %s of VM %s " |
230 |
"into port: %s on network: %s") % |
|
231 |
(attachment, vm_name, new_port_id, service_nets.sbnet_id)) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
232 |
attach_data = {servconts.ATTACHMENT: {servconts.ID: '%s' % attachment}} |
233 |
client.attach_resource(service_nets.sbnet_id, new_port_id, attach_data) |
|
234 |
print ("Connect VM Ended") |
|
235 |
||
236 |
||
237 |
def create_multiport(tenant_id, networks_list, *args): |
|
238 |
"""Creates ports on a single host"""
|
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
239 |
ports_info = {'multiport': |
2.1.11
by Chuck Short
Import upstream version 2012.2~rc1~20120907.1154 |
240 |
{'status': constants.PORT_STATUS_ACTIVE, |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
241 |
'net_id_list': networks_list, |
242 |
'ports_desc': {'key': 'value'}}} |
|
243 |
request_url = "/multiport" |
|
244 |
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id, |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
245 |
action_prefix=servconts.ACTION_PREFIX_CSCO) |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
246 |
data = client.do_request('POST', request_url, body=ports_info) |
247 |
return data |
|
248 |
||
249 |
||
250 |
def build_args(cmd, cmdargs, arglist): |
|
251 |
"""Building the list of args for a particular CLI"""
|
|
252 |
args = [] |
|
253 |
orig_arglist = arglist[:] |
|
254 |
try: |
|
255 |
for cmdarg in cmdargs: |
|
256 |
args.append(arglist[0]) |
|
257 |
del arglist[0] |
|
258 |
except: |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
259 |
LOG.debug("Not enough arguments for \"%s\" (expected: %d, got: %d)" % |
260 |
(cmd, len(cmdargs), len(orig_arglist))) |
|
261 |
print "Service Insertion Usage:\n %s %s" % ( |
|
262 |
cmd, " ".join(["<%s>" % y for y in SERVICE_COMMANDS[cmd]["args"]])) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
263 |
sys.exit() |
264 |
if len(arglist) > 0: |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
265 |
LOG.debug("Too many arguments for \"%s\" (expected: %d, got: %d)" |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
266 |
% (cmd, len(cmdargs), len(orig_arglist))) |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
267 |
print "Service Insertion Usage:\n %s %s" % ( |
268 |
cmd, " ".join(["<%s>" % y for y in SERVICE_COMMANDS[cmd]["args"]])) |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
269 |
sys.exit() |
270 |
return args |
|
271 |
||
272 |
||
273 |
SERVICE_COMMANDS = { |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
274 |
"insert_inpath_service": { |
275 |
"func": insert_inpath_service, |
|
276 |
"args": ["tenant_id", "service_image_id", "management_net_name", |
|
277 |
"northbound_net_name", "southbound_net_name"], |
|
278 |
},
|
|
279 |
"delete_service": { |
|
280 |
"func": delete_service, |
|
281 |
"args": ["tenant_id", "service_instance_id"], |
|
282 |
},
|
|
283 |
"connect_vm": { |
|
284 |
"func": connect_vm, |
|
285 |
"args": ["tenant_id", "vm_image_id", "service_instance_id"], |
|
286 |
},
|
|
287 |
"disconnect_vm": { |
|
288 |
"func": disconnect_vm, |
|
289 |
"args": ["vm_instance_id"], |
|
290 |
},
|
|
291 |
}
|
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
292 |
|
293 |
||
294 |
if __name__ == "__main__": |
|
295 |
os.system("clear") |
|
296 |
usagestr = "Usage: %prog [OPTIONS] <command> [args]" |
|
297 |
PARSER = OptionParser(usage=usagestr) |
|
298 |
PARSER.add_option("-H", "--host", dest="host", |
|
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
299 |
type="string", default="127.0.0.1", |
300 |
help="ip address of api host") |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
301 |
PARSER.add_option("-p", "--port", dest="port", |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
302 |
type="int", default=9696, help="api port") |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
303 |
PARSER.add_option("-s", "--ssl", dest="ssl", |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
304 |
action="store_true", default=False, help="use ssl") |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
305 |
PARSER.add_option("-v", "--verbose", dest="verbose", |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
306 |
action="store_true", default=False, |
307 |
help="turn on verbose logging") |
|
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
308 |
PARSER.add_option("-f", "--logfile", dest="logfile", |
2.1.8
by Chuck Short
Import upstream version 2012.2~f2~20120621.868 |
309 |
type="string", default="syslog", help="log file path") |
2.1.2
by Chuck Short
Import upstream version 2012.1~e2 |
310 |
options, args = PARSER.parse_args() |
311 |
if options.verbose: |
|
312 |
LOG.setLevel(logging.DEBUG) |
|
313 |
else: |
|
314 |
LOG.setLevel(logging.WARN) |
|
315 |
if options.logfile == "syslog": |
|
316 |
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log')) |
|
317 |
else: |
|
318 |
LOG.addHandler(logging.handlers.WatchedFileHandler(options.logfile)) |
|
319 |
os.chmod(options.logfile, 0644) |
|
320 |
service_logic = servlogcs.ServicesLogistics() |
|
321 |
HOST = options.host |
|
322 |
PORT = options.port |
|
323 |
USE_SSL = options.ssl |
|
324 |
CMD = args[0] |
|
325 |
args = build_args(CMD, SERVICE_COMMANDS[CMD]["args"], args[1:]) |
|
326 |
SERVICE_COMMANDS[CMD]["func"](*args) |
|
327 |
sys.exit(0) |