vmware-nsx/quantum/plugins/cisco/services/service_insertion.py

343 lines
14 KiB
Python
Executable File

#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 Cisco Systems, Inc. All rights reserved.
#
# 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: Edgar Magana, Cisco Systems
#
"""
Network Library to insert services using Quantum APIs
Currently has four functionalities:
1. insert_inpath_service <tenant_id> <service_image_id>
<management_net_name> <northbound_net_name> <southbound_net_name>
2. delete_service <tenant_id> <service_instance_id>
3. connect_vm <tenant_id> <vm_image_id> <service_instance_id>
4. disconnect_vm <vm_instance_id>
"""
import logging
import logging.handlers
from optparse import OptionParser
import os
import re
import subprocess
import sys
from quantum.common import constants
from quantum.common import utils
from quantum.plugins.cisco.common import cisco_constants as const
from quantum.plugins.cisco.db import api as db
from quantum.plugins.cisco.db import l2network_db as l2db
from quantum.plugins.cisco.db import services_db as sdb
from quantum.plugins.cisco.services import services_constants as servconts
from quantum.plugins.cisco.services import services_logistics as servlogcs
from quantumclient import Client
LOG = logging.getLogger(__name__)
def insert_inpath_service(tenant_id, service_image_id,
management_net_name, northbound_net_name,
southbound_net_name, *args):
"""Inserting a network service between two networks"""
print _("Creating Network for Services and Servers")
service_logic = servlogcs.ServicesLogistics()
net_list = {}
multiport_net_list = []
networks_name_list = [management_net_name, northbound_net_name,
southbound_net_name]
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id)
for net in networks_name_list:
data = {servconts.NETWORK: {servconts.NAME: net}}
net_list[net] = client.create_network(data)
net_list[net][servconts.PORTS] = []
LOG.debug(_("Network %(net)s Created with ID: %(id)s "),
{'net': net,
'id': net_list[net][servconts.NETWORK][servconts.ID]})
print _("Completed")
print _("Creating Ports on Services and Server Networks")
LOG.debug(_("Operation 'create_port' executed."))
if not service_logic.verify_plugin(const.UCS_PLUGIN):
for net in networks_name_list:
net_list[net][servconts.PORTS].append
(client.create_port
(net_list[net][servconts.NETWORK][servconts.ID]))
LOG.debug(_("Operation 'create_port' executed."))
else:
for net in networks_name_list:
nets = net_list[net][servconts.NETWORK][servconts.ID]
multiport_net_list.append(nets)
data = create_multiport(tenant_id, multiport_net_list)
net_idx = 0
for net in networks_name_list:
port_id = data[servconts.PORTS][net_idx][servconts.ID]
net_list[net][servconts.PORTS].append(port_id)
LOG.debug(_("Port UUID: %(id)s on network: %(net)s"),
{'id': data[servconts.PORTS][net_idx][servconts.ID],
'net': net})
net_idx = net_idx + 1
print _("Completed")
try:
create_vm_args = []
create_vm_args.append(servconts.CREATE_VM_CMD)
create_vm_args.append(service_image_id)
print _("Creating VM with image: %s") % (service_image_id)
process = utils.subprocess_popen(create_vm_args,
stdout=subprocess.PIPE)
result = process.stdout.readlines()
tokens = re.search("i-[a-f0-9]*", str(result[1]))
service_vm_name = tokens.group(0)
print _("Image: %s instantiated successfully") % (service_vm_name)
except Exception as exc:
print exc
service_logic.image_status(service_vm_name)
print _("Completed")
print _("Attaching Ports To VM Service interfaces")
try:
idx = 0
for net in networks_name_list:
network_id = net_list[net][servconts.NETWORK][servconts.ID]
port_id = net_list[net][servconts.PORTS][idx]
attachment = client.show_port_attachment(network_id, port_id)
attachment = attachment[servconts.ATTACHMENT][servconts.ID][:36]
LOG.debug(_("Plugging virtual interface: %(attachment)s of VM "
"%(service_vm_name)s into port: %(port_id)s on "
"network: %(net)s"), locals())
attach_data = {servconts.ATTACHMENT: {servconts.ID: '%s' %
attachment}}
client.attach_resource(network_id, port_id, attach_data)
except Exception as exc:
print exc
print _("Completed")
try:
LOG.debug(_("Registering Service in DB"))
l2db.initialize()
for uuid_net in db.network_id(networks_name_list[0]):
mngnet_id = str(uuid_net.uuid)
for uuid_net in db.network_id(networks_name_list[1]):
nbnet_id = str(uuid_net.uuid)
for uuid_net in db.network_id(networks_name_list[2]):
sbnet_id = str(uuid_net.uuid)
sdb.add_services_binding(service_vm_name, mngnet_id, nbnet_id,
sbnet_id)
except Exception as exc:
print exc
def delete_service(tenant_id, service_instance_id, *args):
"""
Removes a service and all the network configuration
"""
l2db.initialize()
print _("Terminating Service VM")
service_logic = servlogcs.ServicesLogistics()
vms_list = []
vms_list.append(servconts.DELETE_VM_CMD)
vms_list.append(service_instance_id)
if not service_logic.image_exist(service_instance_id):
print _("Service VM does not exist")
sys.exit()
result = subprocess.call(vms_list)
service_logic.image_shutdown_verification(service_instance_id)
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id)
service_nets = sdb.get_service_bindings(service_instance_id)
print _("Terminating Ports and Networks")
network_name = db.network_get(service_nets.mngnet_id)
port_id_net = db.port_list(service_nets.mngnet_id)
for ports_uuid in port_id_net:
client.delete_port(service_nets.mngnet_id, ports_uuid.uuid)
client.delete_network(service_nets.mngnet_id)
network_name = db.network_get(service_nets.nbnet_id)
port_id_net = db.port_list(service_nets.nbnet_id)
for ports_uuid in port_id_net:
client.delete_port(service_nets.nbnet_id, ports_uuid.uuid)
client.delete_network(service_nets.nbnet_id)
network_name = db.network_get(service_nets.sbnet_id)
port_id_net = db.port_list(service_nets.sbnet_id)
for ports_uuid in port_id_net:
client.delete_port(service_nets.sbnet_id, ports_uuid.uuid)
client.delete_network(service_nets.sbnet_id)
service_list = sdb.remove_services_binding(service_instance_id)
print _("Configuration Removed Successfully")
def disconnect_vm(vm_instance_id, *args):
"""
Deletes VMs and Port connection
"""
l2db.initialize()
print _("Terminating Service VM")
service_logic = servlogcs.ServicesLogistics()
vms_list = []
vms_list.append(servconts.DELETE_VM_CMD)
vms_list.append(vm_instance_id)
result = subprocess.call(vms_list)
service_logic.image_shutdown_verification(vm_instance_id)
print _("VM Server Off")
def connect_vm(tenant_id, vm_image_id, service_instance_id, *args):
"""
Starts a VMs and is connected to southbound network
"""
l2db.initialize()
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id)
print (_("Connecting %(vm_image_id)s to Service "
"%(service_instance_id)s") % locals())
service_logic = servlogcs.ServicesLogistics()
service_nets = sdb.get_service_bindings(service_instance_id)
client.create_port(service_nets.mngnet_id)
client.create_port(service_nets.nbnet_id)
sb_port_id = client.create_port(service_nets.sbnet_id)
LOG.debug(_("Operation 'create_port' executed."))
new_port_id = sb_port_id[servconts.PORT][servconts.ID]
try:
create_vm_args = []
create_vm_args.append(servconts.CREATE_VM_CMD)
create_vm_args.append(vm_image_id)
print _("Creating VM with image: %s") % (vm_image_id)
process = utils.subprocess_popen(create_vm_args,
stdout=subprocess.PIPE)
result = process.stdout.readlines()
tokens = re.search("i-[a-f0-9]*", str(result[1]))
vm_name = tokens.group(0)
print _("Image: %s instantiated successfully") % (vm_name)
except Exception as exc:
print exc
service_logic.image_status(vm_name)
print _("Completed")
print _("Attaching Ports To VM Service interfaces")
south_net = service_nets.sbnet_id
attachment = client.show_port_attachment(south_net, new_port_id)
attachment = attachment[servconts.ATTACHMENT][servconts.ID][:36]
LOG.debug(_("Plugging virtual interface: %(attachment)s of VM "
"%(vm_name)s into port: %(new_port_id)s on network: "
"%(sbnet_id)s"), {'attachment': attachment,
'vm_name': vm_name,
'new_port_id': new_port_id,
'sbnet_id': service_nets.sbnet_id})
attach_data = {servconts.ATTACHMENT: {servconts.ID: '%s' % attachment}}
client.attach_resource(service_nets.sbnet_id, new_port_id, attach_data)
print _("Connect VM Ended")
def create_multiport(tenant_id, networks_list, *args):
"""Creates ports on a single host"""
ports_info = {'multiport':
{'status': constants.PORT_STATUS_ACTIVE,
'net_id_list': networks_list,
'ports_desc': {'key': 'value'}}}
request_url = "/multiport"
client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id,
action_prefix=servconts.ACTION_PREFIX_CSCO)
data = client.do_request('POST', request_url, body=ports_info)
return data
def build_args(cmd, cmdargs, arglist):
"""Building the list of args for a particular CLI"""
args = []
orig_arglist = arglist[:]
try:
for cmdarg in cmdargs:
args.append(arglist[0])
del arglist[0]
except:
LOG.debug(_("Not enough arguments for '%(cmd)s' "
"(expected: %(len_cmd)d, got: %(len_args)d)",
{'cmd': cmd, 'len_cmd': len(cmdargs),
'len_args': len(orig_arglist)}))
print (_("Service Insertion Usage:\n %(cmd)s %(usage)s") %
{'cmd': cmd,
'usage': " ".join(["<%s>" % y
for y in SERVICE_COMMANDS[cmd]["args"]])})
sys.exit()
if len(arglist) > 0:
LOG.debug(_("Too many arguments for '%(cmd)s' (expected: %(len)d, "
"got: %(len_args)d)"),
{'cmd': cmd, 'len_cmd': len(cmdargs),
'len_args': len(orig_arglist)})
print (_("Service Insertion Usage:\n %(cmd)s %(usage)s") %
{'cmd': cmd,
'usage': " ".join(["<%s>" % y
for y in SERVICE_COMMANDS[cmd]["args"]])})
sys.exit()
return args
SERVICE_COMMANDS = {
"insert_inpath_service": {
"func": insert_inpath_service,
"args": ["tenant_id", "service_image_id", "management_net_name",
"northbound_net_name", "southbound_net_name"],
},
"delete_service": {
"func": delete_service,
"args": ["tenant_id", "service_instance_id"],
},
"connect_vm": {
"func": connect_vm,
"args": ["tenant_id", "vm_image_id", "service_instance_id"],
},
"disconnect_vm": {
"func": disconnect_vm,
"args": ["vm_instance_id"],
},
}
if __name__ == "__main__":
os.system("clear")
usagestr = _("Usage: %prog [OPTIONS] <command> [args]")
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 port"))
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("-f", "--logfile", dest="logfile",
type="string", default="syslog",
help=_("Log file path"))
options, args = PARSER.parse_args()
if options.verbose:
LOG.setLevel(logging.DEBUG)
else:
LOG.setLevel(logging.WARN)
if options.logfile == "syslog":
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
else:
LOG.addHandler(logging.handlers.WatchedFileHandler(options.logfile))
os.chmod(options.logfile, 0644)
service_logic = servlogcs.ServicesLogistics()
HOST = options.host
PORT = options.port
USE_SSL = options.ssl
CMD = args[0]
args = build_args(CMD, SERVICE_COMMANDS[CMD]["args"], args[1:])
SERVICE_COMMANDS[CMD]["func"](*args)
sys.exit(0)