Merge lp:~danwent/neutron/ovs-plugin-fixes into lp:neutron/diablo

Proposed by dan wendlandt
Status: Merged
Merge reported by: Somik Behera
Merged at revision: not available
Proposed branch: lp:~danwent/neutron/ovs-plugin-fixes
Merge into: lp:neutron/diablo
Diff against target: 547 lines (+239/-110)
10 files modified
quantum/cli.py (+3/-1)
quantum/db/api.py (+10/-9)
quantum/plugins/openvswitch/README (+7/-2)
quantum/plugins/openvswitch/agent/ovs_quantum_agent.py (+42/-43)
quantum/plugins/openvswitch/agent/set_external_ids.sh (+0/-15)
quantum/plugins/openvswitch/ovs_db.py (+0/-18)
quantum/plugins/openvswitch/ovs_models.py (+0/-17)
quantum/plugins/openvswitch/ovs_quantum_plugin.ini (+3/-3)
quantum/plugins/openvswitch/ovs_quantum_plugin.py (+0/-2)
tools/batch_config.py (+174/-0)
To merge this branch: bzr merge lp:~danwent/neutron/ovs-plugin-fixes
Reviewer Review Type Date Requested Status
Somik Behera netstack-core Approve
Brad Hall (community) Approve
Review via email: mp+66024@code.launchpad.net

Description of the change

This branch started out just aiming to tweak the OVS plugin so it could run on hypervisors other than XenServer. In the course, I fixed a couple of bugs in the OVS plugin and in the DB models created for the OVS plugin.

I also introduced a new tool called "batch_config.py" that simplifies testing by making it easy to create network topologies using a single CLI command, instead of copying and pasting UUIDs from individual calls.

Other than batch_config.py, there should be no new functionality, only fixes.

This code has been pretty heavily tested with libvirt, and Brad has tested it with XenServer.

To post a comment you must log in.
Revision history for this message
dan wendlandt (danwent) wrote :

One comment, you will notice a change that makes it permissible for multiple ports to have the empty string as an attachment. This was because the CLI actually performs an unplug using the empty string:

def api_unplug_iface(client, *args):
    tid, nid, pid = args
    data = {'port': {'attachment-id': ''}}

However, I actually think it would be cleaner if this happened by setting attachment-id to a null/none value. We should check with Salvatore on this.

Revision history for this message
Brad Hall (bgh) wrote :

Looks good to me.

review: Approve
Revision history for this message
Somik Behera (somikbehera) wrote :

1) There is 1 pep8 violation, trunk is pep8 clean, so we should make sure to get this merge cleaned up too.

./quantum/cli.py:322:80: E501 line too long (80 characters)

2) quantum/cli.py should raise an exception when it cant set attachement

except exc.NoResultFound:
         pass

But, this bug was pre-existing, I'll file something for this.

3) Otherwise, everything looks good! If you can just fix the pep8 change, we can get this bug fix merged in!

review: Needs Fixing (netstack-core)
lp:~danwent/neutron/ovs-plugin-fixes updated
23. By dan wendlandt

fix pep8 introduced by trunk merge

Revision history for this message
Somik Behera (somikbehera) wrote :

Thanks for fixing that pep8 change that had slipped in!

Got to keep the trunk pep8 clean.

review: Approve (netstack-core)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'quantum/cli.py'
2--- quantum/cli.py 2011-06-24 18:20:03 +0000
3+++ quantum/cli.py 2011-06-27 23:11:53 +0000
4@@ -240,6 +240,7 @@
5
6 def delete_port(manager, *args):
7 tid, nid, pid = args
8+ manager.delete_port(tid, nid, pid)
9 LOG.info("Deleted Virtual Port:%s " \
10 "on Virtual Network:%s" % (pid, nid))
11
12@@ -318,7 +319,8 @@
13 output = res.read()
14 LOG.debug(output)
15 if res.status != 202:
16- LOG.error("Failed to unplug iface from port \"%s\": %s" % (pid, output))
17+ LOG.error("Failed to unplug iface from port \"%s\": %s" % \
18+ (pid, output))
19 return
20 print "Unplugged interface from port:%s on network:%s" % (pid, nid)
21
22
23=== modified file 'quantum/db/api.py'
24--- quantum/db/api.py 2011-06-08 10:21:47 +0000
25+++ quantum/db/api.py 2011-06-27 23:11:53 +0000
26@@ -72,7 +72,7 @@
27 net = None
28 try:
29 net = session.query(models.Network).\
30- filter_by(name=name).\
31+ filter_by(tenant_id=tenant_id, name=name).\
32 one()
33 raise Exception("Network with name \"%s\" already exists" % name)
34 except exc.NoResultFound:
35@@ -104,7 +104,7 @@
36 session = get_session()
37 try:
38 res = session.query(models.Network).\
39- filter_by(name=new_name).\
40+ filter_by(tenant_id=tenant_id, name=new_name).\
41 one()
42 except exc.NoResultFound:
43 net = network_get(net_id)
44@@ -156,13 +156,14 @@
45
46 def port_set_attachment(port_id, new_interface_id):
47 session = get_session()
48- ports = None
49- try:
50- ports = session.query(models.Port).\
51- filter_by(interface_id=new_interface_id).\
52- all()
53- except exc.NoResultFound:
54- pass
55+ ports = []
56+ if new_interface_id != "":
57+ try:
58+ ports = session.query(models.Port).\
59+ filter_by(interface_id=new_interface_id).\
60+ all()
61+ except exc.NoResultFound:
62+ pass
63 if len(ports) == 0:
64 port = port_get(port_id)
65 port.interface_id = new_interface_id
66
67=== modified file 'quantum/plugins/openvswitch/README'
68--- quantum/plugins/openvswitch/README 2011-06-09 14:42:19 +0000
69+++ quantum/plugins/openvswitch/README 2011-06-27 23:11:53 +0000
70@@ -62,20 +62,25 @@
71 distribution tarball (see below) and the agent will use the credentials here
72 to access the database.
73
74-# -- Agent configuration
75+# -- XenServer Agent configuration
76
77 - Create the agent distribution tarball
78
79 $ make agent-dist
80 - Copy the resulting tarball to your xenserver(s) (copy to dom0, not the nova
81 compute node)
82-- Unpack the tarball and run install.sh. This will install all of the
83+- Unpack the tarball and run xenserver_install.sh. This will install all of the
84 necessary pieces into /etc/xapi.d/plugins. It will also spit out the name
85 of the integration bridge that you'll need for your nova configuration.
86 Make sure to specify this in your nova flagfile as --flat_network_bridge.
87 - Run the agent [on your hypervisor (dom0)]:
88 $ /etc/xapi.d/plugins/ovs_quantum_agent.py /etc/xapi.d/plugins/ovs_quantum_plugin.ini
89
90+# -- KVM Agent configuration
91+
92+- Copy ovs_quantum_agent.py and ovs_quantum_plugin.ini to the Linux host and run:
93+$ python ovs_quantum_agent.py ovs_quantum_plugin.ini
94+
95 # -- Getting quantum up and running
96
97 - Start quantum [on the quantum service host]:
98
99=== modified file 'quantum/plugins/openvswitch/agent/ovs_quantum_agent.py'
100--- quantum/plugins/openvswitch/agent/ovs_quantum_agent.py 2011-06-08 10:21:47 +0000
101+++ quantum/plugins/openvswitch/agent/ovs_quantum_agent.py 2011-06-27 23:11:53 +0000
102@@ -130,40 +130,40 @@
103 def get_port_stats(self, port_name):
104 return self.db_get_map("Interface", port_name, "statistics")
105
106+ # this is a hack that should go away once nova properly reports bindings
107+ # to quantum. We have this here for now as it lets us work with
108+ # unmodified nova
109+ def xapi_get_port(self, name):
110+ external_ids = self.db_get_map("Interface", name, "external_ids")
111+ if "attached-mac" not in external_ids:
112+ return None
113+ vm_uuid = external_ids.get("xs-vm-uuid", "")
114+ if len(vm_uuid) == 0:
115+ return None
116+ LOG.debug("iface-id not set, got xs-vm-uuid: %s" % vm_uuid)
117+ res = os.popen("xe vm-list uuid=%s params=name-label --minimal" \
118+ % vm_uuid).readline().strip()
119+ if len(res) == 0:
120+ return None
121+ external_ids["iface-id"] = res
122+ LOG.info("Setting interface \"%s\" iface-id to \"%s\"" % (name, res))
123+ self.set_db_attribute("Interface", name,
124+ "external-ids:iface-id", res)
125+ ofport = self.db_get_val("Interface", name, "ofport")
126+ return VifPort(name, ofport, external_ids["iface-id"],
127+ external_ids["attached-mac"], self)
128+
129 # returns a VIF object for each VIF port
130 def get_vif_ports(self):
131 edge_ports = []
132 port_names = self.get_port_name_list()
133 for name in port_names:
134 external_ids = self.db_get_map("Interface", name, "external_ids")
135- if "iface-id" in external_ids and "attached-mac" in external_ids:
136- ofport = self.db_get_val("Interface", name, "ofport")
137- p = VifPort(name, ofport, external_ids["iface-id"],
138- external_ids["attached-mac"], self)
139- edge_ports.append(p)
140- else:
141- # iface-id might not be set. See if we can figure it out and
142- # set it here.
143- external_ids = self.db_get_map("Interface", name,
144- "external_ids")
145- if "attached-mac" not in external_ids:
146- continue
147- vif_uuid = external_ids.get("xs-vif-uuid", "")
148- if len(vif_uuid) == 0:
149- continue
150- LOG.debug("iface-id not set, got vif-uuid: %s" % vif_uuid)
151- res = os.popen("xe vif-param-get param-name=other-config "
152- "uuid=%s | grep nicira-iface-id | "
153- "awk '{print $2}'"
154- % vif_uuid).readline()
155- res = res.strip()
156- if len(res) == 0:
157- continue
158- external_ids["iface-id"] = res
159- LOG.info("Setting interface \"%s\" iface-id to \"%s\""
160- % (name, res))
161- self.set_db_attribute("Interface", name,
162- "external-ids:iface-id", res)
163+ if "xs-vm-uuid" in external_ids:
164+ p = xapi_get_port(name)
165+ if p is not None:
166+ edge_ports.append(p)
167+ elif "iface-id" in external_ids and "attached-mac" in external_ids:
168 ofport = self.db_get_val("Interface", name, "ofport")
169 p = VifPort(name, ofport, external_ids["iface-id"],
170 external_ids["attached-mac"], self)
171@@ -171,13 +171,15 @@
172 return edge_ports
173
174
175-class OVSNaaSPlugin:
176+class OVSQuantumAgent:
177+
178 def __init__(self, integ_br):
179 self.setup_integration_br(integ_br)
180
181 def port_bound(self, port, vlan_id):
182 self.int_br.set_db_attribute("Port", port.port_name, "tag",
183- str(vlan_id))
184+ str(vlan_id))
185+ self.int_br.delete_flows(match="in_port=%s" % port.ofport)
186
187 def port_unbound(self, port, still_exists):
188 if still_exists:
189@@ -186,13 +188,8 @@
190 def setup_integration_br(self, integ_br):
191 self.int_br = OVSBridge(integ_br)
192 self.int_br.remove_all_flows()
193- # drop all traffic on the 'dead vlan'
194- self.int_br.add_flow(priority=2, match="dl_vlan=4095", actions="drop")
195- # switch all other traffic using L2 learning
196+ # switch all traffic using L2 learning
197 self.int_br.add_flow(priority=1, actions="normal")
198- # FIXME send broadcast everywhere, regardless of tenant
199- #int_br.add_flow(priority=3, match="dl_dst=ff:ff:ff:ff:ff:ff",
200- # actions="normal")
201
202 def daemon_loop(self, conn):
203 self.local_vlan_map = {}
204@@ -201,7 +198,7 @@
205
206 while True:
207 cursor = conn.cursor()
208- cursor.execute("SELECT * FROM network_bindings")
209+ cursor.execute("SELECT * FROM ports")
210 rows = cursor.fetchall()
211 cursor.close()
212 all_bindings = {}
213@@ -226,22 +223,26 @@
214 else:
215 # no binding, put him on the 'dead vlan'
216 self.int_br.set_db_attribute("Port", p.port_name, "tag",
217- "4095")
218+ "4095")
219+ self.int_br.add_flow(priority=2,
220+ match="in_port=%s" % p.ofport, actions="drop")
221+
222 old_b = old_local_bindings.get(p.vif_id, None)
223 new_b = new_local_bindings.get(p.vif_id, None)
224+
225 if old_b != new_b:
226 if old_b is not None:
227 LOG.info("Removing binding to net-id = %s for %s"
228 % (old_b, str(p)))
229 self.port_unbound(p, True)
230 if new_b is not None:
231- LOG.info("Adding binding to net-id = %s for %s" \
232- % (new_b, str(p)))
233 # If we don't have a binding we have to stick it on
234 # the dead vlan
235 vlan_id = vlan_bindings.get(all_bindings[p.vif_id],
236 "4095")
237 self.port_bound(p, vlan_id)
238+ LOG.info("Adding binding to net-id = %s " \
239+ "for %s on vlan %s" % (new_b, str(p), vlan_id))
240 for vif_id in old_vif_ports.keys():
241 if vif_id not in new_vif_ports:
242 LOG.info("Port Disappeared: %s" % vif_id)
243@@ -251,8 +252,6 @@
244
245 old_vif_ports = new_vif_ports
246 old_local_bindings = new_local_bindings
247- self.int_br.run_cmd(["bash",
248- "/etc/xapi.d/plugins/set_external_ids.sh"])
249 time.sleep(2)
250
251 if __name__ == "__main__":
252@@ -291,7 +290,7 @@
253 LOG.info("Connecting to database \"%s\" on %s" % (db_name, db_host))
254 conn = MySQLdb.connect(host=db_host, user=db_user,
255 passwd=db_pass, db=db_name)
256- plugin = OVSNaaSPlugin(integ_br)
257+ plugin = OVSQuantumAgent(integ_br)
258 plugin.daemon_loop(conn)
259 finally:
260 if conn:
261
262=== removed file 'quantum/plugins/openvswitch/agent/set_external_ids.sh'
263--- quantum/plugins/openvswitch/agent/set_external_ids.sh 2011-06-04 03:59:49 +0000
264+++ quantum/plugins/openvswitch/agent/set_external_ids.sh 1970-01-01 00:00:00 +0000
265@@ -1,15 +0,0 @@
266-#!/bin/sh
267-VIFLIST=`xe vif-list params=uuid --minimal | sed s/,/" "/g`
268-for VIF_UUID in $VIFLIST; do
269-DEVICE_NUM=`xe vif-list params=device uuid=$VIF_UUID --minimal`
270- VM_NAME=`xe vif-list params=vm-name-label uuid=$VIF_UUID --minimal`
271- NAME="$VM_NAME-eth$DEVICE_NUM"
272- echo "Vif: $VIF_UUID is '$NAME'"
273- xe vif-param-set uuid=$VIF_UUID other-config:nicira-iface-id="$NAME"
274-done
275-
276-ps auxw | grep -v grep | grep ovs-xapi-sync > /dev/null 2>&1
277-if [ $? -eq 0 ]; then
278- killall -HUP ovs-xapi-sync
279-fi
280-
281
282=== renamed file 'quantum/plugins/openvswitch/agent/install.sh' => 'quantum/plugins/openvswitch/agent/xenserver_install.sh'
283=== modified file 'quantum/plugins/openvswitch/ovs_db.py'
284--- quantum/plugins/openvswitch/ovs_db.py 2011-06-08 10:21:47 +0000
285+++ quantum/plugins/openvswitch/ovs_db.py 2011-06-27 23:11:53 +0000
286@@ -56,21 +56,3 @@
287 except exc.NoResultFound:
288 pass
289 session.flush()
290-
291-
292-def update_network_binding(netid, ifaceid):
293- session = db.get_session()
294- # Add to or delete from the bindings table
295- if ifaceid == None:
296- try:
297- binding = session.query(ovs_models.NetworkBinding).\
298- filter_by(network_id=netid).\
299- one()
300- session.delete(binding)
301- except exc.NoResultFound:
302- raise Exception("No binding found with network_id = %s" % netid)
303- else:
304- binding = ovs_models.NetworkBinding(netid, ifaceid)
305- session.add(binding)
306-
307- session.flush()
308
309=== modified file 'quantum/plugins/openvswitch/ovs_models.py'
310--- quantum/plugins/openvswitch/ovs_models.py 2011-06-08 10:21:47 +0000
311+++ quantum/plugins/openvswitch/ovs_models.py 2011-06-27 23:11:53 +0000
312@@ -26,23 +26,6 @@
313 from quantum.db.models import BASE
314
315
316-class NetworkBinding(BASE):
317- """Represents a binding of network_id, vif_id"""
318- __tablename__ = 'network_bindings'
319-
320- id = Column(Integer, primary_key=True, autoincrement=True)
321- network_id = Column(String(255))
322- vif_id = Column(String(255))
323-
324- def __init__(self, network_id, vif_id):
325- self.network_id = network_id
326- self.vif_id = vif_id
327-
328- def __repr__(self):
329- return "<NetworkBinding(%s,%s)>" % \
330- (self.network_id, self.vif_id)
331-
332-
333 class VlanBinding(BASE):
334 """Represents a binding of network_id, vlan_id"""
335 __tablename__ = 'vlan_bindings'
336
337=== modified file 'quantum/plugins/openvswitch/ovs_quantum_plugin.ini'
338--- quantum/plugins/openvswitch/ovs_quantum_plugin.ini 2011-06-04 03:56:32 +0000
339+++ quantum/plugins/openvswitch/ovs_quantum_plugin.ini 2011-06-27 23:11:53 +0000
340@@ -1,9 +1,9 @@
341 [DATABASE]
342-name = ovs_naas
343+name = ovs_quantum
344 user = root
345-pass = foobar
346+pass = nova
347 host = 127.0.0.1
348 port = 3306
349
350 [OVS]
351-integration-bridge = xapi1
352+integration-bridge = br100
353
354=== modified file 'quantum/plugins/openvswitch/ovs_quantum_plugin.py'
355--- quantum/plugins/openvswitch/ovs_quantum_plugin.py 2011-06-08 10:21:47 +0000
356+++ quantum/plugins/openvswitch/ovs_quantum_plugin.py 2011-06-27 23:11:53 +0000
357@@ -200,11 +200,9 @@
358
359 def plug_interface(self, tenant_id, net_id, port_id, remote_iface_id):
360 db.port_set_attachment(port_id, remote_iface_id)
361- ovs_db.update_network_binding(net_id, remote_iface_id)
362
363 def unplug_interface(self, tenant_id, net_id, port_id):
364 db.port_set_attachment(port_id, "")
365- ovs_db.update_network_binding(net_id, None)
366
367 def get_interface_details(self, tenant_id, net_id, port_id):
368 res = db.port_get(port_id)
369
370=== added file 'tools/batch_config.py'
371--- tools/batch_config.py 1970-01-01 00:00:00 +0000
372+++ tools/batch_config.py 2011-06-27 23:11:53 +0000
373@@ -0,0 +1,174 @@
374+# vim: tabstop=4 shiftwidth=4 softtabstop=4
375+
376+# Copyright 2011 Nicira Networks, Inc.
377+#
378+# Licensed under the Apache License, Version 2.0 (the "License"); you may
379+# not use this file except in compliance with the License. You may obtain
380+# a copy of the License at
381+#
382+# http://www.apache.org/licenses/LICENSE-2.0
383+#
384+# Unless required by applicable law or agreed to in writing, software
385+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
386+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
387+# License for the specific language governing permissions and limitations
388+# under the License.
389+# @author: Dan Wendlandt, Nicira Networks, Inc.
390+
391+import httplib
392+import logging as LOG
393+import json
394+import socket
395+import sys
396+import urllib
397+
398+from quantum.manager import QuantumManager
399+from optparse import OptionParser
400+from quantum.common.wsgi import Serializer
401+from quantum.cli import MiniClient
402+
403+FORMAT = "json"
404+CONTENT_TYPE = "application/" + FORMAT
405+
406+
407+def delete_all_nets(client, tenant_id):
408+ res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT)
409+ resdict = json.loads(res.read())
410+ LOG.debug(resdict)
411+ for n in resdict["networks"]:
412+ nid = n["id"]
413+
414+ res = client.do_request(tenant_id, 'GET',
415+ "/networks/%s/ports.%s" % (nid, FORMAT))
416+ output = res.read()
417+ if res.status != 200:
418+ LOG.error("Failed to list ports: %s" % output)
419+ continue
420+ rd = json.loads(output)
421+ LOG.debug(rd)
422+ for port in rd["ports"]:
423+ pid = port["id"]
424+
425+ data = {'port': {'attachment-id': ''}}
426+ body = Serializer().serialize(data, CONTENT_TYPE)
427+ res = client.do_request(tenant_id, 'DELETE',
428+ "/networks/%s/ports/%s/attachment.%s" % \
429+ (nid, pid, FORMAT), body=body)
430+ output = res.read()
431+ LOG.debug(output)
432+ if res.status != 202:
433+ LOG.error("Failed to unplug iface from port \"%s\": %s" % (vid,
434+ pid, output))
435+ continue
436+ LOG.info("Unplugged interface from port:%s on network:%s" % (pid,
437+ nid))
438+
439+ res = client.do_request(tenant_id, 'DELETE',
440+ "/networks/%s/ports/%s.%s" % (nid, pid, FORMAT))
441+ output = res.read()
442+ if res.status != 202:
443+ LOG.error("Failed to delete port: %s" % output)
444+ continue
445+ print "Deleted Virtual Port:%s " \
446+ "on Virtual Network:%s" % (pid, nid)
447+
448+ res = client.do_request(tenant_id, 'DELETE',
449+ "/networks/" + nid + "." + FORMAT)
450+ status = res.status
451+ if status != 202:
452+ Log.error("Failed to delete network: %s" % nid)
453+ output = res.read()
454+ print output
455+ else:
456+ print "Deleted Virtual Network with ID:%s" % nid
457+
458+
459+def create_net_with_attachments(net_name, iface_ids):
460+ data = {'network': {'network-name': '%s' % net_name}}
461+ body = Serializer().serialize(data, CONTENT_TYPE)
462+ res = client.do_request(tenant_id, 'POST',
463+ "/networks." + FORMAT, body=body)
464+ rd = json.loads(res.read())
465+ LOG.debug(rd)
466+ nid = rd["networks"]["network"]["id"]
467+ print "Created a new Virtual Network %s with ID:%s" % (net_name, nid)
468+
469+ for iface_id in iface_ids:
470+ res = client.do_request(tenant_id, 'POST',
471+ "/networks/%s/ports.%s" % (nid, FORMAT))
472+ output = res.read()
473+ if res.status != 200:
474+ LOG.error("Failed to create port: %s" % output)
475+ continue
476+ rd = json.loads(output)
477+ new_port_id = rd["ports"]["port"]["id"]
478+ print "Created Virtual Port:%s " \
479+ "on Virtual Network:%s" % (new_port_id, nid)
480+ data = {'port': {'attachment-id': '%s' % iface_id}}
481+ body = Serializer().serialize(data, CONTENT_TYPE)
482+ res = client.do_request(tenant_id, 'PUT',
483+ "/networks/%s/ports/%s/attachment.%s" %\
484+ (nid, new_port_id, FORMAT), body=body)
485+ output = res.read()
486+ LOG.debug(output)
487+ if res.status != 202:
488+ LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % \
489+ (iface_id, new_port_id, output))
490+ continue
491+ print "Plugged interface \"%s\" to port:%s on network:%s" % \
492+ (iface_id, new_port_id, nid)
493+
494+if __name__ == "__main__":
495+ usagestr = "Usage: %prog [OPTIONS] <tenant-id> <config-string> [args]\n" \
496+ "Example config-string: net1=instance-1,instance-2"\
497+ ":net2=instance-3,instance-4\n" \
498+ "This string would create two networks: \n" \
499+ "'net1' would have two ports, with iface-ids "\
500+ "instance-1 and instance-2 attached\n" \
501+ "'net2' would have two ports, with iface-ids"\
502+ " instance-3 and instance-4 attached\n"
503+ parser = OptionParser(usage=usagestr)
504+ parser.add_option("-H", "--host", dest="host",
505+ type="string", default="127.0.0.1", help="ip address of api host")
506+ parser.add_option("-p", "--port", dest="port",
507+ type="int", default=9696, help="api poort")
508+ parser.add_option("-s", "--ssl", dest="ssl",
509+ action="store_true", default=False, help="use ssl")
510+ parser.add_option("-v", "--verbose", dest="verbose",
511+ action="store_true", default=False, help="turn on verbose logging")
512+ parser.add_option("-d", "--delete", dest="delete",
513+ action="store_true", default=False, \
514+ help="delete existing tenants networks")
515+
516+ options, args = parser.parse_args()
517+
518+ if options.verbose:
519+ LOG.basicConfig(level=LOG.DEBUG)
520+ else:
521+ LOG.basicConfig(level=LOG.WARN)
522+
523+ if len(args) < 1:
524+ parser.print_help()
525+ help()
526+ sys.exit(1)
527+
528+ nets = {}
529+ tenant_id = args[0]
530+ if len(args) > 1:
531+ config_str = args[1]
532+ for net_str in config_str.split(":"):
533+ arr = net_str.split("=")
534+ net_name = arr[0]
535+ nets[net_name] = arr[1].split(",")
536+
537+ print "nets: %s" % str(nets)
538+
539+ client = MiniClient(options.host, options.port, options.ssl)
540+
541+ if options.delete:
542+ delete_all_nets(client, tenant_id)
543+
544+ for net_name, iface_ids in nets.items():
545+ create_net_with_attachments(net_name, iface_ids)
546+
547+ sys.exit(0)

Subscribers

People subscribed via source and target branches