Merged from quantum trunk

This commit is contained in:
Deepak N 2011-07-18 16:19:11 +05:30
commit cba26a3e7e
16 changed files with 267 additions and 145 deletions

View File

@ -24,6 +24,7 @@ import routes
import webob.dec
import webob.exc
from quantum import manager
from quantum.api import faults
from quantum.api import networks
from quantum.api import ports
@ -46,32 +47,32 @@ class APIRouterV01(wsgi.Router):
super(APIRouterV01, self).__init__(mapper)
def _setup_routes(self, mapper):
# Loads the quantum plugin
plugin = manager.QuantumManager().get_plugin()
uri_prefix = '/tenants/{tenant_id}/'
mapper.resource('network', 'networks',
controller=networks.Controller(),
controller=networks.Controller(plugin),
path_prefix=uri_prefix)
mapper.resource('port', 'ports',
controller=ports.Controller(),
controller=ports.Controller(plugin),
parent_resource=dict(member_name='network',
collection_name=uri_prefix +\
'networks'))
mapper.connect("get_resource",
uri_prefix + 'networks/{network_id}/' \
'ports/{id}/attachment{.format}',
controller=ports.Controller(),
controller=ports.Controller(plugin),
action="get_resource",
conditions=dict(method=['GET']))
mapper.connect("attach_resource",
uri_prefix + 'networks/{network_id}/' \
'ports/{id}/attachment{.format}',
controller=ports.Controller(),
controller=ports.Controller(plugin),
action="attach_resource",
conditions=dict(method=['PUT']))
mapper.connect("detach_resource",
uri_prefix + 'networks/{network_id}/' \
'ports/{id}/attachment{.format}',
controller=ports.Controller(),
controller=ports.Controller(plugin),
action="detach_resource",
conditions=dict(method=['DELETE']))

View File

@ -19,7 +19,6 @@ import logging
from webob import exc
from quantum import manager
from quantum.common import wsgi
XML_NS_V01 = 'http://netstack.org/quantum/api/v0.1'
@ -30,8 +29,8 @@ LOG = logging.getLogger('quantum.api.api_common')
class QuantumController(wsgi.Controller):
""" Base controller class for Quantum API """
def __init__(self, plugin_conf_file=None):
self._setup_network_manager()
def __init__(self, plugin):
self._plugin = plugin
super(QuantumController, self).__init__()
def _parse_request_params(self, req, params):
@ -65,6 +64,3 @@ class QuantumController(wsgi.Controller):
raise exc.HTTPBadRequest(msg)
results[param_name] = param_value or param.get('default-value')
return results
def _setup_network_manager(self):
self.network_manager = manager.QuantumManager().get_manager()

View File

@ -40,9 +40,9 @@ class Controller(common.QuantumController):
},
}
def __init__(self, plugin_conf_file=None):
def __init__(self, plugin):
self._resource_name = 'network'
super(Controller, self).__init__()
super(Controller, self).__init__(plugin)
def index(self, request, tenant_id):
""" Returns a list of network ids """
@ -51,7 +51,7 @@ class Controller(common.QuantumController):
def _items(self, request, tenant_id, is_detail):
""" Returns a list of networks. """
networks = self.network_manager.get_all_networks(tenant_id)
networks = self._plugin.get_all_networks(tenant_id)
builder = networks_view.get_view_builder(request)
result = [builder.build(network, is_detail)['network']
for network in networks]
@ -60,7 +60,7 @@ class Controller(common.QuantumController):
def show(self, request, tenant_id, id):
""" Returns network details for the given network id """
try:
network = self.network_manager.get_network_details(
network = self._plugin.get_network_details(
tenant_id, id)
builder = networks_view.get_view_builder(request)
#build response with details
@ -78,7 +78,7 @@ class Controller(common.QuantumController):
self._network_ops_param_list)
except exc.HTTPError as e:
return faults.Fault(e)
network = self.network_manager.\
network = self._plugin.\
create_network(tenant_id,
request_params['network-name'])
builder = networks_view.get_view_builder(request)
@ -94,7 +94,7 @@ class Controller(common.QuantumController):
except exc.HTTPError as e:
return faults.Fault(e)
try:
network = self.network_manager.rename_network(tenant_id,
network = self._plugin.rename_network(tenant_id,
id, request_params['network-name'])
builder = networks_view.get_view_builder(request)
@ -106,7 +106,7 @@ class Controller(common.QuantumController):
def delete(self, request, tenant_id, id):
""" Destroys the network with the given id """
try:
self.network_manager.delete_network(tenant_id, id)
self._plugin.delete_network(tenant_id, id)
return exc.HTTPAccepted()
except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e))

View File

@ -42,9 +42,9 @@ class Controller(common.QuantumController):
"attributes": {
"port": ["id", "state"], }, }, }
def __init__(self, plugin_conf_file=None):
def __init__(self, plugin):
self._resource_name = 'port'
super(Controller, self).__init__()
super(Controller, self).__init__(plugin)
def index(self, request, tenant_id, network_id):
""" Returns a list of port ids for a given network """
@ -53,7 +53,7 @@ class Controller(common.QuantumController):
def _items(self, request, tenant_id, network_id, is_detail):
""" Returns a list of networks. """
try:
ports = self.network_manager.get_all_ports(tenant_id, network_id)
ports = self._plugin.get_all_ports(tenant_id, network_id)
builder = ports_view.get_view_builder(request)
result = [builder.build(port, is_detail)['port']
for port in ports]
@ -64,7 +64,7 @@ class Controller(common.QuantumController):
def show(self, request, tenant_id, network_id, id):
""" Returns port details for given port and network """
try:
port = self.network_manager.get_port_details(
port = self._plugin.get_port_details(
tenant_id, network_id, id)
builder = ports_view.get_view_builder(request)
#build response with details
@ -84,7 +84,7 @@ class Controller(common.QuantumController):
except exc.HTTPError as e:
return faults.Fault(e)
try:
port = self.network_manager.create_port(tenant_id,
port = self._plugin.create_port(tenant_id,
network_id,
request_params['port-state'])
builder = ports_view.get_view_builder(request)
@ -104,7 +104,7 @@ class Controller(common.QuantumController):
except exc.HTTPError as e:
return faults.Fault(e)
try:
port = self.network_manager.update_port(tenant_id, network_id, id,
port = self._plugin.update_port(tenant_id, network_id, id,
request_params['port-state'])
builder = ports_view.get_view_builder(request)
result = builder.build(port, True)
@ -120,7 +120,7 @@ class Controller(common.QuantumController):
""" Destroys the port with the given id """
#look for port state in request
try:
self.network_manager.delete_port(tenant_id, network_id, id)
self._plugin.delete_port(tenant_id, network_id, id)
return exc.HTTPAccepted()
#TODO(salvatore-orlando): Handle portInUse error
except exception.NetworkNotFound as e:
@ -132,7 +132,7 @@ class Controller(common.QuantumController):
def get_resource(self, request, tenant_id, network_id, id):
try:
result = self.network_manager.get_interface_details(
result = self._plugin.get_interface_details(
tenant_id, network_id, id)
return dict(attachment=result)
except exception.NetworkNotFound as e:
@ -151,7 +151,7 @@ class Controller(common.QuantumController):
except exc.HTTPError as e:
return faults.Fault(e)
try:
self.network_manager.plug_interface(tenant_id,
self._plugin.plug_interface(tenant_id,
network_id, id,
request_params['attachment-id'])
return exc.HTTPAccepted()
@ -167,7 +167,7 @@ class Controller(common.QuantumController):
#TODO - Complete implementation of these APIs
def detach_resource(self, request, tenant_id, network_id, id):
try:
self.network_manager.unplug_interface(tenant_id,
self._plugin.unplug_interface(tenant_id,
network_id, id)
return exc.HTTPAccepted()
except exception.NetworkNotFound as e:

View File

@ -240,6 +240,7 @@ def api_create_port(client, *args):
def delete_port(manager, *args):
tid, nid, pid = args
manager.delete_port(tid, nid, pid)
LOG.info("Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid))
@ -318,8 +319,8 @@ def api_unplug_iface(client, *args):
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to unplug iface from port \"%s\": %s" % (vid,
pid, output))
LOG.error("Failed to unplug iface from port \"%s\": %s" % \
(pid, output))
return
print "Unplugged interface from port:%s on network:%s" % (pid, nid)

View File

@ -72,7 +72,7 @@ def network_create(tenant_id, name):
net = None
try:
net = session.query(models.Network).\
filter_by(name=name).\
filter_by(tenant_id=tenant_id, name=name).\
one()
raise Exception("Network with name \"%s\" already exists" % name)
except exc.NoResultFound:
@ -104,7 +104,7 @@ def network_rename(net_id, tenant_id, new_name):
session = get_session()
try:
res = session.query(models.Network).\
filter_by(name=new_name).\
filter_by(tenant_id=tenant_id, name=new_name).\
one()
except exc.NoResultFound:
net = network_get(net_id)
@ -156,13 +156,14 @@ def port_get(port_id):
def port_set_attachment(port_id, new_interface_id):
session = get_session()
ports = None
try:
ports = session.query(models.Port).\
filter_by(interface_id=new_interface_id).\
all()
except exc.NoResultFound:
pass
ports = []
if new_interface_id != "":
try:
ports = session.query(models.Port).\
filter_by(interface_id=new_interface_id).\
all()
except exc.NoResultFound:
pass
if len(ports) == 0:
port = port_get(port_id)
port.interface_id = new_interface_id

View File

@ -29,8 +29,6 @@ import os
import logging
gettext.install('quantum', unicode=1)
import os
from common import utils
from quantum_plugin_base import QuantumPluginBase
@ -53,7 +51,6 @@ class QuantumManager(object):
else:
self.configuration_file = config
plugin_location = utils.getPluginFromConfig(self.configuration_file)
LOG.debug("PLUGIN LOCATION:%s" % plugin_location)
plugin_klass = utils.import_class(plugin_location)
if not issubclass(plugin_klass, QuantumPluginBase):
raise Exception("Configured Quantum plug-in " \
@ -63,5 +60,5 @@ class QuantumManager(object):
"All compatibility tests passed\n")
self.plugin = plugin_klass()
def get_manager(self):
def get_plugin(self):
return self.plugin

View File

@ -62,20 +62,25 @@ mysql> FLUSH PRIVILEGES;
distribution tarball (see below) and the agent will use the credentials here
to access the database.
# -- Agent configuration
# -- XenServer Agent configuration
- Create the agent distribution tarball
$ make agent-dist
- Copy the resulting tarball to your xenserver(s) (copy to dom0, not the nova
compute node)
- Unpack the tarball and run install.sh. This will install all of the
- Unpack the tarball and run xenserver_install.sh. This will install all of the
necessary pieces into /etc/xapi.d/plugins. It will also spit out the name
of the integration bridge that you'll need for your nova configuration.
Make sure to specify this in your nova flagfile as --flat_network_bridge.
- Run the agent [on your hypervisor (dom0)]:
$ /etc/xapi.d/plugins/ovs_quantum_agent.py /etc/xapi.d/plugins/ovs_quantum_plugin.ini
# -- KVM Agent configuration
- Copy ovs_quantum_agent.py and ovs_quantum_plugin.ini to the Linux host and run:
$ python ovs_quantum_agent.py ovs_quantum_plugin.ini
# -- Getting quantum up and running
- Start quantum [on the quantum service host]:

View File

@ -130,40 +130,40 @@ class OVSBridge:
def get_port_stats(self, port_name):
return self.db_get_map("Interface", port_name, "statistics")
# this is a hack that should go away once nova properly reports bindings
# to quantum. We have this here for now as it lets us work with
# unmodified nova
def xapi_get_port(self, name):
external_ids = self.db_get_map("Interface", name, "external_ids")
if "attached-mac" not in external_ids:
return None
vm_uuid = external_ids.get("xs-vm-uuid", "")
if len(vm_uuid) == 0:
return None
LOG.debug("iface-id not set, got xs-vm-uuid: %s" % vm_uuid)
res = os.popen("xe vm-list uuid=%s params=name-label --minimal" \
% vm_uuid).readline().strip()
if len(res) == 0:
return None
external_ids["iface-id"] = res
LOG.info("Setting interface \"%s\" iface-id to \"%s\"" % (name, res))
self.set_db_attribute("Interface", name,
"external-ids:iface-id", res)
ofport = self.db_get_val("Interface", name, "ofport")
return VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self)
# returns a VIF object for each VIF port
def get_vif_ports(self):
edge_ports = []
port_names = self.get_port_name_list()
for name in port_names:
external_ids = self.db_get_map("Interface", name, "external_ids")
if "iface-id" in external_ids and "attached-mac" in external_ids:
ofport = self.db_get_val("Interface", name, "ofport")
p = VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self)
edge_ports.append(p)
else:
# iface-id might not be set. See if we can figure it out and
# set it here.
external_ids = self.db_get_map("Interface", name,
"external_ids")
if "attached-mac" not in external_ids:
continue
vif_uuid = external_ids.get("xs-vif-uuid", "")
if len(vif_uuid) == 0:
continue
LOG.debug("iface-id not set, got vif-uuid: %s" % vif_uuid)
res = os.popen("xe vif-param-get param-name=other-config "
"uuid=%s | grep nicira-iface-id | "
"awk '{print $2}'"
% vif_uuid).readline()
res = res.strip()
if len(res) == 0:
continue
external_ids["iface-id"] = res
LOG.info("Setting interface \"%s\" iface-id to \"%s\""
% (name, res))
self.set_db_attribute("Interface", name,
"external-ids:iface-id", res)
if "xs-vm-uuid" in external_ids:
p = xapi_get_port(name)
if p is not None:
edge_ports.append(p)
elif "iface-id" in external_ids and "attached-mac" in external_ids:
ofport = self.db_get_val("Interface", name, "ofport")
p = VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self)
@ -171,13 +171,15 @@ class OVSBridge:
return edge_ports
class OVSNaaSPlugin:
class OVSQuantumAgent:
def __init__(self, integ_br):
self.setup_integration_br(integ_br)
def port_bound(self, port, vlan_id):
self.int_br.set_db_attribute("Port", port.port_name, "tag",
str(vlan_id))
str(vlan_id))
self.int_br.delete_flows(match="in_port=%s" % port.ofport)
def port_unbound(self, port, still_exists):
if still_exists:
@ -186,13 +188,8 @@ class OVSNaaSPlugin:
def setup_integration_br(self, integ_br):
self.int_br = OVSBridge(integ_br)
self.int_br.remove_all_flows()
# drop all traffic on the 'dead vlan'
self.int_br.add_flow(priority=2, match="dl_vlan=4095", actions="drop")
# switch all other traffic using L2 learning
# switch all traffic using L2 learning
self.int_br.add_flow(priority=1, actions="normal")
# FIXME send broadcast everywhere, regardless of tenant
#int_br.add_flow(priority=3, match="dl_dst=ff:ff:ff:ff:ff:ff",
# actions="normal")
def daemon_loop(self, conn):
self.local_vlan_map = {}
@ -201,7 +198,7 @@ class OVSNaaSPlugin:
while True:
cursor = conn.cursor()
cursor.execute("SELECT * FROM network_bindings")
cursor.execute("SELECT * FROM ports")
rows = cursor.fetchall()
cursor.close()
all_bindings = {}
@ -226,22 +223,26 @@ class OVSNaaSPlugin:
else:
# no binding, put him on the 'dead vlan'
self.int_br.set_db_attribute("Port", p.port_name, "tag",
"4095")
"4095")
self.int_br.add_flow(priority=2,
match="in_port=%s" % p.ofport, actions="drop")
old_b = old_local_bindings.get(p.vif_id, None)
new_b = new_local_bindings.get(p.vif_id, None)
if old_b != new_b:
if old_b is not None:
LOG.info("Removing binding to net-id = %s for %s"
% (old_b, str(p)))
self.port_unbound(p, True)
if new_b is not None:
LOG.info("Adding binding to net-id = %s for %s" \
% (new_b, str(p)))
# If we don't have a binding we have to stick it on
# the dead vlan
vlan_id = vlan_bindings.get(all_bindings[p.vif_id],
"4095")
self.port_bound(p, vlan_id)
LOG.info("Adding binding to net-id = %s " \
"for %s on vlan %s" % (new_b, str(p), vlan_id))
for vif_id in old_vif_ports.keys():
if vif_id not in new_vif_ports:
LOG.info("Port Disappeared: %s" % vif_id)
@ -251,8 +252,6 @@ class OVSNaaSPlugin:
old_vif_ports = new_vif_ports
old_local_bindings = new_local_bindings
self.int_br.run_cmd(["bash",
"/etc/xapi.d/plugins/set_external_ids.sh"])
time.sleep(2)
if __name__ == "__main__":
@ -291,7 +290,7 @@ if __name__ == "__main__":
LOG.info("Connecting to database \"%s\" on %s" % (db_name, db_host))
conn = MySQLdb.connect(host=db_host, user=db_user,
passwd=db_pass, db=db_name)
plugin = OVSNaaSPlugin(integ_br)
plugin = OVSQuantumAgent(integ_br)
plugin.daemon_loop(conn)
finally:
if conn:

View File

@ -1,15 +0,0 @@
#!/bin/sh
VIFLIST=`xe vif-list params=uuid --minimal | sed s/,/" "/g`
for VIF_UUID in $VIFLIST; do
DEVICE_NUM=`xe vif-list params=device uuid=$VIF_UUID --minimal`
VM_NAME=`xe vif-list params=vm-name-label uuid=$VIF_UUID --minimal`
NAME="$VM_NAME-eth$DEVICE_NUM"
echo "Vif: $VIF_UUID is '$NAME'"
xe vif-param-set uuid=$VIF_UUID other-config:nicira-iface-id="$NAME"
done
ps auxw | grep -v grep | grep ovs-xapi-sync > /dev/null 2>&1
if [ $? -eq 0 ]; then
killall -HUP ovs-xapi-sync
fi

View File

@ -56,21 +56,3 @@ def remove_vlan_binding(netid):
except exc.NoResultFound:
pass
session.flush()
def update_network_binding(netid, ifaceid):
session = db.get_session()
# Add to or delete from the bindings table
if ifaceid == None:
try:
binding = session.query(ovs_models.NetworkBinding).\
filter_by(network_id=netid).\
one()
session.delete(binding)
except exc.NoResultFound:
raise Exception("No binding found with network_id = %s" % netid)
else:
binding = ovs_models.NetworkBinding(netid, ifaceid)
session.add(binding)
session.flush()

View File

@ -26,23 +26,6 @@ from sqlalchemy.orm import relation
from quantum.db.models import BASE
class NetworkBinding(BASE):
"""Represents a binding of network_id, vif_id"""
__tablename__ = 'network_bindings'
id = Column(Integer, primary_key=True, autoincrement=True)
network_id = Column(String(255))
vif_id = Column(String(255))
def __init__(self, network_id, vif_id):
self.network_id = network_id
self.vif_id = vif_id
def __repr__(self):
return "<NetworkBinding(%s,%s)>" % \
(self.network_id, self.vif_id)
class VlanBinding(BASE):
"""Represents a binding of network_id, vlan_id"""
__tablename__ = 'vlan_bindings'

View File

@ -1,9 +1,9 @@
[DATABASE]
name = ovs_naas
name = ovs_quantum
user = root
pass = foobar
pass = nova
host = 127.0.0.1
port = 3306
[OVS]
integration-bridge = xapi1
integration-bridge = br100

View File

@ -200,11 +200,9 @@ class OVSQuantumPlugin(QuantumPluginBase):
def plug_interface(self, tenant_id, net_id, port_id, remote_iface_id):
db.port_set_attachment(port_id, remote_iface_id)
ovs_db.update_network_binding(net_id, remote_iface_id)
def unplug_interface(self, tenant_id, net_id, port_id):
db.port_set_attachment(port_id, "")
ovs_db.update_network_binding(net_id, None)
def get_interface_details(self, tenant_id, net_id, port_id):
res = db.port_get(port_id)

174
tools/batch_config.py Normal file
View File

@ -0,0 +1,174 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 Nicira Networks, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# @author: Dan Wendlandt, Nicira Networks, Inc.
import httplib
import logging as LOG
import json
import socket
import sys
import urllib
from quantum.manager import QuantumManager
from optparse import OptionParser
from quantum.common.wsgi import Serializer
from quantum.cli import MiniClient
FORMAT = "json"
CONTENT_TYPE = "application/" + FORMAT
def delete_all_nets(client, tenant_id):
res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT)
resdict = json.loads(res.read())
LOG.debug(resdict)
for n in resdict["networks"]:
nid = n["id"]
res = client.do_request(tenant_id, 'GET',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to list ports: %s" % output)
continue
rd = json.loads(output)
LOG.debug(rd)
for port in rd["ports"]:
pid = port["id"]
data = {'port': {'attachment-id': ''}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s/attachment.%s" % \
(nid, pid, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to unplug iface from port \"%s\": %s" % (vid,
pid, output))
continue
LOG.info("Unplugged interface from port:%s on network:%s" % (pid,
nid))
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s.%s" % (nid, pid, FORMAT))
output = res.read()
if res.status != 202:
LOG.error("Failed to delete port: %s" % output)
continue
print "Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid)
res = client.do_request(tenant_id, 'DELETE',
"/networks/" + nid + "." + FORMAT)
status = res.status
if status != 202:
Log.error("Failed to delete network: %s" % nid)
output = res.read()
print output
else:
print "Deleted Virtual Network with ID:%s" % nid
def create_net_with_attachments(net_name, iface_ids):
data = {'network': {'network-name': '%s' % net_name}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'POST',
"/networks." + FORMAT, body=body)
rd = json.loads(res.read())
LOG.debug(rd)
nid = rd["networks"]["network"]["id"]
print "Created a new Virtual Network %s with ID:%s" % (net_name, nid)
for iface_id in iface_ids:
res = client.do_request(tenant_id, 'POST',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to create port: %s" % output)
continue
rd = json.loads(output)
new_port_id = rd["ports"]["port"]["id"]
print "Created Virtual Port:%s " \
"on Virtual Network:%s" % (new_port_id, nid)
data = {'port': {'attachment-id': '%s' % iface_id}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'PUT',
"/networks/%s/ports/%s/attachment.%s" %\
(nid, new_port_id, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % \
(iface_id, new_port_id, output))
continue
print "Plugged interface \"%s\" to port:%s on network:%s" % \
(iface_id, new_port_id, nid)
if __name__ == "__main__":
usagestr = "Usage: %prog [OPTIONS] <tenant-id> <config-string> [args]\n" \
"Example config-string: net1=instance-1,instance-2"\
":net2=instance-3,instance-4\n" \
"This string would create two networks: \n" \
"'net1' would have two ports, with iface-ids "\
"instance-1 and instance-2 attached\n" \
"'net2' would have two ports, with iface-ids"\
" instance-3 and instance-4 attached\n"
parser = OptionParser(usage=usagestr)
parser.add_option("-H", "--host", dest="host",
type="string", default="127.0.0.1", help="ip address of api host")
parser.add_option("-p", "--port", dest="port",
type="int", default=9696, help="api poort")
parser.add_option("-s", "--ssl", dest="ssl",
action="store_true", default=False, help="use ssl")
parser.add_option("-v", "--verbose", dest="verbose",
action="store_true", default=False, help="turn on verbose logging")
parser.add_option("-d", "--delete", dest="delete",
action="store_true", default=False, \
help="delete existing tenants networks")
options, args = parser.parse_args()
if options.verbose:
LOG.basicConfig(level=LOG.DEBUG)
else:
LOG.basicConfig(level=LOG.WARN)
if len(args) < 1:
parser.print_help()
help()
sys.exit(1)
nets = {}
tenant_id = args[0]
if len(args) > 1:
config_str = args[1]
for net_str in config_str.split(":"):
arr = net_str.split("=")
net_name = arr[0]
nets[net_name] = arr[1].split(",")
print "nets: %s" % str(nets)
client = MiniClient(options.host, options.port, options.ssl)
if options.delete:
delete_all_nets(client, tenant_id)
for net_name, iface_ids in nets.items():
create_net_with_attachments(net_name, iface_ids)
sys.exit(0)