From 9d458c872cf80b5996df67b87e4b6a0f8054115f Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Sat, 28 Sep 2013 19:43:50 -0700 Subject: [PATCH 001/179] Initial set of scripts to build and start all-in-one node including openstack and contrail components --- contrail_config_templates.py | 273 +++++++++++ setup_contrail.py | 885 +++++++++++++++++++++++++++++++++++ stack.sh | 169 +++++++ stackrc | 1 + unstack.sh | 9 + 5 files changed, 1337 insertions(+) create mode 100644 contrail_config_templates.py create mode 100644 setup_contrail.py diff --git a/contrail_config_templates.py b/contrail_config_templates.py new file mode 100644 index 0000000000..9ffd1d8bb5 --- /dev/null +++ b/contrail_config_templates.py @@ -0,0 +1,273 @@ +import string + +api_server_conf_template = string.Template(""" +[DEFAULTS] +ifmap_server_ip=$__contrail_ifmap_server_ip__ +ifmap_server_port=$__contrail_ifmap_server_port__ +ifmap_username=$__contrail_ifmap_username__ +ifmap_password=$__contrail_ifmap_password__ +cassandra_server_list=$__contrail_cassandra_server_list__ +listen_ip_addr=$__contrail_listen_ip_addr__ +listen_port=$__contrail_listen_port__ +auth=keystone +multi_tenancy=$__contrail_multi_tenancy__ +log_file=$__contrail_log_file__ +disc_server_ip=$__contrail_disc_server_ip__ +disc_server_port=$__contrail_disc_server_port__ + +[SECURITY] +use_certs=$__contrail_use_certs__ +keyfile=$__contrail_keyfile_location__ +certfile=$__contrail_certfile_location__ +ca_certs=$__contrail_cacertfile_location__ + +[KEYSTONE] +auth_host=$__contrail_openstack_ip__ +auth_protocol=http +admin_user=$__contrail_admin_user__ +admin_password=$__contrail_admin_password__ +admin_tenant_name=$__contrail_admin_tenant_name__ +$__contrail_memcached_opt__ +""") + +quantum_conf_template = string.Template(""" +[APISERVER] +api_server_ip = $__contrail_api_server_ip__ +api_server_port = $__contrail_api_server_port__ +multi_tenancy = $__contrail_multi_tenancy__ + +[KEYSTONE] +;auth_url = http://$__contrail_keystone_ip__:35357/v2.0 +;admin_token = $__contrail_admin_token__ +admin_user=$__contrail_admin_user__ +admin_password=$__contrail_admin_password__ +admin_tenant_name=$__contrail_admin_tenant_name__ +""") + +schema_transformer_conf_template = string.Template(""" +[DEFAULTS] +ifmap_server_ip=$__contrail_ifmap_server_ip__ +ifmap_server_port=$__contrail_ifmap_server_port__ +ifmap_username=$__contrail_ifmap_username__ +ifmap_password=$__contrail_ifmap_password__ +api_server_ip=$__contrail_api_server_ip__ +api_server_port=$__contrail_api_server_port__ +zk_server_ip=$__contrail_zookeeper_server_ip__ +zk_server_port=$__contrail_zookeeper_server_port__ +log_file=$__contrail_log_file__ +cassandra_server_list=$__contrail_cassandra_server_list__ +disc_server_ip=$__contrail_disc_server_ip__ +disc_server_port=$__contrail_disc_server_port__ + +[SECURITY] +use_certs=$__contrail_use_certs__ +keyfile=$__contrail_keyfile_location__ +certfile=$__contrail_certfile_location__ +ca_certs=$__contrail_cacertfile_location__ + +[KEYSTONE] +admin_user=$__contrail_admin_user__ +admin_password=$__contrail_admin_password__ +admin_tenant_name=$__contrail_admin_tenant_name__ +""") + +svc_monitor_conf_template = string.Template(""" +[DEFAULTS] +ifmap_server_ip=$__contrail_ifmap_server_ip__ +ifmap_server_port=$__contrail_ifmap_server_port__ +ifmap_username=$__contrail_ifmap_username__ +ifmap_password=$__contrail_ifmap_password__ +api_server_ip=$__contrail_api_server_ip__ +api_server_port=$__contrail_api_server_port__ +zk_server_ip=$__contrail_zookeeper_server_ip__ +zk_server_port=$__contrail_zookeeper_server_port__ +log_file=$__contrail_log_file__ +cassandra_server_list=$__contrail_cassandra_server_list__ +disc_server_ip=$__contrail_disc_server_ip__ +disc_server_port=$__contrail_disc_server_port__ + +[SECURITY] +use_certs=$__contrail_use_certs__ +keyfile=$__contrail_keyfile_location__ +certfile=$__contrail_certfile_location__ +ca_certs=$__contrail_cacertfile_location__ + +[KEYSTONE] +auth_host=$__contrail_openstack_ip__ +admin_user=$__contrail_admin_user__ +admin_password=$__contrail_admin_password__ +admin_tenant_name=$__contrail_admin_tenant_name__ +""") + +bgp_param_template = string.Template(""" +IFMAP_SERVER=$__contrail_ifmap_srv_ip__ +IFMAP_PORT=$__contrail_ifmap_srv_port__ +IFMAP_USER=$__contrail_ifmap_usr__ +IFMAP_PASWD=$__contrail_ifmap_paswd__ +COLLECTOR=$__contrail_collector__ +COLLECTOR_PORT=$__contrail_collector_port__ +DISCOVERY=$__contrail_discovery_ip__ +HOSTNAME=$__contrail_hostname__ +HOSTIP=$__contrail_host_ip__ +BGP_PORT=$__contrail_bgp_port__ +CERT_OPTS=$__contrail_cert_ops__ +LOGFILE=$__contrail_logfile__ +LOG_LOCAL=$__contrail_log_local__ +""") + +dns_param_template = string.Template(""" +IFMAP_SERVER=$__contrail_ifmap_srv_ip__ +IFMAP_PORT=$__contrail_ifmap_srv_port__ +IFMAP_USER=$__contrail_ifmap_usr__ +IFMAP_PASWD=$__contrail_ifmap_paswd__ +COLLECTOR=$__contrail_collector__ +COLLECTOR_PORT=$__contrail_collector_port__ +DISCOVERY=$__contrail_discovery_ip__ +HOSTIP=$__contrail_host_ip__ +CERT_OPTS=$__contrail_cert_ops__ +LOGFILE=$__contrail_logfile__ +LOG_LOCAL=$__contrail_log_local__ +""") + + +discovery_conf_template = string.Template(""" +[DEFAULTS] +zk_server_ip=127.0.0.1 +zk_server_port=$__contrail_zk_server_port__ +listen_ip_addr=$__contrail_listen_ip_addr__ +listen_port=$__contrail_listen_port__ +log_local=$__contrail_log_local__ +log_file=$__contrail_log_file__ + +# minimim time to allow client to cache service information (seconds) +ttl_min=300 + +# maximum time to allow client to cache service information (seconds) +ttl_max=1800 + +# maximum hearbeats to miss before server will declare publisher out of +# service. +hc_max_miss=3 + +# use short TTL for agressive rescheduling if all services are not up +ttl_short=1 + +###################################################################### +# Other service specific knobs ... + +# use short TTL for agressive rescheduling if all services are not up +# ttl_short=1 + +# specify policy to use when assigning services +# policy = [load-balance | round-robin | fixed] +###################################################################### +""") + +vizd_param_template = string.Template(""" +CASSANDRA_SERVER_LIST=$__contrail_cassandra_server_list__ +REDIS_SERVER=$__contrail_redis_server__ +REDIS_SERVER_PORT=$__contrail_redis_server_port__ +DISCOVERY=$__contrail_discovery_ip__ +HOST_IP=$__contrail_host_ip__ +LISTEN_PORT=$__contrail_listen_port__ +HTTP_SERVER_PORT=$__contrail_http_server_port__ +LOG_FILE=$__contrail_log_file__ +LOG_LOCAL=$__contrail_log_local__ +LOG_LEVEL=$__contrail_log_level__ +""") + +qe_param_template = string.Template(""" +CASSANDRA_SERVER_LIST=$__contrail_cassandra_server_list__ +REDIS_SERVER=$__contrail_redis_server__ +REDIS_SERVER_PORT=$__contrail_redis_server_port__ +DISCOVERY=$__contrail_discovery_ip__ +HOST_IP=$__contrail_host_ip__ +LISTEN_PORT=$__contrail_listen_port__ +HTTP_SERVER_PORT=$__contrail_http_server_port__ +LOG_FILE=$__contrail_log_file__ +LOG_LOCAL=$__contrail_log_local__ +LOG_LEVEL=$__contrail_log_level__ +""") + +opserver_param_template = string.Template(""" +REDIS_SERVER=$__contrail_redis_server__ +REDIS_SERVER_PORT=$__contrail_redis_server_port__ +REDIS_QUERY_PORT=$__contrail_redis_query_port__ +COLLECTOR=$__contrail_collector__ +COLLECTOR_PORT=$__contrail_collector_port__ +HTTP_SERVER_PORT=$__contrail_http_server_port__ +REST_API_PORT=$__contrail_rest_api_port__ +LOG_FILE=$__contrail_log_file__ +LOG_LOCAL=$__contrail_log_local__ +LOG_LEVEL=$__contrail_log_level__ +DISCOVERY=$__contrail_discovery_ip__ +""") + +vnc_api_lib_ini_template = string.Template(""" +[global] +;WEB_SERVER = 127.0.0.1 +;WEB_PORT = 9696 ; connection through quantum plugin + +WEB_SERVER = 127.0.0.1 +WEB_PORT = 8082 ; connection to api-server directly +BASE_URL = / +;BASE_URL = /tenants/infra ; common-prefix for all URLs + +; Authentication settings (optional) +[auth] +AUTHN_TYPE = keystone +AUTHN_SERVER=$__contrail_openstack_ip__ +AUTHN_PORT = 35357 +AUTHN_URL = /v2.0/tokens +""") + +agent_param_template = string.Template(""" +LOG=/var/log/contrail.log +CONFIG=/etc/contrail/agent.conf +prog=/usr/bin/vnswad +kmod=vrouter/vrouter.ko +pname=vnswad +LIBDIR=/usr/lib64 +VHOST_CFG=/etc/sysconfig/network-scripts/ifcfg-vhost0 +LOGFILE=--log-file=/var/log/contrail/vrouter.log +COLLECTOR=$__contrail_collector__ +$__contrail_dev__ +""") + +agent_conf_template = string.Template(""" + + + + + + vhost0 + $__contrail_box_ip__ + $__contrail_gateway__ + + + $__contrail_intf__ + + + $__contrail_control_ip__ + + + +""") + +ifconfig_vhost0_template = string.Template(""" +#Contrail vhost0 +DEVICE=vhost0 +ONBOOT=yes +BOOTPROTO=none +IPV6INIT=no +USERCTL=yes +IPADDR=$__contrail_ipaddr__ +NETMASK=$__contrail_netmask__ +NM_CONTROLLED=no +#NETWORK MANAGER BUG WORKAROUND +SUBCHANNELS=1,2,3 +$__contrail_gateway__ +$__contrail_dns__ +$__contrail_domain__ +$__contrail_mtu__ +""") diff --git a/setup_contrail.py b/setup_contrail.py new file mode 100644 index 0000000000..c38831446c --- /dev/null +++ b/setup_contrail.py @@ -0,0 +1,885 @@ +import argparse +import ConfigParser + +import platform +import os +import sys +import time +import re +import string +import socket +import netifaces, netaddr +import subprocess +import fnmatch +import struct +import shutil +import json +from pprint import pformat +import xml.etree.ElementTree as ET +import platform +import getpass + +import tempfile + +# Get Environment Stuff +password='contrail123' +admin_username='admin' +admin_token='contrail123' +admin_tenant ='admin' + +# TODO following keystone credentials hardcoded +ks_admin_user = admin_username +ks_admin_password = admin_token +ks_admin_tenant_name = admin_tenant + +from contrail_config_templates import * + +class Setup(object): + def __init__(self, args_str = None): + self._args = None + if not args_str: + args_str = ' '.join(sys.argv[1:]) + self._parse_args(args_str) + + self._setup_tgt_path = os.path.abspath(os.path.dirname(sys.argv[0])) + + self._temp_dir_name = tempfile.mkdtemp() + self._fixed_qemu_conf = False + #end __init__ + + def _parse_args(self, args_str): + ''' + Eg. python setup.py --cfgm_ip 127.0.0.1 + ''' + + # Source any specified config/ini file + # Turn off help, so we print all options in response to -h + conf_parser = argparse.ArgumentParser(add_help = False) + + conf_parser.add_argument("-c", "--conf_file", + help="Specify config file", metavar="FILE") + args, remaining_argv = conf_parser.parse_known_args(args_str.split()) + + global_defaults = { + 'use_certs': False, + 'puppet_server': None, + } + cfgm_defaults = { + 'cfgm_ip': '127.0.0.1', + 'openstack_ip': '127.0.0.1', + 'service_token': '', + 'multi_tenancy': False, + } + openstack_defaults = { + 'cfgm_ip': '127.0.0.1', + 'service_token': '', + } + control_node_defaults = { + 'cfgm_ip': '127.0.0.1', + 'collector_ip': '127.0.0.1', + 'control_ip': '127.0.0.1', + } + compute_node_defaults = { + 'compute_ip': '127.0.0.1', + 'openstack_ip': '127.0.0.1', + 'service_token': '', + 'ncontrols' : 2, + 'physical_interface': None, + 'non_mgmt_ip': None, + 'non_mgmt_gw': None, + } + collector_defaults = { + 'cfgm_ip': '127.0.0.1', + 'self_collector_ip': '127.0.0.1', + } + database_defaults = { + 'database_dir' : '/usr/share/cassandra', + 'database_listen_ip' : '127.0.0.1', + } + + if args.conf_file: + config = ConfigParser.SafeConfigParser() + config.read([args.conf_file]) + global_defaults.update(dict(config.items("GLOBAL"))) + cfgm_defaults.update(dict(config.items("CFGM"))) + openstack_defaults.update(dict(config.items("OPENSTACK"))) + control_node_defaults.update(dict(config.items("CONTROL-NODE"))) + compute_node_defaults.update(dict(config.items("COMPUTE-NODE"))) + collector_defaults.update(dict(config.items("COLLECTOR"))) + database_defaults.update(dict(config.items("DATABASE"))) + + # Override with CLI options + # Don't surpress add_help here so it will handle -h + parser = argparse.ArgumentParser( + # Inherit options from config_parser + parents=[conf_parser], + # print script description with -h/--help + description=__doc__, + # Don't mess with format of description + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + + all_defaults = {'global': global_defaults, + 'cfgm': cfgm_defaults, + 'openstack': openstack_defaults, + 'control-node': control_node_defaults, + 'compute-node': compute_node_defaults, + 'collector': collector_defaults, + 'database': database_defaults, + } + parser.set_defaults(**all_defaults) + + parser.add_argument("--role", action = 'append', + help = "Role of server (config, openstack, control, compute, collector, webui, database") + parser.add_argument("--cfgm_ip", help = "IP Address of Configuration Node") + parser.add_argument("--openstack_ip", help = "IP Address of Openstack Node") + parser.add_argument("--openstack_mgmt_ip", help = "Management IP Address of Openstack Node") + parser.add_argument("--collector_ip", help = "IP Address of Collector Node") + parser.add_argument("--discovery_ip", help = "IP Address of Discovery Node") + parser.add_argument("--control_ip", help = "IP Address of first Control Node (for control role)") + parser.add_argument("--ncontrols", help = "Number of Control Nodes in the system (for compute role)") + parser.add_argument("--compute_ip", help = "IP Address of Compute Node (for compute role)") + parser.add_argument("--service_token", help = "The service password to access keystone") + parser.add_argument("--physical_interface", help = "Name of the physical interface to use") + parser.add_argument("--non_mgmt_ip", help = "IP Address of non-management interface(fabric network) on the compute node") + parser.add_argument("--non_mgmt_gw", help = "Gateway Address of the non-management interface(fabric network) on the compute node") + parser.add_argument("--use_certs", help = "Use certificates for authentication", + action="store_true") + parser.add_argument("--puppet_server", help = "FQDN of Puppet Master") + parser.add_argument("--multi_tenancy", help = "Enforce resource permissions (implies keystone token validation)", + action="store_true") + parser.add_argument("--cassandra_ip_list", help = "IP Addresses of Cassandra Nodes", nargs = '+', type = str) + parser.add_argument("--database_listen_ip", help = "Listen IP Address of database node", default = '127.0.0.1') + parser.add_argument("--database_dir", help = "Directory where database binary exists", default = '/usr/share/cassandra') + parser.add_argument("--database_initial_token", help = "Initial token for database node") + parser.add_argument("--database_seed_list", help = "List of seed nodes for database", nargs='+') + parser.add_argument("--num_collector_nodes", help = "Number of Collector Nodes", type = int) + parser.add_argument("--redis_master_ip", help = "IP Address of Redis Master Node") + parser.add_argument("--redis_role", help = "Redis Role of Node") + parser.add_argument("--self_collector_ip", help = "Self IP of Collector Node") + + self._args = parser.parse_args(remaining_argv) + + if self._args.physical_interface: + self._args.cfgm_ip = self.get_intf_ip(self._args.physical_interface) + print 'Using IP address %s' % self._args.cfgm_ip + + # dsetia + self._args.openstack_ip = self._args.cfgm_ip + self._args.collector_ip = self._args.cfgm_ip + # self._args.discovery_ip = self._args.cfgm_ip + self._args.control_ip = self._args.cfgm_ip + self._args.compute_ip = self._args.cfgm_ip + self._args.openstack_mgmt_ip = self._args.cfgm_ip + self._args.database_listen_ip = self._args.cfgm_ip + self._args.cassandra_ip_list = ['127.0.0.1'] + self._args.role = ['config', 'openstack', 'control', 'compute', 'collector'] + + #end _parse_args + + def run_cmd(self, cmd): + """Return (status, output) of executing cmd in a shell.""" + pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') + text = '' + while True: + line = pipe.readline() + if line == '': + break + text += line + print line + sts = pipe.close() + if sts is None: sts = 0 + if text[-1:] == '\n': text = text[:-1] + return sts, text + # end + + def run_shell (self, cmd): + s, o = self.run_cmd (cmd) + # if s: raise RuntimeError, '+ %s[%d]\n%s' % (cmd, s, o) + print '+ %s [%d]' % (cmd, s) + return o + + def _template_substitute(self, template, vals): + data = template.safe_substitute(vals) + return data + #end _template_substitute + + def _template_substitute_write(self, template, vals, filename): + data = self._template_substitute(template, vals) + outfile = open(filename, 'w') + outfile.write(data) + outfile.close() + #end _template_substitute_write + + def _replaces_in_file(self, file, replacement_list): + rs = [ (re.compile(regexp), repl) for (regexp, repl) in replacement_list] + file_tmp = file + ".tmp" + with open(file, 'r') as f: + with open(file_tmp, 'w') as f_tmp: + for line in f: + for r, replace in rs: + match = r.search(line) + if match: + line = replace + "\n" + f_tmp.write(line) + shutil.move(file_tmp, file) + #end _replaces_in_file + + def replace_in_file(self, file, regexp, replace): + self._replaces_in_file(file, [(regexp, replace)]) + #end replace_in_file + + def find_gateway (self, dev): + gateway = '' + gateway = self.run_shell("netstat -rn | grep ^\"0.0.0.0\" | grep %s | awk '{ print $2 }'" % dev) + # capture = True).strip() + return gateway + + #end find_gateway + + def get_dns_servers (self, dev): + dns_list = self.run_shell("grep \"^nameserver\\>\" /etc/resolv.conf | awk '{print $2}'") + return dns_list.split() + #end get_dns_servers + + def get_domain_search_list (self): + domain_list = '' + domain_list = self.run_shell("grep ^\"search\" /etc/resolv.conf | awk '{$1=\"\";print $0}'") + if not domain_list: + domain_list = self.run_shell("grep ^\"domain\" /etc/resolv.conf | awk '{$1=\"\"; print $0}'") + return domain_list + + def get_if_mtu (self, dev): + mtu = self.run_shell("ifconfig %s | grep mtu | awk '{ print $NF }'" % dev) + if not mtu: + # for debian + mtu = self.run_shell("ifconfig %s | grep MTU | sed 's/.*MTU.\([0-9]\+\).*/\1/g'" % dev) + if mtu and mtu != '1500': return mtu + return '' + #end if_mtu + + def get_intf_ip (self, intf): + if intf in netifaces.interfaces (): + ip = netifaces.ifaddresses (intf)[netifaces.AF_INET][0]['addr'] + return ip + raise RuntimeError, '%s not configured' % intf + # end + + def get_device_by_ip (self, ip): + for i in netifaces.interfaces (): + try: + if i == 'pkt1': + continue + if netifaces.ifaddresses (i).has_key (netifaces.AF_INET): + if ip == netifaces.ifaddresses (i)[netifaces.AF_INET][0][ + 'addr']: + if i == 'vhost0': + print "vhost0 is already present!" + # raise RuntimeError, 'vhost0 already running with %s'%ip + return i + except ValueError,e: + print "Skipping interface %s" % i + raise RuntimeError, '%s not configured, rerun w/ --physical_interface' % ip + #end get_device_by_ip + + def _is_string_in_file(self, string, filename): + f_lines=[] + if os.path.isfile( filename ): + fd=open(ifcfg_file) + f_lines=fd.readlines() + fd.close() + #end if + found= False + for line in f_lines: + if string in line: + found= True + return found + #end _is_string_in_file + + def _rewrite_ifcfg_file(self, filename, dev, prsv_cfg): + bond = False + mac = '' + temp_dir_name = self._temp_dir_name + + if os.path.isdir ('/sys/class/net/%s/bonding' % dev): + bond = True + # end if os.path.isdir... + + mac = netifaces.ifaddresses(dev)[netifaces.AF_LINK][0]['addr'] + ifcfg_file='/etc/sysconfig/network-scripts/ifcfg-%s' %(dev) + if not os.path.isfile( ifcfg_file ): + ifcfg_file = temp_dir_name + 'ifcfg-' + dev + with open (ifcfg_file, 'w') as f: + f.write ('''#Contrail %s +TYPE=Ethernet +ONBOOT=yes +DEVICE="%s" +USERCTL=yes +NM_CONTROLLED=no +HWADDR=%s +''' % (dev, dev, mac)) + for dcfg in prsv_cfg: + f.write(dcfg+'\n') + f.flush() + fd=open(ifcfg_file) + f_lines=fd.readlines() + fd.close() + new_f_lines=[] + remove_items=['IPADDR', 'NETMASK', 'PREFIX', 'GATEWAY', 'HWADDR', + 'DNS1', 'DNS2', 'BOOTPROTO', 'NM_CONTROLLED', '#Contrail'] + + remove_items.append('DEVICE') + new_f_lines.append('#Contrail %s\n' % dev) + new_f_lines.append('DEVICE=%s\n' % dev) + + + for line in f_lines: + found=False + for text in remove_items: + if text in line: + found=True + if not found: + new_f_lines.append(line) + + new_f_lines.append('NM_CONTROLLED=no\n') + if bond: + new_f_lines.append('SUBCHANNELS=1,2,3\n') + else: + new_f_lines.append('HWADDR=%s\n' % mac) + + fdw=open(filename,'w') + fdw.writelines(new_f_lines) + fdw.close() + + def migrate_routes(self, device): + ''' + Sample output of /proc/net/route : + Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT + p4p1 00000000 FED8CC0A 0003 0 0 0 00000000 0 0 0 + ''' + with open('/etc/sysconfig/network-scripts/route-vhost0', 'w') as route_cfg_file: + for route in open('/proc/net/route', 'r').readlines(): + if route.startswith(device): + route_fields = route.split() + destination = int(route_fields[1], 16) + gateway = int(route_fields[2], 16) + flags = int(route_fields[3], 16) + mask = int(route_fields[7], 16) + if flags & 0x2: + if destination != 0: + route_cfg_file.write(socket.inet_ntoa(struct.pack('I', destination))) + route_cfg_file.write('/' + str(bin(mask).count('1')) + ' ') + route_cfg_file.write('via ') + route_cfg_file.write(socket.inet_ntoa(struct.pack('I', gateway)) + ' ') + route_cfg_file.write('dev vhost0') + #end if detination... + #end if flags &... + #end if route.startswith... + #end for route... + #end with open... + #end def migrate_routes + + def _replace_discovery_server(self, agent_elem, discovery_ip, ncontrols): + for srv in agent_elem.findall('discovery-server'): + agent_elem.remove(srv) + + pri_dss_elem = ET.Element('discovery-server') + pri_dss_ip = ET.SubElement(pri_dss_elem, 'ip-address') + pri_dss_ip.text = '%s' %(discovery_ip) + + xs_instances = ET.SubElement(pri_dss_elem, 'control-instances') + xs_instances.text = '%s' %(ncontrols) + agent_elem.append(pri_dss_elem) + + #end _replace_discovery_server + + + def fixup_config_files(self): + temp_dir_name = self._temp_dir_name + hostname = socket.gethostname() + cfgm_ip = self._args.cfgm_ip + collector_ip = self._args.collector_ip + use_certs = True if self._args.use_certs else False + + whoami = getpass.getuser() + self.run_shell("sudo mkdir -p /etc/contrail") + self.run_shell("sudo chown %s /etc/contrail" % whoami) + self.run_shell("sudo mkdir -p /etc/quantum/plugins/contrail") + self.run_shell("sudo chown %s /etc/quantum/plugins/contrail" % whoami) + # generate service token + self.service_token = self._args.service_token + if not self.service_token: + self.run_shell("sudo openssl rand -hex 10 > /etc/contrail/service.token") + tok_fd = open('/etc/contrail/service.token') + self.service_token = tok_fd.read() + tok_fd.close() + # local("sudo chmod 400 /etc/contrail/service.token") + + """ dsetia + # TODO till post of openstack-horizon.spec is fixed... + if 'config' in self._args.role: + pylibpath = local ('/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"', capture = True) + local('runuser -p apache -c "echo yes | django-admin collectstatic --settings=settings --pythonpath=%s/openstack_dashboard"' % pylibpath) + """ + + # Disable selinux + self.run_shell("sudo sed 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config > config.new") + self.run_shell("sudo mv config.new /etc/selinux/config") + self.run_shell("setenforce 0") + + # Disable iptables + self.run_shell("sudo chkconfig iptables off") + self.run_shell("sudo iptables --flush") + + if 'config' in self._args.role or 'compute' in self._args.role or 'openstack' in self._args.role: + openstack_ip = self._args.openstack_ip + compute_ip = self._args.compute_ip + cfgm_ip = self._args.cfgm_ip + temp_dir_name = "/tmp" + + self.run_shell("echo 'SERVICE_TOKEN=%s' >> %s/ctrl-details" + %(self.service_token, temp_dir_name)) + self.run_shell("echo 'ADMIN_TOKEN=%s' >> %s/ctrl-details" %(ks_admin_password, temp_dir_name)) + self.run_shell("echo 'CONTROLLER=%s' >> %s/ctrl-details" %(openstack_ip, temp_dir_name)) + self.run_shell("echo 'QUANTUM=%s' >> %s/ctrl-details" %(cfgm_ip, temp_dir_name)) + self.run_shell("echo 'COMPUTE=%s' >> %s/ctrl-details" %(compute_ip, temp_dir_name)) + if 'compute' in self._args.role: + self.run_shell("echo 'CONTROLLER_MGMT=%s' >> %s/ctrl-details" %(self._args.openstack_mgmt_ip, temp_dir_name)) + self.run_shell("sudo cp %s/ctrl-details /etc/contrail/ctrl-details" %(temp_dir_name)) + self.run_shell("rm %s/ctrl-details" %(temp_dir_name)) + + # database (cassandra setup in contrail.sh) + + # collector in Phase 2 + + if 'config' in self._args.role: + openstack_ip = self._args.openstack_ip + cassandra_server_list = [(cassandra_server_ip, '9160') for cassandra_server_ip in self._args.cassandra_ip_list] + template_vals = {'__contrail_ifmap_server_ip__': cfgm_ip, + '__contrail_ifmap_server_port__': '8444' if use_certs else '8443', + '__contrail_ifmap_username__': 'api-server', + '__contrail_ifmap_password__': 'api-server', + '__contrail_listen_ip_addr__': '0.0.0.0', + '__contrail_listen_port__': '8082', + '__contrail_use_certs__': use_certs, + '__contrail_keyfile_location__': '/etc/contrail/ssl/private_keys/apiserver_key.pem', + '__contrail_certfile_location__': '/etc/contrail/ssl/certs/apiserver.pem', + '__contrail_cacertfile_location__': '/etc/contrail/ssl/certs/ca.pem', + '__contrail_multi_tenancy__': self._args.multi_tenancy, + '__contrail_openstack_ip__': openstack_ip, + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + '__contrail_memcached_opt__': 'memcache_servers=127.0.0.1:11211' if self._args.multi_tenancy else '', + '__contrail_log_file__': '/var/log/contrail/api.log', + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_disc_server_ip__': self._args.discovery_ip or '', + '__contrail_disc_server_port__': '5998', + } + self._template_substitute_write(api_server_conf_template, + template_vals, temp_dir_name + '/api_server.conf') + self.run_shell("sudo mv %s/api_server.conf /etc/contrail/" %(temp_dir_name)) + + template_vals = {'__contrail_api_server_ip__': cfgm_ip, + '__contrail_api_server_port__': '8082', + '__contrail_multi_tenancy__': self._args.multi_tenancy, + '__contrail_keystone_ip__': '127.0.0.1', + '__contrail_admin_token__': ks_admin_password, + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + } + self._template_substitute_write(quantum_conf_template, + template_vals, temp_dir_name + '/contrail_plugin.ini') + + self.run_shell("sudo mv %s/contrail_plugin.ini /etc/quantum/plugins/contrail/contrail_plugin.ini" %(temp_dir_name)) + + template_vals = {'__contrail_ifmap_server_ip__': cfgm_ip, + '__contrail_ifmap_server_port__': '8444' if use_certs else '8443', + '__contrail_ifmap_username__': 'schema-transformer', + '__contrail_ifmap_password__': 'schema-transformer', + '__contrail_api_server_ip__': cfgm_ip, + '__contrail_api_server_port__': '8082', + '__contrail_zookeeper_server_ip__': '127.0.0.1', + '__contrail_zookeeper_server_port__': '2181', + '__contrail_use_certs__': use_certs, + '__contrail_keyfile_location__': '/etc/contrail/ssl/private_keys/schema_xfer_key.pem', + '__contrail_certfile_location__': '/etc/contrail/ssl/certs/schema_xfer.pem', + '__contrail_cacertfile_location__': '/etc/contrail/ssl/certs/ca.pem', + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + '__contrail_log_file__' : '/var/log/contrail/schema.log', + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_disc_server_ip__': self._args.discovery_ip or '', + '__contrail_disc_server_port__': '5998', + } + self._template_substitute_write(schema_transformer_conf_template, + template_vals, temp_dir_name + '/schema_transformer.conf') + self.run_shell("sudo mv %s/schema_transformer.conf /etc/contrail/schema_transformer.conf" %(temp_dir_name)) + + template_vals = {'__contrail_ifmap_server_ip__': cfgm_ip, + '__contrail_ifmap_server_port__': '8444' if use_certs else '8443', + '__contrail_ifmap_username__': 'svc-monitor', + '__contrail_ifmap_password__': 'svc-monitor', + '__contrail_api_server_ip__': cfgm_ip, + '__contrail_api_server_port__': '8082', + '__contrail_openstack_ip__': openstack_ip, + '__contrail_zookeeper_server_ip__': '127.0.0.1', + '__contrail_zookeeper_server_port__': '2181', + '__contrail_use_certs__': use_certs, + '__contrail_keyfile_location__': '/etc/contrail/ssl/private_keys/svc_monitor_key.pem', + '__contrail_certfile_location__': '/etc/contrail/ssl/certs/svc_monitor.pem', + '__contrail_cacertfile_location__': '/etc/contrail/ssl/certs/ca.pem', + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + '__contrail_log_file__' : '/var/log/contrail/svc-monitor.log', + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_disc_server_ip__': self._args.discovery_ip or '', + '__contrail_disc_server_port__': '5998', + } + self._template_substitute_write(svc_monitor_conf_template, + template_vals, temp_dir_name + '/svc_monitor.conf') + self.run_shell("sudo mv %s/svc_monitor.conf /etc/contrail/svc_monitor.conf" %(temp_dir_name)) + + template_vals = { + '__contrail_zk_server_ip__': '127.0.0.1', + '__contrail_zk_server_port__': '2181', + '__contrail_listen_ip_addr__': cfgm_ip, + '__contrail_listen_port__': '5998', + '__contrail_log_local__': 'True', + '__contrail_log_file__': '/var/log/contrail/discovery.log', + } + self._template_substitute_write(discovery_conf_template, + template_vals, temp_dir_name + '/discovery.conf') + self.run_shell("sudo mv %s/discovery.conf /etc/contrail/" %(temp_dir_name)) + + template_vals = { + '__contrail_openstack_ip__': openstack_ip, + } + self._template_substitute_write(vnc_api_lib_ini_template, + template_vals, temp_dir_name + '/vnc_api_lib.ini') + self.run_shell("sudo mv %s/vnc_api_lib.ini /etc/contrail/" %(temp_dir_name)) + + if 'control' in self._args.role: + control_ip = self._args.control_ip + certdir = '/var/lib/puppet/ssl' if self._args.puppet_server else '/etc/contrail/ssl' + template_vals = {'__contrail_ifmap_srv_ip__': cfgm_ip, + '__contrail_ifmap_srv_port__': '8444' if use_certs else '8443', + '__contrail_ifmap_usr__': '%s' %(control_ip), + '__contrail_ifmap_paswd__': '%s' %(control_ip), + '__contrail_collector__': collector_ip, + '__contrail_collector_port__': '8086', + '__contrail_discovery_ip__': self._args.discovery_ip, + '__contrail_hostname__': hostname, + '__contrail_host_ip__': control_ip, + '__contrail_bgp_port__': '179', + '__contrail_cert_ops__': '"--use-certs=%s"' %(certdir) if use_certs else '', + '__contrail_log_local__': '', + '__contrail_logfile__': '--log-file=/var/log/contrail/control.log', + } + self._template_substitute_write(bgp_param_template, + template_vals, temp_dir_name + '/control_param') + self.run_shell("sudo mv %s/control_param /etc/contrail/control_param" %(temp_dir_name)) + + dns_template_vals = {'__contrail_ifmap_srv_ip__': cfgm_ip, + '__contrail_ifmap_srv_port__': '8444' if use_certs else '8443', + '__contrail_ifmap_usr__': '%s.dns' %(control_ip), + '__contrail_ifmap_paswd__': '%s.dns' %(control_ip), + '__contrail_collector__': collector_ip, + '__contrail_collector_port__': '8086', + '__contrail_discovery_ip__': self._args.discovery_ip, + '__contrail_host_ip__': control_ip, + '__contrail_cert_ops__': '"--use-certs=%s"' %(certdir) if use_certs else '', + '__contrail_log_local__': '', + '__contrail_logfile__': '--log-file=/var/log/contrail/dns.log', + } + self._template_substitute_write(dns_param_template, + dns_template_vals, temp_dir_name + '/dns_param') + self.run_shell("sudo mv %s/dns_param /etc/contrail/dns_param" %(temp_dir_name)) + + dir = "/opt/stack/contrail/third_party/irond-0.3.0-bin" + self.run_shell("echo >> %s/basicauthusers.properties" % dir) + self.run_shell("echo '# Contrail users' >> %s/basicauthusers.properties" % dir) + self.run_shell("echo 'api-server:api-server' >> %s/basicauthusers.properties" % dir) + self.run_shell("echo 'schema-transformer:schema-transformer' >> %s/basicauthusers.properties" % dir) + self.run_shell("sudo sed -e '/%s:/d' -e '/%s.dns:/d' %s/%s > %s/%s.new" \ + %(control_ip, control_ip, dir, 'basicauthusers.properties', + dir, 'basicauthusers.properties')) + self.run_shell("echo '%s:%s' >> %s/%s.new" \ + %(control_ip, control_ip, dir, 'basicauthusers.properties')) + self.run_shell("echo '%s.dns:%s.dns' >> %s/%s.new" \ + %(control_ip, control_ip, dir, 'basicauthusers.properties')) + self.run_shell("sudo mv %s/%s.new %s/%s" \ + % (dir, 'basicauthusers.properties', dir, 'basicauthusers.properties')) + self.run_shell("echo '%s=%s--0000000001-1' >> %s/%s" \ + %(control_ip, control_ip, dir, 'publisher.properties')) + if self._args.puppet_server: + self.run_shell("echo ' server = %s' >> /etc/puppet/puppet.conf" \ + %(self._args.puppet_server)) + + if 'compute' in self._args.role: + dist = platform.dist()[0] + # add /dev/net/tun in cgroup_device_acl needed for type=ethernet interfaces + ret = self.run_cmd("sudo grep -q '^cgroup_device_acl' /etc/libvirt/qemu.conf") + if ret == 1: + self.run_shell('sudo cp /etc/libvirt/qemu.conf qemu.conf') + self.run_shell('sudo chown %s qemu.conf' % whoami) + if dist == 'centos': + self.run_shell('sudo echo "clear_emulator_capabilities = 1" >> qemu.conf') + self.run_shell('sudo echo \'user = "root"\' >> qemu.conf') + self.run_shell('sudo echo \'group = "root"\' >> qemu.conf') + self.run_shell('sudo echo \'cgroup_device_acl = [\' >> qemu.conf') + self.run_shell('sudo echo \' "/dev/null", "/dev/full", "/dev/zero",\' >> qemu.conf') + self.run_shell('sudo echo \' "/dev/random", "/dev/urandom",\' >> qemu.conf') + self.run_shell('sudo echo \' "/dev/ptmx", "/dev/kvm", "/dev/kqemu",\' >> qemu.conf') + self.run_shell('sudo echo \' "/dev/rtc", "/dev/hpet","/dev/net/tun",\' >> qemu.conf') + self.run_shell('sudo echo \']\' >> qemu.conf') + self.run_shell('sudo cp qemu.conf /etc/libvirt/qemu.conf') + self._fixed_qemu_conf = True + # add "alias bridge off" in /etc/modprobe.conf for Centos + if dist == 'centos': + self.run_shell('sudo echo "alias bridge off" > /etc/modprobe.conf') + + if 'compute' in self._args.role : + openstack_ip = self._args.openstack_ip + compute_ip = self._args.compute_ip + discovery_ip = self._args.discovery_ip + ncontrols = self._args.ncontrols + physical_interface = self._args.physical_interface + non_mgmt_ip = self._args.non_mgmt_ip + non_mgmt_gw = self._args.non_mgmt_gw + vhost_ip = compute_ip + multi_net= False + if non_mgmt_ip : + if non_mgmt_ip != compute_ip: + multi_net= True + vhost_ip= non_mgmt_ip + + dev = None + compute_dev = None + if physical_interface: + if physical_interface in netifaces.interfaces (): + dev = physical_interface + else: + raise KeyError, 'Interface %s in present' % ( + physical_interface) + else: + # deduce the phy interface from ip, if configured + dev = self.get_device_by_ip (vhost_ip) + if multi_net: + compute_dev = self.get_device_by_ip (compute_ip) + + mac = None + if dev and dev != 'vhost0' : + mac = netifaces.ifaddresses (dev)[netifaces.AF_LINK][0][ + 'addr'] + if mac: + with open ('%s/default_pmac' % temp_dir_name, 'w') as f: + f.write (mac) + self.run_shell("sudo mv %s/default_pmac /etc/contrail/default_pmac" % (temp_dir_name)) + else: + raise KeyError, 'Interface %s Mac %s' % (str (dev), str (mac)) + netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0][ + 'netmask'] + if multi_net: + gateway= non_mgmt_gw + else: + gateway = self.find_gateway (dev) + cidr = str (netaddr.IPNetwork('%s/%s' % (vhost_ip, netmask))) + + template_vals = { + '__contrail_dev__' : 'dev=%s' % dev, + '__contrail_collector__' : collector_ip + } + self._template_substitute_write(agent_param_template, + template_vals, "agent_param") + self.run_shell("sudo mv agent_param /etc/contrail/agent_param") + + template_vals = { + '__contrail_box_ip__' : cidr, + '__contrail_gateway__' : gateway, + '__contrail_intf__' : dev, + '__contrail_disc_ip__' : discovery_ip, + '__contrail_instances__' : ncontrols, + '__contrail_control_ip__' : cfgm_ip, + } + self._template_substitute_write(agent_conf_template, + template_vals, "agent.conf") + self.run_shell("sudo mv agent.conf /etc/contrail/agent.conf") + + ## make ifcfg-vhost0 + with open ('%s/ifcfg-vhost0' % temp_dir_name, 'w') as f: + f.write ('''#Contrail vhost0 +DEVICE=vhost0 +ONBOOT=yes +BOOTPROTO=none +IPV6INIT=no +USERCTL=yes +IPADDR=%s +NETMASK=%s +NM_CONTROLLED=no +#NETWORK MANAGER BUG WORKAROUND +SUBCHANNELS=1,2,3 +''' % (vhost_ip, netmask )) + # Don't set gateway and DNS on vhost0 if on non-mgmt network + if not multi_net: + if gateway: + f.write('GATEWAY=%s\n' %( gateway ) ) + dns_list = self.get_dns_servers(dev) + for i, dns in enumerate(dns_list): + f.write('DNS%d=%s\n' % (i+1, dns)) + domain_list = self.get_domain_search_list() + if domain_list: + f.write('DOMAIN="%s"\n'% domain_list) + + prsv_cfg = [] + mtu = self.get_if_mtu (dev) + if mtu: + dcfg = 'MTU=%s' % str(mtu) + f.write(dcfg+'\n') + prsv_cfg.append (dcfg) + f.flush () +# if dev != 'vhost0': + self.run_shell("sudo mv %s/ifcfg-vhost0 /etc/sysconfig/network-scripts/ifcfg-vhost0" % (temp_dir_name)) + ## make ifcfg-$dev + if not os.path.isfile ( + '/etc/sysconfig/network-scripts/ifcfg-%s.rpmsave' % dev): + self.run_shell("sudo cp /etc/sysconfig/network-scripts/ifcfg-%s /etc/sysconfig/network-scripts/ifcfg-%s.rpmsave" % (dev, dev)) + self._rewrite_ifcfg_file('%s/ifcfg-%s' % (temp_dir_name, dev), dev, prsv_cfg) + + if multi_net : + self.migrate_routes(dev) + + self.run_shell("sudo mv %s/ifcfg-%s /etc/contrail/" % (temp_dir_name, dev)) + + self.run_shell("sudo chkconfig network on") + self.run_shell("sudo chkconfig supervisor-vrouter on") + else: # of if dev and dev != 'vhost0' + # allow for updating anything except self-ip/gw and eth-port + self.run_shell("sudo sed 's/COLLECTOR=.*/COLLECTOR=%s/g' /etc/contrail/agent_param > agent_param.new" %(collector_ip)) + self.run_shell("sudo mv agent_param.new /etc/contrail/agent_param") + + self.run_shell("sudo cp /etc/contrail/agent.conf %s/agent.conf" %(temp_dir_name)) + agent_tree = ET.parse('%s/agent.conf' %(temp_dir_name)) + agent_root = agent_tree.getroot() + agent_elem = agent_root.find('agent') + self._replace_discovery_server(agent_elem, discovery_ip, ncontrols) + + agent_tree = agent_tree.write('%s/agent.conf' %(temp_dir_name)) + self.run_shell("sudo cp %s/agent.conf /etc/contrail/agent.conf" %(temp_dir_name)) + self.run_shell("sudo rm %s/agent.conf" %(temp_dir_name)) + #end if dev and dev != 'vhost0' : + + # role == compute && !cfgm + + if 'webui' in self._args.role: + openstack_ip = self._args.openstack_ip + self.run_shell("sudo sed \"s/config.cnfg.server_ip.*/config.cnfg.server_ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(cfgm_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + self.run_shell("sudo sed \"s/config.networkManager.ip.*/config.networkManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(cfgm_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + self.run_shell("sudo sed \"s/config.imageManager.ip.*/config.imageManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + self.run_shell("sudo sed \"s/config.computeManager.ip.*/config.computeManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + self.run_shell("sudo sed \"s/config.identityManager.ip.*/config.identityManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + self.run_shell("sudo sed \"s/config.storageManager.ip.*/config.storageManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + if collector_ip: + self.run_shell("sudo sed \"s/config.analytics.server_ip.*/config.analytics.server_ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(collector_ip)) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + if self._args.cassandra_ip_list: + self.run_shell("sudo sed \"s/config.cassandra.server_ips.*/config.cassandra.server_ips = %s;/g\" /etc/contrail/config.global.js > config.global.js.new" %(str(self._args.cassandra_ip_list))) + self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + + """ + if 'config' in self._args.role and self._args.use_certs: + local("sudo ./contrail_setup_utils/setup-pki.sh /etc/contrail/ssl") + """ + + #end fixup_config_files + + def add_vnc_config(self): + if 'compute' in self._args.role: + cfgm_ip = self._args.cfgm_ip + compute_ip = self._args.compute_ip + compute_hostname = socket.gethostname() + with settings(host_string = 'root@%s' %(cfgm_ip), password = env.password): + prov_args = "--host_name %s --host_ip %s --api_server_ip %s --oper add " \ + "--admin_user %s --admin_password %s --admin_tenant_name %s" \ + %(compute_hostname, compute_ip, cfgm_ip, ks_admin_user, ks_admin_password, ks_admin_tenant_name) + run("source /opt/contrail/api-venv/bin/activate && python /opt/contrail/utils/provision_vrouter.py %s" %(prov_args)) + #end add_vnc_config + + def cleanup(self): + os.removedirs(self._temp_dir_name) + #end cleanup + + def do_setup(self): + # local configuration + self.fixup_config_files() + + # global vnc configuration + # self.add_vnc_config() dsetia disabled temporarily + + self.cleanup() + #end do_setup + + def run_services(self): + if 'database' in self._args.role: + local("sudo ./contrail_setup_utils/database-server-setup.sh %s" % (self._args.database_listen_ip)) + + if 'openstack' in self._args.role: + local("sudo ./contrail_setup_utils/keystone-server-setup.sh") + local("sudo ./contrail_setup_utils/glance-server-setup.sh") + local("sudo ./contrail_setup_utils/cinder-server-setup.sh") + local("sudo ./contrail_setup_utils/nova-server-setup.sh") + + if 'config' in self._args.role: + openstack_ip = self._args.openstack_ip + quantum_ip = self._args.cfgm_ip + local("sudo ./contrail_setup_utils/config-server-setup.sh") + local("sudo ./contrail_setup_utils/quantum-server-setup.sh") + with settings(host_string = 'root@%s' %(openstack_ip), password = env.password): + put("/opt/contrail/contrail_installer/contrail_setup_utils/setup-quantum-in-keystone.py", + "/root/setup-quantum-in-keystone.py") + quant_args = "--quant_server_ip %s --tenant %s --user %s --password %s --svc_password %s" \ + %(quantum_ip, ks_admin_tenant_name, ks_admin_user, ks_admin_password, self.service_token) + run("python /root/setup-quantum-in-keystone.py %s" %(quant_args)) + + if 'collector' in self._args.role: + if self._args.num_collector_nodes: + local("sudo ./contrail_setup_utils/collector-server-setup.sh multinode") + else: + local("sudo ./contrail_setup_utils/collector-server-setup.sh") + + if 'control' in self._args.role: + local("sudo ./contrail_setup_utils/control-server-setup.sh") + + if 'compute' in self._args.role: + if self._fixed_qemu_conf: + local("sudo service libvirtd restart") + + if self._args.compute_ip : + # running compute-server-setup.sh on cfgm sets nova.conf's + # sql access from ip instead of localhost, causing privilege + # degradation for nova tables + local("sudo ./contrail_setup_utils/compute-server-setup.sh") + + if 'webui' in self._args.role: + local("sudo ./contrail_setup_utils/webui-server-setup.sh") + + #end run_services + +#end class Setup + +def main(args_str = None): + setup_obj = Setup(args_str) + setup_obj.do_setup() +#end main + +if __name__ == "__main__": + main() diff --git a/stack.sh b/stack.sh index 03d5632495..a77e878a5b 100755 --- a/stack.sh +++ b/stack.sh @@ -1334,6 +1334,175 @@ fi # Check the status of running services service_check +# Contrail +function insert_vrouter() { + source /etc/contrail/agent_param + source $VHOST_CFG + sudo insmod $CONTRAIL_SRC/$kmod + + echo "Creating vhost interface: $DEVICE." + VIF=$CONTRAIL_SRC/build/debug/vrouter/utils/vif + DEV_MAC=$(cat /sys/class/net/$dev/address) + sudo $VIF --create $DEVICE --mac $DEV_MAC + if [ $? != 0 ] + then + echo "Error creating interface: $DEVICE" + fi + + echo "Adding $DEVICE to vrouter" + sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost + if [ $? != 0 ] + then + echo "Error adding $DEVICE to vrouter" + fi + + echo "Adding $dev to vrouter" + sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical + if [ $? != 0 ] + then + echo "Error adding $dev to vrouter" + fi + + echo "Sleeping 10 seconds to allow link state to settle" + sudo ifup $DEVICE + sudo cp /etc/contrail/ifcfg-$dev /etc/sysconfig/network-scripts + sleep 10 + echo "Restarting network service" + sudo service network restart +} + +# Create the destination directory and ensure it is writable by the user +DEST=${DEST:-/opt/contrail} +sudo mkdir -p $DEST +if [ ! -w $DEST ]; then + sudo chown `whoami` $DEST +fi + +# Destination path for service data +DATA_DIR=${DATA_DIR:-${DEST}/data} +sudo mkdir -p $DATA_DIR +sudo chown `whoami` $DATA_DIR + +SCREEN_NAME="contrail" +screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash +sleep 1 +# Set a reasonable status bar +screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" + +PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` +sudo mkdir -p /var/log/contrail +sudo chmod 777 /var/log/contrail + +# basic dependencies +if ! command_exists repo ; then + mkdir -p ~/bin + PATH=~/bin:$PATH + sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo + sudo chmod a+x ~/bin/repo +fi + +# dependencies +if [ $ENABLE_CONTRAIL ]; then + sudo yum -y install patch scons flex bison make vim + sudo yum -y install expat-devel gettext-devel curl-devel + sudo yum -y install gcc-c++ python-devel autoconf automake + sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + + # api server requirements + sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + sudo pip install netifaces fabric argparse + sudo pip install stevedore xmltodict python-keystoneclient + sudo pip install kazoo +fi + +CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} +mkdir -p $CONTRAIL_SRC +contrail_cwd=$(pwd) +cd $CONTRAIL_SRC +if [ ! -d $CONTRAIL_SRC/.repo ]; then + repo init -u git@github.com:Juniper/contrail-vnc +fi +repo sync +python third_party/fetch_packages.py +scons +cd ${contrail_cwd} + +# get cassandra +if [ ! -f "/usr/sbin/cassandra" ] ; then + cat << EOF > datastax.repo +[datastax] +name = DataStax Repo for Apache Cassandra +baseurl = http://rpm.datastax.com/community +enabled = 1 +gpgcheck = 0 +EOF + sudo mv datastax.repo /etc/yum.repos.d/ + sudo yum -y install dsc20 +fi + +# get ifmap +if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + unzip irond-0.3.0-bin.zip + cd ${contrail_cwd} +fi + +if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz + tar xvzf zookeeper-3.4.5.tar.gz + cd zookeeper-3.4.5 + cp conf/zoo_sample.cfg conf/zoo.cfg + cd ${contrail_cwd} +fi + +# ncclient +if [ ! -d $PYLIBPATH/ncclient ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + sudo pip install ncclient-v0.3.2.tar.gz + cd ${contrail_cwd} +fi + +# create config files +# python $TOP_DIR/setup_contrail.py --physical_interface $CONTRAIL_USE_INTF +python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST + +# install contrail modules +echo "Installing contrail modules" +sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + +# launch ... +screen_it cass "sudo /usr/sbin/cassandra -f" +screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" +screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" +sleep 2 +screen_it apiSrv "python $PYLIBPATH/vnc_cfg_api_server/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" +echo "Waiting for api-server to start..." +if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:${API_SERVER_PORT}; do sleep 1; done"; then + echo "api-server did not start" + exit 1 +fi +sleep 2 +screen_it schema "python $PYLIBPATH/schema_transformer/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" + +source /etc/contrail/control_param +screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + +# vrouter +if [ $(lsmod | grep vrouter) ]; then + echo "vrouter module already inserted." +else + insert_vrouter + echo "vrouter kernel module inserted." +fi + +source /etc/contrail/agent_param +screen_it agent "sudo env LD_LIBRARY_PATH=/opt/stack/contrail/build/lib bash -c \"$CONTRAIL_SRC/build/debug/vnsw/agent/vnswad --config-file $CONFIG $LOGFILE\"" # Fin # === diff --git a/stackrc b/stackrc index 3a338d16f2..1252969e43 100644 --- a/stackrc +++ b/stackrc @@ -33,6 +33,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent # Set the default Nova APIs to enable NOVA_ENABLED_APIS=ec2,osapi_compute,metadata diff --git a/unstack.sh b/unstack.sh index 05d9fb7c83..93c2562a6a 100755 --- a/unstack.sh +++ b/unstack.sh @@ -135,4 +135,13 @@ if is_service_enabled trove; then cleanup_trove fi +# Contrail +SCREEN=$(which screen) +if [[ -n "$SCREEN" ]]; then + SESSION=$(screen -ls | awk '/[0-9].contrail/ { print $1 }') + if [[ -n "$SESSION" ]]; then + screen -X -S $SESSION quit + fi +fi + cleanup_tmp From b097cb138610817e38cc451cb9703d9692c0ab65 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Sat, 28 Sep 2013 05:33:39 -0700 Subject: [PATCH 002/179] 1. rename LOGFILE in config files to avoid conflict with stach.sh 2. Enable launch of discovery server 3. cleanup setup file slightly 4. Fix launch of agent as it was failing 5. support unstack.sh which cleans up vhost0 and removes the vrouter module --- contrail_config_templates.py | 6 ++-- setup_contrail.py | 62 +----------------------------------- stack.sh | 30 +++++++++++++---- stackrc | 2 +- unstack.sh | 7 ++++ 5 files changed, 35 insertions(+), 72 deletions(-) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index 9ffd1d8bb5..02791a1f6d 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -111,7 +111,7 @@ HOSTIP=$__contrail_host_ip__ BGP_PORT=$__contrail_bgp_port__ CERT_OPTS=$__contrail_cert_ops__ -LOGFILE=$__contrail_logfile__ +CONTROL_LOGFILE=$__contrail_logfile__ LOG_LOCAL=$__contrail_log_local__ """) @@ -125,7 +125,7 @@ DISCOVERY=$__contrail_discovery_ip__ HOSTIP=$__contrail_host_ip__ CERT_OPTS=$__contrail_cert_ops__ -LOGFILE=$__contrail_logfile__ +DNS_LOGFILE=$__contrail_logfile__ LOG_LOCAL=$__contrail_log_local__ """) @@ -229,7 +229,7 @@ pname=vnswad LIBDIR=/usr/lib64 VHOST_CFG=/etc/sysconfig/network-scripts/ifcfg-vhost0 -LOGFILE=--log-file=/var/log/contrail/vrouter.log +VROUTER_LOGFILE=--log-file=/var/log/contrail/vrouter.log COLLECTOR=$__contrail_collector__ $__contrail_dev__ """) diff --git a/setup_contrail.py b/setup_contrail.py index c38831446c..d671a8690a 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -167,7 +167,7 @@ def _parse_args(self, args_str): # dsetia self._args.openstack_ip = self._args.cfgm_ip self._args.collector_ip = self._args.cfgm_ip - # self._args.discovery_ip = self._args.cfgm_ip + self._args.discovery_ip = self._args.cfgm_ip self._args.control_ip = self._args.cfgm_ip self._args.compute_ip = self._args.cfgm_ip self._args.openstack_mgmt_ip = self._args.cfgm_ip @@ -756,20 +756,6 @@ def fixup_config_files(self): self.run_shell("sudo chkconfig network on") self.run_shell("sudo chkconfig supervisor-vrouter on") - else: # of if dev and dev != 'vhost0' - # allow for updating anything except self-ip/gw and eth-port - self.run_shell("sudo sed 's/COLLECTOR=.*/COLLECTOR=%s/g' /etc/contrail/agent_param > agent_param.new" %(collector_ip)) - self.run_shell("sudo mv agent_param.new /etc/contrail/agent_param") - - self.run_shell("sudo cp /etc/contrail/agent.conf %s/agent.conf" %(temp_dir_name)) - agent_tree = ET.parse('%s/agent.conf' %(temp_dir_name)) - agent_root = agent_tree.getroot() - agent_elem = agent_root.find('agent') - self._replace_discovery_server(agent_elem, discovery_ip, ncontrols) - - agent_tree = agent_tree.write('%s/agent.conf' %(temp_dir_name)) - self.run_shell("sudo cp %s/agent.conf /etc/contrail/agent.conf" %(temp_dir_name)) - self.run_shell("sudo rm %s/agent.conf" %(temp_dir_name)) #end if dev and dev != 'vhost0' : # role == compute && !cfgm @@ -828,52 +814,6 @@ def do_setup(self): self.cleanup() #end do_setup - def run_services(self): - if 'database' in self._args.role: - local("sudo ./contrail_setup_utils/database-server-setup.sh %s" % (self._args.database_listen_ip)) - - if 'openstack' in self._args.role: - local("sudo ./contrail_setup_utils/keystone-server-setup.sh") - local("sudo ./contrail_setup_utils/glance-server-setup.sh") - local("sudo ./contrail_setup_utils/cinder-server-setup.sh") - local("sudo ./contrail_setup_utils/nova-server-setup.sh") - - if 'config' in self._args.role: - openstack_ip = self._args.openstack_ip - quantum_ip = self._args.cfgm_ip - local("sudo ./contrail_setup_utils/config-server-setup.sh") - local("sudo ./contrail_setup_utils/quantum-server-setup.sh") - with settings(host_string = 'root@%s' %(openstack_ip), password = env.password): - put("/opt/contrail/contrail_installer/contrail_setup_utils/setup-quantum-in-keystone.py", - "/root/setup-quantum-in-keystone.py") - quant_args = "--quant_server_ip %s --tenant %s --user %s --password %s --svc_password %s" \ - %(quantum_ip, ks_admin_tenant_name, ks_admin_user, ks_admin_password, self.service_token) - run("python /root/setup-quantum-in-keystone.py %s" %(quant_args)) - - if 'collector' in self._args.role: - if self._args.num_collector_nodes: - local("sudo ./contrail_setup_utils/collector-server-setup.sh multinode") - else: - local("sudo ./contrail_setup_utils/collector-server-setup.sh") - - if 'control' in self._args.role: - local("sudo ./contrail_setup_utils/control-server-setup.sh") - - if 'compute' in self._args.role: - if self._fixed_qemu_conf: - local("sudo service libvirtd restart") - - if self._args.compute_ip : - # running compute-server-setup.sh on cfgm sets nova.conf's - # sql access from ip instead of localhost, causing privilege - # degradation for nova tables - local("sudo ./contrail_setup_utils/compute-server-setup.sh") - - if 'webui' in self._args.role: - local("sudo ./contrail_setup_utils/webui-server-setup.sh") - - #end run_services - #end class Setup def main(args_str = None): diff --git a/stack.sh b/stack.sh index a77e878a5b..6ad47c1623 100755 --- a/stack.sh +++ b/stack.sh @@ -1371,6 +1371,17 @@ function insert_vrouter() { sudo service network restart } +function test_insert_vrouter () +{ + lsmod | grep -q vrouter + if [ $? == 0 ]; then + echo "vrouter module already inserted." + else + insert_vrouter + echo "vrouter kernel module inserted." + fi +} + # Create the destination directory and ensure it is writable by the user DEST=${DEST:-/opt/contrail} sudo mkdir -p $DEST @@ -1481,6 +1492,8 @@ screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 +screen_it disco "python $PYLIBPATH/discovery/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" +sleep 2 screen_it apiSrv "python $PYLIBPATH/vnc_cfg_api_server/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:${API_SERVER_PORT}; do sleep 1; done"; then @@ -1494,15 +1507,18 @@ source /etc/contrail/control_param screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" # vrouter -if [ $(lsmod | grep vrouter) ]; then - echo "vrouter module already inserted." -else - insert_vrouter - echo "vrouter kernel module inserted." -fi +test_insert_vrouter +# agent source /etc/contrail/agent_param -screen_it agent "sudo env LD_LIBRARY_PATH=/opt/stack/contrail/build/lib bash -c \"$CONTRAIL_SRC/build/debug/vnsw/agent/vnswad --config-file $CONFIG $LOGFILE\"" +sudo cat > $TOP_DIR/vnsw.hlpr < Date: Mon, 30 Sep 2013 22:06:03 -0700 Subject: [PATCH 003/179] Specify the API server port for validation --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index 6ad47c1623..ca7c7a3215 100755 --- a/stack.sh +++ b/stack.sh @@ -1496,7 +1496,7 @@ screen_it disco "python $PYLIBPATH/discovery/disc_server_zk.py --conf_file /etc/ sleep 2 screen_it apiSrv "python $PYLIBPATH/vnc_cfg_api_server/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" echo "Waiting for api-server to start..." -if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:${API_SERVER_PORT}; do sleep 1; done"; then +if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" exit 1 fi From be8f0feffb2a17cee3f2139fee1b0e8258d6f56d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 30 Sep 2013 16:56:21 -0700 Subject: [PATCH 004/179] Make all contrail setup conditional --- stack.sh | 209 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/stack.sh b/stack.sh index ca7c7a3215..10dfbce658 100755 --- a/stack.sh +++ b/stack.sh @@ -1382,143 +1382,144 @@ function test_insert_vrouter () fi } -# Create the destination directory and ensure it is writable by the user -DEST=${DEST:-/opt/contrail} -sudo mkdir -p $DEST -if [ ! -w $DEST ]; then - sudo chown `whoami` $DEST -fi +if [ $ENABLE_CONTRAIL ]; then + # Create the destination directory and ensure it is writable by the user + DEST=${DEST:-/opt/contrail} + sudo mkdir -p $DEST + if [ ! -w $DEST ]; then + sudo chown `whoami` $DEST + fi -# Destination path for service data -DATA_DIR=${DATA_DIR:-${DEST}/data} -sudo mkdir -p $DATA_DIR -sudo chown `whoami` $DATA_DIR + # Destination path for service data + DATA_DIR=${DATA_DIR:-${DEST}/data} + sudo mkdir -p $DATA_DIR + sudo chown `whoami` $DATA_DIR -SCREEN_NAME="contrail" -screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash -sleep 1 -# Set a reasonable status bar -screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" + SCREEN_NAME="contrail" + screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash + sleep 1 + # Set a reasonable status bar + screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" -PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` -sudo mkdir -p /var/log/contrail -sudo chmod 777 /var/log/contrail + PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` + sudo mkdir -p /var/log/contrail + sudo chmod 777 /var/log/contrail -# basic dependencies -if ! command_exists repo ; then - mkdir -p ~/bin - PATH=~/bin:$PATH - sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo - sudo chmod a+x ~/bin/repo -fi + # basic dependencies + if ! command_exists repo ; then + mkdir -p ~/bin + PATH=~/bin:$PATH + sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo + sudo chmod a+x ~/bin/repo + fi -# dependencies -if [ $ENABLE_CONTRAIL ]; then + # dependencies sudo yum -y install patch scons flex bison make vim sudo yum -y install expat-devel gettext-devel curl-devel sudo yum -y install gcc-c++ python-devel autoconf automake sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel # api server requirements - sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + sudo pip install gevent geventhttpclient==1.0a thrift sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient sudo pip install kazoo -fi -CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} -mkdir -p $CONTRAIL_SRC -contrail_cwd=$(pwd) -cd $CONTRAIL_SRC -if [ ! -d $CONTRAIL_SRC/.repo ]; then - repo init -u git@github.com:Juniper/contrail-vnc -fi -repo sync -python third_party/fetch_packages.py -scons -cd ${contrail_cwd} + CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} + mkdir -p $CONTRAIL_SRC + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC + if [ ! -d $CONTRAIL_SRC/.repo ]; then + repo init -u git@github.com:Juniper/contrail-vnc + fi + repo sync + python third_party/fetch_packages.py + scons + cd ${contrail_cwd} -# get cassandra -if [ ! -f "/usr/sbin/cassandra" ] ; then - cat << EOF > datastax.repo + # get cassandra + if [ ! -f "/usr/sbin/cassandra" ] ; then + cat << EOF > datastax.repo [datastax] name = DataStax Repo for Apache Cassandra baseurl = http://rpm.datastax.com/community enabled = 1 gpgcheck = 0 EOF - sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install dsc20 -fi + sudo mv datastax.repo /etc/yum.repos.d/ + sudo yum -y install dsc20 + fi -# get ifmap -if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip - unzip irond-0.3.0-bin.zip - cd ${contrail_cwd} -fi - -if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz - tar xvzf zookeeper-3.4.5.tar.gz - cd zookeeper-3.4.5 - cp conf/zoo_sample.cfg conf/zoo.cfg - cd ${contrail_cwd} -fi - -# ncclient -if [ ! -d $PYLIBPATH/ncclient ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz - sudo pip install ncclient-v0.3.2.tar.gz - cd ${contrail_cwd} -fi + # get ifmap + if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + unzip irond-0.3.0-bin.zip + cd ${contrail_cwd} + fi -# create config files -# python $TOP_DIR/setup_contrail.py --physical_interface $CONTRAIL_USE_INTF -python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST + if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz + tar xvzf zookeeper-3.4.5.tar.gz + cd zookeeper-3.4.5 + cp conf/zoo_sample.cfg conf/zoo.cfg + cd ${contrail_cwd} + fi -# install contrail modules -echo "Installing contrail modules" -sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + # ncclient + if [ ! -d $PYLIBPATH/ncclient ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + sudo pip install ncclient-v0.3.2.tar.gz + cd ${contrail_cwd} + fi -# launch ... -screen_it cass "sudo /usr/sbin/cassandra -f" -screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" -screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" -sleep 2 -screen_it disco "python $PYLIBPATH/discovery/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" -sleep 2 -screen_it apiSrv "python $PYLIBPATH/vnc_cfg_api_server/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" -echo "Waiting for api-server to start..." -if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then - echo "api-server did not start" - exit 1 -fi -sleep 2 -screen_it schema "python $PYLIBPATH/schema_transformer/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" + # create config files + # python $TOP_DIR/setup_contrail.py --physical_interface $CONTRAIL_USE_INTF + python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST + + # install contrail modules + echo "Installing contrail modules" + sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + + # launch ... + screen_it cass "sudo /usr/sbin/cassandra -f" + screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" + screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" + sleep 2 + screen_it disco "python $PYLIBPATH/discovery/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" + sleep 2 + screen_it apiSrv "python $PYLIBPATH/vnc_cfg_api_server/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" + echo "Waiting for api-server to start..." + if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then + echo "api-server did not start" + exit 1 + fi + sleep 2 + screen_it schema "python $PYLIBPATH/schema_transformer/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" -source /etc/contrail/control_param -screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + source /etc/contrail/control_param + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" -# vrouter -test_insert_vrouter + # vrouter + test_insert_vrouter -# agent -source /etc/contrail/agent_param -sudo cat > $TOP_DIR/vnsw.hlpr < $TOP_DIR/vnsw.hlpr < Date: Thu, 3 Oct 2013 10:17:32 -0700 Subject: [PATCH 005/179] Handle error removing vrouter module --- unstack.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/unstack.sh b/unstack.sh index a3087e7d2f..e3767fbc20 100755 --- a/unstack.sh +++ b/unstack.sh @@ -145,10 +145,12 @@ if [[ -n "$SCREEN" ]]; then fi cmd=$(lsmod | grep vrouter) if [ $? == 0 ]; then - sudo rmmod vrouter - source /etc/contrail/agent_param - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-$dev - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-vhost0 + cmd=$(sudo rmmod vrouter) + if [ $? == 0 ]; then + source /etc/contrail/agent_param + sudo rm -f /etc/sysconfig/network-scripts/ifcfg-$dev + sudo rm -f /etc/sysconfig/network-scripts/ifcfg-vhost0 + fi fi cleanup_tmp From 2987f81dcd3045891f27e1f628b074c60445c8fd Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 3 Oct 2013 12:08:25 -0700 Subject: [PATCH 006/179] Add suport for neutron contrail patch --- neutron.patch | 4668 +++++++++++++++++++++++++++++++++++++++++++++++++ stack.sh | 65 +- stackrc | 3 + 3 files changed, 4711 insertions(+), 25 deletions(-) create mode 100644 neutron.patch diff --git a/neutron.patch b/neutron.patch new file mode 100644 index 0000000000..9f1ed60402 --- /dev/null +++ b/neutron.patch @@ -0,0 +1,4668 @@ +diff --git etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini +new file mode 100644 +index 0000000..ba1afba +--- /dev/null ++++ etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini +@@ -0,0 +1,4 @@ ++# Juniper plugin specific configuration ++ ++# JunosVContrail specifc configuration for plugin ++[JunosVContrail] +diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py +new file mode 100644 +index 0000000..5d610b3 +--- /dev/null ++++ neutron/extensions/ipam.py +@@ -0,0 +1,140 @@ ++from abc import abstractmethod ++ ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron.api import extensions ++from neutron import manager ++from oslo.config import cfg ++ ++ ++# Ipam Exceptions ++class IpamNotFound(qexception.NotFound): ++ message = _("IPAM %(id)s could not be found") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'ipams': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:regex': attr.UUID_PATTERN}, ++ 'is_visible': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'fq_name': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ 'mgmt': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': None}, ++ 'nets_using': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True, 'default': ''} ++ }, ++} ++ ++# TODO should this be tied to ipam extension? ++EXTENDED_ATTRIBUTES_2_0 = { ++ 'networks': { ++ 'contrail:fq_name': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:policys': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ 'contrail:subnet_ipam': {'allow_post': False, ++ 'allow_put': False, ++ 'default': '', ++ 'is_visible': True}, ++ }, ++ 'subnets': { ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:ipam_fq_name': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ } ++} ++ ++ ++class Ipam(object): ++ ++ @classmethod ++ def get_name(cls): ++ return "Network IP Address Management" ++ ++ @classmethod ++ def get_alias(cls): ++ return "ipam" ++ ++ @classmethod ++ def get_description(cls): ++ return ("Configuration object for holding common to a set of" ++ " IP address blocks") ++ ++ @classmethod ++ def get_namespace(cls): ++ return "http://docs.openstack.org/TODO" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2012-07-20T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ exts = [] ++ plugin = manager.QuantumManager.get_plugin() ++ for resource_name in ['ipam']: ++ collection_name = resource_name + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) ++ ++ member_actions = {} ++ ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, ++ member_actions=member_actions) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ member_actions=member_actions) ++ exts.append(ex) ++ ++ return exts ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return EXTENDED_ATTRIBUTES_2_0 ++ else: ++ return {} ++#end class Ipam ++ ++ ++class IpamPluginBase(object): ++ ++ @abstractmethod ++ def create_ipam(self, context, ipam): ++ pass ++ ++ @abstractmethod ++ def update_ipam(self, context, id, ipam): ++ pass ++ ++ @abstractmethod ++ def get_ipam(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def delete_ipam(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_ipams(self, context, filters=None, fields=None): ++ pass ++#end class IpamPluginBase +diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py +new file mode 100644 +index 0000000..cb64c50 +--- /dev/null ++++ neutron/plugins/juniper/contrail/contrailplugin.py +@@ -0,0 +1,1160 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++ ++import ConfigParser ++import logging ++from pprint import pformat ++ ++#from neutron.manager import NeutronManager ++from neutron.common import exceptions as exc ++from neutron.db import db_base_plugin_v2 ++from neutron.extensions import l3 ++from neutron.extensions import securitygroup ++#from neutron.extensions import vpcroutetable ++ ++import cgitb ++from httplib2 import Http ++from oslo.config import cfg ++import re ++import string ++import sys ++ ++import ctdb.config_db ++ ++LOG = logging.getLogger(__name__) ++ ++vnc_opts = [ ++ cfg.StrOpt('api_server_ip', default='127.0.0.1'), ++ cfg.StrOpt('api_server_port', default='8082'), ++] ++ ++ ++def _read_cfg(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.get(section, option) ++ except (AttributeError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++def _read_cfg_boolean(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.getboolean(section, option) ++ except (AttributeError, ValueError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, ++ l3.RouterPluginBase, ++ securitygroup.SecurityGroupPluginBase): ++#vpcroutetable.RouteTablePluginBase): ++ ++ supported_extension_aliases = ["ipam", "policy", "security-group", ++ "router", "route-table", "port-security"] ++ __native_bulk_support = False ++ _cfgdb = None ++ _args = None ++ _tenant_id_dict = {} ++ _tenant_name_dict = {} ++ ++ @classmethod ++ def _parse_class_args(cls, cfg_parser): ++ cfg_parser.read("/etc/neutron/plugins/juniper/" ++ "contrail/ContrailPlugin.ini" ++ ) ++ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', ++ 'multi_tenancy', False) ++ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') ++ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') ++ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', ++ 'user1') ++ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_password', 'password1') ++ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_tenant_name', ++ 'default-domain') ++ cls._tenants_api = '%s/tenants' % (cls._auth_url) ++ pass ++ ++ @classmethod ++ def _connect_to_db(cls): ++ """ ++ Many instantiations of plugin (base + extensions) but need to have ++ only one config db conn (else error from ifmap-server) ++ """ ++ cls._cfgdb_map = {} ++ if cls._cfgdb is None: ++ sip = cfg.CONF.APISERVER.api_server_ip ++ sport = cfg.CONF.APISERVER.api_server_port ++ # Initialize connection to DB and add default entries ++ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, ++ cls._admin_password, ++ cls._admin_tenant_name, ++ sip, sport) ++ cls._cfgdb.manager = cls ++ ++ @classmethod ++ def _get_user_cfgdb(cls, context): ++ if not cls._multi_tenancy: ++ return cls._cfgdb ++ user_id = context.user_id ++ role = string.join(context.roles, ",") ++ if user_id not in cls._cfgdb_map: ++ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( ++ cls._admin_user, cls._admin_password, cls._admin_tenant_name, ++ cfg.CONF.APISERVER.api_server_ip, ++ cfg.CONF.APISERVER.api_server_port, ++ user_info={'user_id': user_id, 'role': role}) ++ cls._cfgdb_map[user_id].manager = cls ++ ++ return cls._cfgdb_map[user_id] ++ ++ @classmethod ++ def _tenant_list_from_keystone(cls): ++ # get all tenants ++ hdrs = {'X-Auth-Token': cls._admin_token, ++ 'Content-Type': 'application/json'} ++ try: ++ rsp, content = Http().request(cls._tenants_api, ++ method="GET", headers=hdrs) ++ if rsp.status != 200: ++ return ++ except Exception: ++ return ++ ++ # transform needed for python compatibility ++ content = re.sub('true', 'True', content) ++ content = re.sub('null', 'None', content) ++ content = eval(content) ++ ++ # bail if response is unexpected ++ if 'tenants' not in content: ++ return ++ ++ # create a dictionary for id->name and name->id mapping ++ for tenant in content['tenants']: ++ print 'Adding tenant %s:%s to cache' % (tenant['name'], ++ tenant['id']) ++ cls._tenant_id_dict[tenant['id']] = tenant['name'] ++ cls._tenant_name_dict[tenant['name']] = tenant['id'] ++ ++ def update_security_group(self, context, id, security_group): ++ pass ++ ++ def __init__(self): ++ cfg.CONF.register_opts(vnc_opts, 'APISERVER') ++ ++ cfg_parser = ConfigParser.ConfigParser() ++ ContrailPlugin._parse_class_args(cfg_parser) ++ ++ ContrailPlugin._connect_to_db() ++ self._cfgdb = ContrailPlugin._cfgdb ++ ++ ContrailPlugin._tenant_list_from_keystone() ++ ++ @classmethod ++ def tenant_id_to_name(cls, id): ++ # bail if we never built the list successfully ++ if len(cls._tenant_id_dict) == 0: ++ return id ++ # check cache ++ if id in cls._tenant_id_dict: ++ return cls._tenant_id_dict[id] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id ++ ++ @classmethod ++ def tenant_name_to_id(cls, name): ++ # bail if we never built the list successfully ++ if len(cls._tenant_name_dict) == 0: ++ return name ++ # check cache ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ else: ++ return name ++ ++ # Network API handlers ++ def create_network(self, context, network): ++ """ ++ Creates a new Virtual Network, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_create(network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("create_network(): " + pformat(net_dict) + "\n") ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_network(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_read(id, fields) ++ ++ # verify transformation is conforming to api ++ if not fields: ++ # should return all fields ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ fields, False) ++ net_dict.update(net_info['q_extra_data']) ++ else: ++ net_dict = net_info['q_api_data'] ++ ++ LOG.debug("get_network(): " + pformat(net_dict)) ++ return self._fields(net_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_network(self, context, net_id, network): ++ """ ++ Updates the attributes of a particular Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_update(net_id, network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("update_network(): " + pformat(net_dict)) ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_network(self, context, net_id): ++ """ ++ Deletes the network with the specified network identifier ++ belonging to the specified tenant. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.network_delete(net_id) ++ LOG.debug("delete_network(): " + pformat(net_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_info = cfgdb.network_list(filters) ++ ++ nets_dicts = [] ++ for n_info in nets_info: ++ # verify transformation is conforming to api ++ n_dict = self._make_network_dict(n_info['q_api_data'], fields, ++ False) ++ ++ n_dict.update(n_info['q_extra_data']) ++ nets_dicts.append(n_dict) ++ ++ LOG.debug( ++ "get_networks(): filters: " + pformat(filters) + " data: " ++ + pformat(nets_dicts)) ++ return nets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_count = cfgdb.network_count(filters) ++ LOG.debug("get_networks_count(): " + str(nets_count)) ++ return nets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Subnet API handlers ++ def create_subnet(self, context, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_create(subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("create_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnet(self, context, subnet_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_read(subnet_id) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], ++ fields) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("get_subnet(): " + pformat(subnet_dict)) ++ return self._fields(subnet_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_subnet(self, context, subnet_id, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("update_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_subnet(self, context, subnet_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.subnet_delete(subnet_id) ++ ++ LOG.debug("delete_subnet(): " + pformat(subnet_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets(self, context, filters=None, fields=None): ++ """ ++ Called from Neutron API -> get_ ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_info = cfgdb.subnets_list(filters) ++ ++ subnets_dicts = [] ++ for sn_info in subnets_info: ++ # verify transformation is conforming to api ++ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) ++ ++ sn_dict.update(sn_info['q_extra_data']) ++ subnets_dicts.append(sn_dict) ++ ++ LOG.debug( ++ "get_subnets(): filters: " + pformat(filters) + " data: " ++ + pformat(subnets_dicts)) ++ return subnets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_count = cfgdb.subnets_count(filters) ++ LOG.debug("get_subnets_count(): " + str(subnets_count)) ++ return subnets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Ipam API handlers ++ def create_ipam(self, context, ipam): ++ """ ++ Creates a new IPAM, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_create(ipam['ipam']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("create_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipam(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("get_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_ipam(self, context, id, ipam): ++ """ ++ Updates the attributes of a particular IPAM. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_update(id, ipam) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("update_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_ipam(self, context, ipam_id): ++ """ ++ Deletes the ipam with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.ipam_delete(ipam_id) ++ ++ LOG.debug("delete_ipam(): " + pformat(ipam_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_info = cfgdb.ipam_list(filters) ++ ++ ipams_dicts = [] ++ for ipam_info in ipams_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ipams_dicts.append(ipam_dict) ++ ++ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) ++ return ipams_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_count = cfgdb.ipams_count(filters) ++ LOG.debug("get_ipams_count(): " + str(ipams_count)) ++ return ipams_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Policy API handlers ++ def create_policy(self, context, policy): ++ """ ++ Creates a new Policy, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_create(policy['policy']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("create_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("get_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_policy(self, context, id, policy): ++ """ ++ Updates the attributes of a particular Policy. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_update(id, policy) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("update_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_policy(self, context, policy_id): ++ """ ++ Deletes the Policy with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.policy_delete(policy_id) ++ ++ LOG.debug("delete_policy(): " + pformat(policy_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policys(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policys_info = cfgdb.policy_list(filters) ++ ++ policys_dicts = [] ++ for policy_info in policys_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ policys_dicts.append(policy_dict) ++ ++ LOG.debug("get_policys(): " + pformat(policys_dicts)) ++ return policys_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_count = cfgdb.policy_count(filters) ++ LOG.debug("get_policy_count(): " + str(policy_count)) ++ return policy_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Floating IP API handlers ++ def _make_floatingip_dict(self, floatingip, fields=None): ++ res = {'id': floatingip['id'], ++ 'tenant_id': floatingip['tenant_id'], ++ 'floating_ip_address': floatingip['floating_ip_address'], ++ 'floating_network_id': floatingip['floating_network_id'], ++ 'router_id': floatingip['router_id'], ++ 'port_id': floatingip['fixed_port_id'], ++ 'fixed_ip_address': floatingip['fixed_ip_address']} ++ return self._fields(res, fields) ++ ++ def create_floatingip(self, context, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("create_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_floatingip(self, context, fip_id, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_update(fip_id, ++ floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("update_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingip(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_read(id) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("get_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_floatingip(self, context, fip_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.floatingip_delete(fip_id) ++ LOG.debug("delete_floating(): " + pformat(fip_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fips_info = cfgdb.floatingip_list(filters) ++ ++ fips_dicts = [] ++ for fip_info in fips_info: ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ fips_dicts.append(fip_dict) ++ ++ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) ++ return fips_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ floatingips_count = cfgdb.floatingip_count(filters) ++ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) ++ return floatingips_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Port API handlers ++ def create_port(self, context, port): ++ """ ++ Creates a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_create(port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("create_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_port(self, context, port_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_read(port_id) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data'], fields) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("get_port(): " + pformat(port_dict)) ++ return self._fields(port_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_port(self, context, port_id, port): ++ """ ++ Updates the attributes of a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_update(port_id, port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("update_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_port(self, context, port_id): ++ """ ++ Deletes a port on a specified Virtual Network, ++ if the port contains a remote interface attachment, ++ the remote interface is first un-plugged and then the port ++ is deleted. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.port_delete(port_id) ++ LOG.debug("delete_port(): " + pformat(port_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports(self, context, filters=None, fields=None): ++ """ ++ Retrieves all port identifiers belonging to the ++ specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_info = cfgdb.port_list(filters) ++ ++ ports_dicts = [] ++ for p_info in ports_info: ++ # verify transformation is conforming to api ++ p_dict = self._make_port_dict(p_info['q_api_data'], fields) ++ ++ p_dict.update(p_info['q_extra_data']) ++ ports_dicts.append(p_dict) ++ ++ LOG.debug( ++ "get_ports(): filter: " + pformat(filters) + 'data: ' ++ + pformat(ports_dicts)) ++ return ports_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_count = cfgdb.port_count(filters) ++ LOG.debug("get_ports_count(): " + str(ports_count)) ++ return ports_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): ++ """ ++ Attaches a remote interface to the specified port on the ++ specified Virtual Network. ++ """ ++ port = self._get_port(tenant_id, net_id, port_id) ++ # Validate attachment ++ self._validate_attachment(tenant_id, net_id, port_id, ++ remote_interface_id) ++ if port['interface_id']: ++ raise exc.PortInUse(net_id=net_id, port_id=port_id, ++ att_id=port['interface_id']) ++ ++ def unplug_interface(self, tenant_id, net_id, port_id): ++ """ ++ Detaches a remote interface from the specified port on the ++ specified Virtual Network. ++ """ ++ self._get_port(tenant_id, net_id, port_id) ++ ++ # VPC route table handlers ++ def _make_route_table_routes_dict(self, route_table_route, fields=None): ++ res = {'prefix': route_table_route['prefix'], ++ 'next_hop': route_table_route['next_hop']} ++ ++ return self._fields(res, fields) ++ ++ def _make_route_table_dict(self, route_table, fields=None): ++ res = {'id': route_table['id'], ++ 'name': route_table['name'], ++ 'fq_name': route_table['fq_name'], ++ 'tenant_id': route_table['tenant_id']} ++ if route_table['routes']: ++ res['routes'] = [self._make_route_table_routes_dict(r) ++ for r in route_table['routes']['route']] ++ return self._fields(res, fields) ++ ++ def create_route_table(self, context, route_table): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_create( ++ route_table['route_table']) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_route_table(self, context, id, route_table): ++ """ ++ Updates the attributes of a particular route table. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_update(id, route_table['route_table']) ++ ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_route_table(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.route_table_delete(id) ++ LOG.debug("delete_route_table(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_tables(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ route_tables_info = cfgdb.route_table_list(context, filters) ++ ++ route_tables_dicts = [] ++ for rt_info in route_tables_info: ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ route_tables_dicts.append(rt_dict) ++ ++ LOG.debug( ++ "get_route_tables(): filter: " + pformat(filters) ++ + 'data: ' + pformat(route_tables_dicts)) ++ return route_tables_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_table(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_read(id) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ ++ LOG.debug("get_route_table(): " + pformat(rt_dict)) ++ return self._fields(rt_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # VPC route table svc instance handlers ++ def _make_svc_instance_dict(self, svc_instance, fields=None): ++ res = {'id': svc_instance['id'], ++ 'name': svc_instance['name'], ++ 'tenant_id': svc_instance['tenant_id']} ++ if svc_instance['internal_net']: ++ res['internal_net'] = svc_instance['internal_net'] ++ if svc_instance['external_net']: ++ res['external_net'] = svc_instance['external_net'] ++ return self._fields(res, fields) ++ ++ def create_nat_instance(self, context, nat_instance): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_create( ++ nat_instance['nat_instance']) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("create_nat_instance(): " + pformat(si_dict)) ++ return si_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_nat_instance(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.svc_instance_delete(id) ++ LOG.debug("delete_nat_instance(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instances(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ svc_instances_info = cfgdb.svc_instance_list(context, filters) ++ ++ svc_instances_dicts = [] ++ for si_info in svc_instances_info: ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ svc_instances_dicts.append(si_dict) ++ ++ LOG.debug( ++ "get_nat_instances(): filter: " + pformat(filters) ++ + 'data: ' + pformat(svc_instances_dicts)) ++ return svc_instances_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instance(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_read(id) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("get_nat_instance(): " + pformat(si_dict)) ++ return self._fields(si_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Security Group handlers ++ def _make_security_group_rule_dict(self, security_group_rule, fields=None): ++ res = {'id': security_group_rule['id'], ++ 'tenant_id': security_group_rule['tenant_id'], ++ 'security_group_id': security_group_rule['security_group_id'], ++ 'ethertype': security_group_rule['ethertype'], ++ 'direction': security_group_rule['direction'], ++ 'protocol': security_group_rule['protocol'], ++ 'port_range_min': security_group_rule['port_range_min'], ++ 'port_range_max': security_group_rule['port_range_max'], ++ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], ++ 'remote_group_id': security_group_rule['remote_group_id']} ++ ++ return self._fields(res, fields) ++ ++ def _make_security_group_dict(self, security_group, fields=None): ++ res = {'id': security_group['id'], ++ 'name': security_group['name'], ++ 'tenant_id': security_group['tenant_id'], ++ 'description': security_group['description']} ++ res['security_group_rules'] = [self._make_security_group_rule_dict(r) ++ for r in security_group['rules']] ++ return self._fields(res, fields) ++ ++ def create_security_group(self, context, security_group): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_create( ++ security_group['security_group']) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("create_security_group(): " + pformat(sg_dict)) ++ return sg_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_delete(id) ++ LOG.debug("delete_security_group(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_groups(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_groups_info = cfgdb.security_group_list(context, filters) ++ ++ security_groups_dicts = [] ++ for sg_info in security_groups_info: ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ security_groups_dicts.append(sg_dict) ++ ++ LOG.debug( ++ "get_security_groups(): filter: " + pformat(filters) ++ + 'data: ' + pformat(security_groups_dicts)) ++ return security_groups_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_read(id) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("get_security_group(): " + pformat(sg_dict)) ++ return self._fields(sg_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def create_security_group_rule(self, context, security_group_rule): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_create( ++ security_group_rule['security_group_rule']) ++ ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data']) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) ++ return sgr_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group_rule(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_rule_delete(id) ++ LOG.debug("delete_security_group_rule(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rules(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_group_rules_info = cfgdb.security_group_rule_list(filters) ++ ++ security_group_rules_dicts = [] ++ for sgr_info in security_group_rules_info: ++ for sgr in sgr_info: ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr['q_api_data'], fields) ++ sgr_dict.update(sgr['q_extra_data']) ++ security_group_rules_dicts.append(sgr_dict) ++ ++ LOG.debug( ++ "get_security_group_rules(): filter: " + pformat(filters) + ++ 'data: ' + pformat(security_group_rules_dicts)) ++ return security_group_rules_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rule(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_read(id) ++ ++ # verify transformation is conforming to api ++ sgr_dict = {} ++ if sgr_info != {}: ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data'], fields) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) ++ return self._fields(sgr_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e +diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py +new file mode 100644 +index 0000000..a69dda1 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/config_db.py +@@ -0,0 +1,2235 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++import json ++import re ++import requests ++import socket ++import time ++import uuid ++from netaddr import IPNetwork, IPSet, IPAddress ++ ++from neutron.api.v2 import attributes as attr ++from neutron.common import constants ++from neutron.common import exceptions ++from vnc_api.common import exceptions as vnc_exc ++from vnc_api import vnc_api ++ ++_DEFAULT_HEADERS = { ++ 'Content-type': 'application/json; charset="UTF-8"', } ++ ++CREATE = 1 ++READ = 2 ++UPDATE = 3 ++DELETE = 4 ++ ++ ++class DBInterface(object): ++ """ ++ An instance of this class forwards requests to vnc cfg api (web)server ++ """ ++ Q_URL_PREFIX = '/extensions/ct' ++ ++ def __init__(self, admin_name, admin_password, admin_tenant_name, ++ api_srvr_ip, api_srvr_port, user_info=None): ++ self._api_srvr_ip = api_srvr_ip ++ self._api_srvr_port = api_srvr_port ++ ++ self._db_cache = {} ++ self._db_cache['q_networks'] = {} ++ self._db_cache['q_subnets'] = {} ++ self._db_cache['q_subnet_maps'] = {} ++ self._db_cache['q_policies'] = {} ++ self._db_cache['q_ipams'] = {} ++ self._db_cache['q_floatingips'] = {} ++ self._db_cache['q_ports'] = {} ++ self._db_cache['q_fixed_ip_to_subnet'] = {} ++ #obj-uuid to tenant-uuid mapping ++ self._db_cache['q_obj_to_tenant'] = {} ++ #port count per tenant-id ++ self._db_cache['q_tenant_port_count'] = {} ++ self._db_cache['vnc_networks'] = {} ++ self._db_cache['vnc_ports'] = {} ++ self._db_cache['vnc_projects'] = {} ++ self._db_cache['vnc_instance_ips'] = {} ++ ++ # Retry till a api-server is up ++ connected = False ++ while not connected: ++ try: ++ self._vnc_lib = vnc_api.VncApi( ++ admin_name, admin_password, ++ admin_tenant_name, api_srvr_ip, ++ api_srvr_port, '/', user_info=user_info) ++ connected = True ++ except requests.exceptions.RequestException: ++ time.sleep(3) ++ ++ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key ++ subnet_map = self._vnc_lib.kv_retrieve(key=None) ++ for kv_dict in subnet_map: ++ key = kv_dict['key'] ++ if len(key.split()) == 1: ++ subnet_id = key ++ # uuid key, fixup value portion to 'net_id pfx/len' format ++ # if not already so ++ if len(kv_dict['value'].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ net_fq_name = kv_dict['value'].split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ self._vnc_lib.kv_delete(subnet_id) ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, ++ kv_dict['value'].split()[1]) ++ self._vnc_lib.kv_store(subnet_id, new_subnet_key) ++ else: # subnet key ++ if len(key.split()[0].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ # delete old key, convert to new key format and save ++ old_subnet_key = key ++ self._vnc_lib.kv_delete(old_subnet_key) ++ ++ subnet_id = kv_dict['value'] ++ net_fq_name = key.split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) ++ self._vnc_lib.kv_store(new_subnet_key, subnet_id) ++ ++ # Helper routines ++ def _request_api_server(self, url, method, data=None, headers=None): ++ if method == 'GET': ++ return requests.get(url) ++ if method == 'POST': ++ return requests.post(url, data=data, headers=headers) ++ if method == 'DELETE': ++ return requests.delete(url) ++ ++ def _relay_request(self, request): ++ """ ++ Send received request to api server ++ """ ++ # chop neutron parts of url and add api server address ++ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) ++ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, ++ url_path) ++ ++ return self._request_api_server( ++ url, request.environ['REQUEST_METHOD'], ++ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) ++ ++ def _obj_to_json(self, obj): ++ return dict((k, v) for k, v in obj.__dict__.iteritems()) ++ ++ def _ensure_instance_exists(self, instance_id): ++ instance_name = instance_id ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ try: ++ id = self._vnc_lib.obj_to_id(instance_obj) ++ instance_obj = self._vnc_lib.virtual_machine_read(id=id) ++ except vnc_exc.NoIdError: # instance doesn't exist, create it ++ instance_obj.uuid = instance_id ++ self._vnc_lib.virtual_machine_create(instance_obj) ++ ++ return instance_obj ++ ++ def _ensure_default_security_group_exists(self, proj_id): ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ sg_groups = proj_obj.get_security_groups() ++ for sg_group in sg_groups or []: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) ++ if sg_obj.name == 'default': ++ return ++ ++ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) ++ self._vnc_lib.security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ #allow ingress traffic from within default security group ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'ingress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ def _get_obj_tenant_id(self, q_type, obj_uuid): ++ # Get the mapping from cache, else seed cache and return ++ try: ++ return self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except KeyError: ++ # Seed the cache and return ++ if q_type == 'port': ++ port_obj = self._virtual_machine_interface_read(obj_uuid) ++ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] ++ # recurse up type-hierarchy ++ tenant_id = self._get_obj_tenant_id('network', net_id) ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ if q_type == 'network': ++ net_obj = self._virtual_network_read(net_id=obj_uuid) ++ tenant_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ return None ++ ++ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): ++ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid ++ ++ def _del_obj_tenant_id(self, obj_uuid): ++ try: ++ del self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except Exception: ++ pass ++ ++ def _project_read(self, proj_id=None, fq_name=None): ++ if proj_id: ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][proj_id] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ fq_name_str = json.dumps(proj_obj.get_fq_name()) ++ self._db_cache['vnc_projects'][proj_id] = proj_obj ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ return proj_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][fq_name_str] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj ++ return proj_obj ++ ++ def _security_group_rule_create(self, sg_id, sg_rule): ++ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) ++ rules = sg_vnc.get_security_group_entries() ++ if rules is None: ++ rules = vnc_api.PolicyEntriesType([sg_rule]) ++ else: ++ rules.add_policy_rule(sg_rule) ++ ++ sg_vnc.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_vnc) ++ return ++ ++ def _security_group_rule_find(self, sgr_id): ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ ++ for sg in project_sgs: ++ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) ++ sgr_entries = sg_obj.get_security_group_entries() ++ if sgr_entries is None: ++ continue ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ if sg_rule.get_rule_uuid() == sgr_id: ++ return sg_obj, sg_rule ++ ++ return None, None ++ ++ def _security_group_rule_delete(self, sg_obj, sg_rule): ++ rules = sg_obj.get_security_group_entries() ++ rules.get_policy_rule().remove(sg_rule) ++ sg_obj.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_obj) ++ return ++ ++ def _security_group_create(self, sg_obj): ++ sg_uuid = self._vnc_lib.security_group_create(sg_obj) ++ return sg_uuid ++ ++ def _security_group_delete(self, sg_id): ++ self._vnc_lib.security_group_delete(id=sg_id) ++ ++ def _svc_instance_create(self, si_obj): ++ si_uuid = self._vnc_lib.service_instance_create(si_obj) ++ st_fq_name = ['default-domain', 'nat-template'] ++ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) ++ si_obj.set_service_template(st_obj) ++ self._vnc_lib.service_instance_update(si_obj) ++ ++ return si_uuid ++ ++ def _svc_instance_delete(self, si_id): ++ self._vnc_lib.service_instance_delete(id=si_id) ++ ++ def _route_table_create(self, rt_obj): ++ rt_uuid = self._vnc_lib.route_table_create(rt_obj) ++ return rt_uuid ++ ++ def _route_table_delete(self, rt_id): ++ self._vnc_lib.route_table_delete(id=rt_id) ++ ++ def _virtual_network_create(self, net_obj): ++ net_uuid = self._vnc_lib.virtual_network_create(net_obj) ++ ++ return net_uuid ++ ++ def _virtual_network_read(self, net_id=None, fq_name=None): ++ if net_id: ++ try: ++ # return self._db_cache['vnc_networks'][net_id] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(id=net_id) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ self._db_cache['vnc_networks'][net_id] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ return net_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_networks'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ return net_obj ++ ++ def _virtual_network_update(self, net_obj): ++ self._vnc_lib.virtual_network_update(net_obj) ++ # read back to get subnet gw allocated by api-server ++ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ ++ def _virtual_network_delete(self, net_id): ++ fq_name_str = None ++ try: ++ net_obj = self._db_cache['vnc_networks'][net_id] ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_network_delete(id=net_id) ++ ++ try: ++ del self._db_cache['vnc_networks'][net_id] ++ if fq_name_str: ++ del self._db_cache['vnc_networks'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _virtual_machine_interface_create(self, port_obj): ++ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) ++ ++ return port_uuid ++ ++ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): ++ if port_id: ++ try: ++ # return self._db_cache['vnc_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ id=port_id) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ self._db_cache['vnc_ports'][port_id] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ return port_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_ports'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ fq_name=fq_name) ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ return port_obj ++ ++ def _virtual_machine_interface_update(self, port_obj): ++ self._vnc_lib.virtual_machine_interface_update(port_obj) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ ++ def _virtual_machine_interface_delete(self, port_id): ++ fq_name_str = None ++ try: ++ port_obj = self._db_cache['vnc_ports'][port_id] ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_machine_interface_delete(id=port_id) ++ ++ try: ++ del self._db_cache['vnc_ports'][port_id] ++ if fq_name_str: ++ del self._db_cache['vnc_ports'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _instance_ip_create(self, iip_obj): ++ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) ++ ++ return iip_uuid ++ ++ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): ++ if instance_ip_id: ++ try: ++ # return self._db_cache['vnc_instance_ips'][instance_ip_id] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ return iip_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_instance_ips'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ return iip_obj ++ ++ def _instance_ip_update(self, iip_obj): ++ self._vnc_lib.instance_ip_update(iip_obj) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ ++ def _instance_ip_delete(self, instance_ip_id): ++ fq_name_str = None ++ try: ++ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.instance_ip_delete(id=instance_ip_id) ++ ++ try: ++ del self._db_cache['vnc_instance_ips'][instance_ip_id] ++ if fq_name_str: ++ del self._db_cache['vnc_instance_ips'][fq_name_str] ++ except KeyError: ++ pass ++ ++ # find projects on a given domain ++ def _project_list_domain(self, domain_id): ++ fq_name = ['default-domain'] ++ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) ++ ++ return resp_dict['projects'] ++ ++ # find network ids on a given project ++ def _network_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) ++ ++ return resp_dict['virtual-networks'] ++ ++ def _ipam_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) ++ ++ return resp_dict['network-ipams'] ++ ++ def _security_group_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ self._ensure_default_security_group_exists(project_uuid) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _security_group_entries_list_sg(self, sg_id): ++ try: ++ sg_uuid = str(uuid.UUID(sg_id)) ++ except Exception: ++ print "Error in converting SG uuid %s" % (sg_id) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _route_table_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) ++ ++ return resp_dict['route-tables'] ++ ++ def _svc_instance_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) ++ ++ return resp_dict['service-instances'] ++ ++ def _policy_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) ++ ++ return resp_dict['network-policys'] ++ ++ # find floating ip pools a project has access to ++ def _fip_pool_refs_project(self, project_id): ++ project_uuid = str(uuid.UUID(project_id)) ++ project_obj = self._project_read(proj_id=project_uuid) ++ ++ return project_obj.get_floating_ip_pool_refs() ++ ++ # find networks of floating ip pools project has access to ++ def _fip_pool_ref_networks(self, project_id): ++ ret_nets = [] ++ ++ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) ++ if not proj_fip_pool_refs: ++ return ret_nets ++ ++ for fip_pool_ref in proj_fip_pool_refs: ++ fip_uuid = fip_pool_ref['uuid'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) ++ net_uuid = fip_pool_obj.parent_uuid ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ ret_nets.append({'uuid': net_obj.uuid, ++ 'fq_name': net_obj.get_fq_name()}) ++ ++ return ret_nets ++ ++ # find floating ip pools defined by network ++ def _fip_pool_list_network(self, net_id): ++ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) ++ ++ return resp_dict['floating-ip-pools'] ++ ++ # find port ids on a given network ++ def _port_list_network(self, network_id): ++ ret_list = [] ++ ++ try: ++ net_obj = self._virtual_network_read(net_id=network_id) ++ except vnc_exc.NoIdError: ++ return ret_list ++ ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ for port_back_ref in port_back_refs: ++ ret_list.append({'id': port_back_ref['uuid']}) ++ ++ return ret_list ++ ++ # find port ids on a given project ++ def _port_list_project(self, project_id): ++ ret_list = [] ++ project_nets = self._network_list_project(project_id) ++ for net in project_nets: ++ net_ports = self._port_list_network(net['uuid']) ++ ret_list.extend(net_ports) ++ ++ return ret_list ++ ++ # Returns True if ++ # * no filter is specified ++ # OR ++ # * search-param is not present in filters ++ # OR ++ # * 1. search-param is present in filters AND ++ # 2. resource matches param-list AND ++ # 3. shared parameter in filters is False ++ def _filters_is_present(self, filters, key_name, match_value): ++ if filters: ++ if key_name in filters: ++ try: ++ if ('shared' in filters and ++ filters['shared'][0] is True): ++ # yuck, q-api has shared as list always of 1 elem ++ return False # no shared-resource support ++ except ValueError: # not in requested list ++ return False ++ elif len(filters.keys()) == 1: ++ shared_val = filters.get('shared', None) ++ if shared_val and shared_val[0] is True: ++ return False ++ ++ return True ++ ++ def _network_read(self, net_uuid): ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ return net_obj ++ ++ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): ++ #import pdb; pdb.set_trace() ++ self._vnc_lib.kv_store(subnet_id, subnet_key) ++ self._vnc_lib.kv_store(subnet_key, subnet_id) ++ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key ++ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id ++ ++ def _subnet_vnc_read_mapping(self, id=None, key=None): ++ if id: ++ try: ++ return self._db_cache['q_subnet_maps'][id] ++ #raise KeyError ++ except KeyError: ++ subnet_key = self._vnc_lib.kv_retrieve(id) ++ self._db_cache['q_subnet_maps'][id] = subnet_key ++ return subnet_key ++ if key: ++ try: ++ return self._db_cache['q_subnet_maps'][key] ++ #raise KeyError ++ except KeyError: ++ subnet_id = self._vnc_lib.kv_retrieve(key) ++ self._db_cache['q_subnet_maps'][key] = subnet_id ++ return subnet_id ++ ++ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): ++ if id: ++ return self._subnet_vnc_read_mapping(id=id) ++ ++ # if subnet was created outside of neutron handle it and create ++ # neutron representation now (lazily) ++ try: ++ return self._subnet_vnc_read_mapping(key=key) ++ except vnc_exc.NoIdError: ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, key) ++ return self._subnet_vnc_read_mapping(key=key) ++ ++ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): ++ self._vnc_lib.kv_delete(subnet_id) ++ self._vnc_lib.kv_delete(subnet_key) ++ try: ++ del self._db_cache['q_subnet_maps'][subnet_id] ++ del self._db_cache['q_subnet_maps'][subnet_key] ++ except KeyError: ++ pass ++ ++ def _subnet_vnc_get_key(self, subnet_vnc, net_id): ++ pfx = subnet_vnc.subnet.get_ip_prefix() ++ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() ++ ++ return '%s %s/%s' % (net_id, pfx, pfx_len) ++ ++ def _subnet_read(self, net_uuid, subnet_key): ++ try: ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ except vnc_exc.NoIdError: ++ return None ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if not ipam_refs: ++ return None ++ ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_uuid) == subnet_key: ++ return subnet_vnc ++ ++ return None ++ ++ def _ip_address_to_subnet_id(self, ip_addr, net_obj): ++ # find subnet-id for ip-addr, called when instance-ip created ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ if IPAddress(ip_addr) in IPSet([cidr]): ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, ++ net_obj.uuid) ++ subnet_id = self._subnet_vnc_read_mapping( ++ key=subnet_key) ++ return subnet_id ++ ++ return None ++ ++ # Conversion routines between VNC and Quantum objects ++ def _svc_instance_neutron_to_vnc(self, si_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(si_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ net_id = si_q['internal_net'] ++ int_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ net_id = si_q['external_net'] ++ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, ++ auto_scale=False) ++ si_prop = vnc_api.ServiceInstanceType( ++ auto_policy=True, left_virtual_network=int_vn.name, ++ right_virtual_network=ext_vn.name, scale_out=scale_out) ++ si_prop.set_scale_out(scale_out) ++ si_vnc = vnc_api.ServiceInstance( ++ name=si_q['name'], ++ parent_obj=project_obj, ++ service_instance_properties=si_prop) ++ ++ return si_vnc ++ ++ def _svc_instance_vnc_to_neutron(self, si_obj): ++ si_q_dict = json.loads(json.dumps(si_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ si_q_dict['id'] = si_obj.uuid ++ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') ++ si_q_dict['name'] = si_obj.name ++ si_props = si_obj.get_service_instance_properties() ++ if si_props: ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_left_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_right_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ ++ return {'q_api_data': si_q_dict, ++ 'q_extra_data': {}} ++ ++ def _route_table_neutron_to_vnc(self, rt_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(rt_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], ++ parent_obj=project_obj) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ else: ++ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ ++ return rt_vnc ++ ++ def _route_table_vnc_to_neutron(self, rt_obj): ++ rt_q_dict = json.loads(json.dumps(rt_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ rt_q_dict['id'] = rt_obj.uuid ++ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') ++ rt_q_dict['name'] = rt_obj.name ++ rt_q_dict['fq_name'] = rt_obj.fq_name ++ ++ # get route table routes ++ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) ++ return {'q_api_data': rt_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_vnc_to_neutron(self, sg_obj): ++ sg_q_dict = json.loads(json.dumps(sg_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ sg_q_dict['id'] = sg_obj.uuid ++ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sg_q_dict['name'] = sg_obj.name ++ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() ++ ++ # get security group rules ++ sg_q_dict['rules'] = [] ++ rule_list = self.security_group_rules_read(sg_obj.uuid) ++ if rule_list: ++ for rule in rule_list: ++ sg_q_dict['rules'].append(rule['q_api_data']) ++ ++ return {'q_api_data': sg_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_neutron_to_vnc(self, sg_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(sg_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType( ++ enable=True, description=sg_q['description']) ++ sg_vnc = vnc_api.SecurityGroup( ++ name=sg_q['name'], parent_obj=project_obj, ++ id_perms=id_perms) ++ ++ return sg_vnc ++ ++ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): ++ sgr_q_dict = {} ++ if sg_id is None: ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ direction = 'egress' ++ if sg_rule.get_direction() == '<': ++ direction = 'ingress' ++ ++ remote_cidr = '' ++ remote_sg_uuid = '' ++ if direction == 'ingress': ++ addr = sg_rule.get_src_addresses()[0] ++ else: ++ addr = sg_rule.get_dst_addresses()[0] ++ ++ if addr.get_subnet(): ++ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), ++ addr.get_subnet().get_ip_prefix_len()) ++ elif addr.get_security_group(): ++ if (addr.get_security_group() != 'any') and \ ++ (addr.get_security_group() != 'local'): ++ remote_sg = addr.get_security_group() ++ try: ++ remote_sg_obj = self._vnc_lib.security_group_read( ++ fq_name_str=remote_sg) ++ remote_sg_uuid = remote_sg_obj.uuid ++ except vnc_exc.NoIdError: ++ pass ++ ++ sgr_q_dict['id'] = sg_rule.get_rule_uuid() ++ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sgr_q_dict['security_group_id'] = sg_obj.uuid ++ sgr_q_dict['ethertype'] = 'IPv4' ++ sgr_q_dict['direction'] = direction ++ sgr_q_dict['protocol'] = sg_rule.get_protocol() ++ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ ++ get_start_port() ++ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ ++ get_end_port() ++ sgr_q_dict['remote_ip_prefix'] = remote_cidr ++ sgr_q_dict['remote_group_id'] = remote_sg_uuid ++ ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): ++ if oper == CREATE: ++ port_min = 0 ++ port_max = 65535 ++ if sgr_q['port_range_min']: ++ port_min = sgr_q['port_range_min'] ++ if sgr_q['port_range_max']: ++ port_max = sgr_q['port_range_max'] ++ ++ endpt = [vnc_api.AddressType(security_group='any')] ++ if sgr_q['remote_ip_prefix']: ++ cidr = sgr_q['remote_ip_prefix'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ endpt = [vnc_api.AddressType( ++ subnet=vnc_api.SubnetType(pfx, pfx_len))] ++ elif sgr_q['remote_group_id']: ++ sg_obj = self._vnc_lib.security_group_read( ++ id=sgr_q['remote_group_id']) ++ endpt = [vnc_api.AddressType( ++ security_group=sg_obj.get_fq_name_str())] ++ ++ if sgr_q['direction'] == 'ingress': ++ dir = '<' ++ local = endpt ++ remote = [vnc_api.AddressType(security_group='local')] ++ else: ++ dir = '>' ++ remote = endpt ++ local = [vnc_api.AddressType(security_group='local')] ++ ++ if not sgr_q['protocol']: ++ sgr_q['protocol'] = 'any' ++ ++ sgr_uuid = str(uuid.uuid4()) ++ ++ rule = vnc_api.PolicyRuleType( ++ rule_uuid=sgr_uuid, ++ direction=dir, ++ protocol=sgr_q['protocol'], ++ src_addresses=local, ++ src_ports=[vnc_api.PortType(0, 65535)], ++ dst_addresses=remote, ++ dst_ports=[vnc_api.PortType(port_min, port_max)]) ++ return rule ++ ++ def _network_neutron_to_vnc(self, network_q, oper): ++ net_name = network_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(network_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType(enable=True) ++ net_obj = vnc_api.VirtualNetwork( ++ net_name, project_obj, id_perms=id_perms) ++ else: # READ/UPDATE/DELETE ++ net_obj = self._virtual_network_read(net_id=network_q['id']) ++ ++ id_perms = net_obj.get_id_perms() ++ if 'admin_state_up' in network_q: ++ id_perms.enable = network_q['admin_state_up'] ++ net_obj.set_id_perms(id_perms) ++ ++ if 'contrail:policys' in network_q: ++ policy_fq_names = network_q['contrail:policys'] ++ # reset and add with newly specified list ++ net_obj.set_network_policy_list([], []) ++ seq = 0 ++ for p_fq_name in policy_fq_names: ++ domain_name, project_name, policy_name = p_fq_name ++ ++ domain_obj = vnc_api.Domain(domain_name) ++ project_obj = vnc_api.Project(project_name, domain_obj) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ ++ net_obj.add_network_policy( ++ policy_obj, ++ vnc_api.VirtualNetworkPolicyType( ++ sequence=vnc_api.SequenceType(seq, 0))) ++ seq = seq + 1 ++ ++ if 'vpc:route_table' in network_q: ++ rt_fq_name = network_q['vpc:route_table'] ++ if rt_fq_name: ++ try: ++ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) ++ net_obj.set_route_table(rt_obj) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) ++ ++ return net_obj ++ ++ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): ++ net_q_dict = {} ++ extra_dict = {} ++ ++ net_q_dict['id'] = net_obj.uuid ++ net_q_dict['name'] = net_obj.name ++ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() ++ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable ++ net_q_dict['shared'] = False ++ net_q_dict['status'] = constants.NET_STATUS_ACTIVE ++ ++ if net_repr == 'SHOW': ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ #if port_back_refs: ++ # net_q_dict['ports'] = [] ++ # for port_back_ref in port_back_refs: ++ # fq_name = port_back_ref['to'] ++ # try: ++ # port_obj = self._virtual_machine_interface_read( ++ # port_id = fq_name[-1]) ++ # except NoIdError: ++ # continue ++ # ++ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) ++ # port_dict = port_info['q_api_data'] ++ # port_dict.update(port_info['q_extra_data']) ++ # ++ # net_q_dict['ports'].append(port_dict) ++ ++ extra_dict['contrail:instance_count'] = 0 ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ net_policy_refs = net_obj.get_network_policy_refs() ++ if net_policy_refs: ++ extra_dict['contrail:policys'] = \ ++ [np_ref['to'] for np_ref in net_policy_refs] ++ ++ elif net_repr == 'LIST': ++ extra_dict['contrail:instance_count'] = 0 ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ net_q_dict['subnets'] = [] ++ if ipam_refs: ++ extra_dict['contrail:subnet_ipam'] = [] ++ for ipam_ref in ipam_refs: ++ subnets = ipam_ref['attr'].get_ipam_subnets() ++ for subnet in subnets: ++ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, ++ ipam_ref['to']) ++ sn_dict = sn_info['q_api_data'] ++ sn_dict.update(sn_info['q_extra_data']) ++ net_q_dict['subnets'].append(sn_dict) ++ sn_ipam = {} ++ sn_ipam['subnet_cidr'] = sn_dict['cidr'] ++ sn_ipam['ipam_fq_name'] = ipam_ref['to'] ++ extra_dict['contrail:subnet_ipam'].append(sn_ipam) ++ ++ return {'q_api_data': net_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _subnet_neutron_to_vnc(self, subnet_q): ++ cidr = subnet_q['cidr'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: ++ default_gw = subnet_q['gateway_ip'] ++ else: ++ # Assigned by address manager ++ default_gw = None ++ sub_net = vnc_api.SubnetType(ip_prefix=pfx, ++ ip_prefix_len=pfx_len) ++ #subnet_vnc = vnc_api.IpamSubnetType( ++ #subnet=vnc_api.SubnetType(pfx, pfx_len), ++ #default_gateway=default_gw) ++ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, ++ default_gateway=default_gw) ++ return subnet_vnc ++ ++ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): ++ sn_q_dict = {} ++ sn_q_dict['name'] = '' ++ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ sn_q_dict['network_id'] = net_obj.uuid ++ sn_q_dict['ip_version'] = 4 ++ ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ sn_q_dict['cidr'] = cidr ++ ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) ++ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) ++ ++ sn_q_dict['id'] = sn_id ++ ++ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway ++ ++ first_ip = str(IPNetwork(cidr).network + 1) ++ last_ip = str(IPNetwork(cidr).broadcast - 2) ++ sn_q_dict['allocation_pools'] = \ ++ [{'id': 'TODO-allocation_pools-id', ++ 'subnet_id': sn_id, ++ 'first_ip': first_ip, ++ 'last_ip': last_ip, ++ 'available_ranges': {}}] ++ ++ sn_q_dict['enable_dhcp'] = False ++ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['routes'] = [{'destination': 'TODO-destination', ++ 'nexthop': 'TODO-nexthop', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['shared'] = False ++ ++ extra_dict = {} ++ extra_dict['contrail:instance_count'] = 0 ++ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name ++ ++ return {'q_api_data': sn_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _ipam_neutron_to_vnc(self, ipam_q, oper): ++ ipam_name = ipam_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(ipam_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) ++ ++ if ipam_q['mgmt']: ++ ipam_obj.set_network_ipam_mgmt( ++ vnc_api.IpamType.factory(**ipam_q['mgmt'])) ++ ++ return ipam_obj ++ ++ def _ipam_vnc_to_neutron(self, ipam_obj): ++ ipam_q_dict = json.loads(json.dumps(ipam_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') ++ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') ++ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) ++ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ ipam_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ ipam_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': ipam_q_dict, ++ 'q_extra_data': {}} ++ ++ def _policy_neutron_to_vnc(self, policy_q, oper): ++ policy_name = policy_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(policy_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) ++ ++ policy_obj.set_network_policy_entries( ++ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) ++ ++ return policy_obj ++ ++ def _policy_vnc_to_neutron(self, policy_obj): ++ policy_q_dict = json.loads(json.dumps(policy_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ policy_q_dict['id'] = policy_q_dict.pop('uuid') ++ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') ++ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', ++ None) ++ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ policy_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ policy_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': policy_q_dict, ++ 'q_extra_data': {}} ++ ++ def _floatingip_neutron_to_vnc(self, fip_q, oper): ++ if oper == CREATE: ++ # use first available pool on net ++ net_id = fip_q['floating_network_id'] ++ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) ++ fip_name = str(uuid.uuid4()) ++ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) ++ fip_obj.uuid = fip_name ++ ++ proj_id = str(uuid.UUID(fip_q['tenant_id'])) ++ proj_obj = self._project_read(proj_id=proj_id) ++ fip_obj.set_project(proj_obj) ++ else: # READ/UPDATE/DELETE ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) ++ ++ if fip_q['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=fip_q['port_id']) ++ fip_obj.set_virtual_machine_interface(port_obj) ++ else: ++ fip_obj.set_virtual_machine_interface_list([]) ++ ++ return fip_obj ++ ++ def _floatingip_vnc_to_neutron(self, fip_obj): ++ fip_q_dict = {} ++ extra_dict = {} ++ ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( ++ id=fip_obj.parent_uuid) ++ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) ++ ++ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') ++ ++ port_id = None ++ port_refs = fip_obj.get_virtual_machine_interface_refs() ++ if port_refs: ++ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] ++ ++ fip_q_dict['id'] = fip_obj.uuid ++ fip_q_dict['tenant_id'] = tenant_id ++ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() ++ fip_q_dict['floating_network_id'] = net_obj.uuid ++ fip_q_dict['router_id'] = None ++ fip_q_dict['fixed_port_id'] = port_id ++ fip_q_dict['fixed_ip_address'] = None ++ ++ return {'q_api_data': fip_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _port_neutron_to_vnc(self, port_q, net_obj, oper): ++ if oper == CREATE: ++ port_name = str(uuid.uuid4()) ++ instance_name = port_q['device_id'] ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ ++ id_perms = vnc_api.IdPermsType(enable=True) ++ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, ++ id_perms=id_perms) ++ port_obj.uuid = port_name ++ port_obj.set_virtual_network(net_obj) ++ ++ else: # READ/UPDATE/DELETE ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_q['id']) ++ ++ port_obj.set_security_group_list([]) ++ if ('security_groups' in port_q and ++ port_q['security_groups'].__class__ is not object): ++ for sg_id in port_q['security_groups']: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ port_obj.add_security_group(sg_obj) ++ ++ id_perms = port_obj.get_id_perms() ++ if 'admin_state_up' in port_q: ++ id_perms.enable = port_q['admin_state_up'] ++ port_obj.set_id_perms(id_perms) ++ ++ return port_obj ++ ++ def _port_vnc_to_neutron(self, port_obj, net_obj=None): ++ port_q_dict = {} ++ port_q_dict['name'] = port_obj.uuid ++ port_q_dict['id'] = port_obj.uuid ++ ++ if not net_obj: ++ net_refs = port_obj.get_virtual_network_refs() ++ if net_refs: ++ net_id = net_refs[0]['uuid'] ++ else: ++ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) ++ ++ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) ++ proj_id = None ++ if not proj_id: ++ # not in cache, get by reading VN obj, and populate cache ++ net_obj = self._virtual_network_read(net_id=net_id) ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(port_obj.uuid, proj_id) ++ else: ++ net_id = net_obj.uuid ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ ++ port_q_dict['tenant_id'] = proj_id ++ port_q_dict['network_id'] = net_id ++ ++ port_q_dict['mac_address'] = '' ++ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() ++ if mac_refs: ++ port_q_dict['mac_address'] = mac_refs.mac_address[0] ++ ++ port_q_dict['fixed_ips'] = [] ++ ip_back_refs = port_obj.get_instance_ip_back_refs() ++ if ip_back_refs: ++ for ip_back_ref in ip_back_refs: ++ try: ++ ip_obj = self._instance_ip_read( ++ instance_ip_id=ip_back_ref['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ++ ip_addr = ip_obj.get_instance_ip_address() ++ ++ ip_q_dict = {} ++ ip_q_dict['port_id'] = port_obj.uuid ++ ip_q_dict['ip_address'] = ip_addr ++ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, ++ net_obj) ++ ip_q_dict['net_id'] = net_id ++ ++ port_q_dict['fixed_ips'].append(ip_q_dict) ++ ++ sg_dict = {'port_security_enabled': True} ++ sg_dict['security_groups'] = [] ++ sg_refs = port_obj.get_security_group_refs() ++ for sg_ref in sg_refs or []: ++ sg_dict['security_groups'].append(sg_ref['uuid']) ++ ++ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable ++ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE ++ port_q_dict['device_id'] = port_obj.parent_name ++ port_q_dict['device_owner'] = 'TODO-device-owner' ++ ++ return {'q_api_data': port_q_dict, ++ 'q_extra_data': sg_dict} ++ ++ # public methods ++ # network api handlers ++ def network_create(self, network_q): ++ #self._ensure_project_exists(network_q['tenant_id']) ++ ++ net_obj = self._network_neutron_to_vnc(network_q, CREATE) ++ net_uuid = self._virtual_network_create(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_uuid] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_read(self, net_uuid, fields=None): ++ # see if we can return fast... ++ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': ++ tenant_id = self._get_obj_tenant_id('network', net_uuid) ++ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} ++ ++ try: ++ # return self._db_cache['q_networks']['net_uuid'] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ try: ++ net_obj = self._network_read(net_uuid) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_uuid) ++ ++ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ ++ def network_update(self, net_id, network_q): ++ network_q['id'] = net_id ++ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) ++ self._virtual_network_update(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_id] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_delete(self, net_id): ++ self._virtual_network_delete(net_id=net_id) ++ try: ++ del self._db_cache['q_networks'][net_id] ++ except KeyError: ++ pass ++ ++ def network_list(self, filters=None): ++ ret_list = [] ++ ++ if filters and 'shared' in filters: ++ if filters['shared'][0] is True: ++ # no support for shared networks ++ return ret_list ++ ++ # collect phase ++ all_nets = [] # all n/ws in all projects ++ if filters and 'tenant_id' in filters: ++ # project-id is present ++ if 'id' in filters: ++ # required networks are also specified, ++ # just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in project, and prune below ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ if 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(p_id)) ++ else: ++ project_nets = self._network_list_project(p_id) ++ all_nets.append(project_nets) ++ elif filters and 'id' in filters: ++ # required networks are specified, just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in all projects ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ if filters and 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(proj_id)) ++ else: ++ project_nets = self._network_list_project(proj_id) ++ all_nets.append(project_nets) ++ ++ # prune phase ++ for project_nets in all_nets: ++ for proj_net in project_nets: ++ proj_net_id = proj_net['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_net_id): ++ continue ++ ++ proj_net_fq_name = unicode(proj_net['fq_name']) ++ if not self._filters_is_present(filters, 'contrail:fq_name', ++ proj_net_fq_name): ++ continue ++ ++ try: ++ net_obj = self._network_read(proj_net['uuid']) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ except vnc_exc.NoIdError: ++ continue ++ ret_list.append(net_info) ++ ++ return ret_list ++ ++ def network_count(self, filters=None): ++ nets_info = self.network_list(filters) ++ return len(nets_info) ++ ++ # subnet api handlers ++ def subnet_create(self, subnet_q): ++ net_id = subnet_q['network_id'] ++ net_obj = self._virtual_network_read(net_id=net_id) ++ ++ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] ++ if ipam_fq_name != '': ++ domain_name, project_name, ipam_name = ipam_fq_name ++ ++ project_obj = vnc_api.Project(project_name) ++ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # link subnet with default ipam ++ project_obj = vnc_api.Project(net_obj.parent_name) ++ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) ++ ipam_fq_name = netipam_obj.get_fq_name() ++ ++ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) ++ ++ # Locate list of subnets to which this subnet has to be appended ++ net_ipam_ref = None ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ if ipam_ref['to'] == ipam_fq_name: ++ net_ipam_ref = ipam_ref ++ break ++ ++ if not net_ipam_ref: ++ # First link from net to this ipam ++ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) ++ net_obj.add_network_ipam(netipam_obj, vnsn_data) ++ else: # virtual-network already linked to this ipam ++ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): ++ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): ++ # duplicate !! ++ subnet_info = self._subnet_vnc_to_neutron(subnet, ++ net_obj, ++ ipam_fq_name) ++ return subnet_info ++ vnsn_data = net_ipam_ref['attr'] ++ vnsn_data.ipam_subnets.append(subnet_vnc) ++ ++ self._virtual_network_update(net_obj) ++ ++ # allocate an id to the subnet and store mapping with ++ # api-server ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, subnet_key) ++ ++ # Read in subnet from server to get updated values for gw etc. ++ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) ++ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, ++ ipam_fq_name) ++ ++ #self._db_cache['q_subnets'][subnet_id] = subnet_info ++ ++ return subnet_info ++ ++ def subnet_read(self, subnet_id): ++ try: ++ # return self._db_cache['q_subnets'][subnet_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_id) == subnet_key: ++ ret_subnet_q = self._subnet_vnc_to_neutron( ++ subnet_vnc, net_obj, ipam_ref['to']) ++ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q ++ return ret_subnet_q ++ ++ return {} ++ ++ def subnet_delete(self, subnet_id): ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ orig_subnets = ipam_ref['attr'].get_ipam_subnets() ++ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets ++ if self._subnet_vnc_get_key(subnet_vnc, net_id) ++ != subnet_key] ++ if len(orig_subnets) != len(new_subnets): ++ # matched subnet to be deleted ++ ipam_ref['attr'].set_ipam_subnets(new_subnets) ++ self._virtual_network_update(net_obj) ++ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) ++ try: ++ del self._db_cache['q_subnets'][subnet_id] ++ except KeyError: ++ pass ++ ++ return ++ ++ def subnets_list(self, filters=None): ++ ret_subnets = [] ++ ++ if filters and 'id' in filters: ++ # required subnets are specified, ++ # just read in corresponding net_ids ++ net_ids = set([]) ++ for subnet_id in filters['id']: ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ net_ids.add(net_id) ++ else: ++ nets_info = self.network_list() ++ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] ++ ++ for net_id in net_ids: ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, ++ net_obj, ++ ipam_ref['to']) ++ sn_id = sn_info['q_api_data']['id'] ++ sn_proj_id = sn_info['q_api_data']['tenant_id'] ++ sn_net_id = sn_info['q_api_data']['network_id'] ++ ++ if filters: ++ if not self._filters_is_present(filters, 'id', ++ sn_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'tenant_id', ++ sn_proj_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'network_id', ++ sn_net_id): ++ continue ++ ++ ret_subnets.append(sn_info) ++ ++ return ret_subnets ++ ++ def subnets_count(self, filters=None): ++ subnets_info = self.subnets_list(filters) ++ return len(subnets_info) ++ ++ # ipam api handlers ++ def ipam_create(self, ipam_q): ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) ++ self._vnc_lib.network_ipam_create(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_read(self, ipam_id): ++ try: ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=ipam_id) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_update(self, ipam_id, ipam): ++ ipam_q = ipam['ipam'] ++ ipam_q['id'] = ipam_id ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) ++ self._vnc_lib.network_ipam_update(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_delete(self, ipam_id): ++ self._vnc_lib.network_ipam_delete(id=ipam_id) ++ ++ def ipam_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_ipams = [] # all ipams in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_ipams = self._ipam_list_project(p_id) ++ all_ipams.append(project_ipams) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_ipams = self._ipam_list_project(proj_id) ++ all_ipams.append(project_ipams) ++ ++ # prune phase ++ for project_ipams in all_ipams: ++ for proj_ipam in project_ipams: ++ proj_ipam_id = proj_ipam['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_ipam_id): ++ continue ++ ipam_info = self.ipam_read(proj_ipam['uuid']) ++ ret_list.append(ipam_info) ++ ++ return ret_list ++ ++ def ipam_count(self, filters=None): ++ ipam_info = self.ipam_list(filters) ++ return len(ipam_info) ++ ++ # policy api handlers ++ def policy_create(self, policy_q): ++ ++ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) ++ self._vnc_lib.network_policy_create(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_read(self, policy_id): ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_update(self, policy_id, policy): ++ policy_q = policy['policy'] ++ policy_q['id'] = policy_id ++ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) ++ self._vnc_lib.network_policy_update(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_delete(self, policy_id): ++ self._vnc_lib.network_policy_delete(id=policy_id) ++ ++ def policy_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_policys = [] # all policys in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_policys = self._policy_list_project(p_id) ++ all_policys.append(project_policys) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_policys = self._policy_list_project(proj_id) ++ all_policys.append(project_policys) ++ ++ # prune phase ++ for project_policys in all_policys: ++ for proj_policy in project_policys: ++ proj_policy_id = proj_policy['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_policy_id): ++ continue ++ policy_info = self.policy_read(proj_policy['uuid']) ++ ret_list.append(policy_info) ++ ++ return ret_list ++ ++ def policy_count(self, filters=None): ++ policy_info = self.policy_list(filters) ++ return len(policy_info) ++ ++ # floatingip api handlers ++ def floatingip_create(self, fip_q): ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) ++ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_read(self, fip_uuid): ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_update(self, fip_id, fip_q): ++ fip_q['id'] = fip_id ++ fip_obj = self._floatingip_neutron(fip_q, UPDATE) ++ self._vnc_lib.floating_ip_update(fip_obj) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_delete(self, fip_id): ++ self._vnc_lib.floating_ip_delete(id=fip_id) ++ ++ def floatingip_list(self, filters=None): ++ # Find networks, get floatingip backrefs and return ++ ret_list = [] ++ ++ if filters: ++ if 'tenant_id' in filters: ++ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] ++ elif 'port_id' in filters: ++ # required ports are specified, just read and populate ret_list ++ # prune is skipped because proj_objs is empty ++ proj_ids = [] ++ for port_id in filters['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_id) ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron( ++ fip_obj)) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ proj_ids = [proj['uuid'] for proj in dom_projects] ++ ++ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] ++ ++ for proj_obj in proj_objs: ++ fip_back_refs = proj_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) ++ ++ return ret_list ++ ++ def floatingip_count(self, filters=None): ++ floatingip_info = self.floatingip_list(filters) ++ return len(floatingip_info) ++ ++ # port api handlers ++ def port_create(self, port_q): ++ net_id = port_q['network_id'] ++ net_obj = self._network_read(net_id) ++ proj_id = net_obj.parent_uuid ++ ++ self._ensure_instance_exists(port_q['device_id']) ++ ++ # initialize port object ++ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) ++ ++ # if ip address passed then use it ++ ip_addr = None ++ ip_obj = None ++ if port_q['fixed_ips'].__class__ is not object: ++ ip_addr = port_q['fixed_ips'][0]['ip_address'] ++ ip_name = '%s %s' % (net_id, ip_addr) ++ try: ++ ip_obj = self._instance_ip_read(fq_name=[ip_name]) ++ #ip_id = ip_obj.uuid ++ except Exception as e: ++ ip_obj = None ++ ++ # create the object ++ port_id = self._virtual_machine_interface_create(port_obj) ++ ++ # initialize ip object ++ if ip_obj is None: ++ ip_name = str(uuid.uuid4()) ++ ip_obj = vnc_api.InstanceIp(name=ip_name) ++ ip_obj.uuid = ip_name ++ ip_obj.set_virtual_machine_interface(port_obj) ++ ip_obj.set_virtual_network(net_obj) ++ if ip_addr: ++ ip_obj.set_instance_ip_address(ip_addr) ++ try: ++ self._instance_ip_create(ip_obj) ++ except Exception as e: ++ # ResourceExhaustionError, resources are not available ++ self._virtual_machine_interface_delete(port_id=port_id) ++ raise e ++ # shared ip address ++ else: ++ if ip_addr == ip_obj.get_instance_ip_address(): ++ ip_obj.add_virtual_machine_interface(port_obj) ++ self._instance_ip_update(ip_obj) ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) ++ #self._db_cache['q_ports'][port_id] = ret_port_q ++ self._set_obj_tenant_id(port_id, proj_id) ++ ++ # update cache on successful creation ++ tenant_id = proj_id.replace('-', '') ++ if tenant_id not in self._db_cache['q_tenant_port_count']: ++ ncurports = self.port_count({'tenant_id': tenant_id}) ++ else: ++ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] ++ ++ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 ++ ++ return ret_port_q ++ ++ def port_read(self, port_id): ++ try: ++ # return self._db_cache['q_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_update(self, port_id, port_q): ++ port_q['id'] = port_id ++ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) ++ self._virtual_machine_interface_update(port_obj) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_delete(self, port_id): ++ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) ++ instance_id = port_obj.parent_uuid ++ ++ # release instance IP address ++ iip_back_refs = port_obj.get_instance_ip_back_refs() ++ if iip_back_refs: ++ for iip_back_ref in iip_back_refs: ++ # if name contains IP address then this is shared ip ++ iip_obj = self._vnc_lib.instance_ip_read( ++ id=iip_back_ref['uuid']) ++ name = iip_obj.name ++ if len(name.split(' ')) > 1: ++ name = name.split(' ')[1] ++ ++ # in case of shared ip only delete the link to the VMI ++ try: ++ socket.inet_aton(name) ++ iip_obj.del_virtual_machine_interface(port_obj) ++ self._instance_ip_update(iip_obj) ++ except socket.error: ++ self._instance_ip_delete( ++ instance_ip_id=iip_back_ref['uuid']) ++ ++ # disassociate any floating IP used by instance ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if fip_back_refs: ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ self.floatingip_update(fip_obj.uuid, {'port_id': None}) ++ ++ self._virtual_machine_interface_delete(port_id=port_id) ++ ++ # delete instance if this was the last port ++ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) ++ inst_intfs = inst_obj.get_virtual_machine_interfaces() ++ if not inst_intfs: ++ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) ++ ++ try: ++ del self._db_cache['q_ports'][port_id] ++ except KeyError: ++ pass ++ ++ # update cache on successful deletion ++ try: ++ tenant_id = self._get_obj_tenant_id('port', port_id) ++ self._db_cache['q_tenant_port_count'][tenant_id] = \ ++ self._db_cache['q_tenant_port_count'][tenant_id] - 1 ++ except KeyError: ++ pass ++ ++ self._del_obj_tenant_id(port_id) ++ ++ def port_list(self, filters=None): ++ ret_q_ports = [] ++ all_project_ids = [] ++ ++ if 'device_owner' in filters: ++ return ret_q_ports ++ ++ if 'device_id' not in filters: ++ # Listing from back references ++ if not filters: ++ # no filters => return all ports! ++ all_projects = self._project_list_domain(None) ++ all_project_ids = [project['uuid'] for project in all_projects] ++ elif 'tenant_id' in filters: ++ all_project_ids = filters.get('tenant_id') ++ ++ for proj_id in all_project_ids: ++ proj_ports = self._port_list_project(proj_id) ++ for port in proj_ports: ++ try: ++ port_info = self.port_read(port['id']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ for net_id in filters.get('network_id', []): ++ net_ports = self._port_list_network(net_id) ++ for port in net_ports: ++ port_info = self.port_read(port['id']) ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ # Listing from parent to children ++ virtual_machine_ids = filters['device_id'] ++ for vm_id in virtual_machine_ids: ++ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( ++ parent_id=vm_id) ++ vm_intf_ids = resp_dict['virtual-machine-interfaces'] ++ for vm_intf in vm_intf_ids: ++ try: ++ port_info = self.port_read(vm_intf['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ def port_count(self, filters=None): ++ if 'device_owner' in filters: ++ return 0 ++ ++ if 'tenant_id' in filters: ++ project_id = filters['tenant_id'][0] ++ try: ++ return self._db_cache['q_tenant_port_count'][project_id] ++ except KeyError: ++ # do it the hard way but remember for next time ++ nports = len(self._port_list_project(project_id)) ++ self._db_cache['q_tenant_port_count'][project_id] = nports ++ else: ++ # across all projects ++ # get only a count from api-server! ++ nports = len(self.port_list(filters)) ++ ++ return nports ++ ++ # security group api handlers ++ def security_group_create(self, sg_q): ++ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) ++ sg_uuid = self._security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_uuid, rule) ++ ++ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) ++ return ret_sg_q ++ ++ def security_group_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return self._security_group_vnc_to_neutron(sg_obj) ++ ++ def security_group_delete(self, sg_id): ++ self._security_group_delete(sg_id) ++ ++ def security_group_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] # all sgs in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sg_info = self.security_group_read(proj_sg_id) ++ if not self._filters_is_present(filters, 'name', ++ sg_info['q_api_data']['name']): ++ continue ++ ret_list.append(sg_info) ++ ++ return ret_list ++ ++ def security_group_rule_create(self, sgr_q): ++ sg_id = sgr_q['security_group_id'] ++ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) ++ self._security_group_rule_create(sg_id, sg_rule) ++ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, ++ sg_rule) ++ ++ return ret_sg_rule_q ++ ++ def security_group_rule_read(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ ++ return {} ++ ++ def security_group_rule_delete(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_delete(sg_obj, sg_rule) ++ ++ def security_group_rules_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ sgr_entries = sg_obj.get_security_group_entries() ++ sg_rules = [] ++ if sgr_entries is None: ++ return ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ sg_rules.append(sg_info) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return sg_rules ++ ++ def security_group_rule_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sgr_info = self.security_group_rules_read(proj_sg_id) ++ if sgr_info: ++ ret_list.append(sgr_info) ++ ++ return ret_list ++ ++ #route table api handlers ++ def route_table_create(self, rt_q): ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) ++ self._route_table_create(rt_obj) ++ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) ++ return ret_rt_q ++ ++ def route_table_read(self, rt_id): ++ try: ++ rt_obj = self._vnc_lib.route_table_read(id=rt_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=rt_id) ++ ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_update(self, rt_id, rt_q): ++ rt_q['id'] = rt_id ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) ++ self._vnc_lib.route_table_update(rt_obj) ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_delete(self, rt_id): ++ self._route_table_delete(rt_id) ++ ++ def route_table_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_rts = [] # all rts in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_rts = self._route_table_list_project(proj_id) ++ all_rts.append(project_rts) ++ ++ # prune phase ++ for project_rts in all_rts: ++ for proj_rt in project_rts: ++ proj_rt_id = proj_rt['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_rt_id): ++ continue ++ rt_info = self.route_table_read(proj_rt_id) ++ if not self._filters_is_present(filters, 'name', ++ rt_info['q_api_data']['name']): ++ continue ++ ret_list.append(rt_info) ++ ++ return ret_list ++ ++ #service instance api handlers ++ def svc_instance_create(self, si_q): ++ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) ++ self._svc_instance_create(si_obj) ++ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) ++ return ret_si_q ++ ++ def svc_instance_read(self, si_id): ++ try: ++ si_obj = self._vnc_lib.service_instance_read(id=si_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=si_id) ++ ++ return self._svc_instance_vnc_to_neutron(si_obj) ++ ++ def svc_instance_delete(self, si_id): ++ self._svc_instance_delete(si_id) ++ ++ def svc_instance_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sis = [] # all sis in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sis = self._svc_instance_list_project(proj_id) ++ all_sis.append(project_sis) ++ ++ # prune phase ++ for project_sis in all_sis: ++ for proj_si in project_sis: ++ proj_si_id = proj_si['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_si_id): ++ continue ++ si_info = self.svc_instance_read(proj_si_id) ++ if not self._filters_is_present(filters, 'name', ++ si_info['q_api_data']['name']): ++ continue ++ ret_list.append(si_info) ++ ++ return ret_list +diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py +new file mode 100644 +index 0000000..72bebec +--- /dev/null ++++ neutron/tests/unit/juniper/__init__.py +@@ -0,0 +1,14 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. +diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py +new file mode 100644 +index 0000000..decf79e +--- /dev/null ++++ neutron/tests/unit/juniper/test_contrail_plugin.py +@@ -0,0 +1,998 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. ++ ++import datetime ++import mock ++import neutron.db.api ++from neutron.manager import NeutronManager ++from neutron.tests.unit import test_db_plugin as test_plugin ++import sys ++import uuid ++ ++subnet_obj = {u'subnet': ++ {'name': '', 'enable_dhcp': True, ++ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', ++ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', ++ 'dns_nameservers': '', ++ u'contrail:ipam_fq_name': ++ [u'default-domain', u'admin', u'default-network-ipam'], ++ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, ++ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} ++ ++vn_list = [] ++GlobalProjects = [] ++ ++ ++class MockVncApi(mock.MagicMock): ++ def __init__(self, *args, **kwargs): ++ pass ++ ++ def kv_retrieve(self, *args, **kwargs): ++ return [] ++ ++ def kv_store(self, *args, **kwargs): ++ return ++ ++ def kv_delete(self, *args, **kwargs): ++ return ++ ++ def project_read(self, *args, **kwargs): ++ #return MockProject('dummy-proj') ++ return GlobalProjects[0] ++ ++ def virtual_network_create(self, net_obj): ++ net_id = unicode(str(uuid.uuid4())) ++ net_obj.set_uuid(net_id) ++ vn_list.append(net_obj) ++ return net_id ++ ++ def virtual_network_read(self, id, *args, **kwargs): ++ if len(vn_list): ++ for index in range(len(vn_list)): ++ if ((vn_list[index].get_uuid()) == id): ++ return vn_list[index] ++ ++ #return a mock object if it is not created so far ++ return MockVirtualNetwork('dummy-net', MockProject()) ++ ++ def virtual_network_delete(self, *args, **kwargs): ++ return ++ ++ def virtual_network_update(self, *args, **kwargs): ++ return ++ ++ def virtual_networks_list(self, *args, **kwargs): ++ return vn_list ++ ++ ++class MockVncObject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ if not parent_obj: ++ self._fq_name = [name] ++ else: ++ self._fq_name = parent_obj.get_fq_name() + [name] ++ ++ self._ipam_refs = [{'to': [u'default-domain', u'admin', ++ u'default-network-ipam']}] ++ self.uuid = None ++ self.name = name ++ self.network_ipam_refs = [] ++ ++ def set_uuid(self, uuid): ++ self.uuid = uuid ++ ++ def get_uuid(self): ++ return self.uuid ++ ++ def get_fq_name(self): ++ return self._fq_name ++ ++ def get_network_ipam_refs(self): ++ return getattr(self, 'network_ipam_refs', None) ++ ++ def add_network_ipam(self, ref_obj, ref_data): ++ refs = getattr(self, 'network_ipam_refs', []) ++ if not refs: ++ self.network_ipam_refs = [] ++ ++ # if ref already exists, update any attr with it ++ for ref in refs: ++ if ref['to'] == ref_obj.get_fq_name(): ++ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref['uuid'] = ref_obj.uuid ++ return ++ ++ # ref didn't exist before ++ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref_info['uuid'] = ref_obj.uuid ++ ++ self.network_ipam_refs.append(ref_info) ++ ++ ++class MockVirtualNetwork(MockVncObject): ++ pass ++ ++ ++class MockSubnetType(mock.MagicMock): ++ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ip_prefix = ip_prefix ++ self.ip_prefix_len = ip_prefix_len ++ ++ def get_ip_prefix(self): ++ return self.ip_prefix ++ ++ def set_ip_prefix(self, ip_prefix): ++ self.ip_prefix = ip_prefix ++ ++ def get_ip_prefix_len(self): ++ return self.ip_prefix_len ++ ++ def set_ip_prefix_len(self, ip_prefix_len): ++ self.ip_prefix_len = ip_prefix_len ++ ++ ++class MockIpamSubnetType(mock.MagicMock): ++ def __init__(self, name=None, subnet=None, default_gateway=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.subnet = subnet ++ self.default_gateway = default_gateway ++ ++ def get_subnet(self): ++ return self.subnet ++ ++ def set_subnet(self, subnet): ++ self.subnet = subnet ++ ++ def get_default_gateway(self): ++ return self.default_gateway ++ ++ def set_default_gateway(self, default_gateway): ++ self.default_gateway = default_gateway ++ ++ def validate_IpAddressType(self, value): ++ pass ++ ++ ++class MockVnSubnetsType(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ipam_subnets = [] ++ if ipam_subnets: ++ #self.ipam_subnets = copy.deepcopy(ipam_subnets) ++ self.ipam_subnets = ipam_subnets ++ ++ def get_ipam_subnets(self): ++ return self.ipam_subnets ++ ++ def set_ipam_subnets(self, ipam_subnets): ++ self.ipam_subnets = ipam_subnets ++ ++ def add_ipam_subnets(self, value): ++ self.ipam_subnets.append(value) ++ ++ def insert_ipam_subnets(self, index, value): ++ self.ipam_subnets[index] = value ++ ++ def delete_ipam_subnets(self, value): ++ self.ipam_subnets.remove(value) ++ ++ ++class MockNetworkIpam(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ++ network_ipam_mgmt=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'default-network-ipam' ++ self.name = name ++ self.uuid = None ++ if parent_obj: ++ self.parent_type = parent_obj._type ++ # copy parent's fq_name ++ self.fq_name = list(parent_obj.fq_name) ++ self.fq_name.append(name) ++ if not parent_obj.get_network_ipams(): ++ parent_obj.network_ipams = [] ++ parent_obj.network_ipams.append(self) ++ else: # No parent obj specified ++ self.parent_type = 'project' ++ self.fq_name = [u'default-domain', u'default-project'] ++ self.fq_name.append(name) ++ ++ # property fields ++ if network_ipam_mgmt: ++ self.network_ipam_mgmt = network_ipam_mgmt ++ if id_perms: ++ self.id_perms = id_perms ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++class MockProject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'project' ++ self.uuid = None ++ self.parent_type = 'domain' ++ self.fq_name = [u'default-domain'] ++ self.fq_name.append(name) ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++def GlobalProjectApi(project_name): ++ if not GlobalProjects: ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ return GlobalProjects[0] ++ ++ ++# Mock definations for different pkgs, modules and VncApi ++mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) ++mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') ++mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork ++mock_vnc_api_mod.SubnetType = MockSubnetType ++mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType ++mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType ++mock_vnc_api_mod.NetworkIpam = MockNetworkIpam ++mock_vnc_api_mod.Project = GlobalProjectApi ++ ++mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') ++mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') ++mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ ++ mock_vnc_api_pkg ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ ++ mock_vnc_api_mod ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ ++ mock_vnc_common_mod ++sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' ++ 'exceptions')] = \ ++ mock_vnc_exception_mod ++ ++CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" ++ ++ ++class RouterInstance(object): ++ def __init__(self): ++ self._name = 'rounter_instance' ++ ++ ++class Context(object): ++ def __init__(self, tenant_id=''): ++ self.read_only = False ++ self.show_deleted = False ++ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] ++ self._read_deleted = 'no' ++ self.timestamp = datetime.datetime.now() ++ self.auth_token = None ++ self._session = None ++ self._is_admin = True ++ self.admin = uuid.uuid4().hex.decode() ++ self.request_id = 'req-' + str(uuid.uuid4()) ++ self.tenant = tenant_id ++ ++ ++class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): ++ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) ++ ++ def setUp(self): ++ ++ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod ++ ++ mock_vnc_api_mod.common = mock_vnc_common_mod ++ mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++ ++ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++ ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ neutron.db.api._ENGINE = mock.MagicMock() ++ ++ def teardown(self): ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ ++ ++class TestContrailNetworks(test_plugin.TestNetworksV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ if 'contrail:fq_name' not in net.keys(): ++ assert False ++ else: ++ assert True ++ ++ def test_delete_network(self): ++ # First create the network and request to delete the same ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ ++ plugin_obj.delete_network(context_obj, net_id) ++ mock_vnc_api_cls.virtual_network_delete.assert_called_once() ++ ++ def test_update_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ # change one of the attribute and update the network ++ network['admin_state_up'] = 'False' ++ new_dict = plugin_obj.update_network(context_obj, net_id, ++ networks_req) ++ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): ++ assert False ++ else: ++ assert True ++ ++ # Not supported test cases in the this TestClass ++ def test_create_networks_bulk_emulated(self): ++ pass ++ ++ def test_create_networks_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_public_network(self): ++ pass ++ ++ def test_create_networks_bulk_wrong_input(self): ++ pass ++ ++ def test_update_shared_network_noadmin_returns_403(self): ++ pass ++ ++ def test_update_network_set_shared(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_single_tenant(self): ++ pass ++ ++ def test_update_network_set_not_shared_other_tenant_returns_409(self): ++ pass ++ ++ def test_update_network_with_subnet_set_shared(self): ++ pass ++ ++ def test_show_network(self): ++ pass ++ ++ def test_show_network_with_subnet(self): ++ pass ++ ++ def test_list_networks(self): ++ pass ++ ++ def test_list_shared_networks_with_non_admin_user(self): ++ pass ++ ++ def test_list_networks_with_parameters(self): ++ pass ++ ++ def test_list_networks_with_fields(self): ++ pass ++ ++ def test_list_networks_with_parameters_invalid_values(self): ++ pass ++ ++ def test_list_networks_with_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_without_pk_in_fields_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_with_sort_emulated(self): ++ pass ++ ++ def test_list_networks_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_invalid_admin_status(self): ++ pass ++ ++ ++class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: ++ assert False ++ else: ++ assert True ++ ++ def test_delete_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ subnet_id = subnet_dict['id'] ++ plugin_obj.delete_subnet(context_obj, subnet_id) ++ ++ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_delete_network(self): ++ pass ++ ++ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet_adding_additional_host_routes_and_dns(self): ++ pass ++ ++ def test_update_subnet_no_gateway(self): ++ pass ++ ++ def test_create_subnet_bad_cidr(self): ++ pass ++ ++ def test_create_subnet_gw_of_network_force_on_returns_400(self): ++ pass ++ ++ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_create_two_subnets(self): ++ pass ++ ++ def test_create_two_subnets_same_cidr_returns_400(self): ++ pass ++ ++ def test_create_subnet_bad_V4_cidr(self): ++ pass ++ ++ def test_create_subnet_bad_V6_cidr(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): ++ pass ++ ++ def test_create_subnets_bulk_native(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_subnets_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_network(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_other(self): ++ pass ++ ++ def test_create_subnet_bad_tenant(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version_null(self): ++ pass ++ ++ def test_create_subnet_bad_uuid(self): ++ pass ++ ++ def test_create_subnet_bad_boolean(self): ++ pass ++ ++ def test_create_subnet_bad_pools(self): ++ pass ++ ++ def test_create_subnet_bad_nameserver(self): ++ pass ++ ++ def test_create_subnet_bad_hostroutes(self): ++ pass ++ ++ def test_create_subnet_defaults(self): ++ pass ++ ++ def test_create_subnet_gw_values(self): ++ pass ++ ++ def test_create_force_subnet_gw_values(self): ++ pass ++ ++ def test_create_subnet_with_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_fully_allocated(self): ++ pass ++ ++ def test_subnet_with_allocation_range(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_v6_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_large_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_multiple_allocation_pools(self): ++ pass ++ ++ def test_create_subnet_with_dhcp_disabled(self): ++ pass ++ ++ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( ++ self): ++ pass ++ ++ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_create_subnet_overlapping_allocation_pools_returns_409(self): ++ pass ++ ++ def test_create_subnet_invalid_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_shared_returns_400(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_cidrv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_cidrv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_dns_v4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): ++ pass ++ ++ def test_create_subnet_gw_bcast_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet(self): ++ pass ++ ++ def test_update_subnet_shared_returns_400(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_dns_v6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): ++ pass ++ ++ def test_show_subnet(self): ++ pass ++ ++ def test_list_subnets(self): ++ pass ++ ++ def test_list_subnets_shared(self): ++ pass ++ ++ def test_list_subnets_with_parameter(self): ++ pass ++ ++ def test_invalid_ip_version(self): ++ pass ++ ++ def test_invalid_subnet(self): ++ pass ++ ++ def test_invalid_ip_address(self): ++ pass ++ ++ def test_invalid_uuid(self): ++ pass ++ ++ def test_create_subnet_with_one_dns(self): ++ pass ++ ++ def test_create_subnet_with_two_dns(self): ++ pass ++ ++ def test_create_subnet_with_too_many_dns(self): ++ pass ++ ++ def test_create_subnet_with_one_host_route(self): ++ pass ++ ++ def test_create_subnet_with_two_host_routes(self): ++ pass ++ ++ def test_create_subnet_with_too_many_routes(self): ++ pass ++ ++ def test_update_subnet_dns(self): ++ pass ++ ++ def test_update_subnet_dns_to_None(self): ++ pass ++ ++ def test_update_subnet_dns_with_too_many_entries(self): ++ pass ++ ++ def test_update_subnet_route(self): ++ pass ++ ++ def test_update_subnet_route_to_None(self): ++ pass ++ ++ def test_update_subnet_route_with_too_many_entries(self): ++ pass ++ ++ def test_delete_subnet_with_dns(self): ++ pass ++ ++ def test_delete_subnet_with_route(self): ++ pass ++ ++ def test_delete_subnet_with_dns_and_route(self): ++ pass ++ ++ def test_list_subnets_with_pagination_emulated(self): ++ pass ++ ++ def test_list_subnets_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_subnets_with_sort_emulated(self): ++ pass ++ ++ def test_validate_subnet_host_routes_exhausted(self): ++ pass ++ ++ def test_validate_subnet_dns_nameservers_exhausted(self): ++ pass ++ ++ ++class TestContrailPortsV2(test_plugin.TestPortsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_port_json(self): ++ pass ++ ++ def test_create_port_bad_tenant(self): ++ pass ++ ++ def test_create_port_public_network(self): ++ pass ++ ++ def test_create_port_public_network_with_ip(self): ++ pass ++ ++ def test_create_ports_bulk_native(self): ++ pass ++ ++ def test_create_ports_bulk_emulated(self): ++ pass ++ ++ def test_create_ports_bulk_wrong_input(self): ++ pass ++ ++ def test_create_ports_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_ports_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_list_ports(self): ++ pass ++ ++ def test_list_ports_filtered_by_fixed_ip(self): ++ pass ++ ++ def test_list_ports_public_network(self): ++ pass ++ ++ def test_show_port(self): ++ pass ++ ++ def test_delete_port(self): ++ pass ++ ++ def test_delete_port_public_network(self): ++ pass ++ ++ def test_update_port(self): ++ pass ++ ++ def test_update_device_id_null(self): ++ pass ++ ++ def test_delete_network_if_port_exists(self): ++ pass ++ ++ def test_delete_network_port_exists_owned_by_network(self): ++ pass ++ ++ def test_update_port_delete_ip(self): ++ pass ++ ++ def test_no_more_port_exception(self): ++ pass ++ ++ def test_update_port_update_ip(self): ++ pass ++ ++ def test_update_port_update_ip_address_only(self): ++ pass ++ ++ def test_update_port_update_ips(self): ++ pass ++ ++ def test_update_port_add_additional_ip(self): ++ pass ++ ++ def test_requested_duplicate_mac(self): ++ pass ++ ++ def test_mac_generation(self): ++ pass ++ ++ def test_mac_generation_4octet(self): ++ pass ++ ++ def test_bad_mac_format(self): ++ pass ++ ++ def test_mac_exhaustion(self): ++ pass ++ ++ def test_requested_duplicate_ip(self): ++ pass ++ ++ def test_requested_subnet_delete(self): ++ pass ++ ++ def test_requested_subnet_id(self): ++ pass ++ ++ def test_requested_subnet_id_not_on_network(self): ++ pass ++ ++ def test_overlapping_subnets(self): ++ pass ++ ++ def test_requested_subnet_id_v4_and_v6(self): ++ pass ++ ++ def test_range_allocation(self): ++ pass ++ ++ def test_requested_invalid_fixed_ips(self): ++ pass ++ ++ def test_invalid_ip(self): ++ pass ++ ++ def test_requested_split(self): ++ pass ++ ++ def test_duplicate_ips(self): ++ pass ++ ++ def test_fixed_ip_invalid_subnet_id(self): ++ pass ++ ++ def test_fixed_ip_invalid_ip(self): ++ pass ++ ++ def test_requested_ips_only(self): ++ pass ++ ++ def test_recycling(self): ++ pass ++ ++ def test_invalid_admin_state(self): ++ pass ++ ++ def test_invalid_mac_address(self): ++ pass ++ ++ def test_default_allocation_expiration(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration(self): ++ pass ++ ++ def test_port_delete_holds_ip(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration_invalid_address(self): ++ pass ++ ++ def test_hold_ip_address(self): ++ pass ++ ++ def test_recycle_held_ip_address(self): ++ pass ++ ++ def test_recycle_expired_previously_run_within_context(self): ++ pass ++ ++ def test_update_port_not_admin(self): ++ pass ++ ++ def test_list_ports_with_pagination_emulated(self): ++ pass ++ ++ def test_list_ports_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_ports_with_sort_emulated(self): ++ pass ++ ++ def test_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_update_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_recycle_ip_address_without_allocation_pool(self): ++ pass +diff --git setup.cfg setup.cfg +index 4876309..9fc01a2 100644 +--- setup.cfg ++++ setup.cfg +@@ -61,6 +61,7 @@ data_files = + etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini + etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini + etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini ++ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini + scripts = + bin/quantum-rootwrap + bin/neutron-rootwrap diff --git a/stack.sh b/stack.sh index 10dfbce658..c20d0f24b3 100755 --- a/stack.sh +++ b/stack.sh @@ -682,6 +682,13 @@ fi if is_service_enabled neutron; then install_neutron install_neutron_third_party + if [ $ENABLE_CONTRAIL ]; then + echo "Installing Neutron patch" + contrail_cwd=$(pwd) + cd $DEST/neutron + sudo patch -p0 < $TOP_DIR/neutron.patch + cd ${contrail_cwd} + fi fi if is_service_enabled nova; then @@ -1163,31 +1170,7 @@ if is_service_enabled n-api; then start_nova_api fi -if is_service_enabled q-svc; then - echo_summary "Starting Neutron" - - start_neutron_service_and_check - create_neutron_initial_network - setup_neutron_debug -elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then - NM_CONF=${NOVA_CONF} - if is_service_enabled n-cell; then - NM_CONF=${NOVA_CELLS_CONF} - fi - - # Create a small network - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS - - # Create some floating ips - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME - - # Create a second pool - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL -fi - -if is_service_enabled neutron; then - start_neutron_agents -fi +# dsetia - neutron was here if is_service_enabled nova; then echo_summary "Starting Nova" start_nova @@ -1383,6 +1366,9 @@ function test_insert_vrouter () } if [ $ENABLE_CONTRAIL ]; then + # save screen settings + SAVED_SCREEN_NAME=$SCREEN_NAME + # Create the destination directory and ensure it is writable by the user DEST=${DEST:-/opt/contrail} sudo mkdir -p $DEST @@ -1519,6 +1505,35 @@ END sudo mv $TOP_DIR/vnsw.hlpr /opt/contrail/ sudo chmod +x /opt/contrail/vnsw.hlpr screen_it agent "sudo /opt/contrail/vnsw.hlpr" + + # restore saved screen settings + SCREEN_NAME=$SAVED_SCREEN_NAME +fi + +if is_service_enabled q-svc; then + echo_summary "Starting Neutron" + + start_neutron_service_and_check + create_neutron_initial_network + setup_neutron_debug +elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then + NM_CONF=${NOVA_CONF} + if is_service_enabled n-cell; then + NM_CONF=${NOVA_CELLS_CONF} + fi + + # Create a small network + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS + + # Create some floating ips + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME + + # Create a second pool + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL +fi + +if is_service_enabled neutron; then + start_neutron_agents fi # Fin diff --git a/stackrc b/stackrc index 5e05251329..4f894ab276 100644 --- a/stackrc +++ b/stackrc @@ -290,6 +290,9 @@ SCREEN_NAME=${SCREEN_NAME:-stack} # Do not install packages tagged with 'testonly' by default INSTALL_TESTONLY_PACKAGES=${INSTALL_TESTONLY_PACKAGES:-False} +# Contrail plugin +Q_PLUGIN=contrail + # Local variables: # mode: shell-script # End: From fbb86902510d8362f50d334a1cd84f29aa60b680 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 3 Oct 2013 14:18:48 -0700 Subject: [PATCH 007/179] Add missing file - needed for contrail neutron plugin --- lib/neutron_plugins/contrail | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 lib/neutron_plugins/contrail diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail new file mode 100644 index 0000000000..7655750fa0 --- /dev/null +++ b/lib/neutron_plugins/contrail @@ -0,0 +1,46 @@ +# Juniper/Contrail Neutron Plugin +# ------------------------------- + +# Save trace settings +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + +function neutron_plugin_create_nova_conf() { + + NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} +} + +function neutron_plugin_setup_interface_driver() { + : +} + +function neutron_plugin_configure_common() { + Q_PLUGIN_CONF_PATH=etc/neutron/plugins/juniper/contrail + Q_PLUGIN_CONF_FILENAME=ContrailPlugin.ini + Q_DB_NAME="contrail_neutron" + Q_PLUGIN_CLASS="neutron.plugins.juniper.contrail.contrailplugin.ContrailPlugin" +} + +function neutron_plugin_configure_service() { + : +} + +function neutron_plugin_configure_debug_command() { + : +} + +function is_neutron_ovs_base_plugin() { + # False + return 1 +} + +function has_neutron_plugin_security_group() { + # False + return 1 +} + +function neutron_plugin_check_adv_test_requirements() { + is_service_enabled q-agt && is_service_enabled q-dhcp && return 0 +} +# Restore xtrace +$MY_XTRACE From 4165d6db5185f8865107afcd34bd3745a6a19877 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 3 Oct 2013 16:13:00 -0700 Subject: [PATCH 008/179] Save helper file in /etc/contrail as /opt/contrail may not exist --- stack.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stack.sh b/stack.sh index c20d0f24b3..bfa44bc507 100755 --- a/stack.sh +++ b/stack.sh @@ -1502,9 +1502,9 @@ EOF LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/vnsw/agent/vnswad --config-file $CONFIG $VROUTER_LOGFILE END - sudo mv $TOP_DIR/vnsw.hlpr /opt/contrail/ - sudo chmod +x /opt/contrail/vnsw.hlpr - screen_it agent "sudo /opt/contrail/vnsw.hlpr" + sudo mv $TOP_DIR/vnsw.hlpr /etc/contrail/ + sudo chmod +x /etc/contrail/vnsw.hlpr + screen_it agent "sudo /etc/contrail/vnsw.hlpr" # restore saved screen settings SCREEN_NAME=$SAVED_SCREEN_NAME From 2a95ea5fc9eb4faa8cd11972eccc54a81d4ab898 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 1 Oct 2013 09:59:45 -0700 Subject: [PATCH 009/179] Fix ordering so that contrail packages are avilable for neutron --- stack.sh | 205 +++++++++++++++++++++++++++---------------------------- 1 file changed, 100 insertions(+), 105 deletions(-) diff --git a/stack.sh b/stack.sh index bfa44bc507..4ca9e23ba0 100755 --- a/stack.sh +++ b/stack.sh @@ -679,16 +679,22 @@ if is_service_enabled cinder; then configure_cinder fi -if is_service_enabled neutron; then - install_neutron - install_neutron_third_party - if [ $ENABLE_CONTRAIL ]; then +function test_install_neutron_patch() { + contrail_cwd=$(pwd) + cd $DEST/neutron + patch -p0 -N --dry-run --silent < $TOP_DIR/neutron.patch &> /dev/null + if [ $? == 0 ]; then + # patch is missing echo "Installing Neutron patch" - contrail_cwd=$(pwd) - cd $DEST/neutron sudo patch -p0 < $TOP_DIR/neutron.patch - cd ${contrail_cwd} fi + cd ${contrail_cwd} +} + +if is_service_enabled neutron; then + install_neutron + install_neutron_third_party + test_install_neutron_patch fi if is_service_enabled nova; then @@ -927,7 +933,94 @@ if is_service_enabled ir-api ir-cond; then init_ironic fi +# Contrail +# -------- +if [ $ENABLE_CONTRAIL ]; then + PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` + sudo mkdir -p /var/log/contrail + sudo chmod 777 /var/log/contrail + + # basic dependencies + if ! command_exists repo ; then + mkdir -p ~/bin + PATH=~/bin:$PATH + sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo + sudo chmod a+x ~/bin/repo + fi + + # dependencies + sudo yum -y install patch scons flex bison make vim + sudo yum -y install expat-devel gettext-devel curl-devel + sudo yum -y install gcc-c++ python-devel autoconf automake + sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + + # api server requirements + # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + sudo pip install gevent geventhttpclient==1.0a thrift + sudo pip install netifaces fabric argparse + sudo pip install stevedore xmltodict python-keystoneclient + sudo pip install kazoo + + CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} + mkdir -p $CONTRAIL_SRC + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC + if [ ! -d $CONTRAIL_SRC/.repo ]; then + repo init -u git@github.com:Juniper/contrail-vnc + fi + repo sync + python third_party/fetch_packages.py + scons + cd ${contrail_cwd} + + # get cassandra + if [ ! -f "/usr/sbin/cassandra" ] ; then + cat << EOF > datastax.repo +[datastax] +name = DataStax Repo for Apache Cassandra +baseurl = http://rpm.datastax.com/community +enabled = 1 +gpgcheck = 0 +EOF + sudo mv datastax.repo /etc/yum.repos.d/ + sudo yum -y install dsc20 + fi + + # get ifmap + if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + unzip irond-0.3.0-bin.zip + cd ${contrail_cwd} + fi + + if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz + tar xvzf zookeeper-3.4.5.tar.gz + cd zookeeper-3.4.5 + cp conf/zoo_sample.cfg conf/zoo.cfg + cd ${contrail_cwd} + fi + + # ncclient + if [ ! -d $PYLIBPATH/ncclient ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + sudo pip install ncclient-v0.3.2.tar.gz + cd ${contrail_cwd} + fi + + # create config files + python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST + # install contrail modules + echo "Installing contrail modules" + sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) +fi # Neutron # ------- @@ -1170,7 +1263,6 @@ if is_service_enabled n-api; then start_nova_api fi -# dsetia - neutron was here if is_service_enabled nova; then echo_summary "Starting Nova" start_nova @@ -1368,19 +1460,6 @@ function test_insert_vrouter () if [ $ENABLE_CONTRAIL ]; then # save screen settings SAVED_SCREEN_NAME=$SCREEN_NAME - - # Create the destination directory and ensure it is writable by the user - DEST=${DEST:-/opt/contrail} - sudo mkdir -p $DEST - if [ ! -w $DEST ]; then - sudo chown `whoami` $DEST - fi - - # Destination path for service data - DATA_DIR=${DATA_DIR:-${DEST}/data} - sudo mkdir -p $DATA_DIR - sudo chown `whoami` $DATA_DIR - SCREEN_NAME="contrail" screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash sleep 1 @@ -1388,90 +1467,6 @@ if [ $ENABLE_CONTRAIL ]; then screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` - sudo mkdir -p /var/log/contrail - sudo chmod 777 /var/log/contrail - - # basic dependencies - if ! command_exists repo ; then - mkdir -p ~/bin - PATH=~/bin:$PATH - sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo - sudo chmod a+x ~/bin/repo - fi - - # dependencies - sudo yum -y install patch scons flex bison make vim - sudo yum -y install expat-devel gettext-devel curl-devel - sudo yum -y install gcc-c++ python-devel autoconf automake - sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel - - # api server requirements - # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 - sudo pip install gevent geventhttpclient==1.0a thrift - sudo pip install netifaces fabric argparse - sudo pip install stevedore xmltodict python-keystoneclient - sudo pip install kazoo - - CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} - mkdir -p $CONTRAIL_SRC - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC - if [ ! -d $CONTRAIL_SRC/.repo ]; then - repo init -u git@github.com:Juniper/contrail-vnc - fi - repo sync - python third_party/fetch_packages.py - scons - cd ${contrail_cwd} - - # get cassandra - if [ ! -f "/usr/sbin/cassandra" ] ; then - cat << EOF > datastax.repo -[datastax] -name = DataStax Repo for Apache Cassandra -baseurl = http://rpm.datastax.com/community -enabled = 1 -gpgcheck = 0 -EOF - sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install dsc20 - fi - - # get ifmap - if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip - unzip irond-0.3.0-bin.zip - cd ${contrail_cwd} - fi - - if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz - tar xvzf zookeeper-3.4.5.tar.gz - cd zookeeper-3.4.5 - cp conf/zoo_sample.cfg conf/zoo.cfg - cd ${contrail_cwd} - fi - - # ncclient - if [ ! -d $PYLIBPATH/ncclient ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz - sudo pip install ncclient-v0.3.2.tar.gz - cd ${contrail_cwd} - fi - - # create config files - # python $TOP_DIR/setup_contrail.py --physical_interface $CONTRAIL_USE_INTF - python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST - - # install contrail modules - echo "Installing contrail modules" - sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) # launch ... screen_it cass "sudo /usr/sbin/cassandra -f" From 8967a8d761811119e41e3ab2eb33184bf43ce707 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 7 Oct 2013 10:27:38 -0700 Subject: [PATCH 010/179] supervisor-vrouter service not used on devstack based setup --- setup_contrail.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup_contrail.py b/setup_contrail.py index d671a8690a..19d3260182 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -755,7 +755,6 @@ def fixup_config_files(self): self.run_shell("sudo mv %s/ifcfg-%s /etc/contrail/" % (temp_dir_name, dev)) self.run_shell("sudo chkconfig network on") - self.run_shell("sudo chkconfig supervisor-vrouter on") #end if dev and dev != 'vhost0' : # role == compute && !cfgm From 68b91d5265e7a7e72e3d7a4fd51ca4b2e3dd098c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 8 Oct 2013 03:57:35 -0700 Subject: [PATCH 011/179] Move Quantum plugin configuration to localrc. This allows building devstack withiout contrail if needed --- stackrc | 3 --- 1 file changed, 3 deletions(-) diff --git a/stackrc b/stackrc index 4f894ab276..5e05251329 100644 --- a/stackrc +++ b/stackrc @@ -290,9 +290,6 @@ SCREEN_NAME=${SCREEN_NAME:-stack} # Do not install packages tagged with 'testonly' by default INSTALL_TESTONLY_PACKAGES=${INSTALL_TESTONLY_PACKAGES:-False} -# Contrail plugin -Q_PLUGIN=contrail - # Local variables: # mode: shell-script # End: From 22115aafb2f1c6c3040414192068824e4b71787d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 9 Oct 2013 12:21:09 -0700 Subject: [PATCH 012/179] Use default quota driver for contrail --- lib/neutron_plugins/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index 7655750fa0..1f41a276a6 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -22,7 +22,7 @@ function neutron_plugin_configure_common() { } function neutron_plugin_configure_service() { - : + iniset $NEUTRON_CONF quotas quota_driver neutron.quota.ConfDriver } function neutron_plugin_configure_debug_command() { From af6f9c33d8e7f9221d54933e5b37deb073140786 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 9 Oct 2013 12:22:48 -0700 Subject: [PATCH 013/179] Generate ContrailPlugin.ini with API server and keystone information --- contrail_config_templates.py | 12 ++++++++++++ setup_contrail.py | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index 02791a1f6d..60ef72fa4c 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -271,3 +271,15 @@ $__contrail_domain__ $__contrail_mtu__ """) + +contrail_plugin_template = string.Template(""" +[APISERVER] +api_server_ip=$__api_server_ip__ +api_server_port=$__api_server_port__ +multi_tenancy=$__multitenancy__ + +[KEYSTONE] +admin_user=$__contrail_admin_user__ +admin_password=$__contrail_admin_password__ +admin_tenant_name=$__contrail_admin_tenant_name__ +""") diff --git a/setup_contrail.py b/setup_contrail.py index 19d3260182..52e4e476b1 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -562,6 +562,19 @@ def fixup_config_files(self): template_vals, temp_dir_name + '/vnc_api_lib.ini') self.run_shell("sudo mv %s/vnc_api_lib.ini /etc/contrail/" %(temp_dir_name)) + template_vals = { + '__api_server_ip__' : cfgm_ip, + '__api_server_port__': '8082', + '__multitenancy__' : 'False', + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + } + self._template_substitute_write(contrail_plugin_template, + template_vals, temp_dir_name + '/ContrailPlugin.ini') + self.run_shell("sudo cp %s/ContrailPlugin.ini /opt/stack/neutron/etc/neutron/plugins/juniper/contrail/" %(temp_dir_name)) + self.run_shell("sudo mv %s/ContrailPlugin.ini /etc/contrail/" %(temp_dir_name)) + if 'control' in self._args.role: control_ip = self._args.control_ip certdir = '/var/lib/puppet/ssl' if self._args.puppet_server else '/etc/contrail/ssl' From d1035c1ba9400b0c1a2234a9f81b82462425012f Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 10 Oct 2013 00:16:50 -0700 Subject: [PATCH 014/179] Fix generation of qemu.conf --- setup_contrail.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setup_contrail.py b/setup_contrail.py index 52e4e476b1..908a1af18e 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -177,6 +177,11 @@ def _parse_args(self, args_str): #end _parse_args + def call_cmd(self, cmd): + from subprocess import call + return call(cmd, shell=True) + # end + def run_cmd(self, cmd): """Return (status, output) of executing cmd in a shell.""" pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') @@ -635,7 +640,7 @@ def fixup_config_files(self): if 'compute' in self._args.role: dist = platform.dist()[0] # add /dev/net/tun in cgroup_device_acl needed for type=ethernet interfaces - ret = self.run_cmd("sudo grep -q '^cgroup_device_acl' /etc/libvirt/qemu.conf") + ret = self.call_cmd("sudo grep -q '^cgroup_device_acl' /etc/libvirt/qemu.conf") if ret == 1: self.run_shell('sudo cp /etc/libvirt/qemu.conf qemu.conf') self.run_shell('sudo chown %s qemu.conf' % whoami) From e8d1b31296742aaab62494277de0fc2a7043125a Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 9 Oct 2013 19:07:12 -0700 Subject: [PATCH 015/179] Generate control node IP address in agent configuration file till discovery server is deployed --- contrail_config_templates.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index 60ef72fa4c..81f3068997 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -248,8 +248,11 @@ $__contrail_intf__ - $__contrail_control_ip__ + $__contrail_box_ip__ + + $__contrail_control_ip__ + """) From 8eae6d61c8bd376adc898ec3493e62768e1d5f2c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 11 Oct 2013 10:57:14 -0700 Subject: [PATCH 016/179] Add support for Nova plugin --- neutron_v2.patch | 4705 ++++++++++++++++++++++++++++++++++++++++++++++ nova_v1.patch | 3238 +++++++++++++++++++++++++++++++ stack.sh | 36 +- stackrc | 2 +- 4 files changed, 7975 insertions(+), 6 deletions(-) create mode 100644 neutron_v2.patch create mode 100644 nova_v1.patch diff --git a/neutron_v2.patch b/neutron_v2.patch new file mode 100644 index 0000000000..2a294ddab9 --- /dev/null +++ b/neutron_v2.patch @@ -0,0 +1,4705 @@ +diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py +new file mode 100644 +index 0000000..5d610b3 +--- /dev/null ++++ neutron/extensions/ipam.py +@@ -0,0 +1,140 @@ ++from abc import abstractmethod ++ ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron.api import extensions ++from neutron import manager ++from oslo.config import cfg ++ ++ ++# Ipam Exceptions ++class IpamNotFound(qexception.NotFound): ++ message = _("IPAM %(id)s could not be found") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'ipams': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:regex': attr.UUID_PATTERN}, ++ 'is_visible': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'fq_name': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ 'mgmt': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': None}, ++ 'nets_using': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True, 'default': ''} ++ }, ++} ++ ++# TODO should this be tied to ipam extension? ++EXTENDED_ATTRIBUTES_2_0 = { ++ 'networks': { ++ 'contrail:fq_name': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:policys': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ 'contrail:subnet_ipam': {'allow_post': False, ++ 'allow_put': False, ++ 'default': '', ++ 'is_visible': True}, ++ }, ++ 'subnets': { ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:ipam_fq_name': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ } ++} ++ ++ ++class Ipam(object): ++ ++ @classmethod ++ def get_name(cls): ++ return "Network IP Address Management" ++ ++ @classmethod ++ def get_alias(cls): ++ return "ipam" ++ ++ @classmethod ++ def get_description(cls): ++ return ("Configuration object for holding common to a set of" ++ " IP address blocks") ++ ++ @classmethod ++ def get_namespace(cls): ++ return "http://docs.openstack.org/TODO" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2012-07-20T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ exts = [] ++ plugin = manager.QuantumManager.get_plugin() ++ for resource_name in ['ipam']: ++ collection_name = resource_name + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) ++ ++ member_actions = {} ++ ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, ++ member_actions=member_actions) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ member_actions=member_actions) ++ exts.append(ex) ++ ++ return exts ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return EXTENDED_ATTRIBUTES_2_0 ++ else: ++ return {} ++#end class Ipam ++ ++ ++class IpamPluginBase(object): ++ ++ @abstractmethod ++ def create_ipam(self, context, ipam): ++ pass ++ ++ @abstractmethod ++ def update_ipam(self, context, id, ipam): ++ pass ++ ++ @abstractmethod ++ def get_ipam(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def delete_ipam(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_ipams(self, context, filters=None, fields=None): ++ pass ++#end class IpamPluginBase +diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py +index 425f8dc..69f1202 100644 +--- neutron/extensions/portbindings.py ++++ neutron/extensions/portbindings.py +@@ -44,10 +44,11 @@ VIF_TYPE_BRIDGE = 'bridge' + VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_HYPERV = 'hyperv' ++VIF_TYPE_CONTRAIL = 'contrail' + VIF_TYPE_OTHER = 'other' + VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, + VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, +- VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_OTHER] ++ VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_CONTRAIL, VIF_TYPE_OTHER] + + + EXTENDED_ATTRIBUTES_2_0 = { +diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py +new file mode 100644 +index 0000000..8028b32 +--- /dev/null ++++ neutron/plugins/juniper/contrail/contrailplugin.py +@@ -0,0 +1,1187 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++ ++import ConfigParser ++import logging ++from pprint import pformat ++ ++#from neutron.manager import NeutronManager ++from neutron.common import exceptions as exc ++from neutron.db import db_base_plugin_v2 ++from neutron.db import portbindings_base ++from neutron.extensions import l3 ++from neutron.extensions import securitygroup ++from neutron.extensions import portbindings ++#from neutron.extensions import vpcroutetable ++ ++import cgitb ++from httplib2 import Http ++from oslo.config import cfg ++import re ++import string ++import sys ++ ++import ctdb.config_db ++ ++LOG = logging.getLogger(__name__) ++ ++vnc_opts = [ ++ cfg.StrOpt('api_server_ip', default='127.0.0.1'), ++ cfg.StrOpt('api_server_port', default='8082'), ++] ++ ++ ++def _read_cfg(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.get(section, option) ++ except (AttributeError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++def _read_cfg_boolean(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.getboolean(section, option) ++ except (AttributeError, ValueError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, ++ l3.RouterPluginBase, ++ securitygroup.SecurityGroupPluginBase, ++ portbindings_base.PortBindingBaseMixin): ++#vpcroutetable.RouteTablePluginBase): ++ ++ supported_extension_aliases = ["ipam", "policy", "security-group", ++ "router", "route-table", "port-security", ++ "binding",] ++ __native_bulk_support = False ++ _cfgdb = None ++ _args = None ++ _tenant_id_dict = {} ++ _tenant_name_dict = {} ++ ++ @classmethod ++ def _parse_class_args(cls, cfg_parser): ++ cfg_parser.read("/etc/neutron/plugins/juniper/" ++ "contrail/ContrailPlugin.ini" ++ ) ++ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', ++ 'multi_tenancy', False) ++ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') ++ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') ++ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', ++ 'user1') ++ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_password', 'password1') ++ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_tenant_name', ++ 'default-domain') ++ cls._tenants_api = '%s/tenants' % (cls._auth_url) ++ pass ++ ++ @classmethod ++ def _connect_to_db(cls): ++ """ ++ Many instantiations of plugin (base + extensions) but need to have ++ only one config db conn (else error from ifmap-server) ++ """ ++ cls._cfgdb_map = {} ++ if cls._cfgdb is None: ++ sip = cfg.CONF.APISERVER.api_server_ip ++ sport = cfg.CONF.APISERVER.api_server_port ++ # Initialize connection to DB and add default entries ++ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, ++ cls._admin_password, ++ cls._admin_tenant_name, ++ sip, sport) ++ cls._cfgdb.manager = cls ++ ++ @classmethod ++ def _get_user_cfgdb(cls, context): ++ if not cls._multi_tenancy: ++ return cls._cfgdb ++ user_id = context.user_id ++ role = string.join(context.roles, ",") ++ if user_id not in cls._cfgdb_map: ++ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( ++ cls._admin_user, cls._admin_password, cls._admin_tenant_name, ++ cfg.CONF.APISERVER.api_server_ip, ++ cfg.CONF.APISERVER.api_server_port, ++ user_info={'user_id': user_id, 'role': role}) ++ cls._cfgdb_map[user_id].manager = cls ++ ++ return cls._cfgdb_map[user_id] ++ ++ @classmethod ++ def _tenant_list_from_keystone(cls): ++ # get all tenants ++ hdrs = {'X-Auth-Token': cls._admin_token, ++ 'Content-Type': 'application/json'} ++ try: ++ rsp, content = Http().request(cls._tenants_api, ++ method="GET", headers=hdrs) ++ if rsp.status != 200: ++ return ++ except Exception: ++ return ++ ++ # transform needed for python compatibility ++ content = re.sub('true', 'True', content) ++ content = re.sub('null', 'None', content) ++ content = eval(content) ++ ++ # bail if response is unexpected ++ if 'tenants' not in content: ++ return ++ ++ # create a dictionary for id->name and name->id mapping ++ for tenant in content['tenants']: ++ print 'Adding tenant %s:%s to cache' % (tenant['name'], ++ tenant['id']) ++ cls._tenant_id_dict[tenant['id']] = tenant['name'] ++ cls._tenant_name_dict[tenant['name']] = tenant['id'] ++ ++ def update_security_group(self, context, id, security_group): ++ pass ++ ++ def __init__(self): ++ cfg.CONF.register_opts(vnc_opts, 'APISERVER') ++ ++ cfg_parser = ConfigParser.ConfigParser() ++ ContrailPlugin._parse_class_args(cfg_parser) ++ ++ ContrailPlugin._connect_to_db() ++ self._cfgdb = ContrailPlugin._cfgdb ++ ++ ContrailPlugin._tenant_list_from_keystone() ++ self.base_binding_dict = self._get_base_binding_dict() ++ portbindings_base.register_port_dict_function() ++ ++ def _get_base_binding_dict(self): ++ binding = { ++ portbindings.VIF_TYPE: portbindings.VIF_TYPE_CONTRAIL, ++ portbindings.CAPABILITIES: { ++ portbindings.CAP_PORT_FILTER: ++ 'security-group' in self.supported_extension_aliases}} ++ return binding ++ ++ @classmethod ++ def tenant_id_to_name(cls, id): ++ # bail if we never built the list successfully ++ if len(cls._tenant_id_dict) == 0: ++ return id ++ # check cache ++ if id in cls._tenant_id_dict: ++ return cls._tenant_id_dict[id] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id ++ ++ @classmethod ++ def tenant_name_to_id(cls, name): ++ # bail if we never built the list successfully ++ if len(cls._tenant_name_dict) == 0: ++ return name ++ # check cache ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ else: ++ return name ++ ++ # Network API handlers ++ def create_network(self, context, network): ++ """ ++ Creates a new Virtual Network, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_create(network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("create_network(): " + pformat(net_dict) + "\n") ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_network(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_read(id, fields) ++ ++ # verify transformation is conforming to api ++ if not fields: ++ # should return all fields ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ fields, False) ++ net_dict.update(net_info['q_extra_data']) ++ else: ++ net_dict = net_info['q_api_data'] ++ ++ LOG.debug("get_network(): " + pformat(net_dict)) ++ return self._fields(net_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_network(self, context, net_id, network): ++ """ ++ Updates the attributes of a particular Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_update(net_id, network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("update_network(): " + pformat(net_dict)) ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_network(self, context, net_id): ++ """ ++ Deletes the network with the specified network identifier ++ belonging to the specified tenant. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.network_delete(net_id) ++ LOG.debug("delete_network(): " + pformat(net_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_info = cfgdb.network_list(filters) ++ ++ nets_dicts = [] ++ for n_info in nets_info: ++ # verify transformation is conforming to api ++ n_dict = self._make_network_dict(n_info['q_api_data'], fields, ++ False) ++ ++ n_dict.update(n_info['q_extra_data']) ++ nets_dicts.append(n_dict) ++ ++ LOG.debug( ++ "get_networks(): filters: " + pformat(filters) + " data: " ++ + pformat(nets_dicts)) ++ return nets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_count = cfgdb.network_count(filters) ++ LOG.debug("get_networks_count(): " + str(nets_count)) ++ return nets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Subnet API handlers ++ def create_subnet(self, context, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_create(subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("create_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnet(self, context, subnet_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_read(subnet_id) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], ++ fields) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("get_subnet(): " + pformat(subnet_dict)) ++ return self._fields(subnet_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_subnet(self, context, subnet_id, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("update_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_subnet(self, context, subnet_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.subnet_delete(subnet_id) ++ ++ LOG.debug("delete_subnet(): " + pformat(subnet_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets(self, context, filters=None, fields=None): ++ """ ++ Called from Neutron API -> get_ ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_info = cfgdb.subnets_list(filters) ++ ++ subnets_dicts = [] ++ for sn_info in subnets_info: ++ # verify transformation is conforming to api ++ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) ++ ++ sn_dict.update(sn_info['q_extra_data']) ++ subnets_dicts.append(sn_dict) ++ ++ LOG.debug( ++ "get_subnets(): filters: " + pformat(filters) + " data: " ++ + pformat(subnets_dicts)) ++ return subnets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_count = cfgdb.subnets_count(filters) ++ LOG.debug("get_subnets_count(): " + str(subnets_count)) ++ return subnets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Ipam API handlers ++ def create_ipam(self, context, ipam): ++ """ ++ Creates a new IPAM, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_create(ipam['ipam']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("create_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipam(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("get_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_ipam(self, context, id, ipam): ++ """ ++ Updates the attributes of a particular IPAM. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_update(id, ipam) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("update_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_ipam(self, context, ipam_id): ++ """ ++ Deletes the ipam with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.ipam_delete(ipam_id) ++ ++ LOG.debug("delete_ipam(): " + pformat(ipam_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_info = cfgdb.ipam_list(filters) ++ ++ ipams_dicts = [] ++ for ipam_info in ipams_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ipams_dicts.append(ipam_dict) ++ ++ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) ++ return ipams_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_count = cfgdb.ipams_count(filters) ++ LOG.debug("get_ipams_count(): " + str(ipams_count)) ++ return ipams_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Policy API handlers ++ def create_policy(self, context, policy): ++ """ ++ Creates a new Policy, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_create(policy['policy']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("create_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("get_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_policy(self, context, id, policy): ++ """ ++ Updates the attributes of a particular Policy. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_update(id, policy) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("update_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_policy(self, context, policy_id): ++ """ ++ Deletes the Policy with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.policy_delete(policy_id) ++ ++ LOG.debug("delete_policy(): " + pformat(policy_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policys(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policys_info = cfgdb.policy_list(filters) ++ ++ policys_dicts = [] ++ for policy_info in policys_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ policys_dicts.append(policy_dict) ++ ++ LOG.debug("get_policys(): " + pformat(policys_dicts)) ++ return policys_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_count = cfgdb.policy_count(filters) ++ LOG.debug("get_policy_count(): " + str(policy_count)) ++ return policy_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Floating IP API handlers ++ def _make_floatingip_dict(self, floatingip, fields=None): ++ res = {'id': floatingip['id'], ++ 'tenant_id': floatingip['tenant_id'], ++ 'floating_ip_address': floatingip['floating_ip_address'], ++ 'floating_network_id': floatingip['floating_network_id'], ++ 'router_id': floatingip['router_id'], ++ 'port_id': floatingip['fixed_port_id'], ++ 'fixed_ip_address': floatingip['fixed_ip_address']} ++ return self._fields(res, fields) ++ ++ def create_floatingip(self, context, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("create_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_floatingip(self, context, fip_id, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_update(fip_id, ++ floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("update_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingip(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_read(id) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("get_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_floatingip(self, context, fip_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.floatingip_delete(fip_id) ++ LOG.debug("delete_floating(): " + pformat(fip_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fips_info = cfgdb.floatingip_list(filters) ++ ++ fips_dicts = [] ++ for fip_info in fips_info: ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ fips_dicts.append(fip_dict) ++ ++ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) ++ return fips_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ floatingips_count = cfgdb.floatingip_count(filters) ++ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) ++ return floatingips_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Port API handlers ++ def create_port(self, context, port): ++ """ ++ Creates a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_create(port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ ++ LOG.debug("create_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_port(self, context, port_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_read(port_id) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ port_info, ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("get_port(): " + pformat(port_dict)) ++ return self._fields(port_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_port(self, context, port_id, port): ++ """ ++ Updates the attributes of a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_update(port_id, port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("update_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_port(self, context, port_id): ++ """ ++ Deletes a port on a specified Virtual Network, ++ if the port contains a remote interface attachment, ++ the remote interface is first un-plugged and then the port ++ is deleted. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.port_delete(port_id) ++ LOG.debug("delete_port(): " + pformat(port_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports(self, context, filters=None, fields=None): ++ """ ++ Retrieves all port identifiers belonging to the ++ specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_info = cfgdb.port_list(filters) ++ ++ ports_dicts = [] ++ for p_info in ports_info: ++ # verify transformation is conforming to api ++ p_dict = self._make_port_dict(p_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ p_info, ++ p_dict) ++ ++ p_dict.update(p_info['q_extra_data']) ++ ports_dicts.append(p_dict) ++ ++ LOG.debug( ++ "get_ports(): filter: " + pformat(filters) + 'data: ' ++ + pformat(ports_dicts)) ++ return ports_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_count = cfgdb.port_count(filters) ++ LOG.debug("get_ports_count(): " + str(ports_count)) ++ return ports_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): ++ """ ++ Attaches a remote interface to the specified port on the ++ specified Virtual Network. ++ """ ++ port = self._get_port(tenant_id, net_id, port_id) ++ # Validate attachment ++ self._validate_attachment(tenant_id, net_id, port_id, ++ remote_interface_id) ++ if port['interface_id']: ++ raise exc.PortInUse(net_id=net_id, port_id=port_id, ++ att_id=port['interface_id']) ++ ++ def unplug_interface(self, tenant_id, net_id, port_id): ++ """ ++ Detaches a remote interface from the specified port on the ++ specified Virtual Network. ++ """ ++ self._get_port(tenant_id, net_id, port_id) ++ ++ # VPC route table handlers ++ def _make_route_table_routes_dict(self, route_table_route, fields=None): ++ res = {'prefix': route_table_route['prefix'], ++ 'next_hop': route_table_route['next_hop']} ++ ++ return self._fields(res, fields) ++ ++ def _make_route_table_dict(self, route_table, fields=None): ++ res = {'id': route_table['id'], ++ 'name': route_table['name'], ++ 'fq_name': route_table['fq_name'], ++ 'tenant_id': route_table['tenant_id']} ++ if route_table['routes']: ++ res['routes'] = [self._make_route_table_routes_dict(r) ++ for r in route_table['routes']['route']] ++ return self._fields(res, fields) ++ ++ def create_route_table(self, context, route_table): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_create( ++ route_table['route_table']) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_route_table(self, context, id, route_table): ++ """ ++ Updates the attributes of a particular route table. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_update(id, route_table['route_table']) ++ ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_route_table(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.route_table_delete(id) ++ LOG.debug("delete_route_table(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_tables(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ route_tables_info = cfgdb.route_table_list(context, filters) ++ ++ route_tables_dicts = [] ++ for rt_info in route_tables_info: ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ route_tables_dicts.append(rt_dict) ++ ++ LOG.debug( ++ "get_route_tables(): filter: " + pformat(filters) ++ + 'data: ' + pformat(route_tables_dicts)) ++ return route_tables_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_table(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_read(id) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ ++ LOG.debug("get_route_table(): " + pformat(rt_dict)) ++ return self._fields(rt_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # VPC route table svc instance handlers ++ def _make_svc_instance_dict(self, svc_instance, fields=None): ++ res = {'id': svc_instance['id'], ++ 'name': svc_instance['name'], ++ 'tenant_id': svc_instance['tenant_id']} ++ if svc_instance['internal_net']: ++ res['internal_net'] = svc_instance['internal_net'] ++ if svc_instance['external_net']: ++ res['external_net'] = svc_instance['external_net'] ++ return self._fields(res, fields) ++ ++ def create_nat_instance(self, context, nat_instance): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_create( ++ nat_instance['nat_instance']) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("create_nat_instance(): " + pformat(si_dict)) ++ return si_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_nat_instance(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.svc_instance_delete(id) ++ LOG.debug("delete_nat_instance(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instances(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ svc_instances_info = cfgdb.svc_instance_list(context, filters) ++ ++ svc_instances_dicts = [] ++ for si_info in svc_instances_info: ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ svc_instances_dicts.append(si_dict) ++ ++ LOG.debug( ++ "get_nat_instances(): filter: " + pformat(filters) ++ + 'data: ' + pformat(svc_instances_dicts)) ++ return svc_instances_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instance(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_read(id) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("get_nat_instance(): " + pformat(si_dict)) ++ return self._fields(si_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Security Group handlers ++ def _make_security_group_rule_dict(self, security_group_rule, fields=None): ++ res = {'id': security_group_rule['id'], ++ 'tenant_id': security_group_rule['tenant_id'], ++ 'security_group_id': security_group_rule['security_group_id'], ++ 'ethertype': security_group_rule['ethertype'], ++ 'direction': security_group_rule['direction'], ++ 'protocol': security_group_rule['protocol'], ++ 'port_range_min': security_group_rule['port_range_min'], ++ 'port_range_max': security_group_rule['port_range_max'], ++ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], ++ 'remote_group_id': security_group_rule['remote_group_id']} ++ ++ return self._fields(res, fields) ++ ++ def _make_security_group_dict(self, security_group, fields=None): ++ res = {'id': security_group['id'], ++ 'name': security_group['name'], ++ 'tenant_id': security_group['tenant_id'], ++ 'description': security_group['description']} ++ res['security_group_rules'] = [self._make_security_group_rule_dict(r) ++ for r in security_group['rules']] ++ return self._fields(res, fields) ++ ++ def create_security_group(self, context, security_group): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_create( ++ security_group['security_group']) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("create_security_group(): " + pformat(sg_dict)) ++ return sg_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_delete(id) ++ LOG.debug("delete_security_group(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_groups(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_groups_info = cfgdb.security_group_list(context, filters) ++ ++ security_groups_dicts = [] ++ for sg_info in security_groups_info: ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ security_groups_dicts.append(sg_dict) ++ ++ LOG.debug( ++ "get_security_groups(): filter: " + pformat(filters) ++ + 'data: ' + pformat(security_groups_dicts)) ++ return security_groups_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_read(id) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("get_security_group(): " + pformat(sg_dict)) ++ return self._fields(sg_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def create_security_group_rule(self, context, security_group_rule): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_create( ++ security_group_rule['security_group_rule']) ++ ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data']) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) ++ return sgr_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group_rule(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_rule_delete(id) ++ LOG.debug("delete_security_group_rule(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rules(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_group_rules_info = cfgdb.security_group_rule_list(filters) ++ ++ security_group_rules_dicts = [] ++ for sgr_info in security_group_rules_info: ++ for sgr in sgr_info: ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr['q_api_data'], fields) ++ sgr_dict.update(sgr['q_extra_data']) ++ security_group_rules_dicts.append(sgr_dict) ++ ++ LOG.debug( ++ "get_security_group_rules(): filter: " + pformat(filters) + ++ 'data: ' + pformat(security_group_rules_dicts)) ++ return security_group_rules_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rule(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_read(id) ++ ++ # verify transformation is conforming to api ++ sgr_dict = {} ++ if sgr_info != {}: ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data'], fields) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) ++ return self._fields(sgr_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e +diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py +new file mode 100644 +index 0000000..4a87a41 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/config_db.py +@@ -0,0 +1,2238 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++import json ++import re ++import requests ++import socket ++import time ++import uuid ++from netaddr import IPNetwork, IPSet, IPAddress ++ ++from neutron.api.v2 import attributes as attr ++from neutron.common import constants ++from neutron.common import exceptions ++from neutron.extensions import portbindings ++from vnc_api.common import exceptions as vnc_exc ++from vnc_api import vnc_api ++ ++_DEFAULT_HEADERS = { ++ 'Content-type': 'application/json; charset="UTF-8"', } ++ ++CREATE = 1 ++READ = 2 ++UPDATE = 3 ++DELETE = 4 ++ ++ ++class DBInterface(object): ++ """ ++ An instance of this class forwards requests to vnc cfg api (web)server ++ """ ++ Q_URL_PREFIX = '/extensions/ct' ++ ++ def __init__(self, admin_name, admin_password, admin_tenant_name, ++ api_srvr_ip, api_srvr_port, user_info=None): ++ self._api_srvr_ip = api_srvr_ip ++ self._api_srvr_port = api_srvr_port ++ ++ self._db_cache = {} ++ self._db_cache['q_networks'] = {} ++ self._db_cache['q_subnets'] = {} ++ self._db_cache['q_subnet_maps'] = {} ++ self._db_cache['q_policies'] = {} ++ self._db_cache['q_ipams'] = {} ++ self._db_cache['q_floatingips'] = {} ++ self._db_cache['q_ports'] = {} ++ self._db_cache['q_fixed_ip_to_subnet'] = {} ++ #obj-uuid to tenant-uuid mapping ++ self._db_cache['q_obj_to_tenant'] = {} ++ #port count per tenant-id ++ self._db_cache['q_tenant_port_count'] = {} ++ self._db_cache['vnc_networks'] = {} ++ self._db_cache['vnc_ports'] = {} ++ self._db_cache['vnc_projects'] = {} ++ self._db_cache['vnc_instance_ips'] = {} ++ ++ # Retry till a api-server is up ++ connected = False ++ while not connected: ++ try: ++ self._vnc_lib = vnc_api.VncApi( ++ admin_name, admin_password, ++ admin_tenant_name, api_srvr_ip, ++ api_srvr_port, '/', user_info=user_info) ++ connected = True ++ except requests.exceptions.RequestException: ++ time.sleep(3) ++ ++ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key ++ subnet_map = self._vnc_lib.kv_retrieve(key=None) ++ for kv_dict in subnet_map: ++ key = kv_dict['key'] ++ if len(key.split()) == 1: ++ subnet_id = key ++ # uuid key, fixup value portion to 'net_id pfx/len' format ++ # if not already so ++ if len(kv_dict['value'].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ net_fq_name = kv_dict['value'].split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ self._vnc_lib.kv_delete(subnet_id) ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, ++ kv_dict['value'].split()[1]) ++ self._vnc_lib.kv_store(subnet_id, new_subnet_key) ++ else: # subnet key ++ if len(key.split()[0].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ # delete old key, convert to new key format and save ++ old_subnet_key = key ++ self._vnc_lib.kv_delete(old_subnet_key) ++ ++ subnet_id = kv_dict['value'] ++ net_fq_name = key.split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) ++ self._vnc_lib.kv_store(new_subnet_key, subnet_id) ++ ++ # Helper routines ++ def _request_api_server(self, url, method, data=None, headers=None): ++ if method == 'GET': ++ return requests.get(url) ++ if method == 'POST': ++ return requests.post(url, data=data, headers=headers) ++ if method == 'DELETE': ++ return requests.delete(url) ++ ++ def _relay_request(self, request): ++ """ ++ Send received request to api server ++ """ ++ # chop neutron parts of url and add api server address ++ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) ++ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, ++ url_path) ++ ++ return self._request_api_server( ++ url, request.environ['REQUEST_METHOD'], ++ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) ++ ++ def _obj_to_json(self, obj): ++ return dict((k, v) for k, v in obj.__dict__.iteritems()) ++ ++ def _ensure_instance_exists(self, instance_id): ++ instance_name = instance_id ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ try: ++ id = self._vnc_lib.obj_to_id(instance_obj) ++ instance_obj = self._vnc_lib.virtual_machine_read(id=id) ++ except Exception as e: ++ #except vnc_exc.NoIdError: # instance doesn't exist, create it ++ instance_obj.uuid = instance_id ++ self._vnc_lib.virtual_machine_create(instance_obj) ++ ++ return instance_obj ++ ++ def _ensure_default_security_group_exists(self, proj_id): ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ sg_groups = proj_obj.get_security_groups() ++ for sg_group in sg_groups or []: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) ++ if sg_obj.name == 'default': ++ return ++ ++ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) ++ self._vnc_lib.security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ #allow ingress traffic from within default security group ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'ingress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ def _get_obj_tenant_id(self, q_type, obj_uuid): ++ # Get the mapping from cache, else seed cache and return ++ try: ++ return self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except KeyError: ++ # Seed the cache and return ++ if q_type == 'port': ++ port_obj = self._virtual_machine_interface_read(obj_uuid) ++ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] ++ # recurse up type-hierarchy ++ tenant_id = self._get_obj_tenant_id('network', net_id) ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ if q_type == 'network': ++ net_obj = self._virtual_network_read(net_id=obj_uuid) ++ tenant_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ return None ++ ++ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): ++ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid ++ ++ def _del_obj_tenant_id(self, obj_uuid): ++ try: ++ del self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except Exception: ++ pass ++ ++ def _project_read(self, proj_id=None, fq_name=None): ++ if proj_id: ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][proj_id] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ fq_name_str = json.dumps(proj_obj.get_fq_name()) ++ self._db_cache['vnc_projects'][proj_id] = proj_obj ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ return proj_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][fq_name_str] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj ++ return proj_obj ++ ++ def _security_group_rule_create(self, sg_id, sg_rule): ++ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) ++ rules = sg_vnc.get_security_group_entries() ++ if rules is None: ++ rules = vnc_api.PolicyEntriesType([sg_rule]) ++ else: ++ rules.add_policy_rule(sg_rule) ++ ++ sg_vnc.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_vnc) ++ return ++ ++ def _security_group_rule_find(self, sgr_id): ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ ++ for sg in project_sgs: ++ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) ++ sgr_entries = sg_obj.get_security_group_entries() ++ if sgr_entries is None: ++ continue ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ if sg_rule.get_rule_uuid() == sgr_id: ++ return sg_obj, sg_rule ++ ++ return None, None ++ ++ def _security_group_rule_delete(self, sg_obj, sg_rule): ++ rules = sg_obj.get_security_group_entries() ++ rules.get_policy_rule().remove(sg_rule) ++ sg_obj.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_obj) ++ return ++ ++ def _security_group_create(self, sg_obj): ++ sg_uuid = self._vnc_lib.security_group_create(sg_obj) ++ return sg_uuid ++ ++ def _security_group_delete(self, sg_id): ++ self._vnc_lib.security_group_delete(id=sg_id) ++ ++ def _svc_instance_create(self, si_obj): ++ si_uuid = self._vnc_lib.service_instance_create(si_obj) ++ st_fq_name = ['default-domain', 'nat-template'] ++ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) ++ si_obj.set_service_template(st_obj) ++ self._vnc_lib.service_instance_update(si_obj) ++ ++ return si_uuid ++ ++ def _svc_instance_delete(self, si_id): ++ self._vnc_lib.service_instance_delete(id=si_id) ++ ++ def _route_table_create(self, rt_obj): ++ rt_uuid = self._vnc_lib.route_table_create(rt_obj) ++ return rt_uuid ++ ++ def _route_table_delete(self, rt_id): ++ self._vnc_lib.route_table_delete(id=rt_id) ++ ++ def _virtual_network_create(self, net_obj): ++ net_uuid = self._vnc_lib.virtual_network_create(net_obj) ++ ++ return net_uuid ++ ++ def _virtual_network_read(self, net_id=None, fq_name=None): ++ if net_id: ++ try: ++ # return self._db_cache['vnc_networks'][net_id] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(id=net_id) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ self._db_cache['vnc_networks'][net_id] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ return net_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_networks'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ return net_obj ++ ++ def _virtual_network_update(self, net_obj): ++ self._vnc_lib.virtual_network_update(net_obj) ++ # read back to get subnet gw allocated by api-server ++ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ ++ def _virtual_network_delete(self, net_id): ++ fq_name_str = None ++ try: ++ net_obj = self._db_cache['vnc_networks'][net_id] ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_network_delete(id=net_id) ++ ++ try: ++ del self._db_cache['vnc_networks'][net_id] ++ if fq_name_str: ++ del self._db_cache['vnc_networks'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _virtual_machine_interface_create(self, port_obj): ++ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) ++ ++ return port_uuid ++ ++ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): ++ if port_id: ++ try: ++ # return self._db_cache['vnc_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ id=port_id) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ self._db_cache['vnc_ports'][port_id] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ return port_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_ports'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ fq_name=fq_name) ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ return port_obj ++ ++ def _virtual_machine_interface_update(self, port_obj): ++ self._vnc_lib.virtual_machine_interface_update(port_obj) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ ++ def _virtual_machine_interface_delete(self, port_id): ++ fq_name_str = None ++ try: ++ port_obj = self._db_cache['vnc_ports'][port_id] ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_machine_interface_delete(id=port_id) ++ ++ try: ++ del self._db_cache['vnc_ports'][port_id] ++ if fq_name_str: ++ del self._db_cache['vnc_ports'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _instance_ip_create(self, iip_obj): ++ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) ++ ++ return iip_uuid ++ ++ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): ++ if instance_ip_id: ++ try: ++ # return self._db_cache['vnc_instance_ips'][instance_ip_id] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ return iip_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_instance_ips'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ return iip_obj ++ ++ def _instance_ip_update(self, iip_obj): ++ self._vnc_lib.instance_ip_update(iip_obj) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ ++ def _instance_ip_delete(self, instance_ip_id): ++ fq_name_str = None ++ try: ++ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.instance_ip_delete(id=instance_ip_id) ++ ++ try: ++ del self._db_cache['vnc_instance_ips'][instance_ip_id] ++ if fq_name_str: ++ del self._db_cache['vnc_instance_ips'][fq_name_str] ++ except KeyError: ++ pass ++ ++ # find projects on a given domain ++ def _project_list_domain(self, domain_id): ++ fq_name = ['default-domain'] ++ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) ++ ++ return resp_dict['projects'] ++ ++ # find network ids on a given project ++ def _network_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) ++ ++ return resp_dict['virtual-networks'] ++ ++ def _ipam_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) ++ ++ return resp_dict['network-ipams'] ++ ++ def _security_group_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ self._ensure_default_security_group_exists(project_uuid) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _security_group_entries_list_sg(self, sg_id): ++ try: ++ sg_uuid = str(uuid.UUID(sg_id)) ++ except Exception: ++ print "Error in converting SG uuid %s" % (sg_id) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _route_table_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) ++ ++ return resp_dict['route-tables'] ++ ++ def _svc_instance_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) ++ ++ return resp_dict['service-instances'] ++ ++ def _policy_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) ++ ++ return resp_dict['network-policys'] ++ ++ # find floating ip pools a project has access to ++ def _fip_pool_refs_project(self, project_id): ++ project_uuid = str(uuid.UUID(project_id)) ++ project_obj = self._project_read(proj_id=project_uuid) ++ ++ return project_obj.get_floating_ip_pool_refs() ++ ++ # find networks of floating ip pools project has access to ++ def _fip_pool_ref_networks(self, project_id): ++ ret_nets = [] ++ ++ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) ++ if not proj_fip_pool_refs: ++ return ret_nets ++ ++ for fip_pool_ref in proj_fip_pool_refs: ++ fip_uuid = fip_pool_ref['uuid'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) ++ net_uuid = fip_pool_obj.parent_uuid ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ ret_nets.append({'uuid': net_obj.uuid, ++ 'fq_name': net_obj.get_fq_name()}) ++ ++ return ret_nets ++ ++ # find floating ip pools defined by network ++ def _fip_pool_list_network(self, net_id): ++ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) ++ ++ return resp_dict['floating-ip-pools'] ++ ++ # find port ids on a given network ++ def _port_list_network(self, network_id): ++ ret_list = [] ++ ++ try: ++ net_obj = self._virtual_network_read(net_id=network_id) ++ except vnc_exc.NoIdError: ++ return ret_list ++ ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ for port_back_ref in port_back_refs: ++ ret_list.append({'id': port_back_ref['uuid']}) ++ ++ return ret_list ++ ++ # find port ids on a given project ++ def _port_list_project(self, project_id): ++ ret_list = [] ++ project_nets = self._network_list_project(project_id) ++ for net in project_nets: ++ net_ports = self._port_list_network(net['uuid']) ++ ret_list.extend(net_ports) ++ ++ return ret_list ++ ++ # Returns True if ++ # * no filter is specified ++ # OR ++ # * search-param is not present in filters ++ # OR ++ # * 1. search-param is present in filters AND ++ # 2. resource matches param-list AND ++ # 3. shared parameter in filters is False ++ def _filters_is_present(self, filters, key_name, match_value): ++ if filters: ++ if key_name in filters: ++ try: ++ if ('shared' in filters and ++ filters['shared'][0] is True): ++ # yuck, q-api has shared as list always of 1 elem ++ return False # no shared-resource support ++ except ValueError: # not in requested list ++ return False ++ elif len(filters.keys()) == 1: ++ shared_val = filters.get('shared', None) ++ if shared_val and shared_val[0] is True: ++ return False ++ ++ return True ++ ++ def _network_read(self, net_uuid): ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ return net_obj ++ ++ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): ++ #import pdb; pdb.set_trace() ++ self._vnc_lib.kv_store(subnet_id, subnet_key) ++ self._vnc_lib.kv_store(subnet_key, subnet_id) ++ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key ++ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id ++ ++ def _subnet_vnc_read_mapping(self, id=None, key=None): ++ if id: ++ try: ++ return self._db_cache['q_subnet_maps'][id] ++ #raise KeyError ++ except KeyError: ++ subnet_key = self._vnc_lib.kv_retrieve(id) ++ self._db_cache['q_subnet_maps'][id] = subnet_key ++ return subnet_key ++ if key: ++ try: ++ return self._db_cache['q_subnet_maps'][key] ++ #raise KeyError ++ except KeyError: ++ subnet_id = self._vnc_lib.kv_retrieve(key) ++ self._db_cache['q_subnet_maps'][key] = subnet_id ++ return subnet_id ++ ++ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): ++ if id: ++ return self._subnet_vnc_read_mapping(id=id) ++ ++ # if subnet was created outside of neutron handle it and create ++ # neutron representation now (lazily) ++ try: ++ return self._subnet_vnc_read_mapping(key=key) ++ except vnc_exc.NoIdError: ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, key) ++ return self._subnet_vnc_read_mapping(key=key) ++ ++ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): ++ self._vnc_lib.kv_delete(subnet_id) ++ self._vnc_lib.kv_delete(subnet_key) ++ try: ++ del self._db_cache['q_subnet_maps'][subnet_id] ++ del self._db_cache['q_subnet_maps'][subnet_key] ++ except KeyError: ++ pass ++ ++ def _subnet_vnc_get_key(self, subnet_vnc, net_id): ++ pfx = subnet_vnc.subnet.get_ip_prefix() ++ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() ++ ++ return '%s %s/%s' % (net_id, pfx, pfx_len) ++ ++ def _subnet_read(self, net_uuid, subnet_key): ++ try: ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ except vnc_exc.NoIdError: ++ return None ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if not ipam_refs: ++ return None ++ ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_uuid) == subnet_key: ++ return subnet_vnc ++ ++ return None ++ ++ def _ip_address_to_subnet_id(self, ip_addr, net_obj): ++ # find subnet-id for ip-addr, called when instance-ip created ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ if IPAddress(ip_addr) in IPSet([cidr]): ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, ++ net_obj.uuid) ++ subnet_id = self._subnet_vnc_read_mapping( ++ key=subnet_key) ++ return subnet_id ++ ++ return None ++ ++ # Conversion routines between VNC and Quantum objects ++ def _svc_instance_neutron_to_vnc(self, si_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(si_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ net_id = si_q['internal_net'] ++ int_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ net_id = si_q['external_net'] ++ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, ++ auto_scale=False) ++ si_prop = vnc_api.ServiceInstanceType( ++ auto_policy=True, left_virtual_network=int_vn.name, ++ right_virtual_network=ext_vn.name, scale_out=scale_out) ++ si_prop.set_scale_out(scale_out) ++ si_vnc = vnc_api.ServiceInstance( ++ name=si_q['name'], ++ parent_obj=project_obj, ++ service_instance_properties=si_prop) ++ ++ return si_vnc ++ ++ def _svc_instance_vnc_to_neutron(self, si_obj): ++ si_q_dict = json.loads(json.dumps(si_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ si_q_dict['id'] = si_obj.uuid ++ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') ++ si_q_dict['name'] = si_obj.name ++ si_props = si_obj.get_service_instance_properties() ++ if si_props: ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_left_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_right_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ ++ return {'q_api_data': si_q_dict, ++ 'q_extra_data': {}} ++ ++ def _route_table_neutron_to_vnc(self, rt_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(rt_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], ++ parent_obj=project_obj) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ else: ++ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ ++ return rt_vnc ++ ++ def _route_table_vnc_to_neutron(self, rt_obj): ++ rt_q_dict = json.loads(json.dumps(rt_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ rt_q_dict['id'] = rt_obj.uuid ++ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') ++ rt_q_dict['name'] = rt_obj.name ++ rt_q_dict['fq_name'] = rt_obj.fq_name ++ ++ # get route table routes ++ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) ++ return {'q_api_data': rt_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_vnc_to_neutron(self, sg_obj): ++ sg_q_dict = json.loads(json.dumps(sg_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ sg_q_dict['id'] = sg_obj.uuid ++ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sg_q_dict['name'] = sg_obj.name ++ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() ++ ++ # get security group rules ++ sg_q_dict['rules'] = [] ++ rule_list = self.security_group_rules_read(sg_obj.uuid) ++ if rule_list: ++ for rule in rule_list: ++ sg_q_dict['rules'].append(rule['q_api_data']) ++ ++ return {'q_api_data': sg_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_neutron_to_vnc(self, sg_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(sg_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType( ++ enable=True, description=sg_q['description']) ++ sg_vnc = vnc_api.SecurityGroup( ++ name=sg_q['name'], parent_obj=project_obj, ++ id_perms=id_perms) ++ ++ return sg_vnc ++ ++ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): ++ sgr_q_dict = {} ++ if sg_id is None: ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ direction = 'egress' ++ if sg_rule.get_direction() == '<': ++ direction = 'ingress' ++ ++ remote_cidr = '' ++ remote_sg_uuid = '' ++ if direction == 'ingress': ++ addr = sg_rule.get_src_addresses()[0] ++ else: ++ addr = sg_rule.get_dst_addresses()[0] ++ ++ if addr.get_subnet(): ++ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), ++ addr.get_subnet().get_ip_prefix_len()) ++ elif addr.get_security_group(): ++ if (addr.get_security_group() != 'any') and \ ++ (addr.get_security_group() != 'local'): ++ remote_sg = addr.get_security_group() ++ try: ++ remote_sg_obj = self._vnc_lib.security_group_read( ++ fq_name_str=remote_sg) ++ remote_sg_uuid = remote_sg_obj.uuid ++ except vnc_exc.NoIdError: ++ pass ++ ++ sgr_q_dict['id'] = sg_rule.get_rule_uuid() ++ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sgr_q_dict['security_group_id'] = sg_obj.uuid ++ sgr_q_dict['ethertype'] = 'IPv4' ++ sgr_q_dict['direction'] = direction ++ sgr_q_dict['protocol'] = sg_rule.get_protocol() ++ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ ++ get_start_port() ++ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ ++ get_end_port() ++ sgr_q_dict['remote_ip_prefix'] = remote_cidr ++ sgr_q_dict['remote_group_id'] = remote_sg_uuid ++ ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): ++ if oper == CREATE: ++ port_min = 0 ++ port_max = 65535 ++ if sgr_q['port_range_min']: ++ port_min = sgr_q['port_range_min'] ++ if sgr_q['port_range_max']: ++ port_max = sgr_q['port_range_max'] ++ ++ endpt = [vnc_api.AddressType(security_group='any')] ++ if sgr_q['remote_ip_prefix']: ++ cidr = sgr_q['remote_ip_prefix'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ endpt = [vnc_api.AddressType( ++ subnet=vnc_api.SubnetType(pfx, pfx_len))] ++ elif sgr_q['remote_group_id']: ++ sg_obj = self._vnc_lib.security_group_read( ++ id=sgr_q['remote_group_id']) ++ endpt = [vnc_api.AddressType( ++ security_group=sg_obj.get_fq_name_str())] ++ ++ if sgr_q['direction'] == 'ingress': ++ dir = '<' ++ local = endpt ++ remote = [vnc_api.AddressType(security_group='local')] ++ else: ++ dir = '>' ++ remote = endpt ++ local = [vnc_api.AddressType(security_group='local')] ++ ++ if not sgr_q['protocol']: ++ sgr_q['protocol'] = 'any' ++ ++ sgr_uuid = str(uuid.uuid4()) ++ ++ rule = vnc_api.PolicyRuleType( ++ rule_uuid=sgr_uuid, ++ direction=dir, ++ protocol=sgr_q['protocol'], ++ src_addresses=local, ++ src_ports=[vnc_api.PortType(0, 65535)], ++ dst_addresses=remote, ++ dst_ports=[vnc_api.PortType(port_min, port_max)]) ++ return rule ++ ++ def _network_neutron_to_vnc(self, network_q, oper): ++ net_name = network_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(network_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType(enable=True) ++ net_obj = vnc_api.VirtualNetwork( ++ net_name, project_obj, id_perms=id_perms) ++ else: # READ/UPDATE/DELETE ++ net_obj = self._virtual_network_read(net_id=network_q['id']) ++ ++ id_perms = net_obj.get_id_perms() ++ if 'admin_state_up' in network_q: ++ id_perms.enable = network_q['admin_state_up'] ++ net_obj.set_id_perms(id_perms) ++ ++ if 'contrail:policys' in network_q: ++ policy_fq_names = network_q['contrail:policys'] ++ # reset and add with newly specified list ++ net_obj.set_network_policy_list([], []) ++ seq = 0 ++ for p_fq_name in policy_fq_names: ++ domain_name, project_name, policy_name = p_fq_name ++ ++ domain_obj = vnc_api.Domain(domain_name) ++ project_obj = vnc_api.Project(project_name, domain_obj) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ ++ net_obj.add_network_policy( ++ policy_obj, ++ vnc_api.VirtualNetworkPolicyType( ++ sequence=vnc_api.SequenceType(seq, 0))) ++ seq = seq + 1 ++ ++ if 'vpc:route_table' in network_q: ++ rt_fq_name = network_q['vpc:route_table'] ++ if rt_fq_name: ++ try: ++ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) ++ net_obj.set_route_table(rt_obj) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) ++ ++ return net_obj ++ ++ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): ++ net_q_dict = {} ++ extra_dict = {} ++ ++ net_q_dict['id'] = net_obj.uuid ++ net_q_dict['name'] = net_obj.name ++ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() ++ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable ++ net_q_dict['shared'] = False ++ net_q_dict['status'] = constants.NET_STATUS_ACTIVE ++ ++ if net_repr == 'SHOW': ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ #if port_back_refs: ++ # net_q_dict['ports'] = [] ++ # for port_back_ref in port_back_refs: ++ # fq_name = port_back_ref['to'] ++ # try: ++ # port_obj = self._virtual_machine_interface_read( ++ # port_id = fq_name[-1]) ++ # except NoIdError: ++ # continue ++ # ++ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) ++ # port_dict = port_info['q_api_data'] ++ # port_dict.update(port_info['q_extra_data']) ++ # ++ # net_q_dict['ports'].append(port_dict) ++ ++ extra_dict['contrail:instance_count'] = 0 ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ net_policy_refs = net_obj.get_network_policy_refs() ++ if net_policy_refs: ++ extra_dict['contrail:policys'] = \ ++ [np_ref['to'] for np_ref in net_policy_refs] ++ ++ elif net_repr == 'LIST': ++ extra_dict['contrail:instance_count'] = 0 ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ net_q_dict['subnets'] = [] ++ if ipam_refs: ++ extra_dict['contrail:subnet_ipam'] = [] ++ for ipam_ref in ipam_refs: ++ subnets = ipam_ref['attr'].get_ipam_subnets() ++ for subnet in subnets: ++ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, ++ ipam_ref['to']) ++ sn_dict = sn_info['q_api_data'] ++ sn_dict.update(sn_info['q_extra_data']) ++ net_q_dict['subnets'].append(sn_dict) ++ sn_ipam = {} ++ sn_ipam['subnet_cidr'] = sn_dict['cidr'] ++ sn_ipam['ipam_fq_name'] = ipam_ref['to'] ++ extra_dict['contrail:subnet_ipam'].append(sn_ipam) ++ ++ return {'q_api_data': net_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _subnet_neutron_to_vnc(self, subnet_q): ++ cidr = subnet_q['cidr'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: ++ default_gw = subnet_q['gateway_ip'] ++ else: ++ # Assigned by address manager ++ default_gw = None ++ sub_net = vnc_api.SubnetType(ip_prefix=pfx, ++ ip_prefix_len=pfx_len) ++ #subnet_vnc = vnc_api.IpamSubnetType( ++ #subnet=vnc_api.SubnetType(pfx, pfx_len), ++ #default_gateway=default_gw) ++ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, ++ default_gateway=default_gw) ++ return subnet_vnc ++ ++ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): ++ sn_q_dict = {} ++ sn_q_dict['name'] = '' ++ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ sn_q_dict['network_id'] = net_obj.uuid ++ sn_q_dict['ip_version'] = 4 ++ ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ sn_q_dict['cidr'] = cidr ++ ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) ++ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) ++ ++ sn_q_dict['id'] = sn_id ++ ++ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway ++ ++ first_ip = str(IPNetwork(cidr).network + 1) ++ last_ip = str(IPNetwork(cidr).broadcast - 2) ++ sn_q_dict['allocation_pools'] = \ ++ [{'id': 'TODO-allocation_pools-id', ++ 'subnet_id': sn_id, ++ 'first_ip': first_ip, ++ 'last_ip': last_ip, ++ 'available_ranges': {}}] ++ ++ sn_q_dict['enable_dhcp'] = False ++ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['routes'] = [{'destination': 'TODO-destination', ++ 'nexthop': 'TODO-nexthop', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['shared'] = False ++ ++ extra_dict = {} ++ extra_dict['contrail:instance_count'] = 0 ++ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name ++ ++ return {'q_api_data': sn_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _ipam_neutron_to_vnc(self, ipam_q, oper): ++ ipam_name = ipam_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(ipam_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) ++ ++ if ipam_q['mgmt']: ++ ipam_obj.set_network_ipam_mgmt( ++ vnc_api.IpamType.factory(**ipam_q['mgmt'])) ++ ++ return ipam_obj ++ ++ def _ipam_vnc_to_neutron(self, ipam_obj): ++ ipam_q_dict = json.loads(json.dumps(ipam_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') ++ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') ++ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) ++ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ ipam_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ ipam_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': ipam_q_dict, ++ 'q_extra_data': {}} ++ ++ def _policy_neutron_to_vnc(self, policy_q, oper): ++ policy_name = policy_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(policy_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) ++ ++ policy_obj.set_network_policy_entries( ++ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) ++ ++ return policy_obj ++ ++ def _policy_vnc_to_neutron(self, policy_obj): ++ policy_q_dict = json.loads(json.dumps(policy_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ policy_q_dict['id'] = policy_q_dict.pop('uuid') ++ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') ++ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', ++ None) ++ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ policy_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ policy_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': policy_q_dict, ++ 'q_extra_data': {}} ++ ++ def _floatingip_neutron_to_vnc(self, fip_q, oper): ++ if oper == CREATE: ++ # use first available pool on net ++ net_id = fip_q['floating_network_id'] ++ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) ++ fip_name = str(uuid.uuid4()) ++ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) ++ fip_obj.uuid = fip_name ++ ++ proj_id = str(uuid.UUID(fip_q['tenant_id'])) ++ proj_obj = self._project_read(proj_id=proj_id) ++ fip_obj.set_project(proj_obj) ++ else: # READ/UPDATE/DELETE ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) ++ ++ if fip_q['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=fip_q['port_id']) ++ fip_obj.set_virtual_machine_interface(port_obj) ++ else: ++ fip_obj.set_virtual_machine_interface_list([]) ++ ++ return fip_obj ++ ++ def _floatingip_vnc_to_neutron(self, fip_obj): ++ fip_q_dict = {} ++ extra_dict = {} ++ ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( ++ id=fip_obj.parent_uuid) ++ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) ++ ++ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') ++ ++ port_id = None ++ port_refs = fip_obj.get_virtual_machine_interface_refs() ++ if port_refs: ++ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] ++ ++ fip_q_dict['id'] = fip_obj.uuid ++ fip_q_dict['tenant_id'] = tenant_id ++ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() ++ fip_q_dict['floating_network_id'] = net_obj.uuid ++ fip_q_dict['router_id'] = None ++ fip_q_dict['fixed_port_id'] = port_id ++ fip_q_dict['fixed_ip_address'] = None ++ ++ return {'q_api_data': fip_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _port_neutron_to_vnc(self, port_q, net_obj, oper): ++ if oper == CREATE: ++ port_name = str(uuid.uuid4()) ++ instance_name = port_q['device_id'] ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ ++ id_perms = vnc_api.IdPermsType(enable=True) ++ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, ++ id_perms=id_perms) ++ port_obj.uuid = port_name ++ port_obj.set_virtual_network(net_obj) ++ ++ else: # READ/UPDATE/DELETE ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_q['id']) ++ ++ port_obj.set_security_group_list([]) ++ if ('security_groups' in port_q and ++ port_q['security_groups'].__class__ is not object): ++ for sg_id in port_q['security_groups']: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ port_obj.add_security_group(sg_obj) ++ ++ id_perms = port_obj.get_id_perms() ++ if 'admin_state_up' in port_q: ++ id_perms.enable = port_q['admin_state_up'] ++ port_obj.set_id_perms(id_perms) ++ ++ return port_obj ++ ++ def _port_vnc_to_neutron(self, port_obj, net_obj=None): ++ port_q_dict = {} ++ port_q_dict['name'] = port_obj.uuid ++ port_q_dict['id'] = port_obj.uuid ++ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_CONTRAIL ++ ++ if not net_obj: ++ net_refs = port_obj.get_virtual_network_refs() ++ if net_refs: ++ net_id = net_refs[0]['uuid'] ++ else: ++ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) ++ ++ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) ++ proj_id = None ++ if not proj_id: ++ # not in cache, get by reading VN obj, and populate cache ++ net_obj = self._virtual_network_read(net_id=net_id) ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(port_obj.uuid, proj_id) ++ else: ++ net_id = net_obj.uuid ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ ++ port_q_dict['tenant_id'] = proj_id ++ port_q_dict['network_id'] = net_id ++ ++ port_q_dict['mac_address'] = '' ++ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() ++ if mac_refs: ++ port_q_dict['mac_address'] = mac_refs.mac_address[0] ++ ++ port_q_dict['fixed_ips'] = [] ++ ip_back_refs = port_obj.get_instance_ip_back_refs() ++ if ip_back_refs: ++ for ip_back_ref in ip_back_refs: ++ try: ++ ip_obj = self._instance_ip_read( ++ instance_ip_id=ip_back_ref['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ++ ip_addr = ip_obj.get_instance_ip_address() ++ ++ ip_q_dict = {} ++ ip_q_dict['port_id'] = port_obj.uuid ++ ip_q_dict['ip_address'] = ip_addr ++ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, ++ net_obj) ++ ip_q_dict['net_id'] = net_id ++ ++ port_q_dict['fixed_ips'].append(ip_q_dict) ++ ++ sg_dict = {'port_security_enabled': True} ++ sg_dict['security_groups'] = [] ++ sg_refs = port_obj.get_security_group_refs() ++ for sg_ref in sg_refs or []: ++ sg_dict['security_groups'].append(sg_ref['uuid']) ++ ++ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable ++ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE ++ port_q_dict['device_id'] = port_obj.parent_name ++ port_q_dict['device_owner'] = 'TODO-device-owner' ++ ++ return {'q_api_data': port_q_dict, ++ 'q_extra_data': sg_dict} ++ ++ # public methods ++ # network api handlers ++ def network_create(self, network_q): ++ #self._ensure_project_exists(network_q['tenant_id']) ++ ++ net_obj = self._network_neutron_to_vnc(network_q, CREATE) ++ net_uuid = self._virtual_network_create(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_uuid] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_read(self, net_uuid, fields=None): ++ # see if we can return fast... ++ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': ++ tenant_id = self._get_obj_tenant_id('network', net_uuid) ++ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} ++ ++ try: ++ # return self._db_cache['q_networks']['net_uuid'] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ try: ++ net_obj = self._network_read(net_uuid) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_uuid) ++ ++ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ ++ def network_update(self, net_id, network_q): ++ network_q['id'] = net_id ++ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) ++ self._virtual_network_update(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_id] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_delete(self, net_id): ++ self._virtual_network_delete(net_id=net_id) ++ try: ++ del self._db_cache['q_networks'][net_id] ++ except KeyError: ++ pass ++ ++ def network_list(self, filters=None): ++ ret_list = [] ++ ++ if filters and 'shared' in filters: ++ if filters['shared'][0] is True: ++ # no support for shared networks ++ return ret_list ++ ++ # collect phase ++ all_nets = [] # all n/ws in all projects ++ if filters and 'tenant_id' in filters: ++ # project-id is present ++ if 'id' in filters: ++ # required networks are also specified, ++ # just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in project, and prune below ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ if 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(p_id)) ++ else: ++ project_nets = self._network_list_project(p_id) ++ all_nets.append(project_nets) ++ elif filters and 'id' in filters: ++ # required networks are specified, just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in all projects ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ if filters and 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(proj_id)) ++ else: ++ project_nets = self._network_list_project(proj_id) ++ all_nets.append(project_nets) ++ ++ # prune phase ++ for project_nets in all_nets: ++ for proj_net in project_nets: ++ proj_net_id = proj_net['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_net_id): ++ continue ++ ++ proj_net_fq_name = unicode(proj_net['fq_name']) ++ if not self._filters_is_present(filters, 'contrail:fq_name', ++ proj_net_fq_name): ++ continue ++ ++ try: ++ net_obj = self._network_read(proj_net['uuid']) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ except vnc_exc.NoIdError: ++ continue ++ ret_list.append(net_info) ++ ++ return ret_list ++ ++ def network_count(self, filters=None): ++ nets_info = self.network_list(filters) ++ return len(nets_info) ++ ++ # subnet api handlers ++ def subnet_create(self, subnet_q): ++ net_id = subnet_q['network_id'] ++ net_obj = self._virtual_network_read(net_id=net_id) ++ ++ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] ++ if ipam_fq_name != '': ++ domain_name, project_name, ipam_name = ipam_fq_name ++ ++ project_obj = vnc_api.Project(project_name) ++ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # link subnet with default ipam ++ project_obj = vnc_api.Project(net_obj.parent_name) ++ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) ++ ipam_fq_name = netipam_obj.get_fq_name() ++ ++ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) ++ ++ # Locate list of subnets to which this subnet has to be appended ++ net_ipam_ref = None ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ if ipam_ref['to'] == ipam_fq_name: ++ net_ipam_ref = ipam_ref ++ break ++ ++ if not net_ipam_ref: ++ # First link from net to this ipam ++ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) ++ net_obj.add_network_ipam(netipam_obj, vnsn_data) ++ else: # virtual-network already linked to this ipam ++ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): ++ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): ++ # duplicate !! ++ subnet_info = self._subnet_vnc_to_neutron(subnet, ++ net_obj, ++ ipam_fq_name) ++ return subnet_info ++ vnsn_data = net_ipam_ref['attr'] ++ vnsn_data.ipam_subnets.append(subnet_vnc) ++ ++ self._virtual_network_update(net_obj) ++ ++ # allocate an id to the subnet and store mapping with ++ # api-server ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, subnet_key) ++ ++ # Read in subnet from server to get updated values for gw etc. ++ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) ++ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, ++ ipam_fq_name) ++ ++ #self._db_cache['q_subnets'][subnet_id] = subnet_info ++ ++ return subnet_info ++ ++ def subnet_read(self, subnet_id): ++ try: ++ # return self._db_cache['q_subnets'][subnet_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_id) == subnet_key: ++ ret_subnet_q = self._subnet_vnc_to_neutron( ++ subnet_vnc, net_obj, ipam_ref['to']) ++ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q ++ return ret_subnet_q ++ ++ return {} ++ ++ def subnet_delete(self, subnet_id): ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ orig_subnets = ipam_ref['attr'].get_ipam_subnets() ++ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets ++ if self._subnet_vnc_get_key(subnet_vnc, net_id) ++ != subnet_key] ++ if len(orig_subnets) != len(new_subnets): ++ # matched subnet to be deleted ++ ipam_ref['attr'].set_ipam_subnets(new_subnets) ++ self._virtual_network_update(net_obj) ++ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) ++ try: ++ del self._db_cache['q_subnets'][subnet_id] ++ except KeyError: ++ pass ++ ++ return ++ ++ def subnets_list(self, filters=None): ++ ret_subnets = [] ++ ++ if filters and 'id' in filters: ++ # required subnets are specified, ++ # just read in corresponding net_ids ++ net_ids = set([]) ++ for subnet_id in filters['id']: ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ net_ids.add(net_id) ++ else: ++ nets_info = self.network_list() ++ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] ++ ++ for net_id in net_ids: ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, ++ net_obj, ++ ipam_ref['to']) ++ sn_id = sn_info['q_api_data']['id'] ++ sn_proj_id = sn_info['q_api_data']['tenant_id'] ++ sn_net_id = sn_info['q_api_data']['network_id'] ++ ++ if filters: ++ if not self._filters_is_present(filters, 'id', ++ sn_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'tenant_id', ++ sn_proj_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'network_id', ++ sn_net_id): ++ continue ++ ++ ret_subnets.append(sn_info) ++ ++ return ret_subnets ++ ++ def subnets_count(self, filters=None): ++ subnets_info = self.subnets_list(filters) ++ return len(subnets_info) ++ ++ # ipam api handlers ++ def ipam_create(self, ipam_q): ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) ++ self._vnc_lib.network_ipam_create(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_read(self, ipam_id): ++ try: ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=ipam_id) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_update(self, ipam_id, ipam): ++ ipam_q = ipam['ipam'] ++ ipam_q['id'] = ipam_id ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) ++ self._vnc_lib.network_ipam_update(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_delete(self, ipam_id): ++ self._vnc_lib.network_ipam_delete(id=ipam_id) ++ ++ def ipam_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_ipams = [] # all ipams in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_ipams = self._ipam_list_project(p_id) ++ all_ipams.append(project_ipams) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_ipams = self._ipam_list_project(proj_id) ++ all_ipams.append(project_ipams) ++ ++ # prune phase ++ for project_ipams in all_ipams: ++ for proj_ipam in project_ipams: ++ proj_ipam_id = proj_ipam['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_ipam_id): ++ continue ++ ipam_info = self.ipam_read(proj_ipam['uuid']) ++ ret_list.append(ipam_info) ++ ++ return ret_list ++ ++ def ipam_count(self, filters=None): ++ ipam_info = self.ipam_list(filters) ++ return len(ipam_info) ++ ++ # policy api handlers ++ def policy_create(self, policy_q): ++ ++ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) ++ self._vnc_lib.network_policy_create(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_read(self, policy_id): ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_update(self, policy_id, policy): ++ policy_q = policy['policy'] ++ policy_q['id'] = policy_id ++ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) ++ self._vnc_lib.network_policy_update(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_delete(self, policy_id): ++ self._vnc_lib.network_policy_delete(id=policy_id) ++ ++ def policy_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_policys = [] # all policys in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_policys = self._policy_list_project(p_id) ++ all_policys.append(project_policys) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_policys = self._policy_list_project(proj_id) ++ all_policys.append(project_policys) ++ ++ # prune phase ++ for project_policys in all_policys: ++ for proj_policy in project_policys: ++ proj_policy_id = proj_policy['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_policy_id): ++ continue ++ policy_info = self.policy_read(proj_policy['uuid']) ++ ret_list.append(policy_info) ++ ++ return ret_list ++ ++ def policy_count(self, filters=None): ++ policy_info = self.policy_list(filters) ++ return len(policy_info) ++ ++ # floatingip api handlers ++ def floatingip_create(self, fip_q): ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) ++ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_read(self, fip_uuid): ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_update(self, fip_id, fip_q): ++ fip_q['id'] = fip_id ++ fip_obj = self._floatingip_neutron(fip_q, UPDATE) ++ self._vnc_lib.floating_ip_update(fip_obj) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_delete(self, fip_id): ++ self._vnc_lib.floating_ip_delete(id=fip_id) ++ ++ def floatingip_list(self, filters=None): ++ # Find networks, get floatingip backrefs and return ++ ret_list = [] ++ ++ if filters: ++ if 'tenant_id' in filters: ++ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] ++ elif 'port_id' in filters: ++ # required ports are specified, just read and populate ret_list ++ # prune is skipped because proj_objs is empty ++ proj_ids = [] ++ for port_id in filters['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_id) ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron( ++ fip_obj)) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ proj_ids = [proj['uuid'] for proj in dom_projects] ++ ++ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] ++ ++ for proj_obj in proj_objs: ++ fip_back_refs = proj_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) ++ ++ return ret_list ++ ++ def floatingip_count(self, filters=None): ++ floatingip_info = self.floatingip_list(filters) ++ return len(floatingip_info) ++ ++ # port api handlers ++ def port_create(self, port_q): ++ net_id = port_q['network_id'] ++ net_obj = self._network_read(net_id) ++ proj_id = net_obj.parent_uuid ++ ++ self._ensure_instance_exists(port_q['device_id']) ++ ++ # initialize port object ++ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) ++ ++ # if ip address passed then use it ++ ip_addr = None ++ ip_obj = None ++ if port_q['fixed_ips'].__class__ is not object: ++ ip_addr = port_q['fixed_ips'][0]['ip_address'] ++ ip_name = '%s %s' % (net_id, ip_addr) ++ try: ++ ip_obj = self._instance_ip_read(fq_name=[ip_name]) ++ #ip_id = ip_obj.uuid ++ except Exception as e: ++ ip_obj = None ++ ++ # create the object ++ port_id = self._virtual_machine_interface_create(port_obj) ++ ++ # initialize ip object ++ if ip_obj is None: ++ ip_name = str(uuid.uuid4()) ++ ip_obj = vnc_api.InstanceIp(name=ip_name) ++ ip_obj.uuid = ip_name ++ ip_obj.set_virtual_machine_interface(port_obj) ++ ip_obj.set_virtual_network(net_obj) ++ if ip_addr: ++ ip_obj.set_instance_ip_address(ip_addr) ++ try: ++ self._instance_ip_create(ip_obj) ++ except Exception as e: ++ # ResourceExhaustionError, resources are not available ++ self._virtual_machine_interface_delete(port_id=port_id) ++ raise e ++ # shared ip address ++ else: ++ if ip_addr == ip_obj.get_instance_ip_address(): ++ ip_obj.add_virtual_machine_interface(port_obj) ++ self._instance_ip_update(ip_obj) ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) ++ #self._db_cache['q_ports'][port_id] = ret_port_q ++ self._set_obj_tenant_id(port_id, proj_id) ++ ++ # update cache on successful creation ++ tenant_id = proj_id.replace('-', '') ++ if tenant_id not in self._db_cache['q_tenant_port_count']: ++ ncurports = self.port_count({'tenant_id': tenant_id}) ++ else: ++ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] ++ ++ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 ++ ++ return ret_port_q ++ ++ def port_read(self, port_id): ++ try: ++ # return self._db_cache['q_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_update(self, port_id, port_q): ++ port_q['id'] = port_id ++ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) ++ self._virtual_machine_interface_update(port_obj) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_delete(self, port_id): ++ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) ++ instance_id = port_obj.parent_uuid ++ ++ # release instance IP address ++ iip_back_refs = port_obj.get_instance_ip_back_refs() ++ if iip_back_refs: ++ for iip_back_ref in iip_back_refs: ++ # if name contains IP address then this is shared ip ++ iip_obj = self._vnc_lib.instance_ip_read( ++ id=iip_back_ref['uuid']) ++ name = iip_obj.name ++ if len(name.split(' ')) > 1: ++ name = name.split(' ')[1] ++ ++ # in case of shared ip only delete the link to the VMI ++ try: ++ socket.inet_aton(name) ++ iip_obj.del_virtual_machine_interface(port_obj) ++ self._instance_ip_update(iip_obj) ++ except socket.error: ++ self._instance_ip_delete( ++ instance_ip_id=iip_back_ref['uuid']) ++ ++ # disassociate any floating IP used by instance ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if fip_back_refs: ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ self.floatingip_update(fip_obj.uuid, {'port_id': None}) ++ ++ self._virtual_machine_interface_delete(port_id=port_id) ++ ++ # delete instance if this was the last port ++ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) ++ inst_intfs = inst_obj.get_virtual_machine_interfaces() ++ if not inst_intfs: ++ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) ++ ++ try: ++ del self._db_cache['q_ports'][port_id] ++ except KeyError: ++ pass ++ ++ # update cache on successful deletion ++ try: ++ tenant_id = self._get_obj_tenant_id('port', port_id) ++ self._db_cache['q_tenant_port_count'][tenant_id] = \ ++ self._db_cache['q_tenant_port_count'][tenant_id] - 1 ++ except KeyError: ++ pass ++ ++ self._del_obj_tenant_id(port_id) ++ ++ def port_list(self, filters=None): ++ ret_q_ports = [] ++ all_project_ids = [] ++ ++ if 'device_owner' in filters: ++ return ret_q_ports ++ ++ if 'device_id' not in filters: ++ # Listing from back references ++ if not filters: ++ # no filters => return all ports! ++ all_projects = self._project_list_domain(None) ++ all_project_ids = [project['uuid'] for project in all_projects] ++ elif 'tenant_id' in filters: ++ all_project_ids = filters.get('tenant_id') ++ ++ for proj_id in all_project_ids: ++ proj_ports = self._port_list_project(proj_id) ++ for port in proj_ports: ++ try: ++ port_info = self.port_read(port['id']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ for net_id in filters.get('network_id', []): ++ net_ports = self._port_list_network(net_id) ++ for port in net_ports: ++ port_info = self.port_read(port['id']) ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ # Listing from parent to children ++ virtual_machine_ids = filters['device_id'] ++ for vm_id in virtual_machine_ids: ++ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( ++ parent_id=vm_id) ++ vm_intf_ids = resp_dict['virtual-machine-interfaces'] ++ for vm_intf in vm_intf_ids: ++ try: ++ port_info = self.port_read(vm_intf['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ def port_count(self, filters=None): ++ if 'device_owner' in filters: ++ return 0 ++ ++ if 'tenant_id' in filters: ++ project_id = filters['tenant_id'][0] ++ try: ++ return self._db_cache['q_tenant_port_count'][project_id] ++ except KeyError: ++ # do it the hard way but remember for next time ++ nports = len(self._port_list_project(project_id)) ++ self._db_cache['q_tenant_port_count'][project_id] = nports ++ else: ++ # across all projects ++ # get only a count from api-server! ++ nports = len(self.port_list(filters)) ++ ++ return nports ++ ++ # security group api handlers ++ def security_group_create(self, sg_q): ++ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) ++ sg_uuid = self._security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_uuid, rule) ++ ++ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) ++ return ret_sg_q ++ ++ def security_group_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return self._security_group_vnc_to_neutron(sg_obj) ++ ++ def security_group_delete(self, sg_id): ++ self._security_group_delete(sg_id) ++ ++ def security_group_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] # all sgs in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sg_info = self.security_group_read(proj_sg_id) ++ if not self._filters_is_present(filters, 'name', ++ sg_info['q_api_data']['name']): ++ continue ++ ret_list.append(sg_info) ++ ++ return ret_list ++ ++ def security_group_rule_create(self, sgr_q): ++ sg_id = sgr_q['security_group_id'] ++ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) ++ self._security_group_rule_create(sg_id, sg_rule) ++ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, ++ sg_rule) ++ ++ return ret_sg_rule_q ++ ++ def security_group_rule_read(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ ++ return {} ++ ++ def security_group_rule_delete(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_delete(sg_obj, sg_rule) ++ ++ def security_group_rules_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ sgr_entries = sg_obj.get_security_group_entries() ++ sg_rules = [] ++ if sgr_entries is None: ++ return ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ sg_rules.append(sg_info) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return sg_rules ++ ++ def security_group_rule_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sgr_info = self.security_group_rules_read(proj_sg_id) ++ if sgr_info: ++ ret_list.append(sgr_info) ++ ++ return ret_list ++ ++ #route table api handlers ++ def route_table_create(self, rt_q): ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) ++ self._route_table_create(rt_obj) ++ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) ++ return ret_rt_q ++ ++ def route_table_read(self, rt_id): ++ try: ++ rt_obj = self._vnc_lib.route_table_read(id=rt_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=rt_id) ++ ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_update(self, rt_id, rt_q): ++ rt_q['id'] = rt_id ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) ++ self._vnc_lib.route_table_update(rt_obj) ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_delete(self, rt_id): ++ self._route_table_delete(rt_id) ++ ++ def route_table_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_rts = [] # all rts in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_rts = self._route_table_list_project(proj_id) ++ all_rts.append(project_rts) ++ ++ # prune phase ++ for project_rts in all_rts: ++ for proj_rt in project_rts: ++ proj_rt_id = proj_rt['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_rt_id): ++ continue ++ rt_info = self.route_table_read(proj_rt_id) ++ if not self._filters_is_present(filters, 'name', ++ rt_info['q_api_data']['name']): ++ continue ++ ret_list.append(rt_info) ++ ++ return ret_list ++ ++ #service instance api handlers ++ def svc_instance_create(self, si_q): ++ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) ++ self._svc_instance_create(si_obj) ++ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) ++ return ret_si_q ++ ++ def svc_instance_read(self, si_id): ++ try: ++ si_obj = self._vnc_lib.service_instance_read(id=si_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=si_id) ++ ++ return self._svc_instance_vnc_to_neutron(si_obj) ++ ++ def svc_instance_delete(self, si_id): ++ self._svc_instance_delete(si_id) ++ ++ def svc_instance_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sis = [] # all sis in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sis = self._svc_instance_list_project(proj_id) ++ all_sis.append(project_sis) ++ ++ # prune phase ++ for project_sis in all_sis: ++ for proj_si in project_sis: ++ proj_si_id = proj_si['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_si_id): ++ continue ++ si_info = self.svc_instance_read(proj_si_id) ++ if not self._filters_is_present(filters, 'name', ++ si_info['q_api_data']['name']): ++ continue ++ ret_list.append(si_info) ++ ++ return ret_list +diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py +new file mode 100644 +index 0000000..72bebec +--- /dev/null ++++ neutron/tests/unit/juniper/__init__.py +@@ -0,0 +1,14 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. +diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py +new file mode 100644 +index 0000000..decf79e +--- /dev/null ++++ neutron/tests/unit/juniper/test_contrail_plugin.py +@@ -0,0 +1,998 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. ++ ++import datetime ++import mock ++import neutron.db.api ++from neutron.manager import NeutronManager ++from neutron.tests.unit import test_db_plugin as test_plugin ++import sys ++import uuid ++ ++subnet_obj = {u'subnet': ++ {'name': '', 'enable_dhcp': True, ++ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', ++ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', ++ 'dns_nameservers': '', ++ u'contrail:ipam_fq_name': ++ [u'default-domain', u'admin', u'default-network-ipam'], ++ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, ++ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} ++ ++vn_list = [] ++GlobalProjects = [] ++ ++ ++class MockVncApi(mock.MagicMock): ++ def __init__(self, *args, **kwargs): ++ pass ++ ++ def kv_retrieve(self, *args, **kwargs): ++ return [] ++ ++ def kv_store(self, *args, **kwargs): ++ return ++ ++ def kv_delete(self, *args, **kwargs): ++ return ++ ++ def project_read(self, *args, **kwargs): ++ #return MockProject('dummy-proj') ++ return GlobalProjects[0] ++ ++ def virtual_network_create(self, net_obj): ++ net_id = unicode(str(uuid.uuid4())) ++ net_obj.set_uuid(net_id) ++ vn_list.append(net_obj) ++ return net_id ++ ++ def virtual_network_read(self, id, *args, **kwargs): ++ if len(vn_list): ++ for index in range(len(vn_list)): ++ if ((vn_list[index].get_uuid()) == id): ++ return vn_list[index] ++ ++ #return a mock object if it is not created so far ++ return MockVirtualNetwork('dummy-net', MockProject()) ++ ++ def virtual_network_delete(self, *args, **kwargs): ++ return ++ ++ def virtual_network_update(self, *args, **kwargs): ++ return ++ ++ def virtual_networks_list(self, *args, **kwargs): ++ return vn_list ++ ++ ++class MockVncObject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ if not parent_obj: ++ self._fq_name = [name] ++ else: ++ self._fq_name = parent_obj.get_fq_name() + [name] ++ ++ self._ipam_refs = [{'to': [u'default-domain', u'admin', ++ u'default-network-ipam']}] ++ self.uuid = None ++ self.name = name ++ self.network_ipam_refs = [] ++ ++ def set_uuid(self, uuid): ++ self.uuid = uuid ++ ++ def get_uuid(self): ++ return self.uuid ++ ++ def get_fq_name(self): ++ return self._fq_name ++ ++ def get_network_ipam_refs(self): ++ return getattr(self, 'network_ipam_refs', None) ++ ++ def add_network_ipam(self, ref_obj, ref_data): ++ refs = getattr(self, 'network_ipam_refs', []) ++ if not refs: ++ self.network_ipam_refs = [] ++ ++ # if ref already exists, update any attr with it ++ for ref in refs: ++ if ref['to'] == ref_obj.get_fq_name(): ++ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref['uuid'] = ref_obj.uuid ++ return ++ ++ # ref didn't exist before ++ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref_info['uuid'] = ref_obj.uuid ++ ++ self.network_ipam_refs.append(ref_info) ++ ++ ++class MockVirtualNetwork(MockVncObject): ++ pass ++ ++ ++class MockSubnetType(mock.MagicMock): ++ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ip_prefix = ip_prefix ++ self.ip_prefix_len = ip_prefix_len ++ ++ def get_ip_prefix(self): ++ return self.ip_prefix ++ ++ def set_ip_prefix(self, ip_prefix): ++ self.ip_prefix = ip_prefix ++ ++ def get_ip_prefix_len(self): ++ return self.ip_prefix_len ++ ++ def set_ip_prefix_len(self, ip_prefix_len): ++ self.ip_prefix_len = ip_prefix_len ++ ++ ++class MockIpamSubnetType(mock.MagicMock): ++ def __init__(self, name=None, subnet=None, default_gateway=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.subnet = subnet ++ self.default_gateway = default_gateway ++ ++ def get_subnet(self): ++ return self.subnet ++ ++ def set_subnet(self, subnet): ++ self.subnet = subnet ++ ++ def get_default_gateway(self): ++ return self.default_gateway ++ ++ def set_default_gateway(self, default_gateway): ++ self.default_gateway = default_gateway ++ ++ def validate_IpAddressType(self, value): ++ pass ++ ++ ++class MockVnSubnetsType(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ipam_subnets = [] ++ if ipam_subnets: ++ #self.ipam_subnets = copy.deepcopy(ipam_subnets) ++ self.ipam_subnets = ipam_subnets ++ ++ def get_ipam_subnets(self): ++ return self.ipam_subnets ++ ++ def set_ipam_subnets(self, ipam_subnets): ++ self.ipam_subnets = ipam_subnets ++ ++ def add_ipam_subnets(self, value): ++ self.ipam_subnets.append(value) ++ ++ def insert_ipam_subnets(self, index, value): ++ self.ipam_subnets[index] = value ++ ++ def delete_ipam_subnets(self, value): ++ self.ipam_subnets.remove(value) ++ ++ ++class MockNetworkIpam(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ++ network_ipam_mgmt=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'default-network-ipam' ++ self.name = name ++ self.uuid = None ++ if parent_obj: ++ self.parent_type = parent_obj._type ++ # copy parent's fq_name ++ self.fq_name = list(parent_obj.fq_name) ++ self.fq_name.append(name) ++ if not parent_obj.get_network_ipams(): ++ parent_obj.network_ipams = [] ++ parent_obj.network_ipams.append(self) ++ else: # No parent obj specified ++ self.parent_type = 'project' ++ self.fq_name = [u'default-domain', u'default-project'] ++ self.fq_name.append(name) ++ ++ # property fields ++ if network_ipam_mgmt: ++ self.network_ipam_mgmt = network_ipam_mgmt ++ if id_perms: ++ self.id_perms = id_perms ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++class MockProject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'project' ++ self.uuid = None ++ self.parent_type = 'domain' ++ self.fq_name = [u'default-domain'] ++ self.fq_name.append(name) ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++def GlobalProjectApi(project_name): ++ if not GlobalProjects: ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ return GlobalProjects[0] ++ ++ ++# Mock definations for different pkgs, modules and VncApi ++mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) ++mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') ++mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork ++mock_vnc_api_mod.SubnetType = MockSubnetType ++mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType ++mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType ++mock_vnc_api_mod.NetworkIpam = MockNetworkIpam ++mock_vnc_api_mod.Project = GlobalProjectApi ++ ++mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') ++mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') ++mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ ++ mock_vnc_api_pkg ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ ++ mock_vnc_api_mod ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ ++ mock_vnc_common_mod ++sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' ++ 'exceptions')] = \ ++ mock_vnc_exception_mod ++ ++CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" ++ ++ ++class RouterInstance(object): ++ def __init__(self): ++ self._name = 'rounter_instance' ++ ++ ++class Context(object): ++ def __init__(self, tenant_id=''): ++ self.read_only = False ++ self.show_deleted = False ++ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] ++ self._read_deleted = 'no' ++ self.timestamp = datetime.datetime.now() ++ self.auth_token = None ++ self._session = None ++ self._is_admin = True ++ self.admin = uuid.uuid4().hex.decode() ++ self.request_id = 'req-' + str(uuid.uuid4()) ++ self.tenant = tenant_id ++ ++ ++class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): ++ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) ++ ++ def setUp(self): ++ ++ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod ++ ++ mock_vnc_api_mod.common = mock_vnc_common_mod ++ mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++ ++ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++ ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ neutron.db.api._ENGINE = mock.MagicMock() ++ ++ def teardown(self): ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ ++ ++class TestContrailNetworks(test_plugin.TestNetworksV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ if 'contrail:fq_name' not in net.keys(): ++ assert False ++ else: ++ assert True ++ ++ def test_delete_network(self): ++ # First create the network and request to delete the same ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ ++ plugin_obj.delete_network(context_obj, net_id) ++ mock_vnc_api_cls.virtual_network_delete.assert_called_once() ++ ++ def test_update_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ # change one of the attribute and update the network ++ network['admin_state_up'] = 'False' ++ new_dict = plugin_obj.update_network(context_obj, net_id, ++ networks_req) ++ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): ++ assert False ++ else: ++ assert True ++ ++ # Not supported test cases in the this TestClass ++ def test_create_networks_bulk_emulated(self): ++ pass ++ ++ def test_create_networks_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_public_network(self): ++ pass ++ ++ def test_create_networks_bulk_wrong_input(self): ++ pass ++ ++ def test_update_shared_network_noadmin_returns_403(self): ++ pass ++ ++ def test_update_network_set_shared(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_single_tenant(self): ++ pass ++ ++ def test_update_network_set_not_shared_other_tenant_returns_409(self): ++ pass ++ ++ def test_update_network_with_subnet_set_shared(self): ++ pass ++ ++ def test_show_network(self): ++ pass ++ ++ def test_show_network_with_subnet(self): ++ pass ++ ++ def test_list_networks(self): ++ pass ++ ++ def test_list_shared_networks_with_non_admin_user(self): ++ pass ++ ++ def test_list_networks_with_parameters(self): ++ pass ++ ++ def test_list_networks_with_fields(self): ++ pass ++ ++ def test_list_networks_with_parameters_invalid_values(self): ++ pass ++ ++ def test_list_networks_with_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_without_pk_in_fields_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_with_sort_emulated(self): ++ pass ++ ++ def test_list_networks_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_invalid_admin_status(self): ++ pass ++ ++ ++class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: ++ assert False ++ else: ++ assert True ++ ++ def test_delete_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ subnet_id = subnet_dict['id'] ++ plugin_obj.delete_subnet(context_obj, subnet_id) ++ ++ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_delete_network(self): ++ pass ++ ++ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet_adding_additional_host_routes_and_dns(self): ++ pass ++ ++ def test_update_subnet_no_gateway(self): ++ pass ++ ++ def test_create_subnet_bad_cidr(self): ++ pass ++ ++ def test_create_subnet_gw_of_network_force_on_returns_400(self): ++ pass ++ ++ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_create_two_subnets(self): ++ pass ++ ++ def test_create_two_subnets_same_cidr_returns_400(self): ++ pass ++ ++ def test_create_subnet_bad_V4_cidr(self): ++ pass ++ ++ def test_create_subnet_bad_V6_cidr(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): ++ pass ++ ++ def test_create_subnets_bulk_native(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_subnets_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_network(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_other(self): ++ pass ++ ++ def test_create_subnet_bad_tenant(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version_null(self): ++ pass ++ ++ def test_create_subnet_bad_uuid(self): ++ pass ++ ++ def test_create_subnet_bad_boolean(self): ++ pass ++ ++ def test_create_subnet_bad_pools(self): ++ pass ++ ++ def test_create_subnet_bad_nameserver(self): ++ pass ++ ++ def test_create_subnet_bad_hostroutes(self): ++ pass ++ ++ def test_create_subnet_defaults(self): ++ pass ++ ++ def test_create_subnet_gw_values(self): ++ pass ++ ++ def test_create_force_subnet_gw_values(self): ++ pass ++ ++ def test_create_subnet_with_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_fully_allocated(self): ++ pass ++ ++ def test_subnet_with_allocation_range(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_v6_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_large_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_multiple_allocation_pools(self): ++ pass ++ ++ def test_create_subnet_with_dhcp_disabled(self): ++ pass ++ ++ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( ++ self): ++ pass ++ ++ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_create_subnet_overlapping_allocation_pools_returns_409(self): ++ pass ++ ++ def test_create_subnet_invalid_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_shared_returns_400(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_cidrv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_cidrv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_dns_v4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): ++ pass ++ ++ def test_create_subnet_gw_bcast_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet(self): ++ pass ++ ++ def test_update_subnet_shared_returns_400(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_dns_v6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): ++ pass ++ ++ def test_show_subnet(self): ++ pass ++ ++ def test_list_subnets(self): ++ pass ++ ++ def test_list_subnets_shared(self): ++ pass ++ ++ def test_list_subnets_with_parameter(self): ++ pass ++ ++ def test_invalid_ip_version(self): ++ pass ++ ++ def test_invalid_subnet(self): ++ pass ++ ++ def test_invalid_ip_address(self): ++ pass ++ ++ def test_invalid_uuid(self): ++ pass ++ ++ def test_create_subnet_with_one_dns(self): ++ pass ++ ++ def test_create_subnet_with_two_dns(self): ++ pass ++ ++ def test_create_subnet_with_too_many_dns(self): ++ pass ++ ++ def test_create_subnet_with_one_host_route(self): ++ pass ++ ++ def test_create_subnet_with_two_host_routes(self): ++ pass ++ ++ def test_create_subnet_with_too_many_routes(self): ++ pass ++ ++ def test_update_subnet_dns(self): ++ pass ++ ++ def test_update_subnet_dns_to_None(self): ++ pass ++ ++ def test_update_subnet_dns_with_too_many_entries(self): ++ pass ++ ++ def test_update_subnet_route(self): ++ pass ++ ++ def test_update_subnet_route_to_None(self): ++ pass ++ ++ def test_update_subnet_route_with_too_many_entries(self): ++ pass ++ ++ def test_delete_subnet_with_dns(self): ++ pass ++ ++ def test_delete_subnet_with_route(self): ++ pass ++ ++ def test_delete_subnet_with_dns_and_route(self): ++ pass ++ ++ def test_list_subnets_with_pagination_emulated(self): ++ pass ++ ++ def test_list_subnets_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_subnets_with_sort_emulated(self): ++ pass ++ ++ def test_validate_subnet_host_routes_exhausted(self): ++ pass ++ ++ def test_validate_subnet_dns_nameservers_exhausted(self): ++ pass ++ ++ ++class TestContrailPortsV2(test_plugin.TestPortsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_port_json(self): ++ pass ++ ++ def test_create_port_bad_tenant(self): ++ pass ++ ++ def test_create_port_public_network(self): ++ pass ++ ++ def test_create_port_public_network_with_ip(self): ++ pass ++ ++ def test_create_ports_bulk_native(self): ++ pass ++ ++ def test_create_ports_bulk_emulated(self): ++ pass ++ ++ def test_create_ports_bulk_wrong_input(self): ++ pass ++ ++ def test_create_ports_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_ports_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_list_ports(self): ++ pass ++ ++ def test_list_ports_filtered_by_fixed_ip(self): ++ pass ++ ++ def test_list_ports_public_network(self): ++ pass ++ ++ def test_show_port(self): ++ pass ++ ++ def test_delete_port(self): ++ pass ++ ++ def test_delete_port_public_network(self): ++ pass ++ ++ def test_update_port(self): ++ pass ++ ++ def test_update_device_id_null(self): ++ pass ++ ++ def test_delete_network_if_port_exists(self): ++ pass ++ ++ def test_delete_network_port_exists_owned_by_network(self): ++ pass ++ ++ def test_update_port_delete_ip(self): ++ pass ++ ++ def test_no_more_port_exception(self): ++ pass ++ ++ def test_update_port_update_ip(self): ++ pass ++ ++ def test_update_port_update_ip_address_only(self): ++ pass ++ ++ def test_update_port_update_ips(self): ++ pass ++ ++ def test_update_port_add_additional_ip(self): ++ pass ++ ++ def test_requested_duplicate_mac(self): ++ pass ++ ++ def test_mac_generation(self): ++ pass ++ ++ def test_mac_generation_4octet(self): ++ pass ++ ++ def test_bad_mac_format(self): ++ pass ++ ++ def test_mac_exhaustion(self): ++ pass ++ ++ def test_requested_duplicate_ip(self): ++ pass ++ ++ def test_requested_subnet_delete(self): ++ pass ++ ++ def test_requested_subnet_id(self): ++ pass ++ ++ def test_requested_subnet_id_not_on_network(self): ++ pass ++ ++ def test_overlapping_subnets(self): ++ pass ++ ++ def test_requested_subnet_id_v4_and_v6(self): ++ pass ++ ++ def test_range_allocation(self): ++ pass ++ ++ def test_requested_invalid_fixed_ips(self): ++ pass ++ ++ def test_invalid_ip(self): ++ pass ++ ++ def test_requested_split(self): ++ pass ++ ++ def test_duplicate_ips(self): ++ pass ++ ++ def test_fixed_ip_invalid_subnet_id(self): ++ pass ++ ++ def test_fixed_ip_invalid_ip(self): ++ pass ++ ++ def test_requested_ips_only(self): ++ pass ++ ++ def test_recycling(self): ++ pass ++ ++ def test_invalid_admin_state(self): ++ pass ++ ++ def test_invalid_mac_address(self): ++ pass ++ ++ def test_default_allocation_expiration(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration(self): ++ pass ++ ++ def test_port_delete_holds_ip(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration_invalid_address(self): ++ pass ++ ++ def test_hold_ip_address(self): ++ pass ++ ++ def test_recycle_held_ip_address(self): ++ pass ++ ++ def test_recycle_expired_previously_run_within_context(self): ++ pass ++ ++ def test_update_port_not_admin(self): ++ pass ++ ++ def test_list_ports_with_pagination_emulated(self): ++ pass ++ ++ def test_list_ports_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_ports_with_sort_emulated(self): ++ pass ++ ++ def test_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_update_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_recycle_ip_address_without_allocation_pool(self): ++ pass +diff --git setup.cfg setup.cfg +index af52a4d..27ef0ce 100644 +--- setup.cfg ++++ setup.cfg +@@ -61,6 +61,7 @@ data_files = + etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini + etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini + etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini ++ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini + scripts = + bin/quantum-rootwrap + bin/neutron-rootwrap diff --git a/nova_v1.patch b/nova_v1.patch new file mode 100644 index 0000000000..b0bc529a93 --- /dev/null +++ b/nova_v1.patch @@ -0,0 +1,3238 @@ +diff --git nova/network/model.py nova/network/model.py +index b8905a5..e50f75f 100644 +--- nova/network/model.py ++++ nova/network/model.py +@@ -37,6 +37,7 @@ VIF_TYPE_BRIDGE = 'bridge' + VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' ++VIF_TYPE_CONTRAIL = 'contrail' + VIF_TYPE_OTHER = 'other' + + # Constant for max length of network interface names +diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py +index 1bb8f62..9a8b0e9 100644 +--- nova/virt/libvirt/vif.py ++++ nova/virt/libvirt/vif.py +@@ -301,6 +301,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + + return conf + ++ def get_config_contrail(self, instance, vif, image_meta, ++ inst_type): ++ conf = super(LibvirtGenericVIFDriver, ++ self).get_config(instance, vif, ++ image_meta, inst_type) ++ ++ dev = self.get_vif_devname(vif) ++ designer.set_vif_host_backend_ethernet_config(conf, dev) ++ ++ return conf ++ + def get_config_mlnx_direct(self, instance, vif, image_meta, + inst_type): + conf = super(LibvirtGenericVIFDriver, +@@ -359,6 +370,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + vif, + image_meta, + inst_type) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ return self.get_config_contrail(instance, ++ vif, ++ image_meta, ++ inst_type) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -535,6 +551,28 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except exception.ProcessExecutionError: + LOG.exception(_("Failed while plugging vif"), instance=instance) + ++ def plug_contrail(self, instance, vif): ++ """Plug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).plug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ linux_net.create_tap_dev(dev) ++ iface_id = vif['id'] ++ from nova.virt import netutils ++ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) ++ import sys ++ sys.path.append('/opt/stack/nova/plugins/contrail') ++ from config_parser import ContrailVifUpdate ++ ContrailVifUpdate(vif['id'], ++ dev, vif['network']['subnets'][0]['ips'][0]['address'], ++ instance['uuid'], vif['network']['id'], ++ vif['address'], ++ instance['display_name'], ++ instance['hostname'], ++ instance['host'], ++ prefix_len) ++ + def plug(self, instance, vif): + vif_type = vif['type'] + +@@ -542,7 +580,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + 'vif=%(vif)s'), + {'vif_type': vif_type, 'instance': instance, + 'vif': vif}) +- + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " +@@ -561,6 +598,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.plug_iovisor(instance, vif) + elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: + self.plug_mlnx_direct(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ self.plug_contrail(instance, vif) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -696,6 +735,18 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except exception.ProcessExecutionError: + LOG.exception(_("Failed while unplugging vif"), instance=instance) + ++ def unplug_contrail(self, instance, vif): ++ """Unplug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).unplug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ import sys ++ sys.path.append('/opt/stack/nova/plugins/contrail') ++ from config_parser import ContrailVifDelete ++ ContrailVifDelete(vif['id']) ++ linux_net.delete_net_dev(dev) ++ + def unplug(self, instance, vif): + vif_type = vif['type'] + +@@ -720,6 +771,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.unplug_ivs(instance, vif) + elif vif_type == network_model.VIF_TYPE_IOVISOR: + self.unplug_iovisor(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ self.unplug_contrail(instance, vif) + elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: + self.unplug_mlnx_direct(instance, vif) + else: +diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py +new file mode 100644 +index 0000000..043b77c +--- /dev/null ++++ plugins/contrail/config_parser.py +@@ -0,0 +1,116 @@ ++import os ++import sys ++import cgitb ++import argparse ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' ++ ++class ContrailVifDelete(object): ++ def __init__(self, port_id): ++ if os.path.exists(VIF_DIR+port_id): ++ os.remove(VIF_DIR+port_id) ++ #end __init__ ++# end ContrailVifDelete ++ ++class ContrailVifUpdate(object): ++ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, ++ hostname, host, prefix_len): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ self.__update_vif(port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, display_name, ++ hostname, host, prefix_len) ++ ++ # end __init__ ++ ++ def __update_vif(self, port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, ++ display_name, ++ hostname, ++ host, prefix_len): ++ if (port_id and tap_name and ++ ip_address and instance_id and ++ vn_id and mac_address and ++ host and prefix_len): ++ import ConfigParser ++ config = ConfigParser.RawConfigParser() ++ config.add_section('Vif') ++ config.set('Vif', 'port_id', port_id) ++ config.set('Vif', 'tap_name', tap_name) ++ config.set('Vif', 'ip_address', ip_address) ++ config.set('Vif', 'instance_id', instance_id) ++ config.set('Vif', 'vn_id', vn_id) ++ config.set('Vif', 'mac_address', mac_address) ++ config.set('Vif', 'display_name', display_name) ++ config.set('Vif', 'hostname', hostname) ++ config.set('Vif', 'host', host) ++ config.set('Vif', 'prefix_len', prefix_len) ++ with open(VIF_DIR + port_id, 'wb') as configfile: ++ config.write(configfile) ++ ++ # end __update_vif ++# end ContrailVifUpdate ++ ++def update_vif_file(args): ++ #import pdb; pdb.set_trace() ++ if (args.port_id and args.tap_name and ++ args.ip_address and args.instance_id and ++ args.vn_id and args.mac_address and ++ args.host and args.prefix_len): ++ ContrailVifUpdate(args.port_id, args.tap_name, ++ args.ip_address, args.instance_id, ++ args.vn_id, args.mac_address, args.display_name, ++ args.hostname, args.host, args.prefix_len) ++ ++# end update_vif_file ++ ++def parse_args(args_str): ++ ''' ++ ''' ++ # Source any specified config/ini file ++ # Turn off help, so we all options in response to -h ++ conf_parser = argparse.ArgumentParser(add_help=False) ++ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) ++ parser = argparse.ArgumentParser( ++ # Inherit options from config_parser ++ parents=[conf_parser], ++ # print script description with -h/--help ++ description=__doc__, ++ # Don't mess with format of description ++ formatter_class=argparse.RawDescriptionHelpFormatter, ++ ) ++ #defaults.update(secopts) ++ #defaults.update(ksopts) ++ #parser.set_defaults(**defaults) ++ ++ parser.add_argument("--port_id", help = "port id") ++ parser.add_argument("--tap_name", help = "tap_name") ++ parser.add_argument("--ip_address", help = "ip_address") ++ parser.add_argument("--instance_id", help = "instance_id") ++ parser.add_argument("--vn_id", help = "vn_id") ++ parser.add_argument("--mac_address", help = "mac_address") ++ parser.add_argument("--display_name", help = "display_name") ++ parser.add_argument("--hostname", help = "hostname") ++ parser.add_argument("--host", help = "host") ++ parser.add_argument("--prefix_len", help = "prefix_len") ++ args = parser.parse_args(remaining_argv) ++ update_vif_file(args) ++# end parse_args ++ ++def main(args_str=None): ++ #import pdb; pdb.set_trace() ++ if not args_str: ++ args_str = ' '.join(sys.argv[1:]) ++ args = parse_args(args_str) ++# end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py +new file mode 100644 +index 0000000..7d004a0 +--- /dev/null ++++ plugins/contrail/contrail_vif.py +@@ -0,0 +1,298 @@ ++# ++# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. ++# ++ ++""" ++contril vif plug, communicate with contrail agent ++""" ++import os ++import pyinotify ++import sys ++import socket ++import cgitb ++from nova import utils ++from nova import exception ++from nova.openstack.common import log as logging ++from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent ++import gevent ++from gevent import monkey; monkey.patch_time() ++ ++LOG = logging.getLogger(__name__) ++ ++''' ++struct Port { ++ 1:required tuuid port_id, ++ 2:required tuuid instance_id, ++ 3:required string tap_name, ++ 4:required string ip_address, ++ 5:required tuuid vn_id, ++ 6:required string mac_address, ++ 7:optional string display_name, ++ 8:optional string hostname, ++ 9:optional string host; ++ 10: optional byte prefix_len; ++} ++''' ++ ++class ContrailVifPlug(object): ++ "" ++ "" ++ def __init__(self): ++ self._agent_alive = False ++ self._agent_connected = False ++ self._port_dict = {} ++ self._protocol = None ++ self._notifier = None ++ #end __init__ ++ ++ def _agent_connect(self, protocol): ++ # Agent connect for first time ++ if protocol != None: ++ from instance_service import InstanceService ++ service = InstanceService.Client(protocol) ++ return service.Connect() ++ else: ++ return False ++ #end __agent_connect ++ ++ def _keep_alive(self): ++ try: ++ if self._agent_alive == False: ++ self._protocol = self._agent_conn_open() ++ if self._protocol == None: ++ return ++ from instance_service import InstanceService ++ service = InstanceService.Client(self._protocol) ++ aa_latest = service.KeepAliveCheck() ++ if self._agent_alive == False and aa_latest == True: ++ port_l = [v for k, v in self._port_dict.iteritems()] ++ service.AddPort(port_l) ++ self._agent_alive = True ++ return ++ if self._agent_alive == True and aa_latest == False: ++ self._agent_alive = False ++ return ++ except: ++ self._agent_alive = False ++ #end _keep_alive ++ ++ def _agent_conn_open(self): ++ import socket ++ import sys ++ import uuid ++ from thrift.transport import TTransport, TSocket ++ from thrift.transport.TTransport import TTransportException ++ from thrift.protocol import TBinaryProtocol, TProtocol ++ from instance_service import InstanceService ++ from instance_service import ttypes ++ try: ++ socket = TSocket.TSocket("127.0.0.1", 9090) ++ transport = TTransport.TFramedTransport(socket) ++ transport.open() ++ protocol = TBinaryProtocol.TBinaryProtocol(transport) ++ self._agent_connected = self._agent_connect(protocol) ++ return protocol ++ except TTransportException: ++ return None ++ #end _agent_conn_open ++ ++ def get_dev_name(self, iface_id): ++ return "tap" + iface_id[0:11] ++ #end get_dev_name ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _agent_inform_port_add(self, port, port_id): ++ # First add to the port list ++ self._port_dict[port_id] = port ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.AddPort([port]) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_add ++ ++ def _agent_inform_port_delete(self, port_id): ++ # First add to the port list ++ if port_id in self._port_dict: ++ del_port_id = self._port_dict[port_id].port_id ++ del self._port_dict[port_id] ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.DeletePort(del_port_id) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_delete ++ ++ ++#end class ContrailVifPlug ++ ++def launch_interval_looping(contrail_vif_plug): ++ while True: ++ contrail_vif_plug._keep_alive() ++ gevent.sleep(2) ++#end launch_internal_looping ++ ++ ++class ContrailVifDir(ProcessEvent): ++ def __init__(self, contrail_vif, vif_dir): ++ self._create_port_list(contrail_vif, vif_dir) ++ self._contrail_vif_plug = contrail_vif ++ #end __init__ ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _create_port_list(self, contrail_vif, vif_dir): ++ import os ++ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] ++ for f in files: ++ print f ++ file_name = os.path.join(vif_dir, f) ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ contrail_vif._agent_inform_port_add(port, port_id) ++ #end create_port_list ++ ++ def _get_port_info(self, config): ++ import ConfigParser ++ #import pdb; pdb.set_trace() ++ from instance_service import ttypes ++ try: ++ vif = 'Vif' ++ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), ++ self._convert_to_bl(config.get(vif, 'instance_id')), ++ config.get(vif, 'tap_name'), ++ config.get(vif, 'ip_address'), ++ self._convert_to_bl(config.get(vif, 'vn_id')), ++ config.get(vif, 'mac_address'), ++ config.get(vif, 'display_name'), ++ config.get(vif, 'hostname'), ++ config.get(vif, 'host')) ++ #print config.get(vif, 'prefix_len') ++ return port ++ except: ++ return None ++ ++ def _print_port_info(self, config): ++ import ConfigParser ++ try: ++ vif = 'Vif' ++ print config.get(vif, 'port_id') ++ print config.get(vif, 'instance_id') ++ print config.get(vif, 'tap_name') ++ print config.get(vif, 'ip_address') ++ print config.get(vif, 'vn_id') ++ print config.get(vif, 'mac_address') ++ print config.get(vif, 'display_name') ++ print config.get(vif, 'hostname') ++ print config.get(vif, 'host') ++ print config.get(vif, 'prefix_len') ++ except: ++ return ++ #end __print_port_into ++ ++ def _read_port_info_from_file(self, file_name): ++ import ConfigParser ++ config = ConfigParser.ConfigParser() ++ config.read(file_name) ++ self._print_port_info(config) ++ port = self._get_port_info(config) ++ if port is not None: ++ return port, config.get('Vif', 'port_id') ++ else: ++ return None, None ++ #end _read_port_info_from_file ++ ++ def _is_allowed(self, file_name): ++ ret = True ++ if (file_name[0] == '.' or file_name[-1] == '~'): ++ ret = False ++ return ret ++ #end _is_allowed ++ ++ def process_IN_CREATE(self, event): ++ file_name = os.path.join(event.path, event.name) ++ if not self._is_allowed(event.name): ++ return ++ print "Create: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In create: %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ ++ #end process_IN_CREATE ++ ++ def process_IN_DELETE(self, event): ++ if not self._is_allowed(event.name): ++ return ++ print "Remove: %s" % os.path.join(event.path, event.name) ++ file_name = os.path.join(event.path, event.name) ++ #import pdb; pdb.set_trace() ++ if self._is_allowed(event.name): ++ self._contrail_vif_plug._agent_inform_port_delete(event.name) ++ return ++ ++ #end process_IN_DELETE ++ ++ def process_IN_MODIFY(self, event): ++ if not self._is_allowed(event.name): ++ return ++ file_name = os.path.join(event.path, event.name) ++ print "Modify: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In modify %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ #end process_IN_MODIFY ++#end ContrilVifDir ++ ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' ++def contrail_vif_dir_monitor(contrail_vif_plug): ++ #import pdb; pdb.set_trace() ++ wm = WatchManager() ++ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) ++ contrail_vif_plug._notifier = notifier ++ # watched events ++ mask = pyinotify.IN_DELETE | \ ++ pyinotify.IN_CREATE | \ ++ pyinotify.IN_MODIFY | \ ++ pyinotify.IN_ISDIR ++ wm.add_watch(VIF_DIR, mask, quiet=False) ++ notifier.start() ++#end contrail_vif_dir_monitor ++ ++def main(args_str = None): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ contrail_vif_plug = ContrailVifPlug() ++ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) ++ #import pdb; pdb.set_trace() ++ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) ++ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) ++#end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote +new file mode 100644 +index 0000000..76626d4 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService-remote +@@ -0,0 +1,165 @@ ++#!/usr/bin/env python ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++import sys ++import pprint ++from urlparse import urlparse ++from thrift.transport import TTransport ++from thrift.transport import TSocket ++from thrift.transport import THttpClient ++from thrift.protocol import TBinaryProtocol ++ ++import InstanceService ++from ttypes import * ++ ++if len(sys.argv) <= 1 or sys.argv[1] == '--help': ++ print '' ++ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' ++ print '' ++ print 'Functions:' ++ print ' bool AddPort(PortList port_list)' ++ print ' bool KeepAliveCheck()' ++ print ' bool Connect()' ++ print ' bool DeletePort(tuuid port_id)' ++ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' ++ print ' bool AddHostRoute(string ip_address, string vrf_name)' ++ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' ++ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool CreateVrf(string vrf_name)' ++ print '' ++ sys.exit(0) ++ ++pp = pprint.PrettyPrinter(indent = 2) ++host = 'localhost' ++port = 9090 ++uri = '' ++framed = False ++http = False ++argi = 1 ++ ++if sys.argv[argi] == '-h': ++ parts = sys.argv[argi+1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ argi += 2 ++ ++if sys.argv[argi] == '-u': ++ url = urlparse(sys.argv[argi+1]) ++ parts = url[1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ else: ++ port = 80 ++ uri = url[2] ++ if url[4]: ++ uri += '?%s' % url[4] ++ http = True ++ argi += 2 ++ ++if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': ++ framed = True ++ argi += 1 ++ ++cmd = sys.argv[argi] ++args = sys.argv[argi+1:] ++ ++if http: ++ transport = THttpClient.THttpClient(host, port, uri) ++else: ++ socket = TSocket.TSocket(host, port) ++ if framed: ++ transport = TTransport.TFramedTransport(socket) ++ else: ++ transport = TTransport.TBufferedTransport(socket) ++protocol = TBinaryProtocol.TBinaryProtocol(transport) ++client = InstanceService.Client(protocol) ++transport.open() ++ ++if cmd == 'AddPort': ++ if len(args) != 1: ++ print 'AddPort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.AddPort(eval(args[0]),)) ++ ++elif cmd == 'KeepAliveCheck': ++ if len(args) != 0: ++ print 'KeepAliveCheck requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.KeepAliveCheck()) ++ ++elif cmd == 'Connect': ++ if len(args) != 0: ++ print 'Connect requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.Connect()) ++ ++elif cmd == 'DeletePort': ++ if len(args) != 1: ++ print 'DeletePort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.DeletePort(eval(args[0]),)) ++ ++elif cmd == 'TunnelNHEntryAdd': ++ if len(args) != 3: ++ print 'TunnelNHEntryAdd requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) ++ ++elif cmd == 'TunnelNHEntryDelete': ++ if len(args) != 3: ++ print 'TunnelNHEntryDelete requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) ++ ++elif cmd == 'RouteEntryAdd': ++ if len(args) != 4: ++ print 'RouteEntryAdd requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'RouteEntryDelete': ++ if len(args) != 2: ++ print 'RouteEntryDelete requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) ++ ++elif cmd == 'AddHostRoute': ++ if len(args) != 2: ++ print 'AddHostRoute requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.AddHostRoute(args[0],args[1],)) ++ ++elif cmd == 'AddLocalVmRoute': ++ if len(args) != 4: ++ print 'AddLocalVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'AddRemoteVmRoute': ++ if len(args) != 4: ++ print 'AddRemoteVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'CreateVrf': ++ if len(args) != 1: ++ print 'CreateVrf requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.CreateVrf(args[0],)) ++ ++else: ++ print 'Unrecognized method %s' % cmd ++ sys.exit(1) ++ ++transport.close() +diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py +new file mode 100644 +index 0000000..2219045 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService.py +@@ -0,0 +1,2275 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++from thrift.Thrift import TProcessor ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++class Iface: ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ pass ++ ++ def KeepAliveCheck(self, ): ++ pass ++ ++ def Connect(self, ): ++ pass ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ pass ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ pass ++ ++ ++class Client(Iface): ++ def __init__(self, iprot, oprot=None): ++ self._iprot = self._oprot = iprot ++ if oprot is not None: ++ self._oprot = oprot ++ self._seqid = 0 ++ ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ self.send_AddPort(port_list) ++ return self.recv_AddPort() ++ ++ def send_AddPort(self, port_list): ++ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) ++ args = AddPort_args() ++ args.port_list = port_list ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddPort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddPort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); ++ ++ def KeepAliveCheck(self, ): ++ self.send_KeepAliveCheck() ++ return self.recv_KeepAliveCheck() ++ ++ def send_KeepAliveCheck(self, ): ++ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) ++ args = KeepAliveCheck_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_KeepAliveCheck(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = KeepAliveCheck_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); ++ ++ def Connect(self, ): ++ self.send_Connect() ++ return self.recv_Connect() ++ ++ def send_Connect(self, ): ++ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) ++ args = Connect_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_Connect(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = Connect_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ self.send_DeletePort(port_id) ++ return self.recv_DeletePort() ++ ++ def send_DeletePort(self, port_id): ++ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) ++ args = DeletePort_args() ++ args.port_id = port_id ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_DeletePort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = DeletePort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryAdd() ++ ++ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryAdd_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryDelete() ++ ++ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryDelete_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) ++ return self.recv_RouteEntryAdd() ++ ++ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) ++ args = RouteEntryAdd_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_RouteEntryDelete(ip_address, vrf_name) ++ return self.recv_RouteEntryDelete() ++ ++ def send_RouteEntryDelete(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) ++ args = RouteEntryDelete_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_AddHostRoute(ip_address, vrf_name) ++ return self.recv_AddHostRoute() ++ ++ def send_AddHostRoute(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) ++ args = AddHostRoute_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddHostRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddHostRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) ++ return self.recv_AddLocalVmRoute() ++ ++ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) ++ args = AddLocalVmRoute_args() ++ args.ip_address = ip_address ++ args.intf_uuid = intf_uuid ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddLocalVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddLocalVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) ++ return self.recv_AddRemoteVmRoute() ++ ++ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) ++ args = AddRemoteVmRoute_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddRemoteVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddRemoteVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ self.send_CreateVrf(vrf_name) ++ return self.recv_CreateVrf() ++ ++ def send_CreateVrf(self, vrf_name): ++ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) ++ args = CreateVrf_args() ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_CreateVrf(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = CreateVrf_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); ++ ++ ++class Processor(Iface, TProcessor): ++ def __init__(self, handler): ++ self._handler = handler ++ self._processMap = {} ++ self._processMap["AddPort"] = Processor.process_AddPort ++ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck ++ self._processMap["Connect"] = Processor.process_Connect ++ self._processMap["DeletePort"] = Processor.process_DeletePort ++ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd ++ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete ++ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd ++ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete ++ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute ++ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute ++ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute ++ self._processMap["CreateVrf"] = Processor.process_CreateVrf ++ ++ def process(self, iprot, oprot): ++ (name, type, seqid) = iprot.readMessageBegin() ++ if name not in self._processMap: ++ iprot.skip(TType.STRUCT) ++ iprot.readMessageEnd() ++ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) ++ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) ++ x.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ return ++ else: ++ self._processMap[name](self, seqid, iprot, oprot) ++ return True ++ ++ def process_AddPort(self, seqid, iprot, oprot): ++ args = AddPort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddPort_result() ++ result.success = self._handler.AddPort(args.port_list) ++ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_KeepAliveCheck(self, seqid, iprot, oprot): ++ args = KeepAliveCheck_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = KeepAliveCheck_result() ++ result.success = self._handler.KeepAliveCheck() ++ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_Connect(self, seqid, iprot, oprot): ++ args = Connect_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = Connect_result() ++ result.success = self._handler.Connect() ++ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_DeletePort(self, seqid, iprot, oprot): ++ args = DeletePort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = DeletePort_result() ++ result.success = self._handler.DeletePort(args.port_id) ++ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): ++ args = TunnelNHEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryAdd_result() ++ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): ++ args = TunnelNHEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryDelete_result() ++ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryAdd(self, seqid, iprot, oprot): ++ args = RouteEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryAdd_result() ++ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryDelete(self, seqid, iprot, oprot): ++ args = RouteEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryDelete_result() ++ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddHostRoute(self, seqid, iprot, oprot): ++ args = AddHostRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddHostRoute_result() ++ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddLocalVmRoute(self, seqid, iprot, oprot): ++ args = AddLocalVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddLocalVmRoute_result() ++ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): ++ args = AddRemoteVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddRemoteVmRoute_result() ++ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_CreateVrf(self, seqid, iprot, oprot): ++ args = CreateVrf_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = CreateVrf_result() ++ result.success = self._handler.CreateVrf(args.vrf_name) ++ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ ++# HELPER FUNCTIONS AND STRUCTURES ++ ++class AddPort_args: ++ """ ++ Attributes: ++ - port_list ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_list=None,): ++ self.port_list = port_list ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_list = [] ++ (_etype24, _size21) = iprot.readListBegin() ++ for _i25 in xrange(_size21): ++ _elem26 = Port() ++ _elem26.read(iprot) ++ self.port_list.append(_elem26) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_args') ++ if self.port_list is not None: ++ oprot.writeFieldBegin('port_list', TType.LIST, -1) ++ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) ++ for iter27 in self.port_list: ++ iter27.write(oprot) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddPort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_args: ++ """ ++ Attributes: ++ - port_id ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_id=None,): ++ self.port_id = port_id ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype31, _size28) = iprot.readListBegin() ++ for _i32 in xrange(_size28): ++ _elem33 = iprot.readI16(); ++ self.port_id.append(_elem33) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_args') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, -1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter34 in self.port_id: ++ oprot.writeI16(iter34) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.intf_uuid = intf_uuid ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.intf_uuid = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.intf_uuid is not None: ++ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) ++ oprot.writeString(self.intf_uuid) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.intf_uuid is None: ++ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_args: ++ """ ++ Attributes: ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'vrf_name', None, None, ), # 1 ++ ) ++ ++ def __init__(self, vrf_name=None,): ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_args') ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) +diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py +new file mode 100644 +index 0000000..f34ead4 +--- /dev/null ++++ plugins/contrail/instance_service/__init__.py +@@ -0,0 +1 @@ ++__all__ = ['ttypes', 'constants', 'InstanceService'] +diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py +new file mode 100644 +index 0000000..73f07fe +--- /dev/null ++++ plugins/contrail/instance_service/constants.py +@@ -0,0 +1,11 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++ +diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py +new file mode 100644 +index 0000000..564f82e +--- /dev/null ++++ plugins/contrail/instance_service/ttypes.py +@@ -0,0 +1,210 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++ ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++ ++class Port: ++ """ ++ Attributes: ++ - port_id ++ - instance_id ++ - tap_name ++ - ip_address ++ - vn_id ++ - mac_address ++ - display_name ++ - hostname ++ - host ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 ++ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 ++ (3, TType.STRING, 'tap_name', None, None, ), # 3 ++ (4, TType.STRING, 'ip_address', None, None, ), # 4 ++ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 ++ (6, TType.STRING, 'mac_address', None, None, ), # 6 ++ (7, TType.STRING, 'display_name', None, None, ), # 7 ++ (8, TType.STRING, 'hostname', None, None, ), # 8 ++ (9, TType.STRING, 'host', None, None, ), # 9 ++ ) ++ ++ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): ++ self.port_id = port_id ++ self.instance_id = instance_id ++ self.tap_name = tap_name ++ self.ip_address = ip_address ++ self.vn_id = vn_id ++ self.mac_address = mac_address ++ self.display_name = display_name ++ self.hostname = hostname ++ self.host = host ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype3, _size0) = iprot.readListBegin() ++ for _i4 in xrange(_size0): ++ _elem5 = iprot.readI16(); ++ self.port_id.append(_elem5) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.LIST: ++ self.instance_id = [] ++ (_etype9, _size6) = iprot.readListBegin() ++ for _i10 in xrange(_size6): ++ _elem11 = iprot.readI16(); ++ self.instance_id.append(_elem11) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.tap_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 5: ++ if ftype == TType.LIST: ++ self.vn_id = [] ++ (_etype15, _size12) = iprot.readListBegin() ++ for _i16 in xrange(_size12): ++ _elem17 = iprot.readI16(); ++ self.vn_id.append(_elem17) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 6: ++ if ftype == TType.STRING: ++ self.mac_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 7: ++ if ftype == TType.STRING: ++ self.display_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 8: ++ if ftype == TType.STRING: ++ self.hostname = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 9: ++ if ftype == TType.STRING: ++ self.host = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Port') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, 1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter18 in self.port_id: ++ oprot.writeI16(iter18) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.instance_id is not None: ++ oprot.writeFieldBegin('instance_id', TType.LIST, 2) ++ oprot.writeListBegin(TType.I16, len(self.instance_id)) ++ for iter19 in self.instance_id: ++ oprot.writeI16(iter19) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.tap_name is not None: ++ oprot.writeFieldBegin('tap_name', TType.STRING, 3) ++ oprot.writeString(self.tap_name) ++ oprot.writeFieldEnd() ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 4) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vn_id is not None: ++ oprot.writeFieldBegin('vn_id', TType.LIST, 5) ++ oprot.writeListBegin(TType.I16, len(self.vn_id)) ++ for iter20 in self.vn_id: ++ oprot.writeI16(iter20) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.mac_address is not None: ++ oprot.writeFieldBegin('mac_address', TType.STRING, 6) ++ oprot.writeString(self.mac_address) ++ oprot.writeFieldEnd() ++ if self.display_name is not None: ++ oprot.writeFieldBegin('display_name', TType.STRING, 7) ++ oprot.writeString(self.display_name) ++ oprot.writeFieldEnd() ++ if self.hostname is not None: ++ oprot.writeFieldBegin('hostname', TType.STRING, 8) ++ oprot.writeString(self.hostname) ++ oprot.writeFieldEnd() ++ if self.host is not None: ++ oprot.writeFieldBegin('host', TType.STRING, 9) ++ oprot.writeString(self.host) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.port_id is None: ++ raise TProtocol.TProtocolException(message='Required field port_id is unset!') ++ if self.instance_id is None: ++ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') ++ if self.tap_name is None: ++ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vn_id is None: ++ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') ++ if self.mac_address is None: ++ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) diff --git a/stack.sh b/stack.sh index 4ca9e23ba0..f5574747c5 100755 --- a/stack.sh +++ b/stack.sh @@ -680,26 +680,50 @@ if is_service_enabled cinder; then fi function test_install_neutron_patch() { + patch_name="neutron_v2.patch" contrail_cwd=$(pwd) cd $DEST/neutron - patch -p0 -N --dry-run --silent < $TOP_DIR/neutron.patch &> /dev/null + patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null if [ $? == 0 ]; then # patch is missing - echo "Installing Neutron patch" - sudo patch -p0 < $TOP_DIR/neutron.patch + echo "Installing neutron patch" + patch -p0 < $TOP_DIR/$patch_name fi cd ${contrail_cwd} } +function test_install_nova_patch() { + patch_name="nova_v1.patch" + contrail_cwd=$(pwd) + cd $DEST/nova + patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null + if [ $? == 0 ]; then + # patch is missing + echo "Installing nova patch" + patch -p0 < $TOP_DIR/$patch_name + fi + cd ${contrail_cwd} +} + +function command_exists() { + hash "$1" &> /dev/null ; +} + + if is_service_enabled neutron; then install_neutron install_neutron_third_party - test_install_neutron_patch + if [ $ENABLE_CONTRAIL ]; then + test_install_neutron_patch + fi fi if is_service_enabled nova; then # compute service install_nova + if [ $ENABLE_CONTRAIL ]; then + test_install_nova_patch + fi cleanup_nova configure_nova fi @@ -959,7 +983,7 @@ if [ $ENABLE_CONTRAIL ]; then sudo pip install gevent geventhttpclient==1.0a thrift sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient - sudo pip install kazoo + sudo pip install kazoo pyinotify CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} mkdir -p $CONTRAIL_SRC @@ -1501,6 +1525,8 @@ END sudo chmod +x /etc/contrail/vnsw.hlpr screen_it agent "sudo /etc/contrail/vnsw.hlpr" + screen_it vif "python /opt/stack/nova/plugins/contrail/contrail_vif.py" + # restore saved screen settings SCREEN_NAME=$SAVED_SCREEN_NAME fi diff --git a/stackrc b/stackrc index 5e05251329..c8e74775ba 100644 --- a/stackrc +++ b/stackrc @@ -33,7 +33,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent,disco +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent,disco,vif # Set the default Nova APIs to enable NOVA_ENABLED_APIS=ec2,osapi_compute,metadata From 29f398e6bcb865157dd65d11933c502d3542aa05 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 17 Oct 2013 04:17:29 +0000 Subject: [PATCH 017/179] fixed get_if_mtu() to use pyton re and not be confused by \r from shell --- setup_contrail.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/setup_contrail.py b/setup_contrail.py index 908a1af18e..e91f0a953c 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -18,6 +18,7 @@ import xml.etree.ElementTree as ET import platform import getpass +import re import tempfile @@ -255,12 +256,14 @@ def get_domain_search_list (self): return domain_list def get_if_mtu (self, dev): - mtu = self.run_shell("ifconfig %s | grep mtu | awk '{ print $NF }'" % dev) - if not mtu: - # for debian - mtu = self.run_shell("ifconfig %s | grep MTU | sed 's/.*MTU.\([0-9]\+\).*/\1/g'" % dev) - if mtu and mtu != '1500': return mtu - return '' + ifconfig = self.run_shell("ifconfig %s" % dev) + m = re.search(r'(?i)mtu[:\s]*(\d+)\b', ifconfig) + mtu = '' + if m: + mtu = m.group(1) + if mtu == '1500': + mtu = '' + return mtu #end if_mtu def get_intf_ip (self, intf): From 7eabff1588e800dfae971d89e7faae8779b1c8fb Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 17 Oct 2013 04:34:10 +0000 Subject: [PATCH 018/179] porting stack.sh to debian --- stack.sh | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/stack.sh b/stack.sh index f5574747c5..d6c8542477 100755 --- a/stack.sh +++ b/stack.sh @@ -993,8 +993,8 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - python third_party/fetch_packages.py - scons + #python third_party/fetch_packages.py + #scons cd ${contrail_cwd} # get cassandra @@ -1039,7 +1039,8 @@ EOF fi # create config files - python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST + # DEBUG - NBK + python $TOP_DIR/setup_contrail.py --physical_interface=eth1 # --cfgm_ip $SERVICE_HOST # install contrail modules echo "Installing contrail modules" @@ -1436,8 +1437,19 @@ service_check # Contrail function insert_vrouter() { source /etc/contrail/agent_param - source $VHOST_CFG - sudo insmod $CONTRAIL_SRC/$kmod + EXT_DEV=$dev + if [ -e $VHOST_CFG ]; then + source $VHOST_CFG + else + DEVICE=vhost0 + IPADDR=$(ifconfig $EXT_DEV | sed -ne 's/.*inet *addr[: ]*\([0-9.]*\).*/\1/i p') + NETMASK=$(ifconfig $EXT_DEV | sed -ne 's/.*mask[: *]\([0-9.]*\).*/\1/i p') + fi + # don't die in small memory environments + sudo insmod $CONTRAIL_SRC/$kmod vr_flow_entries=4096 vr_oflow_entries=512 + + # DEBUG - don't bring the network down! + exit 1 echo "Creating vhost interface: $DEVICE." VIF=$CONTRAIL_SRC/build/debug/vrouter/utils/vif From 98c85d749ea3b41224bb97d945dfdb5d90105af7 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 17 Oct 2013 07:45:10 +0000 Subject: [PATCH 019/179] stack.sh completes ok on ubuntu, installs vrouter module, sets up vhost0 interface setup_contrail gets admin passwords from environment --- setup_contrail.py | 8 ++-- stack.sh | 109 ++++++++++++++++++++++++++++------------------ 2 files changed, 71 insertions(+), 46 deletions(-) diff --git a/setup_contrail.py b/setup_contrail.py index e91f0a953c..4f84616be5 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -23,10 +23,10 @@ import tempfile # Get Environment Stuff -password='contrail123' -admin_username='admin' -admin_token='contrail123' -admin_tenant ='admin' +password = os.environ['ADMIN_PASSWORD'] or 'contrail123' +admin_username = os.environ['CONTRAIL_ADMIN_USERNAME'] or 'admin' +admin_token = os.environ['SERVICE_TOKEN'] or 'contrail123' +admin_tenant = os.environ['CONTRAIL_ADMIN_TENANT'] or 'admin' # TODO following keystone credentials hardcoded ks_admin_user = admin_username diff --git a/stack.sh b/stack.sh index d6c8542477..7f2d365b93 100755 --- a/stack.sh +++ b/stack.sh @@ -965,18 +965,24 @@ if [ $ENABLE_CONTRAIL ]; then sudo chmod 777 /var/log/contrail # basic dependencies - if ! command_exists repo ; then - mkdir -p ~/bin - PATH=~/bin:$PATH - sudo curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo - sudo chmod a+x ~/bin/repo + if ! which repo > /dev/null 2>&1 ; then + curl -O https://dl-ssl.google.com/dl/googlesource/git-repo/repo + chmod 0755 repo + sudo mv repo /usr/bin fi # dependencies - sudo yum -y install patch scons flex bison make vim - sudo yum -y install expat-devel gettext-devel curl-devel - sudo yum -y install gcc-c++ python-devel autoconf automake - sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + if is_ubuntu; then + apt_get install patch scons flex bison make vim + apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev + apt_get install python-dev autoconf automake build-essential + apt_get install libevent-dev libxml2-dev libxslt-dev + else + sudo yum -y install patch scons flex bison make vim + sudo yum -y install expat-devel gettext-devel curl-devel + sudo yum -y install gcc-c++ python-devel autoconf automake + sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + fi # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 @@ -998,16 +1004,29 @@ if [ $ENABLE_CONTRAIL ]; then cd ${contrail_cwd} # get cassandra - if [ ! -f "/usr/sbin/cassandra" ] ; then - cat << EOF > datastax.repo + if ! which cassandra > /dev/null 2>&1 ; then + if is_ubuntu; then + echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | + sudo tee /etc/apt/sources.list.d/cassandra.list + + gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D + gpg --export --armor F758CE318D77295D | sudo apt-key add - + gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 + gpg --export --armor 2B5C1B00 | sudo apt-key add - + + apt_get update + apt_get install cassandra + else + cat << EOF > datastax.repo [datastax] name = DataStax Repo for Apache Cassandra baseurl = http://rpm.datastax.com/community enabled = 1 gpgcheck = 0 EOF - sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install dsc20 + sudo mv datastax.repo /etc/yum.repos.d/ + sudo yum -y install dsc20 + fi fi # get ifmap @@ -1039,8 +1058,10 @@ EOF fi # create config files - # DEBUG - NBK - python $TOP_DIR/setup_contrail.py --physical_interface=eth1 # --cfgm_ip $SERVICE_HOST + # export passwords in a subshell so setup_contrail can pick them up but they won't leak later + (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && + python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE # --cfgm_ip $SERVICE_HOST + ) # install contrail modules echo "Installing contrail modules" @@ -1448,44 +1469,46 @@ function insert_vrouter() { # don't die in small memory environments sudo insmod $CONTRAIL_SRC/$kmod vr_flow_entries=4096 vr_oflow_entries=512 - # DEBUG - don't bring the network down! - exit 1 - echo "Creating vhost interface: $DEVICE." VIF=$CONTRAIL_SRC/build/debug/vrouter/utils/vif DEV_MAC=$(cat /sys/class/net/$dev/address) - sudo $VIF --create $DEVICE --mac $DEV_MAC - if [ $? != 0 ] - then - echo "Error creating interface: $DEVICE" - fi + sudo $VIF --create $DEVICE --mac $DEV_MAC \ + || echo "Error creating interface: $DEVICE" echo "Adding $DEVICE to vrouter" - sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost - if [ $? != 0 ] - then - echo "Error adding $DEVICE to vrouter" - fi + sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost \ + || echo "Error adding $DEVICE to vrouter" echo "Adding $dev to vrouter" - sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical - if [ $? != 0 ] - then - echo "Error adding $dev to vrouter" - fi + sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical \ + || echo "Error adding $dev to vrouter" + + if is_ubuntu; then + cat > /tmp/interfaces < Date: Thu, 17 Oct 2013 17:35:16 -0700 Subject: [PATCH 020/179] 1. Update neutron patch to account for addition of VIF type 2. Use get to avoid key error 3. Re-enable repo sync, ask for physical interface to use --- neutron_v3.patch | 4706 +++++++++++++++++++++++++++++++++++++++++++++ setup_contrail.py | 8 +- stack.sh | 12 +- 3 files changed, 4718 insertions(+), 8 deletions(-) create mode 100644 neutron_v3.patch mode change 100644 => 100755 setup_contrail.py diff --git a/neutron_v3.patch b/neutron_v3.patch new file mode 100644 index 0000000000..16d835bfe5 --- /dev/null +++ b/neutron_v3.patch @@ -0,0 +1,4706 @@ +diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py +new file mode 100644 +index 0000000..5d610b3 +--- /dev/null ++++ neutron/extensions/ipam.py +@@ -0,0 +1,140 @@ ++from abc import abstractmethod ++ ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron.api import extensions ++from neutron import manager ++from oslo.config import cfg ++ ++ ++# Ipam Exceptions ++class IpamNotFound(qexception.NotFound): ++ message = _("IPAM %(id)s could not be found") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'ipams': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:regex': attr.UUID_PATTERN}, ++ 'is_visible': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'fq_name': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ 'mgmt': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': None}, ++ 'nets_using': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True, 'default': ''} ++ }, ++} ++ ++# TODO should this be tied to ipam extension? ++EXTENDED_ATTRIBUTES_2_0 = { ++ 'networks': { ++ 'contrail:fq_name': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:policys': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ 'contrail:subnet_ipam': {'allow_post': False, ++ 'allow_put': False, ++ 'default': '', ++ 'is_visible': True}, ++ }, ++ 'subnets': { ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:ipam_fq_name': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ } ++} ++ ++ ++class Ipam(object): ++ ++ @classmethod ++ def get_name(cls): ++ return "Network IP Address Management" ++ ++ @classmethod ++ def get_alias(cls): ++ return "ipam" ++ ++ @classmethod ++ def get_description(cls): ++ return ("Configuration object for holding common to a set of" ++ " IP address blocks") ++ ++ @classmethod ++ def get_namespace(cls): ++ return "http://docs.openstack.org/TODO" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2012-07-20T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ exts = [] ++ plugin = manager.QuantumManager.get_plugin() ++ for resource_name in ['ipam']: ++ collection_name = resource_name + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) ++ ++ member_actions = {} ++ ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, ++ member_actions=member_actions) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ member_actions=member_actions) ++ exts.append(ex) ++ ++ return exts ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return EXTENDED_ATTRIBUTES_2_0 ++ else: ++ return {} ++#end class Ipam ++ ++ ++class IpamPluginBase(object): ++ ++ @abstractmethod ++ def create_ipam(self, context, ipam): ++ pass ++ ++ @abstractmethod ++ def update_ipam(self, context, id, ipam): ++ pass ++ ++ @abstractmethod ++ def get_ipam(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def delete_ipam(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_ipams(self, context, filters=None, fields=None): ++ pass ++#end class IpamPluginBase +diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py +index dbef592..f6b2144 100644 +--- neutron/extensions/portbindings.py ++++ neutron/extensions/portbindings.py +@@ -45,11 +45,12 @@ VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_HYPERV = 'hyperv' + VIF_TYPE_MIDONET = 'midonet' ++VIF_TYPE_CONTRAIL = 'contrail' + VIF_TYPE_OTHER = 'other' + VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, + VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, + VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_MIDONET, +- VIF_TYPE_OTHER] ++ VIF_TYPE_CONTRAIL, VIF_TYPE_OTHER] + + + EXTENDED_ATTRIBUTES_2_0 = { +diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py +new file mode 100644 +index 0000000..8028b32 +--- /dev/null ++++ neutron/plugins/juniper/contrail/contrailplugin.py +@@ -0,0 +1,1187 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++ ++import ConfigParser ++import logging ++from pprint import pformat ++ ++#from neutron.manager import NeutronManager ++from neutron.common import exceptions as exc ++from neutron.db import db_base_plugin_v2 ++from neutron.db import portbindings_base ++from neutron.extensions import l3 ++from neutron.extensions import securitygroup ++from neutron.extensions import portbindings ++#from neutron.extensions import vpcroutetable ++ ++import cgitb ++from httplib2 import Http ++from oslo.config import cfg ++import re ++import string ++import sys ++ ++import ctdb.config_db ++ ++LOG = logging.getLogger(__name__) ++ ++vnc_opts = [ ++ cfg.StrOpt('api_server_ip', default='127.0.0.1'), ++ cfg.StrOpt('api_server_port', default='8082'), ++] ++ ++ ++def _read_cfg(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.get(section, option) ++ except (AttributeError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++def _read_cfg_boolean(cfg_parser, section, option, default): ++ try: ++ val = cfg_parser.getboolean(section, option) ++ except (AttributeError, ValueError, ++ ConfigParser.NoOptionError, ++ ConfigParser.NoSectionError): ++ val = default ++ ++ return val ++ ++ ++class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, ++ l3.RouterPluginBase, ++ securitygroup.SecurityGroupPluginBase, ++ portbindings_base.PortBindingBaseMixin): ++#vpcroutetable.RouteTablePluginBase): ++ ++ supported_extension_aliases = ["ipam", "policy", "security-group", ++ "router", "route-table", "port-security", ++ "binding",] ++ __native_bulk_support = False ++ _cfgdb = None ++ _args = None ++ _tenant_id_dict = {} ++ _tenant_name_dict = {} ++ ++ @classmethod ++ def _parse_class_args(cls, cfg_parser): ++ cfg_parser.read("/etc/neutron/plugins/juniper/" ++ "contrail/ContrailPlugin.ini" ++ ) ++ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', ++ 'multi_tenancy', False) ++ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') ++ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') ++ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', ++ 'user1') ++ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_password', 'password1') ++ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', ++ 'admin_tenant_name', ++ 'default-domain') ++ cls._tenants_api = '%s/tenants' % (cls._auth_url) ++ pass ++ ++ @classmethod ++ def _connect_to_db(cls): ++ """ ++ Many instantiations of plugin (base + extensions) but need to have ++ only one config db conn (else error from ifmap-server) ++ """ ++ cls._cfgdb_map = {} ++ if cls._cfgdb is None: ++ sip = cfg.CONF.APISERVER.api_server_ip ++ sport = cfg.CONF.APISERVER.api_server_port ++ # Initialize connection to DB and add default entries ++ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, ++ cls._admin_password, ++ cls._admin_tenant_name, ++ sip, sport) ++ cls._cfgdb.manager = cls ++ ++ @classmethod ++ def _get_user_cfgdb(cls, context): ++ if not cls._multi_tenancy: ++ return cls._cfgdb ++ user_id = context.user_id ++ role = string.join(context.roles, ",") ++ if user_id not in cls._cfgdb_map: ++ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( ++ cls._admin_user, cls._admin_password, cls._admin_tenant_name, ++ cfg.CONF.APISERVER.api_server_ip, ++ cfg.CONF.APISERVER.api_server_port, ++ user_info={'user_id': user_id, 'role': role}) ++ cls._cfgdb_map[user_id].manager = cls ++ ++ return cls._cfgdb_map[user_id] ++ ++ @classmethod ++ def _tenant_list_from_keystone(cls): ++ # get all tenants ++ hdrs = {'X-Auth-Token': cls._admin_token, ++ 'Content-Type': 'application/json'} ++ try: ++ rsp, content = Http().request(cls._tenants_api, ++ method="GET", headers=hdrs) ++ if rsp.status != 200: ++ return ++ except Exception: ++ return ++ ++ # transform needed for python compatibility ++ content = re.sub('true', 'True', content) ++ content = re.sub('null', 'None', content) ++ content = eval(content) ++ ++ # bail if response is unexpected ++ if 'tenants' not in content: ++ return ++ ++ # create a dictionary for id->name and name->id mapping ++ for tenant in content['tenants']: ++ print 'Adding tenant %s:%s to cache' % (tenant['name'], ++ tenant['id']) ++ cls._tenant_id_dict[tenant['id']] = tenant['name'] ++ cls._tenant_name_dict[tenant['name']] = tenant['id'] ++ ++ def update_security_group(self, context, id, security_group): ++ pass ++ ++ def __init__(self): ++ cfg.CONF.register_opts(vnc_opts, 'APISERVER') ++ ++ cfg_parser = ConfigParser.ConfigParser() ++ ContrailPlugin._parse_class_args(cfg_parser) ++ ++ ContrailPlugin._connect_to_db() ++ self._cfgdb = ContrailPlugin._cfgdb ++ ++ ContrailPlugin._tenant_list_from_keystone() ++ self.base_binding_dict = self._get_base_binding_dict() ++ portbindings_base.register_port_dict_function() ++ ++ def _get_base_binding_dict(self): ++ binding = { ++ portbindings.VIF_TYPE: portbindings.VIF_TYPE_CONTRAIL, ++ portbindings.CAPABILITIES: { ++ portbindings.CAP_PORT_FILTER: ++ 'security-group' in self.supported_extension_aliases}} ++ return binding ++ ++ @classmethod ++ def tenant_id_to_name(cls, id): ++ # bail if we never built the list successfully ++ if len(cls._tenant_id_dict) == 0: ++ return id ++ # check cache ++ if id in cls._tenant_id_dict: ++ return cls._tenant_id_dict[id] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id ++ ++ @classmethod ++ def tenant_name_to_id(cls, name): ++ # bail if we never built the list successfully ++ if len(cls._tenant_name_dict) == 0: ++ return name ++ # check cache ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ # otherwise refresh ++ cls._tenant_list_from_keystone() ++ # second time's a charm? ++ if name in cls._tenant_name_dict: ++ return cls._tenant_name_dict[name] ++ else: ++ return name ++ ++ # Network API handlers ++ def create_network(self, context, network): ++ """ ++ Creates a new Virtual Network, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_create(network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("create_network(): " + pformat(net_dict) + "\n") ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_network(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_read(id, fields) ++ ++ # verify transformation is conforming to api ++ if not fields: ++ # should return all fields ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ fields, False) ++ net_dict.update(net_info['q_extra_data']) ++ else: ++ net_dict = net_info['q_api_data'] ++ ++ LOG.debug("get_network(): " + pformat(net_dict)) ++ return self._fields(net_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_network(self, context, net_id, network): ++ """ ++ Updates the attributes of a particular Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ net_info = cfgdb.network_update(net_id, network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ net_dict.update(net_info['q_extra_data']) ++ ++ LOG.debug("update_network(): " + pformat(net_dict)) ++ return net_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_network(self, context, net_id): ++ """ ++ Deletes the network with the specified network identifier ++ belonging to the specified tenant. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.network_delete(net_id) ++ LOG.debug("delete_network(): " + pformat(net_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_info = cfgdb.network_list(filters) ++ ++ nets_dicts = [] ++ for n_info in nets_info: ++ # verify transformation is conforming to api ++ n_dict = self._make_network_dict(n_info['q_api_data'], fields, ++ False) ++ ++ n_dict.update(n_info['q_extra_data']) ++ nets_dicts.append(n_dict) ++ ++ LOG.debug( ++ "get_networks(): filters: " + pformat(filters) + " data: " ++ + pformat(nets_dicts)) ++ return nets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_networks_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ nets_count = cfgdb.network_count(filters) ++ LOG.debug("get_networks_count(): " + str(nets_count)) ++ return nets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Subnet API handlers ++ def create_subnet(self, context, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_create(subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("create_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnet(self, context, subnet_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_read(subnet_id) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], ++ fields) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("get_subnet(): " + pformat(subnet_dict)) ++ return self._fields(subnet_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_subnet(self, context, subnet_id, subnet): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ subnet_dict.update(subnet_info['q_extra_data']) ++ ++ LOG.debug("update_subnet(): " + pformat(subnet_dict)) ++ return subnet_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_subnet(self, context, subnet_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.subnet_delete(subnet_id) ++ ++ LOG.debug("delete_subnet(): " + pformat(subnet_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets(self, context, filters=None, fields=None): ++ """ ++ Called from Neutron API -> get_ ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_info = cfgdb.subnets_list(filters) ++ ++ subnets_dicts = [] ++ for sn_info in subnets_info: ++ # verify transformation is conforming to api ++ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) ++ ++ sn_dict.update(sn_info['q_extra_data']) ++ subnets_dicts.append(sn_dict) ++ ++ LOG.debug( ++ "get_subnets(): filters: " + pformat(filters) + " data: " ++ + pformat(subnets_dicts)) ++ return subnets_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_subnets_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ subnets_count = cfgdb.subnets_count(filters) ++ LOG.debug("get_subnets_count(): " + str(subnets_count)) ++ return subnets_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Ipam API handlers ++ def create_ipam(self, context, ipam): ++ """ ++ Creates a new IPAM, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_create(ipam['ipam']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("create_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipam(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("get_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_ipam(self, context, id, ipam): ++ """ ++ Updates the attributes of a particular IPAM. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipam_info = cfgdb.ipam_update(id, ipam) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ++ LOG.debug("update_ipam(): " + pformat(ipam_dict)) ++ return ipam_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_ipam(self, context, ipam_id): ++ """ ++ Deletes the ipam with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.ipam_delete(ipam_id) ++ ++ LOG.debug("delete_ipam(): " + pformat(ipam_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_info = cfgdb.ipam_list(filters) ++ ++ ipams_dicts = [] ++ for ipam_info in ipams_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ ipam_dict = ipam_info['q_api_data'] ++ ipam_dict.update(ipam_info['q_extra_data']) ++ ipams_dicts.append(ipam_dict) ++ ++ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) ++ return ipams_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ipams_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ipams_count = cfgdb.ipams_count(filters) ++ LOG.debug("get_ipams_count(): " + str(ipams_count)) ++ return ipams_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Policy API handlers ++ def create_policy(self, context, policy): ++ """ ++ Creates a new Policy, and assigns it ++ a symbolic name. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_create(policy['policy']) ++ ++ ##verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("create_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_read(id) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("get_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_policy(self, context, id, policy): ++ """ ++ Updates the attributes of a particular Policy. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_info = cfgdb.policy_update(id, policy) ++ ++ ## verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ ++ LOG.debug("update_policy(): " + pformat(policy_dict)) ++ return policy_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_policy(self, context, policy_id): ++ """ ++ Deletes the Policy with the specified identifier ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.policy_delete(policy_id) ++ ++ LOG.debug("delete_policy(): " + pformat(policy_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policys(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policys_info = cfgdb.policy_list(filters) ++ ++ policys_dicts = [] ++ for policy_info in policys_info: ++ # verify transformation is conforming to api ++ #ipam_dict = self._make_ipam_dict(ipam_info) ++ policy_dict = policy_info['q_api_data'] ++ policy_dict.update(policy_info['q_extra_data']) ++ policys_dicts.append(policy_dict) ++ ++ LOG.debug("get_policys(): " + pformat(policys_dicts)) ++ return policys_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_policy_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ policy_count = cfgdb.policy_count(filters) ++ LOG.debug("get_policy_count(): " + str(policy_count)) ++ return policy_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Floating IP API handlers ++ def _make_floatingip_dict(self, floatingip, fields=None): ++ res = {'id': floatingip['id'], ++ 'tenant_id': floatingip['tenant_id'], ++ 'floating_ip_address': floatingip['floating_ip_address'], ++ 'floating_network_id': floatingip['floating_network_id'], ++ 'router_id': floatingip['router_id'], ++ 'port_id': floatingip['fixed_port_id'], ++ 'fixed_ip_address': floatingip['fixed_ip_address']} ++ return self._fields(res, fields) ++ ++ def create_floatingip(self, context, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("create_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_floatingip(self, context, fip_id, floatingip): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_update(fip_id, ++ floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("update_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingip(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_read(id) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ ++ LOG.debug("get_floatingip(): " + pformat(fip_dict)) ++ return fip_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_floatingip(self, context, fip_id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.floatingip_delete(fip_id) ++ LOG.debug("delete_floating(): " + pformat(fip_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips(self, context, filters=None, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ fips_info = cfgdb.floatingip_list(filters) ++ ++ fips_dicts = [] ++ for fip_info in fips_info: ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fip_dict.update(fip_info['q_extra_data']) ++ fips_dicts.append(fip_dict) ++ ++ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) ++ return fips_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_floatingips_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ floatingips_count = cfgdb.floatingip_count(filters) ++ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) ++ return floatingips_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Port API handlers ++ def create_port(self, context, port): ++ """ ++ Creates a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_create(port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ ++ LOG.debug("create_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_port(self, context, port_id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_read(port_id) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ port_info, ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("get_port(): " + pformat(port_dict)) ++ return self._fields(port_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_port(self, context, port_id, port): ++ """ ++ Updates the attributes of a port on the specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ port_info = cfgdb.port_update(port_id, port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_dict) ++ ++ port_dict.update(port_info['q_extra_data']) ++ ++ LOG.debug("update_port(): " + pformat(port_dict)) ++ return port_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_port(self, context, port_id): ++ """ ++ Deletes a port on a specified Virtual Network, ++ if the port contains a remote interface attachment, ++ the remote interface is first un-plugged and then the port ++ is deleted. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.port_delete(port_id) ++ LOG.debug("delete_port(): " + pformat(port_id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports(self, context, filters=None, fields=None): ++ """ ++ Retrieves all port identifiers belonging to the ++ specified Virtual Network. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_info = cfgdb.port_list(filters) ++ ++ ports_dicts = [] ++ for p_info in ports_info: ++ # verify transformation is conforming to api ++ p_dict = self._make_port_dict(p_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ p_info, ++ p_dict) ++ ++ p_dict.update(p_info['q_extra_data']) ++ ports_dicts.append(p_dict) ++ ++ LOG.debug( ++ "get_ports(): filter: " + pformat(filters) + 'data: ' ++ + pformat(ports_dicts)) ++ return ports_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_ports_count(self, context, filters=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ ports_count = cfgdb.port_count(filters) ++ LOG.debug("get_ports_count(): " + str(ports_count)) ++ return ports_count ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): ++ """ ++ Attaches a remote interface to the specified port on the ++ specified Virtual Network. ++ """ ++ port = self._get_port(tenant_id, net_id, port_id) ++ # Validate attachment ++ self._validate_attachment(tenant_id, net_id, port_id, ++ remote_interface_id) ++ if port['interface_id']: ++ raise exc.PortInUse(net_id=net_id, port_id=port_id, ++ att_id=port['interface_id']) ++ ++ def unplug_interface(self, tenant_id, net_id, port_id): ++ """ ++ Detaches a remote interface from the specified port on the ++ specified Virtual Network. ++ """ ++ self._get_port(tenant_id, net_id, port_id) ++ ++ # VPC route table handlers ++ def _make_route_table_routes_dict(self, route_table_route, fields=None): ++ res = {'prefix': route_table_route['prefix'], ++ 'next_hop': route_table_route['next_hop']} ++ ++ return self._fields(res, fields) ++ ++ def _make_route_table_dict(self, route_table, fields=None): ++ res = {'id': route_table['id'], ++ 'name': route_table['name'], ++ 'fq_name': route_table['fq_name'], ++ 'tenant_id': route_table['tenant_id']} ++ if route_table['routes']: ++ res['routes'] = [self._make_route_table_routes_dict(r) ++ for r in route_table['routes']['route']] ++ return self._fields(res, fields) ++ ++ def create_route_table(self, context, route_table): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_create( ++ route_table['route_table']) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def update_route_table(self, context, id, route_table): ++ """ ++ Updates the attributes of a particular route table. ++ """ ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_update(id, route_table['route_table']) ++ ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) ++ rt_dict.update(rt_info['q_extra_data']) ++ LOG.debug("create_route_table(): " + pformat(rt_dict)) ++ return rt_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_route_table(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.route_table_delete(id) ++ LOG.debug("delete_route_table(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_tables(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ route_tables_info = cfgdb.route_table_list(context, filters) ++ ++ route_tables_dicts = [] ++ for rt_info in route_tables_info: ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ route_tables_dicts.append(rt_dict) ++ ++ LOG.debug( ++ "get_route_tables(): filter: " + pformat(filters) ++ + 'data: ' + pformat(route_tables_dicts)) ++ return route_tables_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_route_table(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ rt_info = cfgdb.route_table_read(id) ++ ++ # verify transformation is conforming to api ++ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], ++ fields) ++ ++ rt_dict.update(rt_info['q_extra_data']) ++ ++ LOG.debug("get_route_table(): " + pformat(rt_dict)) ++ return self._fields(rt_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # VPC route table svc instance handlers ++ def _make_svc_instance_dict(self, svc_instance, fields=None): ++ res = {'id': svc_instance['id'], ++ 'name': svc_instance['name'], ++ 'tenant_id': svc_instance['tenant_id']} ++ if svc_instance['internal_net']: ++ res['internal_net'] = svc_instance['internal_net'] ++ if svc_instance['external_net']: ++ res['external_net'] = svc_instance['external_net'] ++ return self._fields(res, fields) ++ ++ def create_nat_instance(self, context, nat_instance): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_create( ++ nat_instance['nat_instance']) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("create_nat_instance(): " + pformat(si_dict)) ++ return si_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_nat_instance(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.svc_instance_delete(id) ++ LOG.debug("delete_nat_instance(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instances(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ svc_instances_info = cfgdb.svc_instance_list(context, filters) ++ ++ svc_instances_dicts = [] ++ for si_info in svc_instances_info: ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ svc_instances_dicts.append(si_dict) ++ ++ LOG.debug( ++ "get_nat_instances(): filter: " + pformat(filters) ++ + 'data: ' + pformat(svc_instances_dicts)) ++ return svc_instances_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_nat_instance(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ si_info = cfgdb.svc_instance_read(id) ++ ++ # verify transformation is conforming to api ++ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], ++ fields) ++ ++ si_dict.update(si_info['q_extra_data']) ++ ++ LOG.debug("get_nat_instance(): " + pformat(si_dict)) ++ return self._fields(si_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ # Security Group handlers ++ def _make_security_group_rule_dict(self, security_group_rule, fields=None): ++ res = {'id': security_group_rule['id'], ++ 'tenant_id': security_group_rule['tenant_id'], ++ 'security_group_id': security_group_rule['security_group_id'], ++ 'ethertype': security_group_rule['ethertype'], ++ 'direction': security_group_rule['direction'], ++ 'protocol': security_group_rule['protocol'], ++ 'port_range_min': security_group_rule['port_range_min'], ++ 'port_range_max': security_group_rule['port_range_max'], ++ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], ++ 'remote_group_id': security_group_rule['remote_group_id']} ++ ++ return self._fields(res, fields) ++ ++ def _make_security_group_dict(self, security_group, fields=None): ++ res = {'id': security_group['id'], ++ 'name': security_group['name'], ++ 'tenant_id': security_group['tenant_id'], ++ 'description': security_group['description']} ++ res['security_group_rules'] = [self._make_security_group_rule_dict(r) ++ for r in security_group['rules']] ++ return self._fields(res, fields) ++ ++ def create_security_group(self, context, security_group): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_create( ++ security_group['security_group']) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("create_security_group(): " + pformat(sg_dict)) ++ return sg_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_delete(id) ++ LOG.debug("delete_security_group(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_groups(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_groups_info = cfgdb.security_group_list(context, filters) ++ ++ security_groups_dicts = [] ++ for sg_info in security_groups_info: ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ security_groups_dicts.append(sg_dict) ++ ++ LOG.debug( ++ "get_security_groups(): filter: " + pformat(filters) ++ + 'data: ' + pformat(security_groups_dicts)) ++ return security_groups_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_read(id) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ sg_dict.update(sg_info['q_extra_data']) ++ ++ LOG.debug("get_security_group(): " + pformat(sg_dict)) ++ return self._fields(sg_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def create_security_group_rule(self, context, security_group_rule): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_create( ++ security_group_rule['security_group_rule']) ++ ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data']) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) ++ return sgr_dict ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def delete_security_group_rule(self, context, id): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ cfgdb.security_group_rule_delete(id) ++ LOG.debug("delete_security_group_rule(): " + pformat(id)) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rules(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ security_group_rules_info = cfgdb.security_group_rule_list(filters) ++ ++ security_group_rules_dicts = [] ++ for sgr_info in security_group_rules_info: ++ for sgr in sgr_info: ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr['q_api_data'], fields) ++ sgr_dict.update(sgr['q_extra_data']) ++ security_group_rules_dicts.append(sgr_dict) ++ ++ LOG.debug( ++ "get_security_group_rules(): filter: " + pformat(filters) + ++ 'data: ' + pformat(security_group_rules_dicts)) ++ return security_group_rules_dicts ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e ++ ++ def get_security_group_rule(self, context, id, fields=None): ++ try: ++ cfgdb = ContrailPlugin._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_read(id) ++ ++ # verify transformation is conforming to api ++ sgr_dict = {} ++ if sgr_info != {}: ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data'], fields) ++ sgr_dict.update(sgr_info['q_extra_data']) ++ ++ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) ++ return self._fields(sgr_dict, fields) ++ except Exception as e: ++ cgitb.Hook(format="text").handle(sys.exc_info()) ++ raise e +diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py +new file mode 100644 +index 0000000..4a87a41 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/config_db.py +@@ -0,0 +1,2238 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++import json ++import re ++import requests ++import socket ++import time ++import uuid ++from netaddr import IPNetwork, IPSet, IPAddress ++ ++from neutron.api.v2 import attributes as attr ++from neutron.common import constants ++from neutron.common import exceptions ++from neutron.extensions import portbindings ++from vnc_api.common import exceptions as vnc_exc ++from vnc_api import vnc_api ++ ++_DEFAULT_HEADERS = { ++ 'Content-type': 'application/json; charset="UTF-8"', } ++ ++CREATE = 1 ++READ = 2 ++UPDATE = 3 ++DELETE = 4 ++ ++ ++class DBInterface(object): ++ """ ++ An instance of this class forwards requests to vnc cfg api (web)server ++ """ ++ Q_URL_PREFIX = '/extensions/ct' ++ ++ def __init__(self, admin_name, admin_password, admin_tenant_name, ++ api_srvr_ip, api_srvr_port, user_info=None): ++ self._api_srvr_ip = api_srvr_ip ++ self._api_srvr_port = api_srvr_port ++ ++ self._db_cache = {} ++ self._db_cache['q_networks'] = {} ++ self._db_cache['q_subnets'] = {} ++ self._db_cache['q_subnet_maps'] = {} ++ self._db_cache['q_policies'] = {} ++ self._db_cache['q_ipams'] = {} ++ self._db_cache['q_floatingips'] = {} ++ self._db_cache['q_ports'] = {} ++ self._db_cache['q_fixed_ip_to_subnet'] = {} ++ #obj-uuid to tenant-uuid mapping ++ self._db_cache['q_obj_to_tenant'] = {} ++ #port count per tenant-id ++ self._db_cache['q_tenant_port_count'] = {} ++ self._db_cache['vnc_networks'] = {} ++ self._db_cache['vnc_ports'] = {} ++ self._db_cache['vnc_projects'] = {} ++ self._db_cache['vnc_instance_ips'] = {} ++ ++ # Retry till a api-server is up ++ connected = False ++ while not connected: ++ try: ++ self._vnc_lib = vnc_api.VncApi( ++ admin_name, admin_password, ++ admin_tenant_name, api_srvr_ip, ++ api_srvr_port, '/', user_info=user_info) ++ connected = True ++ except requests.exceptions.RequestException: ++ time.sleep(3) ++ ++ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key ++ subnet_map = self._vnc_lib.kv_retrieve(key=None) ++ for kv_dict in subnet_map: ++ key = kv_dict['key'] ++ if len(key.split()) == 1: ++ subnet_id = key ++ # uuid key, fixup value portion to 'net_id pfx/len' format ++ # if not already so ++ if len(kv_dict['value'].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ net_fq_name = kv_dict['value'].split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ self._vnc_lib.kv_delete(subnet_id) ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, ++ kv_dict['value'].split()[1]) ++ self._vnc_lib.kv_store(subnet_id, new_subnet_key) ++ else: # subnet key ++ if len(key.split()[0].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ # delete old key, convert to new key format and save ++ old_subnet_key = key ++ self._vnc_lib.kv_delete(old_subnet_key) ++ ++ subnet_id = kv_dict['value'] ++ net_fq_name = key.split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) ++ self._vnc_lib.kv_store(new_subnet_key, subnet_id) ++ ++ # Helper routines ++ def _request_api_server(self, url, method, data=None, headers=None): ++ if method == 'GET': ++ return requests.get(url) ++ if method == 'POST': ++ return requests.post(url, data=data, headers=headers) ++ if method == 'DELETE': ++ return requests.delete(url) ++ ++ def _relay_request(self, request): ++ """ ++ Send received request to api server ++ """ ++ # chop neutron parts of url and add api server address ++ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) ++ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, ++ url_path) ++ ++ return self._request_api_server( ++ url, request.environ['REQUEST_METHOD'], ++ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) ++ ++ def _obj_to_json(self, obj): ++ return dict((k, v) for k, v in obj.__dict__.iteritems()) ++ ++ def _ensure_instance_exists(self, instance_id): ++ instance_name = instance_id ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ try: ++ id = self._vnc_lib.obj_to_id(instance_obj) ++ instance_obj = self._vnc_lib.virtual_machine_read(id=id) ++ except Exception as e: ++ #except vnc_exc.NoIdError: # instance doesn't exist, create it ++ instance_obj.uuid = instance_id ++ self._vnc_lib.virtual_machine_create(instance_obj) ++ ++ return instance_obj ++ ++ def _ensure_default_security_group_exists(self, proj_id): ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ sg_groups = proj_obj.get_security_groups() ++ for sg_group in sg_groups or []: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) ++ if sg_obj.name == 'default': ++ return ++ ++ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) ++ self._vnc_lib.security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ #allow ingress traffic from within default security group ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'ingress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ def _get_obj_tenant_id(self, q_type, obj_uuid): ++ # Get the mapping from cache, else seed cache and return ++ try: ++ return self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except KeyError: ++ # Seed the cache and return ++ if q_type == 'port': ++ port_obj = self._virtual_machine_interface_read(obj_uuid) ++ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] ++ # recurse up type-hierarchy ++ tenant_id = self._get_obj_tenant_id('network', net_id) ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ if q_type == 'network': ++ net_obj = self._virtual_network_read(net_id=obj_uuid) ++ tenant_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ return None ++ ++ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): ++ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid ++ ++ def _del_obj_tenant_id(self, obj_uuid): ++ try: ++ del self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except Exception: ++ pass ++ ++ def _project_read(self, proj_id=None, fq_name=None): ++ if proj_id: ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][proj_id] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ fq_name_str = json.dumps(proj_obj.get_fq_name()) ++ self._db_cache['vnc_projects'][proj_id] = proj_obj ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ return proj_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # disable cache for now as fip pool might be put without ++ # neutron knowing it ++ raise KeyError ++ #return self._db_cache['vnc_projects'][fq_name_str] ++ except KeyError: ++ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj ++ return proj_obj ++ ++ def _security_group_rule_create(self, sg_id, sg_rule): ++ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) ++ rules = sg_vnc.get_security_group_entries() ++ if rules is None: ++ rules = vnc_api.PolicyEntriesType([sg_rule]) ++ else: ++ rules.add_policy_rule(sg_rule) ++ ++ sg_vnc.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_vnc) ++ return ++ ++ def _security_group_rule_find(self, sgr_id): ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ ++ for sg in project_sgs: ++ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) ++ sgr_entries = sg_obj.get_security_group_entries() ++ if sgr_entries is None: ++ continue ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ if sg_rule.get_rule_uuid() == sgr_id: ++ return sg_obj, sg_rule ++ ++ return None, None ++ ++ def _security_group_rule_delete(self, sg_obj, sg_rule): ++ rules = sg_obj.get_security_group_entries() ++ rules.get_policy_rule().remove(sg_rule) ++ sg_obj.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_obj) ++ return ++ ++ def _security_group_create(self, sg_obj): ++ sg_uuid = self._vnc_lib.security_group_create(sg_obj) ++ return sg_uuid ++ ++ def _security_group_delete(self, sg_id): ++ self._vnc_lib.security_group_delete(id=sg_id) ++ ++ def _svc_instance_create(self, si_obj): ++ si_uuid = self._vnc_lib.service_instance_create(si_obj) ++ st_fq_name = ['default-domain', 'nat-template'] ++ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) ++ si_obj.set_service_template(st_obj) ++ self._vnc_lib.service_instance_update(si_obj) ++ ++ return si_uuid ++ ++ def _svc_instance_delete(self, si_id): ++ self._vnc_lib.service_instance_delete(id=si_id) ++ ++ def _route_table_create(self, rt_obj): ++ rt_uuid = self._vnc_lib.route_table_create(rt_obj) ++ return rt_uuid ++ ++ def _route_table_delete(self, rt_id): ++ self._vnc_lib.route_table_delete(id=rt_id) ++ ++ def _virtual_network_create(self, net_obj): ++ net_uuid = self._vnc_lib.virtual_network_create(net_obj) ++ ++ return net_uuid ++ ++ def _virtual_network_read(self, net_id=None, fq_name=None): ++ if net_id: ++ try: ++ # return self._db_cache['vnc_networks'][net_id] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(id=net_id) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ self._db_cache['vnc_networks'][net_id] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ return net_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_networks'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ return net_obj ++ ++ def _virtual_network_update(self, net_obj): ++ self._vnc_lib.virtual_network_update(net_obj) ++ # read back to get subnet gw allocated by api-server ++ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ ++ def _virtual_network_delete(self, net_id): ++ fq_name_str = None ++ try: ++ net_obj = self._db_cache['vnc_networks'][net_id] ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_network_delete(id=net_id) ++ ++ try: ++ del self._db_cache['vnc_networks'][net_id] ++ if fq_name_str: ++ del self._db_cache['vnc_networks'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _virtual_machine_interface_create(self, port_obj): ++ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) ++ ++ return port_uuid ++ ++ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): ++ if port_id: ++ try: ++ # return self._db_cache['vnc_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ id=port_id) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ self._db_cache['vnc_ports'][port_id] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ return port_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_ports'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ fq_name=fq_name) ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ return port_obj ++ ++ def _virtual_machine_interface_update(self, port_obj): ++ self._vnc_lib.virtual_machine_interface_update(port_obj) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ ++ def _virtual_machine_interface_delete(self, port_id): ++ fq_name_str = None ++ try: ++ port_obj = self._db_cache['vnc_ports'][port_id] ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_machine_interface_delete(id=port_id) ++ ++ try: ++ del self._db_cache['vnc_ports'][port_id] ++ if fq_name_str: ++ del self._db_cache['vnc_ports'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _instance_ip_create(self, iip_obj): ++ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) ++ ++ return iip_uuid ++ ++ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): ++ if instance_ip_id: ++ try: ++ # return self._db_cache['vnc_instance_ips'][instance_ip_id] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ return iip_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ try: ++ # return self._db_cache['vnc_instance_ips'][fq_name_str] ++ raise KeyError ++ except KeyError: ++ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ return iip_obj ++ ++ def _instance_ip_update(self, iip_obj): ++ self._vnc_lib.instance_ip_update(iip_obj) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ ++ def _instance_ip_delete(self, instance_ip_id): ++ fq_name_str = None ++ try: ++ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.instance_ip_delete(id=instance_ip_id) ++ ++ try: ++ del self._db_cache['vnc_instance_ips'][instance_ip_id] ++ if fq_name_str: ++ del self._db_cache['vnc_instance_ips'][fq_name_str] ++ except KeyError: ++ pass ++ ++ # find projects on a given domain ++ def _project_list_domain(self, domain_id): ++ fq_name = ['default-domain'] ++ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) ++ ++ return resp_dict['projects'] ++ ++ # find network ids on a given project ++ def _network_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) ++ ++ return resp_dict['virtual-networks'] ++ ++ def _ipam_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) ++ ++ return resp_dict['network-ipams'] ++ ++ def _security_group_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ self._ensure_default_security_group_exists(project_uuid) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _security_group_entries_list_sg(self, sg_id): ++ try: ++ sg_uuid = str(uuid.UUID(sg_id)) ++ except Exception: ++ print "Error in converting SG uuid %s" % (sg_id) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _route_table_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) ++ ++ return resp_dict['route-tables'] ++ ++ def _svc_instance_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) ++ ++ return resp_dict['service-instances'] ++ ++ def _policy_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ print "Error in converting uuid %s" % (project_id) ++ ++ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) ++ ++ return resp_dict['network-policys'] ++ ++ # find floating ip pools a project has access to ++ def _fip_pool_refs_project(self, project_id): ++ project_uuid = str(uuid.UUID(project_id)) ++ project_obj = self._project_read(proj_id=project_uuid) ++ ++ return project_obj.get_floating_ip_pool_refs() ++ ++ # find networks of floating ip pools project has access to ++ def _fip_pool_ref_networks(self, project_id): ++ ret_nets = [] ++ ++ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) ++ if not proj_fip_pool_refs: ++ return ret_nets ++ ++ for fip_pool_ref in proj_fip_pool_refs: ++ fip_uuid = fip_pool_ref['uuid'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) ++ net_uuid = fip_pool_obj.parent_uuid ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ ret_nets.append({'uuid': net_obj.uuid, ++ 'fq_name': net_obj.get_fq_name()}) ++ ++ return ret_nets ++ ++ # find floating ip pools defined by network ++ def _fip_pool_list_network(self, net_id): ++ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) ++ ++ return resp_dict['floating-ip-pools'] ++ ++ # find port ids on a given network ++ def _port_list_network(self, network_id): ++ ret_list = [] ++ ++ try: ++ net_obj = self._virtual_network_read(net_id=network_id) ++ except vnc_exc.NoIdError: ++ return ret_list ++ ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ for port_back_ref in port_back_refs: ++ ret_list.append({'id': port_back_ref['uuid']}) ++ ++ return ret_list ++ ++ # find port ids on a given project ++ def _port_list_project(self, project_id): ++ ret_list = [] ++ project_nets = self._network_list_project(project_id) ++ for net in project_nets: ++ net_ports = self._port_list_network(net['uuid']) ++ ret_list.extend(net_ports) ++ ++ return ret_list ++ ++ # Returns True if ++ # * no filter is specified ++ # OR ++ # * search-param is not present in filters ++ # OR ++ # * 1. search-param is present in filters AND ++ # 2. resource matches param-list AND ++ # 3. shared parameter in filters is False ++ def _filters_is_present(self, filters, key_name, match_value): ++ if filters: ++ if key_name in filters: ++ try: ++ if ('shared' in filters and ++ filters['shared'][0] is True): ++ # yuck, q-api has shared as list always of 1 elem ++ return False # no shared-resource support ++ except ValueError: # not in requested list ++ return False ++ elif len(filters.keys()) == 1: ++ shared_val = filters.get('shared', None) ++ if shared_val and shared_val[0] is True: ++ return False ++ ++ return True ++ ++ def _network_read(self, net_uuid): ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ return net_obj ++ ++ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): ++ #import pdb; pdb.set_trace() ++ self._vnc_lib.kv_store(subnet_id, subnet_key) ++ self._vnc_lib.kv_store(subnet_key, subnet_id) ++ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key ++ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id ++ ++ def _subnet_vnc_read_mapping(self, id=None, key=None): ++ if id: ++ try: ++ return self._db_cache['q_subnet_maps'][id] ++ #raise KeyError ++ except KeyError: ++ subnet_key = self._vnc_lib.kv_retrieve(id) ++ self._db_cache['q_subnet_maps'][id] = subnet_key ++ return subnet_key ++ if key: ++ try: ++ return self._db_cache['q_subnet_maps'][key] ++ #raise KeyError ++ except KeyError: ++ subnet_id = self._vnc_lib.kv_retrieve(key) ++ self._db_cache['q_subnet_maps'][key] = subnet_id ++ return subnet_id ++ ++ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): ++ if id: ++ return self._subnet_vnc_read_mapping(id=id) ++ ++ # if subnet was created outside of neutron handle it and create ++ # neutron representation now (lazily) ++ try: ++ return self._subnet_vnc_read_mapping(key=key) ++ except vnc_exc.NoIdError: ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, key) ++ return self._subnet_vnc_read_mapping(key=key) ++ ++ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): ++ self._vnc_lib.kv_delete(subnet_id) ++ self._vnc_lib.kv_delete(subnet_key) ++ try: ++ del self._db_cache['q_subnet_maps'][subnet_id] ++ del self._db_cache['q_subnet_maps'][subnet_key] ++ except KeyError: ++ pass ++ ++ def _subnet_vnc_get_key(self, subnet_vnc, net_id): ++ pfx = subnet_vnc.subnet.get_ip_prefix() ++ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() ++ ++ return '%s %s/%s' % (net_id, pfx, pfx_len) ++ ++ def _subnet_read(self, net_uuid, subnet_key): ++ try: ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ except vnc_exc.NoIdError: ++ return None ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if not ipam_refs: ++ return None ++ ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_uuid) == subnet_key: ++ return subnet_vnc ++ ++ return None ++ ++ def _ip_address_to_subnet_id(self, ip_addr, net_obj): ++ # find subnet-id for ip-addr, called when instance-ip created ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ if IPAddress(ip_addr) in IPSet([cidr]): ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, ++ net_obj.uuid) ++ subnet_id = self._subnet_vnc_read_mapping( ++ key=subnet_key) ++ return subnet_id ++ ++ return None ++ ++ # Conversion routines between VNC and Quantum objects ++ def _svc_instance_neutron_to_vnc(self, si_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(si_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ net_id = si_q['internal_net'] ++ int_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ net_id = si_q['external_net'] ++ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) ++ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, ++ auto_scale=False) ++ si_prop = vnc_api.ServiceInstanceType( ++ auto_policy=True, left_virtual_network=int_vn.name, ++ right_virtual_network=ext_vn.name, scale_out=scale_out) ++ si_prop.set_scale_out(scale_out) ++ si_vnc = vnc_api.ServiceInstance( ++ name=si_q['name'], ++ parent_obj=project_obj, ++ service_instance_properties=si_prop) ++ ++ return si_vnc ++ ++ def _svc_instance_vnc_to_neutron(self, si_obj): ++ si_q_dict = json.loads(json.dumps(si_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ si_q_dict['id'] = si_obj.uuid ++ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') ++ si_q_dict['name'] = si_obj.name ++ si_props = si_obj.get_service_instance_properties() ++ if si_props: ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_left_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ vn_fq_name = si_obj.get_parent_fq_name() ++ vn_name = si_props.get_right_virtual_network() ++ vn_fq_name.extend([vn_name]) ++ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) ++ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name ++ ++ return {'q_api_data': si_q_dict, ++ 'q_extra_data': {}} ++ ++ def _route_table_neutron_to_vnc(self, rt_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(rt_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], ++ parent_obj=project_obj) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ else: ++ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) ++ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) ++ ++ return rt_vnc ++ ++ def _route_table_vnc_to_neutron(self, rt_obj): ++ rt_q_dict = json.loads(json.dumps(rt_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ rt_q_dict['id'] = rt_obj.uuid ++ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') ++ rt_q_dict['name'] = rt_obj.name ++ rt_q_dict['fq_name'] = rt_obj.fq_name ++ ++ # get route table routes ++ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) ++ return {'q_api_data': rt_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_vnc_to_neutron(self, sg_obj): ++ sg_q_dict = json.loads(json.dumps(sg_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ sg_q_dict['id'] = sg_obj.uuid ++ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sg_q_dict['name'] = sg_obj.name ++ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() ++ ++ # get security group rules ++ sg_q_dict['rules'] = [] ++ rule_list = self.security_group_rules_read(sg_obj.uuid) ++ if rule_list: ++ for rule in rule_list: ++ sg_q_dict['rules'].append(rule['q_api_data']) ++ ++ return {'q_api_data': sg_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_neutron_to_vnc(self, sg_q, oper): ++ if oper == CREATE: ++ project_id = str(uuid.UUID(sg_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType( ++ enable=True, description=sg_q['description']) ++ sg_vnc = vnc_api.SecurityGroup( ++ name=sg_q['name'], parent_obj=project_obj, ++ id_perms=id_perms) ++ ++ return sg_vnc ++ ++ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): ++ sgr_q_dict = {} ++ if sg_id is None: ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ direction = 'egress' ++ if sg_rule.get_direction() == '<': ++ direction = 'ingress' ++ ++ remote_cidr = '' ++ remote_sg_uuid = '' ++ if direction == 'ingress': ++ addr = sg_rule.get_src_addresses()[0] ++ else: ++ addr = sg_rule.get_dst_addresses()[0] ++ ++ if addr.get_subnet(): ++ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), ++ addr.get_subnet().get_ip_prefix_len()) ++ elif addr.get_security_group(): ++ if (addr.get_security_group() != 'any') and \ ++ (addr.get_security_group() != 'local'): ++ remote_sg = addr.get_security_group() ++ try: ++ remote_sg_obj = self._vnc_lib.security_group_read( ++ fq_name_str=remote_sg) ++ remote_sg_uuid = remote_sg_obj.uuid ++ except vnc_exc.NoIdError: ++ pass ++ ++ sgr_q_dict['id'] = sg_rule.get_rule_uuid() ++ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sgr_q_dict['security_group_id'] = sg_obj.uuid ++ sgr_q_dict['ethertype'] = 'IPv4' ++ sgr_q_dict['direction'] = direction ++ sgr_q_dict['protocol'] = sg_rule.get_protocol() ++ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ ++ get_start_port() ++ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ ++ get_end_port() ++ sgr_q_dict['remote_ip_prefix'] = remote_cidr ++ sgr_q_dict['remote_group_id'] = remote_sg_uuid ++ ++ return {'q_api_data': sgr_q_dict, ++ 'q_extra_data': {}} ++ ++ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): ++ if oper == CREATE: ++ port_min = 0 ++ port_max = 65535 ++ if sgr_q['port_range_min']: ++ port_min = sgr_q['port_range_min'] ++ if sgr_q['port_range_max']: ++ port_max = sgr_q['port_range_max'] ++ ++ endpt = [vnc_api.AddressType(security_group='any')] ++ if sgr_q['remote_ip_prefix']: ++ cidr = sgr_q['remote_ip_prefix'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ endpt = [vnc_api.AddressType( ++ subnet=vnc_api.SubnetType(pfx, pfx_len))] ++ elif sgr_q['remote_group_id']: ++ sg_obj = self._vnc_lib.security_group_read( ++ id=sgr_q['remote_group_id']) ++ endpt = [vnc_api.AddressType( ++ security_group=sg_obj.get_fq_name_str())] ++ ++ if sgr_q['direction'] == 'ingress': ++ dir = '<' ++ local = endpt ++ remote = [vnc_api.AddressType(security_group='local')] ++ else: ++ dir = '>' ++ remote = endpt ++ local = [vnc_api.AddressType(security_group='local')] ++ ++ if not sgr_q['protocol']: ++ sgr_q['protocol'] = 'any' ++ ++ sgr_uuid = str(uuid.uuid4()) ++ ++ rule = vnc_api.PolicyRuleType( ++ rule_uuid=sgr_uuid, ++ direction=dir, ++ protocol=sgr_q['protocol'], ++ src_addresses=local, ++ src_ports=[vnc_api.PortType(0, 65535)], ++ dst_addresses=remote, ++ dst_ports=[vnc_api.PortType(port_min, port_max)]) ++ return rule ++ ++ def _network_neutron_to_vnc(self, network_q, oper): ++ net_name = network_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(network_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType(enable=True) ++ net_obj = vnc_api.VirtualNetwork( ++ net_name, project_obj, id_perms=id_perms) ++ else: # READ/UPDATE/DELETE ++ net_obj = self._virtual_network_read(net_id=network_q['id']) ++ ++ id_perms = net_obj.get_id_perms() ++ if 'admin_state_up' in network_q: ++ id_perms.enable = network_q['admin_state_up'] ++ net_obj.set_id_perms(id_perms) ++ ++ if 'contrail:policys' in network_q: ++ policy_fq_names = network_q['contrail:policys'] ++ # reset and add with newly specified list ++ net_obj.set_network_policy_list([], []) ++ seq = 0 ++ for p_fq_name in policy_fq_names: ++ domain_name, project_name, policy_name = p_fq_name ++ ++ domain_obj = vnc_api.Domain(domain_name) ++ project_obj = vnc_api.Project(project_name, domain_obj) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ ++ net_obj.add_network_policy( ++ policy_obj, ++ vnc_api.VirtualNetworkPolicyType( ++ sequence=vnc_api.SequenceType(seq, 0))) ++ seq = seq + 1 ++ ++ if 'vpc:route_table' in network_q: ++ rt_fq_name = network_q['vpc:route_table'] ++ if rt_fq_name: ++ try: ++ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) ++ net_obj.set_route_table(rt_obj) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) ++ ++ return net_obj ++ ++ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): ++ net_q_dict = {} ++ extra_dict = {} ++ ++ net_q_dict['id'] = net_obj.uuid ++ net_q_dict['name'] = net_obj.name ++ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() ++ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable ++ net_q_dict['shared'] = False ++ net_q_dict['status'] = constants.NET_STATUS_ACTIVE ++ ++ if net_repr == 'SHOW': ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ #if port_back_refs: ++ # net_q_dict['ports'] = [] ++ # for port_back_ref in port_back_refs: ++ # fq_name = port_back_ref['to'] ++ # try: ++ # port_obj = self._virtual_machine_interface_read( ++ # port_id = fq_name[-1]) ++ # except NoIdError: ++ # continue ++ # ++ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) ++ # port_dict = port_info['q_api_data'] ++ # port_dict.update(port_info['q_extra_data']) ++ # ++ # net_q_dict['ports'].append(port_dict) ++ ++ extra_dict['contrail:instance_count'] = 0 ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ net_policy_refs = net_obj.get_network_policy_refs() ++ if net_policy_refs: ++ extra_dict['contrail:policys'] = \ ++ [np_ref['to'] for np_ref in net_policy_refs] ++ ++ elif net_repr == 'LIST': ++ extra_dict['contrail:instance_count'] = 0 ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ extra_dict['contrail:instance_count'] = len(port_back_refs) ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ net_q_dict['subnets'] = [] ++ if ipam_refs: ++ extra_dict['contrail:subnet_ipam'] = [] ++ for ipam_ref in ipam_refs: ++ subnets = ipam_ref['attr'].get_ipam_subnets() ++ for subnet in subnets: ++ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, ++ ipam_ref['to']) ++ sn_dict = sn_info['q_api_data'] ++ sn_dict.update(sn_info['q_extra_data']) ++ net_q_dict['subnets'].append(sn_dict) ++ sn_ipam = {} ++ sn_ipam['subnet_cidr'] = sn_dict['cidr'] ++ sn_ipam['ipam_fq_name'] = ipam_ref['to'] ++ extra_dict['contrail:subnet_ipam'].append(sn_ipam) ++ ++ return {'q_api_data': net_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _subnet_neutron_to_vnc(self, subnet_q): ++ cidr = subnet_q['cidr'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: ++ default_gw = subnet_q['gateway_ip'] ++ else: ++ # Assigned by address manager ++ default_gw = None ++ sub_net = vnc_api.SubnetType(ip_prefix=pfx, ++ ip_prefix_len=pfx_len) ++ #subnet_vnc = vnc_api.IpamSubnetType( ++ #subnet=vnc_api.SubnetType(pfx, pfx_len), ++ #default_gateway=default_gw) ++ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, ++ default_gateway=default_gw) ++ return subnet_vnc ++ ++ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): ++ sn_q_dict = {} ++ sn_q_dict['name'] = '' ++ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ sn_q_dict['network_id'] = net_obj.uuid ++ sn_q_dict['ip_version'] = 4 ++ ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ sn_q_dict['cidr'] = cidr ++ ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) ++ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) ++ ++ sn_q_dict['id'] = sn_id ++ ++ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway ++ ++ first_ip = str(IPNetwork(cidr).network + 1) ++ last_ip = str(IPNetwork(cidr).broadcast - 2) ++ sn_q_dict['allocation_pools'] = \ ++ [{'id': 'TODO-allocation_pools-id', ++ 'subnet_id': sn_id, ++ 'first_ip': first_ip, ++ 'last_ip': last_ip, ++ 'available_ranges': {}}] ++ ++ sn_q_dict['enable_dhcp'] = False ++ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['routes'] = [{'destination': 'TODO-destination', ++ 'nexthop': 'TODO-nexthop', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['shared'] = False ++ ++ extra_dict = {} ++ extra_dict['contrail:instance_count'] = 0 ++ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name ++ ++ return {'q_api_data': sn_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _ipam_neutron_to_vnc(self, ipam_q, oper): ++ ipam_name = ipam_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(ipam_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) ++ ++ if ipam_q['mgmt']: ++ ipam_obj.set_network_ipam_mgmt( ++ vnc_api.IpamType.factory(**ipam_q['mgmt'])) ++ ++ return ipam_obj ++ ++ def _ipam_vnc_to_neutron(self, ipam_obj): ++ ipam_q_dict = json.loads(json.dumps(ipam_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') ++ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') ++ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) ++ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ ipam_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ ipam_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': ipam_q_dict, ++ 'q_extra_data': {}} ++ ++ def _policy_neutron_to_vnc(self, policy_q, oper): ++ policy_name = policy_q.get('name', None) ++ if oper == CREATE: ++ project_id = str(uuid.UUID(policy_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ else: # READ/UPDATE/DELETE ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) ++ ++ policy_obj.set_network_policy_entries( ++ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) ++ ++ return policy_obj ++ ++ def _policy_vnc_to_neutron(self, policy_obj): ++ policy_q_dict = json.loads(json.dumps(policy_obj, ++ default=self._obj_to_json)) ++ ++ # replace field names ++ policy_q_dict['id'] = policy_q_dict.pop('uuid') ++ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') ++ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', ++ None) ++ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) ++ if net_back_refs: ++ policy_q_dict['nets_using'] = [] ++ for net_back_ref in net_back_refs: ++ net_fq_name = net_back_ref['to'] ++ policy_q_dict['nets_using'].append(net_fq_name) ++ ++ return {'q_api_data': policy_q_dict, ++ 'q_extra_data': {}} ++ ++ def _floatingip_neutron_to_vnc(self, fip_q, oper): ++ if oper == CREATE: ++ # use first available pool on net ++ net_id = fip_q['floating_network_id'] ++ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) ++ fip_name = str(uuid.uuid4()) ++ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) ++ fip_obj.uuid = fip_name ++ ++ proj_id = str(uuid.UUID(fip_q['tenant_id'])) ++ proj_obj = self._project_read(proj_id=proj_id) ++ fip_obj.set_project(proj_obj) ++ else: # READ/UPDATE/DELETE ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) ++ ++ if fip_q['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=fip_q['port_id']) ++ fip_obj.set_virtual_machine_interface(port_obj) ++ else: ++ fip_obj.set_virtual_machine_interface_list([]) ++ ++ return fip_obj ++ ++ def _floatingip_vnc_to_neutron(self, fip_obj): ++ fip_q_dict = {} ++ extra_dict = {} ++ ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( ++ id=fip_obj.parent_uuid) ++ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) ++ ++ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') ++ ++ port_id = None ++ port_refs = fip_obj.get_virtual_machine_interface_refs() ++ if port_refs: ++ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] ++ ++ fip_q_dict['id'] = fip_obj.uuid ++ fip_q_dict['tenant_id'] = tenant_id ++ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() ++ fip_q_dict['floating_network_id'] = net_obj.uuid ++ fip_q_dict['router_id'] = None ++ fip_q_dict['fixed_port_id'] = port_id ++ fip_q_dict['fixed_ip_address'] = None ++ ++ return {'q_api_data': fip_q_dict, ++ 'q_extra_data': extra_dict} ++ ++ def _port_neutron_to_vnc(self, port_q, net_obj, oper): ++ if oper == CREATE: ++ port_name = str(uuid.uuid4()) ++ instance_name = port_q['device_id'] ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ ++ id_perms = vnc_api.IdPermsType(enable=True) ++ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, ++ id_perms=id_perms) ++ port_obj.uuid = port_name ++ port_obj.set_virtual_network(net_obj) ++ ++ else: # READ/UPDATE/DELETE ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_q['id']) ++ ++ port_obj.set_security_group_list([]) ++ if ('security_groups' in port_q and ++ port_q['security_groups'].__class__ is not object): ++ for sg_id in port_q['security_groups']: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ port_obj.add_security_group(sg_obj) ++ ++ id_perms = port_obj.get_id_perms() ++ if 'admin_state_up' in port_q: ++ id_perms.enable = port_q['admin_state_up'] ++ port_obj.set_id_perms(id_perms) ++ ++ return port_obj ++ ++ def _port_vnc_to_neutron(self, port_obj, net_obj=None): ++ port_q_dict = {} ++ port_q_dict['name'] = port_obj.uuid ++ port_q_dict['id'] = port_obj.uuid ++ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_CONTRAIL ++ ++ if not net_obj: ++ net_refs = port_obj.get_virtual_network_refs() ++ if net_refs: ++ net_id = net_refs[0]['uuid'] ++ else: ++ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) ++ ++ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) ++ proj_id = None ++ if not proj_id: ++ # not in cache, get by reading VN obj, and populate cache ++ net_obj = self._virtual_network_read(net_id=net_id) ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(port_obj.uuid, proj_id) ++ else: ++ net_id = net_obj.uuid ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ ++ port_q_dict['tenant_id'] = proj_id ++ port_q_dict['network_id'] = net_id ++ ++ port_q_dict['mac_address'] = '' ++ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() ++ if mac_refs: ++ port_q_dict['mac_address'] = mac_refs.mac_address[0] ++ ++ port_q_dict['fixed_ips'] = [] ++ ip_back_refs = port_obj.get_instance_ip_back_refs() ++ if ip_back_refs: ++ for ip_back_ref in ip_back_refs: ++ try: ++ ip_obj = self._instance_ip_read( ++ instance_ip_id=ip_back_ref['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ++ ip_addr = ip_obj.get_instance_ip_address() ++ ++ ip_q_dict = {} ++ ip_q_dict['port_id'] = port_obj.uuid ++ ip_q_dict['ip_address'] = ip_addr ++ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, ++ net_obj) ++ ip_q_dict['net_id'] = net_id ++ ++ port_q_dict['fixed_ips'].append(ip_q_dict) ++ ++ sg_dict = {'port_security_enabled': True} ++ sg_dict['security_groups'] = [] ++ sg_refs = port_obj.get_security_group_refs() ++ for sg_ref in sg_refs or []: ++ sg_dict['security_groups'].append(sg_ref['uuid']) ++ ++ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable ++ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE ++ port_q_dict['device_id'] = port_obj.parent_name ++ port_q_dict['device_owner'] = 'TODO-device-owner' ++ ++ return {'q_api_data': port_q_dict, ++ 'q_extra_data': sg_dict} ++ ++ # public methods ++ # network api handlers ++ def network_create(self, network_q): ++ #self._ensure_project_exists(network_q['tenant_id']) ++ ++ net_obj = self._network_neutron_to_vnc(network_q, CREATE) ++ net_uuid = self._virtual_network_create(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_uuid] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_read(self, net_uuid, fields=None): ++ # see if we can return fast... ++ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': ++ tenant_id = self._get_obj_tenant_id('network', net_uuid) ++ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} ++ ++ try: ++ # return self._db_cache['q_networks']['net_uuid'] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ try: ++ net_obj = self._network_read(net_uuid) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_uuid) ++ ++ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ ++ def network_update(self, net_id, network_q): ++ network_q['id'] = net_id ++ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) ++ self._virtual_network_update(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_id] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_delete(self, net_id): ++ self._virtual_network_delete(net_id=net_id) ++ try: ++ del self._db_cache['q_networks'][net_id] ++ except KeyError: ++ pass ++ ++ def network_list(self, filters=None): ++ ret_list = [] ++ ++ if filters and 'shared' in filters: ++ if filters['shared'][0] is True: ++ # no support for shared networks ++ return ret_list ++ ++ # collect phase ++ all_nets = [] # all n/ws in all projects ++ if filters and 'tenant_id' in filters: ++ # project-id is present ++ if 'id' in filters: ++ # required networks are also specified, ++ # just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in project, and prune below ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ if 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(p_id)) ++ else: ++ project_nets = self._network_list_project(p_id) ++ all_nets.append(project_nets) ++ elif filters and 'id' in filters: ++ # required networks are specified, just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in all projects ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ if filters and 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(proj_id)) ++ else: ++ project_nets = self._network_list_project(proj_id) ++ all_nets.append(project_nets) ++ ++ # prune phase ++ for project_nets in all_nets: ++ for proj_net in project_nets: ++ proj_net_id = proj_net['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_net_id): ++ continue ++ ++ proj_net_fq_name = unicode(proj_net['fq_name']) ++ if not self._filters_is_present(filters, 'contrail:fq_name', ++ proj_net_fq_name): ++ continue ++ ++ try: ++ net_obj = self._network_read(proj_net['uuid']) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ except vnc_exc.NoIdError: ++ continue ++ ret_list.append(net_info) ++ ++ return ret_list ++ ++ def network_count(self, filters=None): ++ nets_info = self.network_list(filters) ++ return len(nets_info) ++ ++ # subnet api handlers ++ def subnet_create(self, subnet_q): ++ net_id = subnet_q['network_id'] ++ net_obj = self._virtual_network_read(net_id=net_id) ++ ++ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] ++ if ipam_fq_name != '': ++ domain_name, project_name, ipam_name = ipam_fq_name ++ ++ project_obj = vnc_api.Project(project_name) ++ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # link subnet with default ipam ++ project_obj = vnc_api.Project(net_obj.parent_name) ++ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) ++ ipam_fq_name = netipam_obj.get_fq_name() ++ ++ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) ++ ++ # Locate list of subnets to which this subnet has to be appended ++ net_ipam_ref = None ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ if ipam_ref['to'] == ipam_fq_name: ++ net_ipam_ref = ipam_ref ++ break ++ ++ if not net_ipam_ref: ++ # First link from net to this ipam ++ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) ++ net_obj.add_network_ipam(netipam_obj, vnsn_data) ++ else: # virtual-network already linked to this ipam ++ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): ++ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): ++ # duplicate !! ++ subnet_info = self._subnet_vnc_to_neutron(subnet, ++ net_obj, ++ ipam_fq_name) ++ return subnet_info ++ vnsn_data = net_ipam_ref['attr'] ++ vnsn_data.ipam_subnets.append(subnet_vnc) ++ ++ self._virtual_network_update(net_obj) ++ ++ # allocate an id to the subnet and store mapping with ++ # api-server ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, subnet_key) ++ ++ # Read in subnet from server to get updated values for gw etc. ++ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) ++ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, ++ ipam_fq_name) ++ ++ #self._db_cache['q_subnets'][subnet_id] = subnet_info ++ ++ return subnet_info ++ ++ def subnet_read(self, subnet_id): ++ try: ++ # return self._db_cache['q_subnets'][subnet_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_id) == subnet_key: ++ ret_subnet_q = self._subnet_vnc_to_neutron( ++ subnet_vnc, net_obj, ipam_ref['to']) ++ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q ++ return ret_subnet_q ++ ++ return {} ++ ++ def subnet_delete(self, subnet_id): ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ orig_subnets = ipam_ref['attr'].get_ipam_subnets() ++ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets ++ if self._subnet_vnc_get_key(subnet_vnc, net_id) ++ != subnet_key] ++ if len(orig_subnets) != len(new_subnets): ++ # matched subnet to be deleted ++ ipam_ref['attr'].set_ipam_subnets(new_subnets) ++ self._virtual_network_update(net_obj) ++ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) ++ try: ++ del self._db_cache['q_subnets'][subnet_id] ++ except KeyError: ++ pass ++ ++ return ++ ++ def subnets_list(self, filters=None): ++ ret_subnets = [] ++ ++ if filters and 'id' in filters: ++ # required subnets are specified, ++ # just read in corresponding net_ids ++ net_ids = set([]) ++ for subnet_id in filters['id']: ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ net_ids.add(net_id) ++ else: ++ nets_info = self.network_list() ++ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] ++ ++ for net_id in net_ids: ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, ++ net_obj, ++ ipam_ref['to']) ++ sn_id = sn_info['q_api_data']['id'] ++ sn_proj_id = sn_info['q_api_data']['tenant_id'] ++ sn_net_id = sn_info['q_api_data']['network_id'] ++ ++ if filters: ++ if not self._filters_is_present(filters, 'id', ++ sn_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'tenant_id', ++ sn_proj_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'network_id', ++ sn_net_id): ++ continue ++ ++ ret_subnets.append(sn_info) ++ ++ return ret_subnets ++ ++ def subnets_count(self, filters=None): ++ subnets_info = self.subnets_list(filters) ++ return len(subnets_info) ++ ++ # ipam api handlers ++ def ipam_create(self, ipam_q): ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) ++ self._vnc_lib.network_ipam_create(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_read(self, ipam_id): ++ try: ++ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=ipam_id) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_update(self, ipam_id, ipam): ++ ipam_q = ipam['ipam'] ++ ipam_q['id'] = ipam_id ++ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) ++ self._vnc_lib.network_ipam_update(ipam_obj) ++ ++ return self._ipam_vnc_to_neutron(ipam_obj) ++ ++ def ipam_delete(self, ipam_id): ++ self._vnc_lib.network_ipam_delete(id=ipam_id) ++ ++ def ipam_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_ipams = [] # all ipams in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_ipams = self._ipam_list_project(p_id) ++ all_ipams.append(project_ipams) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_ipams = self._ipam_list_project(proj_id) ++ all_ipams.append(project_ipams) ++ ++ # prune phase ++ for project_ipams in all_ipams: ++ for proj_ipam in project_ipams: ++ proj_ipam_id = proj_ipam['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_ipam_id): ++ continue ++ ipam_info = self.ipam_read(proj_ipam['uuid']) ++ ret_list.append(ipam_info) ++ ++ return ret_list ++ ++ def ipam_count(self, filters=None): ++ ipam_info = self.ipam_list(filters) ++ return len(ipam_info) ++ ++ # policy api handlers ++ def policy_create(self, policy_q): ++ ++ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) ++ self._vnc_lib.network_policy_create(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_read(self, policy_id): ++ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_update(self, policy_id, policy): ++ policy_q = policy['policy'] ++ policy_q['id'] = policy_id ++ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) ++ self._vnc_lib.network_policy_update(policy_obj) ++ ++ return self._policy_vnc_to_neutron(policy_obj) ++ ++ def policy_delete(self, policy_id): ++ self._vnc_lib.network_policy_delete(id=policy_id) ++ ++ def policy_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_policys = [] # all policys in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_policys = self._policy_list_project(p_id) ++ all_policys.append(project_policys) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_policys = self._policy_list_project(proj_id) ++ all_policys.append(project_policys) ++ ++ # prune phase ++ for project_policys in all_policys: ++ for proj_policy in project_policys: ++ proj_policy_id = proj_policy['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_policy_id): ++ continue ++ policy_info = self.policy_read(proj_policy['uuid']) ++ ret_list.append(policy_info) ++ ++ return ret_list ++ ++ def policy_count(self, filters=None): ++ policy_info = self.policy_list(filters) ++ return len(policy_info) ++ ++ # floatingip api handlers ++ def floatingip_create(self, fip_q): ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) ++ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_read(self, fip_uuid): ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_update(self, fip_id, fip_q): ++ fip_q['id'] = fip_id ++ fip_obj = self._floatingip_neutron(fip_q, UPDATE) ++ self._vnc_lib.floating_ip_update(fip_obj) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_delete(self, fip_id): ++ self._vnc_lib.floating_ip_delete(id=fip_id) ++ ++ def floatingip_list(self, filters=None): ++ # Find networks, get floatingip backrefs and return ++ ret_list = [] ++ ++ if filters: ++ if 'tenant_id' in filters: ++ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] ++ elif 'port_id' in filters: ++ # required ports are specified, just read and populate ret_list ++ # prune is skipped because proj_objs is empty ++ proj_ids = [] ++ for port_id in filters['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_id) ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron( ++ fip_obj)) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ proj_ids = [proj['uuid'] for proj in dom_projects] ++ ++ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] ++ ++ for proj_obj in proj_objs: ++ fip_back_refs = proj_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) ++ ++ return ret_list ++ ++ def floatingip_count(self, filters=None): ++ floatingip_info = self.floatingip_list(filters) ++ return len(floatingip_info) ++ ++ # port api handlers ++ def port_create(self, port_q): ++ net_id = port_q['network_id'] ++ net_obj = self._network_read(net_id) ++ proj_id = net_obj.parent_uuid ++ ++ self._ensure_instance_exists(port_q['device_id']) ++ ++ # initialize port object ++ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) ++ ++ # if ip address passed then use it ++ ip_addr = None ++ ip_obj = None ++ if port_q['fixed_ips'].__class__ is not object: ++ ip_addr = port_q['fixed_ips'][0]['ip_address'] ++ ip_name = '%s %s' % (net_id, ip_addr) ++ try: ++ ip_obj = self._instance_ip_read(fq_name=[ip_name]) ++ #ip_id = ip_obj.uuid ++ except Exception as e: ++ ip_obj = None ++ ++ # create the object ++ port_id = self._virtual_machine_interface_create(port_obj) ++ ++ # initialize ip object ++ if ip_obj is None: ++ ip_name = str(uuid.uuid4()) ++ ip_obj = vnc_api.InstanceIp(name=ip_name) ++ ip_obj.uuid = ip_name ++ ip_obj.set_virtual_machine_interface(port_obj) ++ ip_obj.set_virtual_network(net_obj) ++ if ip_addr: ++ ip_obj.set_instance_ip_address(ip_addr) ++ try: ++ self._instance_ip_create(ip_obj) ++ except Exception as e: ++ # ResourceExhaustionError, resources are not available ++ self._virtual_machine_interface_delete(port_id=port_id) ++ raise e ++ # shared ip address ++ else: ++ if ip_addr == ip_obj.get_instance_ip_address(): ++ ip_obj.add_virtual_machine_interface(port_obj) ++ self._instance_ip_update(ip_obj) ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) ++ #self._db_cache['q_ports'][port_id] = ret_port_q ++ self._set_obj_tenant_id(port_id, proj_id) ++ ++ # update cache on successful creation ++ tenant_id = proj_id.replace('-', '') ++ if tenant_id not in self._db_cache['q_tenant_port_count']: ++ ncurports = self.port_count({'tenant_id': tenant_id}) ++ else: ++ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] ++ ++ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 ++ ++ return ret_port_q ++ ++ def port_read(self, port_id): ++ try: ++ # return self._db_cache['q_ports'][port_id] ++ raise KeyError ++ except KeyError: ++ pass ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_update(self, port_id, port_q): ++ port_q['id'] = port_id ++ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) ++ self._virtual_machine_interface_update(port_obj) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_delete(self, port_id): ++ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) ++ instance_id = port_obj.parent_uuid ++ ++ # release instance IP address ++ iip_back_refs = port_obj.get_instance_ip_back_refs() ++ if iip_back_refs: ++ for iip_back_ref in iip_back_refs: ++ # if name contains IP address then this is shared ip ++ iip_obj = self._vnc_lib.instance_ip_read( ++ id=iip_back_ref['uuid']) ++ name = iip_obj.name ++ if len(name.split(' ')) > 1: ++ name = name.split(' ')[1] ++ ++ # in case of shared ip only delete the link to the VMI ++ try: ++ socket.inet_aton(name) ++ iip_obj.del_virtual_machine_interface(port_obj) ++ self._instance_ip_update(iip_obj) ++ except socket.error: ++ self._instance_ip_delete( ++ instance_ip_id=iip_back_ref['uuid']) ++ ++ # disassociate any floating IP used by instance ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if fip_back_refs: ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ self.floatingip_update(fip_obj.uuid, {'port_id': None}) ++ ++ self._virtual_machine_interface_delete(port_id=port_id) ++ ++ # delete instance if this was the last port ++ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) ++ inst_intfs = inst_obj.get_virtual_machine_interfaces() ++ if not inst_intfs: ++ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) ++ ++ try: ++ del self._db_cache['q_ports'][port_id] ++ except KeyError: ++ pass ++ ++ # update cache on successful deletion ++ try: ++ tenant_id = self._get_obj_tenant_id('port', port_id) ++ self._db_cache['q_tenant_port_count'][tenant_id] = \ ++ self._db_cache['q_tenant_port_count'][tenant_id] - 1 ++ except KeyError: ++ pass ++ ++ self._del_obj_tenant_id(port_id) ++ ++ def port_list(self, filters=None): ++ ret_q_ports = [] ++ all_project_ids = [] ++ ++ if 'device_owner' in filters: ++ return ret_q_ports ++ ++ if 'device_id' not in filters: ++ # Listing from back references ++ if not filters: ++ # no filters => return all ports! ++ all_projects = self._project_list_domain(None) ++ all_project_ids = [project['uuid'] for project in all_projects] ++ elif 'tenant_id' in filters: ++ all_project_ids = filters.get('tenant_id') ++ ++ for proj_id in all_project_ids: ++ proj_ports = self._port_list_project(proj_id) ++ for port in proj_ports: ++ try: ++ port_info = self.port_read(port['id']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ for net_id in filters.get('network_id', []): ++ net_ports = self._port_list_network(net_id) ++ for port in net_ports: ++ port_info = self.port_read(port['id']) ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ # Listing from parent to children ++ virtual_machine_ids = filters['device_id'] ++ for vm_id in virtual_machine_ids: ++ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( ++ parent_id=vm_id) ++ vm_intf_ids = resp_dict['virtual-machine-interfaces'] ++ for vm_intf in vm_intf_ids: ++ try: ++ port_info = self.port_read(vm_intf['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ def port_count(self, filters=None): ++ if 'device_owner' in filters: ++ return 0 ++ ++ if 'tenant_id' in filters: ++ project_id = filters['tenant_id'][0] ++ try: ++ return self._db_cache['q_tenant_port_count'][project_id] ++ except KeyError: ++ # do it the hard way but remember for next time ++ nports = len(self._port_list_project(project_id)) ++ self._db_cache['q_tenant_port_count'][project_id] = nports ++ else: ++ # across all projects ++ # get only a count from api-server! ++ nports = len(self.port_list(filters)) ++ ++ return nports ++ ++ # security group api handlers ++ def security_group_create(self, sg_q): ++ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) ++ sg_uuid = self._security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = {} ++ def_rule['port_range_min'] = 0 ++ def_rule['port_range_max'] = 65535 ++ def_rule['direction'] = 'egress' ++ def_rule['remote_ip_prefix'] = None ++ def_rule['remote_group_id'] = None ++ def_rule['protocol'] = 'any' ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_uuid, rule) ++ ++ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) ++ return ret_sg_q ++ ++ def security_group_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return self._security_group_vnc_to_neutron(sg_obj) ++ ++ def security_group_delete(self, sg_id): ++ self._security_group_delete(sg_id) ++ ++ def security_group_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] # all sgs in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sg_info = self.security_group_read(proj_sg_id) ++ if not self._filters_is_present(filters, 'name', ++ sg_info['q_api_data']['name']): ++ continue ++ ret_list.append(sg_info) ++ ++ return ret_list ++ ++ def security_group_rule_create(self, sgr_q): ++ sg_id = sgr_q['security_group_id'] ++ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) ++ self._security_group_rule_create(sg_id, sg_rule) ++ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, ++ sg_rule) ++ ++ return ret_sg_rule_q ++ ++ def security_group_rule_read(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ ++ return {} ++ ++ def security_group_rule_delete(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_delete(sg_obj, sg_rule) ++ ++ def security_group_rules_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ sgr_entries = sg_obj.get_security_group_entries() ++ sg_rules = [] ++ if sgr_entries is None: ++ return ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ sg_rules.append(sg_info) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return sg_rules ++ ++ def security_group_rule_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sgs = [] ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sgs = self._security_group_list_project(p_id) ++ all_sgs.append(project_sgs) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ all_sgs.append(project_sgs) ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sgr_info = self.security_group_rules_read(proj_sg_id) ++ if sgr_info: ++ ret_list.append(sgr_info) ++ ++ return ret_list ++ ++ #route table api handlers ++ def route_table_create(self, rt_q): ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) ++ self._route_table_create(rt_obj) ++ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) ++ return ret_rt_q ++ ++ def route_table_read(self, rt_id): ++ try: ++ rt_obj = self._vnc_lib.route_table_read(id=rt_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=rt_id) ++ ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_update(self, rt_id, rt_q): ++ rt_q['id'] = rt_id ++ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) ++ self._vnc_lib.route_table_update(rt_obj) ++ return self._route_table_vnc_to_neutron(rt_obj) ++ ++ def route_table_delete(self, rt_id): ++ self._route_table_delete(rt_id) ++ ++ def route_table_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_rts = [] # all rts in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_rts = self._route_table_list_project(p_id) ++ all_rts.append(project_rts) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_rts = self._route_table_list_project(proj_id) ++ all_rts.append(project_rts) ++ ++ # prune phase ++ for project_rts in all_rts: ++ for proj_rt in project_rts: ++ proj_rt_id = proj_rt['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_rt_id): ++ continue ++ rt_info = self.route_table_read(proj_rt_id) ++ if not self._filters_is_present(filters, 'name', ++ rt_info['q_api_data']['name']): ++ continue ++ ret_list.append(rt_info) ++ ++ return ret_list ++ ++ #service instance api handlers ++ def svc_instance_create(self, si_q): ++ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) ++ self._svc_instance_create(si_obj) ++ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) ++ return ret_si_q ++ ++ def svc_instance_read(self, si_id): ++ try: ++ si_obj = self._vnc_lib.service_instance_read(id=si_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=si_id) ++ ++ return self._svc_instance_vnc_to_neutron(si_obj) ++ ++ def svc_instance_delete(self, si_id): ++ self._svc_instance_delete(si_id) ++ ++ def svc_instance_list(self, context, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ all_sis = [] # all sis in all projects ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ elif filters and 'name' in filters: ++ p_id = str(uuid.UUID(context.tenant)) ++ project_sis = self._svc_instance_list_project(p_id) ++ all_sis.append(project_sis) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sis = self._svc_instance_list_project(proj_id) ++ all_sis.append(project_sis) ++ ++ # prune phase ++ for project_sis in all_sis: ++ for proj_si in project_sis: ++ proj_si_id = proj_si['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_si_id): ++ continue ++ si_info = self.svc_instance_read(proj_si_id) ++ if not self._filters_is_present(filters, 'name', ++ si_info['q_api_data']['name']): ++ continue ++ ret_list.append(si_info) ++ ++ return ret_list +diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py +new file mode 100644 +index 0000000..72bebec +--- /dev/null ++++ neutron/tests/unit/juniper/__init__.py +@@ -0,0 +1,14 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. +diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py +new file mode 100644 +index 0000000..decf79e +--- /dev/null ++++ neutron/tests/unit/juniper/test_contrail_plugin.py +@@ -0,0 +1,998 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. ++ ++import datetime ++import mock ++import neutron.db.api ++from neutron.manager import NeutronManager ++from neutron.tests.unit import test_db_plugin as test_plugin ++import sys ++import uuid ++ ++subnet_obj = {u'subnet': ++ {'name': '', 'enable_dhcp': True, ++ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', ++ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', ++ 'dns_nameservers': '', ++ u'contrail:ipam_fq_name': ++ [u'default-domain', u'admin', u'default-network-ipam'], ++ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, ++ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} ++ ++vn_list = [] ++GlobalProjects = [] ++ ++ ++class MockVncApi(mock.MagicMock): ++ def __init__(self, *args, **kwargs): ++ pass ++ ++ def kv_retrieve(self, *args, **kwargs): ++ return [] ++ ++ def kv_store(self, *args, **kwargs): ++ return ++ ++ def kv_delete(self, *args, **kwargs): ++ return ++ ++ def project_read(self, *args, **kwargs): ++ #return MockProject('dummy-proj') ++ return GlobalProjects[0] ++ ++ def virtual_network_create(self, net_obj): ++ net_id = unicode(str(uuid.uuid4())) ++ net_obj.set_uuid(net_id) ++ vn_list.append(net_obj) ++ return net_id ++ ++ def virtual_network_read(self, id, *args, **kwargs): ++ if len(vn_list): ++ for index in range(len(vn_list)): ++ if ((vn_list[index].get_uuid()) == id): ++ return vn_list[index] ++ ++ #return a mock object if it is not created so far ++ return MockVirtualNetwork('dummy-net', MockProject()) ++ ++ def virtual_network_delete(self, *args, **kwargs): ++ return ++ ++ def virtual_network_update(self, *args, **kwargs): ++ return ++ ++ def virtual_networks_list(self, *args, **kwargs): ++ return vn_list ++ ++ ++class MockVncObject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ if not parent_obj: ++ self._fq_name = [name] ++ else: ++ self._fq_name = parent_obj.get_fq_name() + [name] ++ ++ self._ipam_refs = [{'to': [u'default-domain', u'admin', ++ u'default-network-ipam']}] ++ self.uuid = None ++ self.name = name ++ self.network_ipam_refs = [] ++ ++ def set_uuid(self, uuid): ++ self.uuid = uuid ++ ++ def get_uuid(self): ++ return self.uuid ++ ++ def get_fq_name(self): ++ return self._fq_name ++ ++ def get_network_ipam_refs(self): ++ return getattr(self, 'network_ipam_refs', None) ++ ++ def add_network_ipam(self, ref_obj, ref_data): ++ refs = getattr(self, 'network_ipam_refs', []) ++ if not refs: ++ self.network_ipam_refs = [] ++ ++ # if ref already exists, update any attr with it ++ for ref in refs: ++ if ref['to'] == ref_obj.get_fq_name(): ++ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref['uuid'] = ref_obj.uuid ++ return ++ ++ # ref didn't exist before ++ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref_info['uuid'] = ref_obj.uuid ++ ++ self.network_ipam_refs.append(ref_info) ++ ++ ++class MockVirtualNetwork(MockVncObject): ++ pass ++ ++ ++class MockSubnetType(mock.MagicMock): ++ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ip_prefix = ip_prefix ++ self.ip_prefix_len = ip_prefix_len ++ ++ def get_ip_prefix(self): ++ return self.ip_prefix ++ ++ def set_ip_prefix(self, ip_prefix): ++ self.ip_prefix = ip_prefix ++ ++ def get_ip_prefix_len(self): ++ return self.ip_prefix_len ++ ++ def set_ip_prefix_len(self, ip_prefix_len): ++ self.ip_prefix_len = ip_prefix_len ++ ++ ++class MockIpamSubnetType(mock.MagicMock): ++ def __init__(self, name=None, subnet=None, default_gateway=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.subnet = subnet ++ self.default_gateway = default_gateway ++ ++ def get_subnet(self): ++ return self.subnet ++ ++ def set_subnet(self, subnet): ++ self.subnet = subnet ++ ++ def get_default_gateway(self): ++ return self.default_gateway ++ ++ def set_default_gateway(self, default_gateway): ++ self.default_gateway = default_gateway ++ ++ def validate_IpAddressType(self, value): ++ pass ++ ++ ++class MockVnSubnetsType(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ipam_subnets = [] ++ if ipam_subnets: ++ #self.ipam_subnets = copy.deepcopy(ipam_subnets) ++ self.ipam_subnets = ipam_subnets ++ ++ def get_ipam_subnets(self): ++ return self.ipam_subnets ++ ++ def set_ipam_subnets(self, ipam_subnets): ++ self.ipam_subnets = ipam_subnets ++ ++ def add_ipam_subnets(self, value): ++ self.ipam_subnets.append(value) ++ ++ def insert_ipam_subnets(self, index, value): ++ self.ipam_subnets[index] = value ++ ++ def delete_ipam_subnets(self, value): ++ self.ipam_subnets.remove(value) ++ ++ ++class MockNetworkIpam(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ++ network_ipam_mgmt=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'default-network-ipam' ++ self.name = name ++ self.uuid = None ++ if parent_obj: ++ self.parent_type = parent_obj._type ++ # copy parent's fq_name ++ self.fq_name = list(parent_obj.fq_name) ++ self.fq_name.append(name) ++ if not parent_obj.get_network_ipams(): ++ parent_obj.network_ipams = [] ++ parent_obj.network_ipams.append(self) ++ else: # No parent obj specified ++ self.parent_type = 'project' ++ self.fq_name = [u'default-domain', u'default-project'] ++ self.fq_name.append(name) ++ ++ # property fields ++ if network_ipam_mgmt: ++ self.network_ipam_mgmt = network_ipam_mgmt ++ if id_perms: ++ self.id_perms = id_perms ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++class MockProject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'project' ++ self.uuid = None ++ self.parent_type = 'domain' ++ self.fq_name = [u'default-domain'] ++ self.fq_name.append(name) ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++def GlobalProjectApi(project_name): ++ if not GlobalProjects: ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ return GlobalProjects[0] ++ ++ ++# Mock definations for different pkgs, modules and VncApi ++mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) ++mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') ++mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork ++mock_vnc_api_mod.SubnetType = MockSubnetType ++mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType ++mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType ++mock_vnc_api_mod.NetworkIpam = MockNetworkIpam ++mock_vnc_api_mod.Project = GlobalProjectApi ++ ++mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') ++mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') ++mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ ++ mock_vnc_api_pkg ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ ++ mock_vnc_api_mod ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ ++ mock_vnc_common_mod ++sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' ++ 'exceptions')] = \ ++ mock_vnc_exception_mod ++ ++CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" ++ ++ ++class RouterInstance(object): ++ def __init__(self): ++ self._name = 'rounter_instance' ++ ++ ++class Context(object): ++ def __init__(self, tenant_id=''): ++ self.read_only = False ++ self.show_deleted = False ++ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] ++ self._read_deleted = 'no' ++ self.timestamp = datetime.datetime.now() ++ self.auth_token = None ++ self._session = None ++ self._is_admin = True ++ self.admin = uuid.uuid4().hex.decode() ++ self.request_id = 'req-' + str(uuid.uuid4()) ++ self.tenant = tenant_id ++ ++ ++class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): ++ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) ++ ++ def setUp(self): ++ ++ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod ++ ++ mock_vnc_api_mod.common = mock_vnc_common_mod ++ mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++ ++ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++ ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ neutron.db.api._ENGINE = mock.MagicMock() ++ ++ def teardown(self): ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ ++ ++class TestContrailNetworks(test_plugin.TestNetworksV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ if 'contrail:fq_name' not in net.keys(): ++ assert False ++ else: ++ assert True ++ ++ def test_delete_network(self): ++ # First create the network and request to delete the same ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ ++ plugin_obj.delete_network(context_obj, net_id) ++ mock_vnc_api_cls.virtual_network_delete.assert_called_once() ++ ++ def test_update_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ # change one of the attribute and update the network ++ network['admin_state_up'] = 'False' ++ new_dict = plugin_obj.update_network(context_obj, net_id, ++ networks_req) ++ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): ++ assert False ++ else: ++ assert True ++ ++ # Not supported test cases in the this TestClass ++ def test_create_networks_bulk_emulated(self): ++ pass ++ ++ def test_create_networks_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_public_network(self): ++ pass ++ ++ def test_create_networks_bulk_wrong_input(self): ++ pass ++ ++ def test_update_shared_network_noadmin_returns_403(self): ++ pass ++ ++ def test_update_network_set_shared(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_single_tenant(self): ++ pass ++ ++ def test_update_network_set_not_shared_other_tenant_returns_409(self): ++ pass ++ ++ def test_update_network_with_subnet_set_shared(self): ++ pass ++ ++ def test_show_network(self): ++ pass ++ ++ def test_show_network_with_subnet(self): ++ pass ++ ++ def test_list_networks(self): ++ pass ++ ++ def test_list_shared_networks_with_non_admin_user(self): ++ pass ++ ++ def test_list_networks_with_parameters(self): ++ pass ++ ++ def test_list_networks_with_fields(self): ++ pass ++ ++ def test_list_networks_with_parameters_invalid_values(self): ++ pass ++ ++ def test_list_networks_with_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_without_pk_in_fields_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_with_sort_emulated(self): ++ pass ++ ++ def test_list_networks_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_invalid_admin_status(self): ++ pass ++ ++ ++class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: ++ assert False ++ else: ++ assert True ++ ++ def test_delete_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ network = {} ++ router_inst = RouterInstance() ++ network['router:external'] = router_inst ++ network[u'name'] = u'network1' ++ network['admin_state_up'] = 'True' ++ network['tenant_id'] = uuid.uuid4().hex.decode() ++ network['vpc:route_table'] = '' ++ network['shared'] = False ++ network['port_security_enabled'] = True ++ network[u'contrail:policys'] = [] ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ subnet_id = subnet_dict['id'] ++ plugin_obj.delete_subnet(context_obj, subnet_id) ++ ++ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_delete_network(self): ++ pass ++ ++ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet_adding_additional_host_routes_and_dns(self): ++ pass ++ ++ def test_update_subnet_no_gateway(self): ++ pass ++ ++ def test_create_subnet_bad_cidr(self): ++ pass ++ ++ def test_create_subnet_gw_of_network_force_on_returns_400(self): ++ pass ++ ++ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_create_two_subnets(self): ++ pass ++ ++ def test_create_two_subnets_same_cidr_returns_400(self): ++ pass ++ ++ def test_create_subnet_bad_V4_cidr(self): ++ pass ++ ++ def test_create_subnet_bad_V6_cidr(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): ++ pass ++ ++ def test_create_subnets_bulk_native(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_subnets_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_network(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_other(self): ++ pass ++ ++ def test_create_subnet_bad_tenant(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version_null(self): ++ pass ++ ++ def test_create_subnet_bad_uuid(self): ++ pass ++ ++ def test_create_subnet_bad_boolean(self): ++ pass ++ ++ def test_create_subnet_bad_pools(self): ++ pass ++ ++ def test_create_subnet_bad_nameserver(self): ++ pass ++ ++ def test_create_subnet_bad_hostroutes(self): ++ pass ++ ++ def test_create_subnet_defaults(self): ++ pass ++ ++ def test_create_subnet_gw_values(self): ++ pass ++ ++ def test_create_force_subnet_gw_values(self): ++ pass ++ ++ def test_create_subnet_with_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_fully_allocated(self): ++ pass ++ ++ def test_subnet_with_allocation_range(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_v6_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_large_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_multiple_allocation_pools(self): ++ pass ++ ++ def test_create_subnet_with_dhcp_disabled(self): ++ pass ++ ++ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( ++ self): ++ pass ++ ++ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_create_subnet_overlapping_allocation_pools_returns_409(self): ++ pass ++ ++ def test_create_subnet_invalid_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_shared_returns_400(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_cidrv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_cidrv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_dns_v4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): ++ pass ++ ++ def test_create_subnet_gw_bcast_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet(self): ++ pass ++ ++ def test_update_subnet_shared_returns_400(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_dns_v6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): ++ pass ++ ++ def test_show_subnet(self): ++ pass ++ ++ def test_list_subnets(self): ++ pass ++ ++ def test_list_subnets_shared(self): ++ pass ++ ++ def test_list_subnets_with_parameter(self): ++ pass ++ ++ def test_invalid_ip_version(self): ++ pass ++ ++ def test_invalid_subnet(self): ++ pass ++ ++ def test_invalid_ip_address(self): ++ pass ++ ++ def test_invalid_uuid(self): ++ pass ++ ++ def test_create_subnet_with_one_dns(self): ++ pass ++ ++ def test_create_subnet_with_two_dns(self): ++ pass ++ ++ def test_create_subnet_with_too_many_dns(self): ++ pass ++ ++ def test_create_subnet_with_one_host_route(self): ++ pass ++ ++ def test_create_subnet_with_two_host_routes(self): ++ pass ++ ++ def test_create_subnet_with_too_many_routes(self): ++ pass ++ ++ def test_update_subnet_dns(self): ++ pass ++ ++ def test_update_subnet_dns_to_None(self): ++ pass ++ ++ def test_update_subnet_dns_with_too_many_entries(self): ++ pass ++ ++ def test_update_subnet_route(self): ++ pass ++ ++ def test_update_subnet_route_to_None(self): ++ pass ++ ++ def test_update_subnet_route_with_too_many_entries(self): ++ pass ++ ++ def test_delete_subnet_with_dns(self): ++ pass ++ ++ def test_delete_subnet_with_route(self): ++ pass ++ ++ def test_delete_subnet_with_dns_and_route(self): ++ pass ++ ++ def test_list_subnets_with_pagination_emulated(self): ++ pass ++ ++ def test_list_subnets_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_subnets_with_sort_emulated(self): ++ pass ++ ++ def test_validate_subnet_host_routes_exhausted(self): ++ pass ++ ++ def test_validate_subnet_dns_nameservers_exhausted(self): ++ pass ++ ++ ++class TestContrailPortsV2(test_plugin.TestPortsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_port_json(self): ++ pass ++ ++ def test_create_port_bad_tenant(self): ++ pass ++ ++ def test_create_port_public_network(self): ++ pass ++ ++ def test_create_port_public_network_with_ip(self): ++ pass ++ ++ def test_create_ports_bulk_native(self): ++ pass ++ ++ def test_create_ports_bulk_emulated(self): ++ pass ++ ++ def test_create_ports_bulk_wrong_input(self): ++ pass ++ ++ def test_create_ports_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_ports_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_list_ports(self): ++ pass ++ ++ def test_list_ports_filtered_by_fixed_ip(self): ++ pass ++ ++ def test_list_ports_public_network(self): ++ pass ++ ++ def test_show_port(self): ++ pass ++ ++ def test_delete_port(self): ++ pass ++ ++ def test_delete_port_public_network(self): ++ pass ++ ++ def test_update_port(self): ++ pass ++ ++ def test_update_device_id_null(self): ++ pass ++ ++ def test_delete_network_if_port_exists(self): ++ pass ++ ++ def test_delete_network_port_exists_owned_by_network(self): ++ pass ++ ++ def test_update_port_delete_ip(self): ++ pass ++ ++ def test_no_more_port_exception(self): ++ pass ++ ++ def test_update_port_update_ip(self): ++ pass ++ ++ def test_update_port_update_ip_address_only(self): ++ pass ++ ++ def test_update_port_update_ips(self): ++ pass ++ ++ def test_update_port_add_additional_ip(self): ++ pass ++ ++ def test_requested_duplicate_mac(self): ++ pass ++ ++ def test_mac_generation(self): ++ pass ++ ++ def test_mac_generation_4octet(self): ++ pass ++ ++ def test_bad_mac_format(self): ++ pass ++ ++ def test_mac_exhaustion(self): ++ pass ++ ++ def test_requested_duplicate_ip(self): ++ pass ++ ++ def test_requested_subnet_delete(self): ++ pass ++ ++ def test_requested_subnet_id(self): ++ pass ++ ++ def test_requested_subnet_id_not_on_network(self): ++ pass ++ ++ def test_overlapping_subnets(self): ++ pass ++ ++ def test_requested_subnet_id_v4_and_v6(self): ++ pass ++ ++ def test_range_allocation(self): ++ pass ++ ++ def test_requested_invalid_fixed_ips(self): ++ pass ++ ++ def test_invalid_ip(self): ++ pass ++ ++ def test_requested_split(self): ++ pass ++ ++ def test_duplicate_ips(self): ++ pass ++ ++ def test_fixed_ip_invalid_subnet_id(self): ++ pass ++ ++ def test_fixed_ip_invalid_ip(self): ++ pass ++ ++ def test_requested_ips_only(self): ++ pass ++ ++ def test_recycling(self): ++ pass ++ ++ def test_invalid_admin_state(self): ++ pass ++ ++ def test_invalid_mac_address(self): ++ pass ++ ++ def test_default_allocation_expiration(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration(self): ++ pass ++ ++ def test_port_delete_holds_ip(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration_invalid_address(self): ++ pass ++ ++ def test_hold_ip_address(self): ++ pass ++ ++ def test_recycle_held_ip_address(self): ++ pass ++ ++ def test_recycle_expired_previously_run_within_context(self): ++ pass ++ ++ def test_update_port_not_admin(self): ++ pass ++ ++ def test_list_ports_with_pagination_emulated(self): ++ pass ++ ++ def test_list_ports_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_ports_with_sort_emulated(self): ++ pass ++ ++ def test_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_update_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_recycle_ip_address_without_allocation_pool(self): ++ pass +diff --git setup.cfg setup.cfg +index af52a4d..27ef0ce 100644 +--- setup.cfg ++++ setup.cfg +@@ -61,6 +61,7 @@ data_files = + etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini + etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini + etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini ++ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini + scripts = + bin/quantum-rootwrap + bin/neutron-rootwrap diff --git a/setup_contrail.py b/setup_contrail.py old mode 100644 new mode 100755 index 4f84616be5..2d1a71d9fc --- a/setup_contrail.py +++ b/setup_contrail.py @@ -23,10 +23,10 @@ import tempfile # Get Environment Stuff -password = os.environ['ADMIN_PASSWORD'] or 'contrail123' -admin_username = os.environ['CONTRAIL_ADMIN_USERNAME'] or 'admin' -admin_token = os.environ['SERVICE_TOKEN'] or 'contrail123' -admin_tenant = os.environ['CONTRAIL_ADMIN_TENANT'] or 'admin' +password = os.environ.get('ADMIN_PASSWORD', 'contrail123') +admin_username = os.environ.get('CONTRAIL_ADMIN_USERNAME', 'admin') +admin_token = os.environ.get('SERVICE_TOKEN', 'contrail123') +admin_tenant = os.environ.get('CONTRAIL_ADMIN_TENANT', 'admin') # TODO following keystone credentials hardcoded ks_admin_user = admin_username diff --git a/stack.sh b/stack.sh index 7f2d365b93..adb90651e0 100755 --- a/stack.sh +++ b/stack.sh @@ -436,6 +436,10 @@ if is_service_enabled s-proxy; then read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH." fi +if [ $ENABLE_CONTRAIL ]; then + read_password PHYSICAL_INTERFACE "ENTER PHYSICAL INTERFACE TO USE FOR FOR VROUTER" +fi + # Configure logging # ----------------- @@ -680,7 +684,7 @@ if is_service_enabled cinder; then fi function test_install_neutron_patch() { - patch_name="neutron_v2.patch" + patch_name="neutron_v3.patch" contrail_cwd=$(pwd) cd $DEST/neutron patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null @@ -966,7 +970,7 @@ if [ $ENABLE_CONTRAIL ]; then # basic dependencies if ! which repo > /dev/null 2>&1 ; then - curl -O https://dl-ssl.google.com/dl/googlesource/git-repo/repo + curl -o repo -O https://git-repo.googlecode.com/files/repo-1.19 chmod 0755 repo sudo mv repo /usr/bin fi @@ -999,8 +1003,8 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - #python third_party/fetch_packages.py - #scons + python third_party/fetch_packages.py + scons cd ${contrail_cwd} # get cassandra From bb55f27c808adf9a3b71bbf6cc1bde4d2a7f8bdd Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Sun, 20 Oct 2013 15:14:13 +0530 Subject: [PATCH 021/179] Simple gateway support. Example localrc entries CONTRAIL_VGW_INTERFACE=vgw CONTRAIL_VGW_PUBLIC_SUBNET=2.2.2.0/24 CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public --- contrail_config_templates.py | 27 +++++++++++++++++++++ setup_contrail.py | 46 +++++++++++++++++++++++++++--------- stack.sh | 16 +++++++++++++ unstack.sh | 6 +++++ 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index 81f3068997..cab5064cd2 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -257,6 +257,33 @@ """) +agent_vgw_conf_template = string.Template(""" + + + + + + vhost0 + $__contrail_box_ip__ + $__contrail_gateway__ + + + $__contrail_intf__ + + + $__contrail_control_ip__ + + + $__contrail_control_ip__ + + + $__contrail_vgw_interface__ + $__contrail_vgw_public_subnet__ + + + +""") + ifconfig_vhost0_template = string.Template(""" #Contrail vhost0 DEVICE=vhost0 diff --git a/setup_contrail.py b/setup_contrail.py index 2d1a71d9fc..8ea074f5b7 100755 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -50,7 +50,7 @@ def __init__(self, args_str = None): def _parse_args(self, args_str): ''' - Eg. python setup.py --cfgm_ip 127.0.0.1 + Eg. python setup.py --cfgm_ip 127.0.0.1 --vgw_interface vgw --vgw_public_subnet 1.1.1.0/24 --vgw_public_network default-domain:default-project:public:public ''' # Source any specified config/ini file @@ -159,6 +159,11 @@ def _parse_args(self, args_str): parser.add_argument("--redis_role", help = "Redis Role of Node") parser.add_argument("--self_collector_ip", help = "Self IP of Collector Node") + #Simple gateway interface + parser.add_argument("--vgw_interface", help="Simple Virtual Gateway interface") + parser.add_argument("--vgw_public_subnet", help="Simple Virtual Gateway public sub-net") + parser.add_argument("--vgw_public_network", help="FQDN for public network") + self._args = parser.parse_args(remaining_argv) if self._args.physical_interface: @@ -672,6 +677,9 @@ def fixup_config_files(self): non_mgmt_ip = self._args.non_mgmt_ip non_mgmt_gw = self._args.non_mgmt_gw vhost_ip = compute_ip + vgw_interface = self._args.vgw_interface + vgw_public_subnet = self._args.vgw_public_subnet + vgw_public_network = self._args.vgw_public_network multi_net= False if non_mgmt_ip : if non_mgmt_ip != compute_ip: @@ -718,16 +726,32 @@ def fixup_config_files(self): template_vals, "agent_param") self.run_shell("sudo mv agent_param /etc/contrail/agent_param") - template_vals = { - '__contrail_box_ip__' : cidr, - '__contrail_gateway__' : gateway, - '__contrail_intf__' : dev, - '__contrail_disc_ip__' : discovery_ip, - '__contrail_instances__' : ncontrols, - '__contrail_control_ip__' : cfgm_ip, - } - self._template_substitute_write(agent_conf_template, - template_vals, "agent.conf") + if vgw_interface is None or vgw_public_subnet is None or vgw_public_network is None: + template_vals = { + '__contrail_box_ip__' : cidr, + '__contrail_gateway__' : gateway, + '__contrail_intf__' : dev, + '__contrail_disc_ip__' : discovery_ip, + '__contrail_instances__' : ncontrols, + '__contrail_control_ip__' : cfgm_ip, + } + self._template_substitute_write(agent_conf_template, + template_vals, "agent.conf") + else: + template_vals = { + '__contrail_box_ip__' : cidr, + '__contrail_gateway__' : gateway, + '__contrail_intf__' : dev, + '__contrail_disc_ip__' : discovery_ip, + '__contrail_instances__' : ncontrols, + '__contrail_control_ip__' : cfgm_ip, + '__contrail_vgw_interface__' : vgw_interface, + '__contrail_vgw_public_subnet__' : vgw_public_subnet, + '__contrail_vgw_public_network__' : vgw_public_network, + } + self._template_substitute_write(agent_vgw_conf_template, + template_vals, "agent.conf") + self.run_shell("sudo mv agent.conf /etc/contrail/agent.conf") ## make ifcfg-vhost0 diff --git a/stack.sh b/stack.sh index adb90651e0..bd0d197e56 100755 --- a/stack.sh +++ b/stack.sh @@ -981,11 +981,13 @@ if [ $ENABLE_CONTRAIL ]; then apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev apt_get install python-dev autoconf automake build-essential apt_get install libevent-dev libxml2-dev libxslt-dev + apt_get install tunctl else sudo yum -y install patch scons flex bison make vim sudo yum -y install expat-devel gettext-devel curl-devel sudo yum -y install gcc-c++ python-devel autoconf automake sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + sudo yum -y install tunctl fi # api server requirements @@ -1067,6 +1069,13 @@ EOF python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE # --cfgm_ip $SERVICE_HOST ) + # process gateway configuration if present + contrail_gw_interface="" + if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then + contrail_gw_interface="--vgw_interface $CONTRAIL_VGW_INTERFACE --vgw_public_subnet $CONTRAIL_VGW_PUBLIC_SUBNET --vgw_public_network $CONTRAIL_VGW_PUBLIC_NETWORK" + fi + python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST $contrail_gw_interface + # install contrail modules echo "Installing contrail modules" sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) @@ -1556,6 +1565,13 @@ if [ $ENABLE_CONTRAIL ]; then test_insert_vrouter # agent + if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then + sudo sysctl -w net.ipv4.ip_forward=1 + sudo /opt/stack/contrail/build/debug/vrouter/utils/vif --create vgw --mac 00:01:00:5e:00:00 + #sudo tunctl -p -t vgw + sudo ifconfig vgw up + sudo route add -net $CONTRAIL_VGW_PUBLIC_SUBNET dev vgw + fi source /etc/contrail/agent_param sudo cat > $TOP_DIR/vnsw.hlpr < Date: Sun, 20 Oct 2013 15:21:44 +0530 Subject: [PATCH 022/179] Remove unused code --- stack.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/stack.sh b/stack.sh index bd0d197e56..912c85c161 100755 --- a/stack.sh +++ b/stack.sh @@ -1568,7 +1568,6 @@ if [ $ENABLE_CONTRAIL ]; then if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then sudo sysctl -w net.ipv4.ip_forward=1 sudo /opt/stack/contrail/build/debug/vrouter/utils/vif --create vgw --mac 00:01:00:5e:00:00 - #sudo tunctl -p -t vgw sudo ifconfig vgw up sudo route add -net $CONTRAIL_VGW_PUBLIC_SUBNET dev vgw fi From 35a8d19dde3e32d4526d62efdfd5b3c39cab16f3 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 21 Oct 2013 01:11:55 +0000 Subject: [PATCH 023/179] devstack+contrail works on ubuntu updated url for latest version of repo install distribute added reset_config=True to api_server.conf don't start cassandra at boot, just by stack.sh handle different python package install paths with pywhere make a fake contrail-version when contrail isn't installed by yum --- contrail_config_templates.py | 3 ++- stack.sh | 52 ++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index cab5064cd2..2d8534488e 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -2,6 +2,7 @@ api_server_conf_template = string.Template(""" [DEFAULTS] +reset_config=True ifmap_server_ip=$__contrail_ifmap_server_ip__ ifmap_server_port=$__contrail_ifmap_server_port__ ifmap_username=$__contrail_ifmap_username__ @@ -229,7 +230,7 @@ pname=vnswad LIBDIR=/usr/lib64 VHOST_CFG=/etc/sysconfig/network-scripts/ifcfg-vhost0 -VROUTER_LOGFILE=--log-file=/var/log/contrail/vrouter.log +VROUTER_LOGFILE=--log-file=/var/log/vrouter.log COLLECTOR=$__contrail_collector__ $__contrail_dev__ """) diff --git a/stack.sh b/stack.sh index 912c85c161..bab43dbcb3 100755 --- a/stack.sh +++ b/stack.sh @@ -964,13 +964,12 @@ fi # Contrail # -------- if [ $ENABLE_CONTRAIL ]; then - PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` sudo mkdir -p /var/log/contrail sudo chmod 777 /var/log/contrail # basic dependencies if ! which repo > /dev/null 2>&1 ; then - curl -o repo -O https://git-repo.googlecode.com/files/repo-1.19 + wget http://commondatastorage.googleapis.com/git-repo-downloads/repo chmod 0755 repo sudo mv repo /usr/bin fi @@ -992,6 +991,7 @@ if [ $ENABLE_CONTRAIL ]; then # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + sudo easy_install -U distribute sudo pip install gevent geventhttpclient==1.0a thrift sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient @@ -1022,6 +1022,8 @@ if [ $ENABLE_CONTRAIL ]; then apt_get update apt_get install cassandra + # don't start cassandra at boot + sudo update-rc.d -f cassandra remove else cat << EOF > datastax.repo [datastax] @@ -1055,7 +1057,7 @@ EOF fi # ncclient - if [ ! -d $PYLIBPATH/ncclient ]; then + if ! python -c 'import ncclient' >/dev/null 2>&1; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz @@ -1529,6 +1531,11 @@ function test_insert_vrouter () fi } +function pywhere() { + module=$1 + python -c "import $module; import os; print os.path.dirname($module.__file__)" +} + if [ $ENABLE_CONTRAIL ]; then # save screen settings SAVED_SCREEN_NAME=$SCREEN_NAME @@ -1538,25 +1545,25 @@ if [ $ENABLE_CONTRAIL ]; then # Set a reasonable status bar screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" - PYLIBPATH=`/usr/bin/python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"` - # launch ... screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 - screen_it disco "python $PYLIBPATH/discovery/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" + + + screen_it disco "python $(pywhere discovery)/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" sleep 2 + # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - vnc_cfg_api_server_path=$(python -c 'import vnc_cfg_api_server; from os.path import dirname; print dirname(vnc_cfg_api_server.__file__)') - screen_it apiSrv "python ${vnc_cfg_api_server_path}/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" exit 1 fi sleep 2 - screen_it schema "python $PYLIBPATH/schema_transformer/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" + screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" source /etc/contrail/control_param screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" @@ -1572,14 +1579,31 @@ if [ $ENABLE_CONTRAIL ]; then sudo route add -net $CONTRAIL_VGW_PUBLIC_SUBNET dev vgw fi source /etc/contrail/agent_param - sudo cat > $TOP_DIR/vnsw.hlpr </dev/null 2>&1; then + cat >$TOP_DIR/bin/contrail-version < $TOP_DIR/bin/vnsw.hlpr < Date: Thu, 24 Oct 2013 16:23:51 -0700 Subject: [PATCH 024/179] Add support for redis --- nova_v2.patch | 3238 +++++++++++++++++++++++++++++++++++++++++++++++++ stack.sh | 12 +- stackrc | 2 +- 3 files changed, 3250 insertions(+), 2 deletions(-) create mode 100644 nova_v2.patch diff --git a/nova_v2.patch b/nova_v2.patch new file mode 100644 index 0000000000..282d29f3a3 --- /dev/null +++ b/nova_v2.patch @@ -0,0 +1,3238 @@ +diff --git nova/network/model.py nova/network/model.py +index e11bfeb..a004cb4 100644 +--- nova/network/model.py ++++ nova/network/model.py +@@ -38,6 +38,7 @@ VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' + VIF_TYPE_MIDONET = 'midonet' ++VIF_TYPE_CONTRAIL = 'contrail' + VIF_TYPE_OTHER = 'other' + + # Constant for max length of network interface names +diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py +index 3e4004a..340b2fa 100644 +--- nova/virt/libvirt/vif.py ++++ nova/virt/libvirt/vif.py +@@ -312,6 +312,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + + return conf + ++ def get_config_contrail(self, instance, vif, image_meta, ++ inst_type): ++ conf = super(LibvirtGenericVIFDriver, ++ self).get_config(instance, vif, ++ image_meta, inst_type) ++ ++ dev = self.get_vif_devname(vif) ++ designer.set_vif_host_backend_ethernet_config(conf, dev) ++ ++ return conf ++ + def get_config_mlnx_direct(self, instance, vif, image_meta, + inst_type): + conf = super(LibvirtGenericVIFDriver, +@@ -375,6 +386,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + vif, + image_meta, + inst_type) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ return self.get_config_contrail(instance, ++ vif, ++ image_meta, ++ inst_type) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -567,6 +583,28 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except exception.ProcessExecutionError: + LOG.exception(_("Failed while plugging vif"), instance=instance) + ++ def plug_contrail(self, instance, vif): ++ """Plug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).plug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ linux_net.create_tap_dev(dev) ++ iface_id = vif['id'] ++ from nova.virt import netutils ++ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) ++ import sys ++ sys.path.append('/opt/stack/nova/plugins/contrail') ++ from config_parser import ContrailVifUpdate ++ ContrailVifUpdate(vif['id'], ++ dev, vif['network']['subnets'][0]['ips'][0]['address'], ++ instance['uuid'], vif['network']['id'], ++ vif['address'], ++ instance['display_name'], ++ instance['hostname'], ++ instance['host'], ++ prefix_len) ++ + def plug(self, instance, vif): + vif_type = vif['type'] + +@@ -574,7 +612,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + 'vif=%(vif)s'), + {'vif_type': vif_type, 'instance': instance, + 'vif': vif}) +- + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " +@@ -595,6 +632,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.plug_mlnx_direct(instance, vif) + elif vif_type == network_model.VIF_TYPE_MIDONET: + self.plug_midonet(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ self.plug_contrail(instance, vif) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -746,6 +785,18 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except exception.ProcessExecutionError: + LOG.exception(_("Failed while unplugging vif"), instance=instance) + ++ def unplug_contrail(self, instance, vif): ++ """Unplug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).unplug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ import sys ++ sys.path.append('/opt/stack/nova/plugins/contrail') ++ from config_parser import ContrailVifDelete ++ ContrailVifDelete(vif['id']) ++ linux_net.delete_net_dev(dev) ++ + def unplug(self, instance, vif): + vif_type = vif['type'] + +@@ -770,6 +821,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.unplug_ivs(instance, vif) + elif vif_type == network_model.VIF_TYPE_IOVISOR: + self.unplug_iovisor(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_CONTRAIL: ++ self.unplug_contrail(instance, vif) + elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: + self.unplug_mlnx_direct(instance, vif) + elif vif_type == network_model.VIF_TYPE_MIDONET: +diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py +new file mode 100644 +index 0000000..043b77c +--- /dev/null ++++ plugins/contrail/config_parser.py +@@ -0,0 +1,116 @@ ++import os ++import sys ++import cgitb ++import argparse ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' ++ ++class ContrailVifDelete(object): ++ def __init__(self, port_id): ++ if os.path.exists(VIF_DIR+port_id): ++ os.remove(VIF_DIR+port_id) ++ #end __init__ ++# end ContrailVifDelete ++ ++class ContrailVifUpdate(object): ++ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, ++ hostname, host, prefix_len): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ self.__update_vif(port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, display_name, ++ hostname, host, prefix_len) ++ ++ # end __init__ ++ ++ def __update_vif(self, port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, ++ display_name, ++ hostname, ++ host, prefix_len): ++ if (port_id and tap_name and ++ ip_address and instance_id and ++ vn_id and mac_address and ++ host and prefix_len): ++ import ConfigParser ++ config = ConfigParser.RawConfigParser() ++ config.add_section('Vif') ++ config.set('Vif', 'port_id', port_id) ++ config.set('Vif', 'tap_name', tap_name) ++ config.set('Vif', 'ip_address', ip_address) ++ config.set('Vif', 'instance_id', instance_id) ++ config.set('Vif', 'vn_id', vn_id) ++ config.set('Vif', 'mac_address', mac_address) ++ config.set('Vif', 'display_name', display_name) ++ config.set('Vif', 'hostname', hostname) ++ config.set('Vif', 'host', host) ++ config.set('Vif', 'prefix_len', prefix_len) ++ with open(VIF_DIR + port_id, 'wb') as configfile: ++ config.write(configfile) ++ ++ # end __update_vif ++# end ContrailVifUpdate ++ ++def update_vif_file(args): ++ #import pdb; pdb.set_trace() ++ if (args.port_id and args.tap_name and ++ args.ip_address and args.instance_id and ++ args.vn_id and args.mac_address and ++ args.host and args.prefix_len): ++ ContrailVifUpdate(args.port_id, args.tap_name, ++ args.ip_address, args.instance_id, ++ args.vn_id, args.mac_address, args.display_name, ++ args.hostname, args.host, args.prefix_len) ++ ++# end update_vif_file ++ ++def parse_args(args_str): ++ ''' ++ ''' ++ # Source any specified config/ini file ++ # Turn off help, so we all options in response to -h ++ conf_parser = argparse.ArgumentParser(add_help=False) ++ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) ++ parser = argparse.ArgumentParser( ++ # Inherit options from config_parser ++ parents=[conf_parser], ++ # print script description with -h/--help ++ description=__doc__, ++ # Don't mess with format of description ++ formatter_class=argparse.RawDescriptionHelpFormatter, ++ ) ++ #defaults.update(secopts) ++ #defaults.update(ksopts) ++ #parser.set_defaults(**defaults) ++ ++ parser.add_argument("--port_id", help = "port id") ++ parser.add_argument("--tap_name", help = "tap_name") ++ parser.add_argument("--ip_address", help = "ip_address") ++ parser.add_argument("--instance_id", help = "instance_id") ++ parser.add_argument("--vn_id", help = "vn_id") ++ parser.add_argument("--mac_address", help = "mac_address") ++ parser.add_argument("--display_name", help = "display_name") ++ parser.add_argument("--hostname", help = "hostname") ++ parser.add_argument("--host", help = "host") ++ parser.add_argument("--prefix_len", help = "prefix_len") ++ args = parser.parse_args(remaining_argv) ++ update_vif_file(args) ++# end parse_args ++ ++def main(args_str=None): ++ #import pdb; pdb.set_trace() ++ if not args_str: ++ args_str = ' '.join(sys.argv[1:]) ++ args = parse_args(args_str) ++# end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py +new file mode 100644 +index 0000000..7d004a0 +--- /dev/null ++++ plugins/contrail/contrail_vif.py +@@ -0,0 +1,298 @@ ++# ++# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. ++# ++ ++""" ++contril vif plug, communicate with contrail agent ++""" ++import os ++import pyinotify ++import sys ++import socket ++import cgitb ++from nova import utils ++from nova import exception ++from nova.openstack.common import log as logging ++from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent ++import gevent ++from gevent import monkey; monkey.patch_time() ++ ++LOG = logging.getLogger(__name__) ++ ++''' ++struct Port { ++ 1:required tuuid port_id, ++ 2:required tuuid instance_id, ++ 3:required string tap_name, ++ 4:required string ip_address, ++ 5:required tuuid vn_id, ++ 6:required string mac_address, ++ 7:optional string display_name, ++ 8:optional string hostname, ++ 9:optional string host; ++ 10: optional byte prefix_len; ++} ++''' ++ ++class ContrailVifPlug(object): ++ "" ++ "" ++ def __init__(self): ++ self._agent_alive = False ++ self._agent_connected = False ++ self._port_dict = {} ++ self._protocol = None ++ self._notifier = None ++ #end __init__ ++ ++ def _agent_connect(self, protocol): ++ # Agent connect for first time ++ if protocol != None: ++ from instance_service import InstanceService ++ service = InstanceService.Client(protocol) ++ return service.Connect() ++ else: ++ return False ++ #end __agent_connect ++ ++ def _keep_alive(self): ++ try: ++ if self._agent_alive == False: ++ self._protocol = self._agent_conn_open() ++ if self._protocol == None: ++ return ++ from instance_service import InstanceService ++ service = InstanceService.Client(self._protocol) ++ aa_latest = service.KeepAliveCheck() ++ if self._agent_alive == False and aa_latest == True: ++ port_l = [v for k, v in self._port_dict.iteritems()] ++ service.AddPort(port_l) ++ self._agent_alive = True ++ return ++ if self._agent_alive == True and aa_latest == False: ++ self._agent_alive = False ++ return ++ except: ++ self._agent_alive = False ++ #end _keep_alive ++ ++ def _agent_conn_open(self): ++ import socket ++ import sys ++ import uuid ++ from thrift.transport import TTransport, TSocket ++ from thrift.transport.TTransport import TTransportException ++ from thrift.protocol import TBinaryProtocol, TProtocol ++ from instance_service import InstanceService ++ from instance_service import ttypes ++ try: ++ socket = TSocket.TSocket("127.0.0.1", 9090) ++ transport = TTransport.TFramedTransport(socket) ++ transport.open() ++ protocol = TBinaryProtocol.TBinaryProtocol(transport) ++ self._agent_connected = self._agent_connect(protocol) ++ return protocol ++ except TTransportException: ++ return None ++ #end _agent_conn_open ++ ++ def get_dev_name(self, iface_id): ++ return "tap" + iface_id[0:11] ++ #end get_dev_name ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _agent_inform_port_add(self, port, port_id): ++ # First add to the port list ++ self._port_dict[port_id] = port ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.AddPort([port]) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_add ++ ++ def _agent_inform_port_delete(self, port_id): ++ # First add to the port list ++ if port_id in self._port_dict: ++ del_port_id = self._port_dict[port_id].port_id ++ del self._port_dict[port_id] ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.DeletePort(del_port_id) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_delete ++ ++ ++#end class ContrailVifPlug ++ ++def launch_interval_looping(contrail_vif_plug): ++ while True: ++ contrail_vif_plug._keep_alive() ++ gevent.sleep(2) ++#end launch_internal_looping ++ ++ ++class ContrailVifDir(ProcessEvent): ++ def __init__(self, contrail_vif, vif_dir): ++ self._create_port_list(contrail_vif, vif_dir) ++ self._contrail_vif_plug = contrail_vif ++ #end __init__ ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _create_port_list(self, contrail_vif, vif_dir): ++ import os ++ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] ++ for f in files: ++ print f ++ file_name = os.path.join(vif_dir, f) ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ contrail_vif._agent_inform_port_add(port, port_id) ++ #end create_port_list ++ ++ def _get_port_info(self, config): ++ import ConfigParser ++ #import pdb; pdb.set_trace() ++ from instance_service import ttypes ++ try: ++ vif = 'Vif' ++ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), ++ self._convert_to_bl(config.get(vif, 'instance_id')), ++ config.get(vif, 'tap_name'), ++ config.get(vif, 'ip_address'), ++ self._convert_to_bl(config.get(vif, 'vn_id')), ++ config.get(vif, 'mac_address'), ++ config.get(vif, 'display_name'), ++ config.get(vif, 'hostname'), ++ config.get(vif, 'host')) ++ #print config.get(vif, 'prefix_len') ++ return port ++ except: ++ return None ++ ++ def _print_port_info(self, config): ++ import ConfigParser ++ try: ++ vif = 'Vif' ++ print config.get(vif, 'port_id') ++ print config.get(vif, 'instance_id') ++ print config.get(vif, 'tap_name') ++ print config.get(vif, 'ip_address') ++ print config.get(vif, 'vn_id') ++ print config.get(vif, 'mac_address') ++ print config.get(vif, 'display_name') ++ print config.get(vif, 'hostname') ++ print config.get(vif, 'host') ++ print config.get(vif, 'prefix_len') ++ except: ++ return ++ #end __print_port_into ++ ++ def _read_port_info_from_file(self, file_name): ++ import ConfigParser ++ config = ConfigParser.ConfigParser() ++ config.read(file_name) ++ self._print_port_info(config) ++ port = self._get_port_info(config) ++ if port is not None: ++ return port, config.get('Vif', 'port_id') ++ else: ++ return None, None ++ #end _read_port_info_from_file ++ ++ def _is_allowed(self, file_name): ++ ret = True ++ if (file_name[0] == '.' or file_name[-1] == '~'): ++ ret = False ++ return ret ++ #end _is_allowed ++ ++ def process_IN_CREATE(self, event): ++ file_name = os.path.join(event.path, event.name) ++ if not self._is_allowed(event.name): ++ return ++ print "Create: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In create: %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ ++ #end process_IN_CREATE ++ ++ def process_IN_DELETE(self, event): ++ if not self._is_allowed(event.name): ++ return ++ print "Remove: %s" % os.path.join(event.path, event.name) ++ file_name = os.path.join(event.path, event.name) ++ #import pdb; pdb.set_trace() ++ if self._is_allowed(event.name): ++ self._contrail_vif_plug._agent_inform_port_delete(event.name) ++ return ++ ++ #end process_IN_DELETE ++ ++ def process_IN_MODIFY(self, event): ++ if not self._is_allowed(event.name): ++ return ++ file_name = os.path.join(event.path, event.name) ++ print "Modify: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In modify %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ #end process_IN_MODIFY ++#end ContrilVifDir ++ ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' ++def contrail_vif_dir_monitor(contrail_vif_plug): ++ #import pdb; pdb.set_trace() ++ wm = WatchManager() ++ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) ++ contrail_vif_plug._notifier = notifier ++ # watched events ++ mask = pyinotify.IN_DELETE | \ ++ pyinotify.IN_CREATE | \ ++ pyinotify.IN_MODIFY | \ ++ pyinotify.IN_ISDIR ++ wm.add_watch(VIF_DIR, mask, quiet=False) ++ notifier.start() ++#end contrail_vif_dir_monitor ++ ++def main(args_str = None): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ contrail_vif_plug = ContrailVifPlug() ++ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) ++ #import pdb; pdb.set_trace() ++ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) ++ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) ++#end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote +new file mode 100644 +index 0000000..76626d4 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService-remote +@@ -0,0 +1,165 @@ ++#!/usr/bin/env python ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++import sys ++import pprint ++from urlparse import urlparse ++from thrift.transport import TTransport ++from thrift.transport import TSocket ++from thrift.transport import THttpClient ++from thrift.protocol import TBinaryProtocol ++ ++import InstanceService ++from ttypes import * ++ ++if len(sys.argv) <= 1 or sys.argv[1] == '--help': ++ print '' ++ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' ++ print '' ++ print 'Functions:' ++ print ' bool AddPort(PortList port_list)' ++ print ' bool KeepAliveCheck()' ++ print ' bool Connect()' ++ print ' bool DeletePort(tuuid port_id)' ++ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' ++ print ' bool AddHostRoute(string ip_address, string vrf_name)' ++ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' ++ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool CreateVrf(string vrf_name)' ++ print '' ++ sys.exit(0) ++ ++pp = pprint.PrettyPrinter(indent = 2) ++host = 'localhost' ++port = 9090 ++uri = '' ++framed = False ++http = False ++argi = 1 ++ ++if sys.argv[argi] == '-h': ++ parts = sys.argv[argi+1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ argi += 2 ++ ++if sys.argv[argi] == '-u': ++ url = urlparse(sys.argv[argi+1]) ++ parts = url[1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ else: ++ port = 80 ++ uri = url[2] ++ if url[4]: ++ uri += '?%s' % url[4] ++ http = True ++ argi += 2 ++ ++if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': ++ framed = True ++ argi += 1 ++ ++cmd = sys.argv[argi] ++args = sys.argv[argi+1:] ++ ++if http: ++ transport = THttpClient.THttpClient(host, port, uri) ++else: ++ socket = TSocket.TSocket(host, port) ++ if framed: ++ transport = TTransport.TFramedTransport(socket) ++ else: ++ transport = TTransport.TBufferedTransport(socket) ++protocol = TBinaryProtocol.TBinaryProtocol(transport) ++client = InstanceService.Client(protocol) ++transport.open() ++ ++if cmd == 'AddPort': ++ if len(args) != 1: ++ print 'AddPort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.AddPort(eval(args[0]),)) ++ ++elif cmd == 'KeepAliveCheck': ++ if len(args) != 0: ++ print 'KeepAliveCheck requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.KeepAliveCheck()) ++ ++elif cmd == 'Connect': ++ if len(args) != 0: ++ print 'Connect requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.Connect()) ++ ++elif cmd == 'DeletePort': ++ if len(args) != 1: ++ print 'DeletePort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.DeletePort(eval(args[0]),)) ++ ++elif cmd == 'TunnelNHEntryAdd': ++ if len(args) != 3: ++ print 'TunnelNHEntryAdd requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) ++ ++elif cmd == 'TunnelNHEntryDelete': ++ if len(args) != 3: ++ print 'TunnelNHEntryDelete requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) ++ ++elif cmd == 'RouteEntryAdd': ++ if len(args) != 4: ++ print 'RouteEntryAdd requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'RouteEntryDelete': ++ if len(args) != 2: ++ print 'RouteEntryDelete requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) ++ ++elif cmd == 'AddHostRoute': ++ if len(args) != 2: ++ print 'AddHostRoute requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.AddHostRoute(args[0],args[1],)) ++ ++elif cmd == 'AddLocalVmRoute': ++ if len(args) != 4: ++ print 'AddLocalVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'AddRemoteVmRoute': ++ if len(args) != 4: ++ print 'AddRemoteVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'CreateVrf': ++ if len(args) != 1: ++ print 'CreateVrf requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.CreateVrf(args[0],)) ++ ++else: ++ print 'Unrecognized method %s' % cmd ++ sys.exit(1) ++ ++transport.close() +diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py +new file mode 100644 +index 0000000..2219045 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService.py +@@ -0,0 +1,2275 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++from thrift.Thrift import TProcessor ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++class Iface: ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ pass ++ ++ def KeepAliveCheck(self, ): ++ pass ++ ++ def Connect(self, ): ++ pass ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ pass ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ pass ++ ++ ++class Client(Iface): ++ def __init__(self, iprot, oprot=None): ++ self._iprot = self._oprot = iprot ++ if oprot is not None: ++ self._oprot = oprot ++ self._seqid = 0 ++ ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ self.send_AddPort(port_list) ++ return self.recv_AddPort() ++ ++ def send_AddPort(self, port_list): ++ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) ++ args = AddPort_args() ++ args.port_list = port_list ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddPort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddPort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); ++ ++ def KeepAliveCheck(self, ): ++ self.send_KeepAliveCheck() ++ return self.recv_KeepAliveCheck() ++ ++ def send_KeepAliveCheck(self, ): ++ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) ++ args = KeepAliveCheck_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_KeepAliveCheck(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = KeepAliveCheck_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); ++ ++ def Connect(self, ): ++ self.send_Connect() ++ return self.recv_Connect() ++ ++ def send_Connect(self, ): ++ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) ++ args = Connect_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_Connect(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = Connect_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ self.send_DeletePort(port_id) ++ return self.recv_DeletePort() ++ ++ def send_DeletePort(self, port_id): ++ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) ++ args = DeletePort_args() ++ args.port_id = port_id ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_DeletePort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = DeletePort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryAdd() ++ ++ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryAdd_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryDelete() ++ ++ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryDelete_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) ++ return self.recv_RouteEntryAdd() ++ ++ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) ++ args = RouteEntryAdd_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_RouteEntryDelete(ip_address, vrf_name) ++ return self.recv_RouteEntryDelete() ++ ++ def send_RouteEntryDelete(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) ++ args = RouteEntryDelete_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_AddHostRoute(ip_address, vrf_name) ++ return self.recv_AddHostRoute() ++ ++ def send_AddHostRoute(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) ++ args = AddHostRoute_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddHostRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddHostRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) ++ return self.recv_AddLocalVmRoute() ++ ++ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) ++ args = AddLocalVmRoute_args() ++ args.ip_address = ip_address ++ args.intf_uuid = intf_uuid ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddLocalVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddLocalVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) ++ return self.recv_AddRemoteVmRoute() ++ ++ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) ++ args = AddRemoteVmRoute_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddRemoteVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddRemoteVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ self.send_CreateVrf(vrf_name) ++ return self.recv_CreateVrf() ++ ++ def send_CreateVrf(self, vrf_name): ++ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) ++ args = CreateVrf_args() ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_CreateVrf(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = CreateVrf_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); ++ ++ ++class Processor(Iface, TProcessor): ++ def __init__(self, handler): ++ self._handler = handler ++ self._processMap = {} ++ self._processMap["AddPort"] = Processor.process_AddPort ++ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck ++ self._processMap["Connect"] = Processor.process_Connect ++ self._processMap["DeletePort"] = Processor.process_DeletePort ++ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd ++ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete ++ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd ++ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete ++ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute ++ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute ++ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute ++ self._processMap["CreateVrf"] = Processor.process_CreateVrf ++ ++ def process(self, iprot, oprot): ++ (name, type, seqid) = iprot.readMessageBegin() ++ if name not in self._processMap: ++ iprot.skip(TType.STRUCT) ++ iprot.readMessageEnd() ++ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) ++ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) ++ x.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ return ++ else: ++ self._processMap[name](self, seqid, iprot, oprot) ++ return True ++ ++ def process_AddPort(self, seqid, iprot, oprot): ++ args = AddPort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddPort_result() ++ result.success = self._handler.AddPort(args.port_list) ++ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_KeepAliveCheck(self, seqid, iprot, oprot): ++ args = KeepAliveCheck_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = KeepAliveCheck_result() ++ result.success = self._handler.KeepAliveCheck() ++ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_Connect(self, seqid, iprot, oprot): ++ args = Connect_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = Connect_result() ++ result.success = self._handler.Connect() ++ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_DeletePort(self, seqid, iprot, oprot): ++ args = DeletePort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = DeletePort_result() ++ result.success = self._handler.DeletePort(args.port_id) ++ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): ++ args = TunnelNHEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryAdd_result() ++ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): ++ args = TunnelNHEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryDelete_result() ++ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryAdd(self, seqid, iprot, oprot): ++ args = RouteEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryAdd_result() ++ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryDelete(self, seqid, iprot, oprot): ++ args = RouteEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryDelete_result() ++ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddHostRoute(self, seqid, iprot, oprot): ++ args = AddHostRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddHostRoute_result() ++ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddLocalVmRoute(self, seqid, iprot, oprot): ++ args = AddLocalVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddLocalVmRoute_result() ++ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): ++ args = AddRemoteVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddRemoteVmRoute_result() ++ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_CreateVrf(self, seqid, iprot, oprot): ++ args = CreateVrf_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = CreateVrf_result() ++ result.success = self._handler.CreateVrf(args.vrf_name) ++ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ ++# HELPER FUNCTIONS AND STRUCTURES ++ ++class AddPort_args: ++ """ ++ Attributes: ++ - port_list ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_list=None,): ++ self.port_list = port_list ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_list = [] ++ (_etype24, _size21) = iprot.readListBegin() ++ for _i25 in xrange(_size21): ++ _elem26 = Port() ++ _elem26.read(iprot) ++ self.port_list.append(_elem26) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_args') ++ if self.port_list is not None: ++ oprot.writeFieldBegin('port_list', TType.LIST, -1) ++ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) ++ for iter27 in self.port_list: ++ iter27.write(oprot) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddPort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_args: ++ """ ++ Attributes: ++ - port_id ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_id=None,): ++ self.port_id = port_id ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype31, _size28) = iprot.readListBegin() ++ for _i32 in xrange(_size28): ++ _elem33 = iprot.readI16(); ++ self.port_id.append(_elem33) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_args') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, -1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter34 in self.port_id: ++ oprot.writeI16(iter34) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.intf_uuid = intf_uuid ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.intf_uuid = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.intf_uuid is not None: ++ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) ++ oprot.writeString(self.intf_uuid) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.intf_uuid is None: ++ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_args: ++ """ ++ Attributes: ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'vrf_name', None, None, ), # 1 ++ ) ++ ++ def __init__(self, vrf_name=None,): ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_args') ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) +diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py +new file mode 100644 +index 0000000..f34ead4 +--- /dev/null ++++ plugins/contrail/instance_service/__init__.py +@@ -0,0 +1 @@ ++__all__ = ['ttypes', 'constants', 'InstanceService'] +diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py +new file mode 100644 +index 0000000..73f07fe +--- /dev/null ++++ plugins/contrail/instance_service/constants.py +@@ -0,0 +1,11 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++ +diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py +new file mode 100644 +index 0000000..564f82e +--- /dev/null ++++ plugins/contrail/instance_service/ttypes.py +@@ -0,0 +1,210 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++ ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++ ++class Port: ++ """ ++ Attributes: ++ - port_id ++ - instance_id ++ - tap_name ++ - ip_address ++ - vn_id ++ - mac_address ++ - display_name ++ - hostname ++ - host ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 ++ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 ++ (3, TType.STRING, 'tap_name', None, None, ), # 3 ++ (4, TType.STRING, 'ip_address', None, None, ), # 4 ++ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 ++ (6, TType.STRING, 'mac_address', None, None, ), # 6 ++ (7, TType.STRING, 'display_name', None, None, ), # 7 ++ (8, TType.STRING, 'hostname', None, None, ), # 8 ++ (9, TType.STRING, 'host', None, None, ), # 9 ++ ) ++ ++ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): ++ self.port_id = port_id ++ self.instance_id = instance_id ++ self.tap_name = tap_name ++ self.ip_address = ip_address ++ self.vn_id = vn_id ++ self.mac_address = mac_address ++ self.display_name = display_name ++ self.hostname = hostname ++ self.host = host ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype3, _size0) = iprot.readListBegin() ++ for _i4 in xrange(_size0): ++ _elem5 = iprot.readI16(); ++ self.port_id.append(_elem5) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.LIST: ++ self.instance_id = [] ++ (_etype9, _size6) = iprot.readListBegin() ++ for _i10 in xrange(_size6): ++ _elem11 = iprot.readI16(); ++ self.instance_id.append(_elem11) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.tap_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 5: ++ if ftype == TType.LIST: ++ self.vn_id = [] ++ (_etype15, _size12) = iprot.readListBegin() ++ for _i16 in xrange(_size12): ++ _elem17 = iprot.readI16(); ++ self.vn_id.append(_elem17) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 6: ++ if ftype == TType.STRING: ++ self.mac_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 7: ++ if ftype == TType.STRING: ++ self.display_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 8: ++ if ftype == TType.STRING: ++ self.hostname = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 9: ++ if ftype == TType.STRING: ++ self.host = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Port') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, 1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter18 in self.port_id: ++ oprot.writeI16(iter18) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.instance_id is not None: ++ oprot.writeFieldBegin('instance_id', TType.LIST, 2) ++ oprot.writeListBegin(TType.I16, len(self.instance_id)) ++ for iter19 in self.instance_id: ++ oprot.writeI16(iter19) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.tap_name is not None: ++ oprot.writeFieldBegin('tap_name', TType.STRING, 3) ++ oprot.writeString(self.tap_name) ++ oprot.writeFieldEnd() ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 4) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vn_id is not None: ++ oprot.writeFieldBegin('vn_id', TType.LIST, 5) ++ oprot.writeListBegin(TType.I16, len(self.vn_id)) ++ for iter20 in self.vn_id: ++ oprot.writeI16(iter20) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.mac_address is not None: ++ oprot.writeFieldBegin('mac_address', TType.STRING, 6) ++ oprot.writeString(self.mac_address) ++ oprot.writeFieldEnd() ++ if self.display_name is not None: ++ oprot.writeFieldBegin('display_name', TType.STRING, 7) ++ oprot.writeString(self.display_name) ++ oprot.writeFieldEnd() ++ if self.hostname is not None: ++ oprot.writeFieldBegin('hostname', TType.STRING, 8) ++ oprot.writeString(self.hostname) ++ oprot.writeFieldEnd() ++ if self.host is not None: ++ oprot.writeFieldBegin('host', TType.STRING, 9) ++ oprot.writeString(self.host) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.port_id is None: ++ raise TProtocol.TProtocolException(message='Required field port_id is unset!') ++ if self.instance_id is None: ++ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') ++ if self.tap_name is None: ++ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vn_id is None: ++ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') ++ if self.mac_address is None: ++ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) diff --git a/stack.sh b/stack.sh index bab43dbcb3..b1ff8af696 100755 --- a/stack.sh +++ b/stack.sh @@ -697,7 +697,7 @@ function test_install_neutron_patch() { } function test_install_nova_patch() { - patch_name="nova_v1.patch" + patch_name="nova_v2.patch" contrail_cwd=$(pwd) cd $DEST/nova patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null @@ -987,6 +987,7 @@ if [ $ENABLE_CONTRAIL ]; then sudo yum -y install gcc-c++ python-devel autoconf automake sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel sudo yum -y install tunctl + sudo yum -y install redis fi # api server requirements @@ -1009,6 +1010,14 @@ if [ $ENABLE_CONTRAIL ]; then scons cd ${contrail_cwd} + # setup redis + if [ -e /etc/redis.conf ]; then + grep -q 6382 /etc/redis.conf || + echo "Setting Redis listen port to 6382" + (sed 's/^port .*/port 6382/g' /etc/redis.conf > redis.conf.new && \ + sudo mv redis.conf.new /etc/redis.conf) + fi + # get cassandra if ! which cassandra > /dev/null 2>&1 ; then if is_ubuntu; then @@ -1547,6 +1556,7 @@ if [ $ENABLE_CONTRAIL ]; then # launch ... screen_it cass "sudo /usr/sbin/cassandra -f" + screen_it redis "sudo redis-server /etc/redis.conf" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 diff --git a/stackrc b/stackrc index c8e74775ba..3857212101 100644 --- a/stackrc +++ b/stackrc @@ -33,7 +33,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent,disco,vif +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent,disco,vif,redis # Set the default Nova APIs to enable NOVA_ENABLED_APIS=ec2,osapi_compute,metadata From e0cd08532a2b6d05c572a403cf136bddb0edbfcd Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 25 Oct 2013 04:54:40 +0000 Subject: [PATCH 025/179] fixed setup_contrail to use $PHYSICAL_INTERFACE, $SERVICE_HOST, $contrail_gw_interface install redis and tunctl in ubuntu redis uses non-standard port so made custom contrail/etc/redis.conf. RH and Debian install redis.conf in different directories --- contrail/etc/redis.conf | 418 ++++++++++++++++++++++++++++++++++++++++ stack.sh | 29 ++- 2 files changed, 430 insertions(+), 17 deletions(-) create mode 100644 contrail/etc/redis.conf diff --git a/contrail/etc/redis.conf b/contrail/etc/redis.conf new file mode 100644 index 0000000000..b1e863ef1f --- /dev/null +++ b/contrail/etc/redis.conf @@ -0,0 +1,418 @@ +# Redis configuration file example + +# Note on units: when memory size is needed, it is possible to specifiy +# it in the usual form of 1k 5GB 4M and so forth: +# +# 1k => 1000 bytes +# 1kb => 1024 bytes +# 1m => 1000000 bytes +# 1mb => 1024*1024 bytes +# 1g => 1000000000 bytes +# 1gb => 1024*1024*1024 bytes +# +# units are case insensitive so 1GB 1Gb 1gB are all the same. + +# By default Redis does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +#daemonize yes + +# When running daemonized, Redis writes a pid file in /var/run/redis.pid by +# default. You can specify a custom pid file location here. +pidfile /var/run/redis/redis-server.pid + +# Accept connections on the specified port, default is 6379. +# If port 0 is specified Redis will not listen on a TCP socket. +# contrail uses redis on 6382 +port 6382 + +# If you want you can bind a single interface, if the bind option is not +# specified all the interfaces will listen for incoming connections. +# +bind 127.0.0.1 + +# Specify the path for the unix socket that will be used to listen for +# incoming connections. There is no default, so Redis will not listen +# on a unix socket when not specified. +# +# unixsocket /var/run/redis/redis.sock + +# Close the connection after a client is idle for N seconds (0 to disable) +timeout 300 + +# Set server verbosity to 'debug' +# it can be one of: +# debug (a lot of information, useful for development/testing) +# verbose (many rarely useful info, but not a mess like the debug level) +# notice (moderately verbose, what you want in production probably) +# warning (only very important / critical messages are logged) +loglevel notice + +# Specify the log file name. Also 'stdout' can be used to force +# Redis to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile /var/log/redis/redis-server.log + +# To enable logging to the system logger, just set 'syslog-enabled' to yes, +# and optionally update the other syslog parameters to suit your needs. +# syslog-enabled no + +# Specify the syslog identity. +# syslog-ident redis + +# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. +# syslog-facility local0 + +# Set the number of databases. The default database is DB 0, you can select +# a different one on a per-connection basis using SELECT where +# dbid is a number between 0 and 'databases'-1 +databases 16 + +################################ SNAPSHOTTING ################################# +# +# Save the DB on disk: +# +# save +# +# Will save the DB if both the given number of seconds and the given +# number of write operations against the DB occurred. +# +# In the example below the behaviour will be to save: +# after 900 sec (15 min) if at least 1 key changed +# after 300 sec (5 min) if at least 10 keys changed +# after 60 sec if at least 10000 keys changed +# +# Note: you can disable saving at all commenting all the "save" lines. + +save 900 1 +save 300 10 +save 60 10000 + +# Compress string objects using LZF when dump .rdb databases? +# For default that's set to 'yes' as it's almost always a win. +# If you want to save some CPU in the saving child set it to 'no' but +# the dataset will likely be bigger if you have compressible values or keys. +rdbcompression yes + +# The filename where to dump the DB +dbfilename dump.rdb + +# The working directory. +# +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# Also the Append Only File will be created inside this directory. +# +# Note that you must specify a directory here, not a file name. +dir /var/lib/redis + +################################# REPLICATION ################################# + +# Master-Slave replication. Use slaveof to make a Redis instance a copy of +# another Redis server. Note that the configuration is local to the slave +# so for example it is possible to configure the slave to save the DB with a +# different interval, or to listen to another port, and so on. +# +# slaveof + +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the slave to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the slave request. +# +# masterauth + +# When a slave lost the connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of data data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +slave-serve-stale-data yes + +################################## SECURITY ################################### + +# Require clients to issue AUTH before processing any other +# commands. This might be useful in environments in which you do not trust +# others with access to the host running redis-server. +# +# This should stay commented out for backward compatibility and because most +# people do not need auth (e.g. they run their own servers). +# +# Warning: since Redis is pretty fast an outside user can try up to +# 150k passwords per second against a good box. This means that you should +# use a very strong password otherwise it will be very easy to break. +# +# requirepass foobared + +# Command renaming. +# +# It is possilbe to change the name of dangerous commands in a shared +# environment. For instance the CONFIG command may be renamed into something +# of hard to guess so that it will be still available for internal-use +# tools but not available for general clients. +# +# Example: +# +# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 +# +# It is also possilbe to completely kill a command renaming it into +# an empty string: +# +# rename-command CONFIG "" + +################################### LIMITS #################################### + +# Set the max number of connected clients at the same time. By default there +# is no limit, and it's up to the number of file descriptors the Redis process +# is able to open. The special value '0' means no limits. +# Once the limit is reached Redis will close all the new connections sending +# an error 'max number of clients reached'. +# +# maxclients 128 + +# Don't use more memory than the specified amount of bytes. +# When the memory limit is reached Redis will try to remove keys with an +# EXPIRE set. It will try to start freeing keys that are going to expire +# in little time and preserve keys with a longer time to live. +# Redis will also try to remove objects from free lists if possible. +# +# If all this fails, Redis will start to reply with errors to commands +# that will use more memory, like SET, LPUSH, and so on, and will continue +# to reply to most read-only commands like GET. +# +# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a +# 'state' server or cache, not as a real DB. When Redis is used as a real +# database the memory usage will grow over the weeks, it will be obvious if +# it is going to use too much memory in the long run, and you'll have the time +# to upgrade. With maxmemory after the limit is reached you'll start to get +# errors for write operations, and this may even lead to DB inconsistency. +# +# maxmemory + +# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory +# is reached? You can select among five behavior: +# +# volatile-lru -> remove the key with an expire set using an LRU algorithm +# allkeys-lru -> remove any key accordingly to the LRU algorithm +# volatile-random -> remove a random key with an expire set +# allkeys->random -> remove a random key, any key +# volatile-ttl -> remove the key with the nearest expire time (minor TTL) +# noeviction -> don't expire at all, just return an error on write operations +# +# Note: with all the kind of policies, Redis will return an error on write +# operations, when there are not suitable keys for eviction. +# +# At the date of writing this commands are: set setnx setex append +# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd +# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby +# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby +# getset mset msetnx exec sort +# +# The default is: +# +# maxmemory-policy volatile-lru + +# LRU and minimal TTL algorithms are not precise algorithms but approximated +# algorithms (in order to save memory), so you can select as well the sample +# size to check. For instance for default Redis will check three keys and +# pick the one that was used less recently, you can change the sample size +# using the following configuration directive. +# +# maxmemory-samples 3 + +############################## APPEND ONLY MODE ############################### + +# By default Redis asynchronously dumps the dataset on disk. If you can live +# with the idea that the latest records will be lost if something like a crash +# happens this is the preferred way to run Redis. If instead you care a lot +# about your data and don't want to that a single record can get lost you should +# enable the append only mode: when this mode is enabled Redis will append +# every write operation received in the file appendonly.aof. This file will +# be read on startup in order to rebuild the full dataset in memory. +# +# Note that you can have both the async dumps and the append only file if you +# like (you have to comment the "save" statements above to disable the dumps). +# Still if append only mode is enabled Redis will load the data from the +# log file at startup ignoring the dump.rdb file. +# +# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append +# log file in background when it gets too big. + +appendonly no + +# The name of the append only file (default: "appendonly.aof") +# appendfilename appendonly.aof + +# The fsync() call tells the Operating System to actually write data on disk +# instead to wait for more data in the output buffer. Some OS will really flush +# data on disk, some other OS will just try to do it ASAP. +# +# Redis supports three different modes: +# +# no: don't fsync, just let the OS flush the data when it wants. Faster. +# always: fsync after every write to the append only log . Slow, Safest. +# everysec: fsync only if one second passed since the last fsync. Compromise. +# +# The default is "everysec" that's usually the right compromise between +# speed and data safety. It's up to you to understand if you can relax this to +# "no" that will will let the operating system flush the output buffer when +# it wants, for better performances (but if you can live with the idea of +# some data loss consider the default persistence mode that's snapshotting), +# or on the contrary, use "always" that's very slow but a bit safer than +# everysec. +# +# If unsure, use "everysec". + +# appendfsync always +appendfsync everysec +# appendfsync no + +# When the AOF fsync policy is set to always or everysec, and a background +# saving process (a background save or AOF log background rewriting) is +# performing a lot of I/O against the disk, in some Linux configurations +# Redis may block too long on the fsync() call. Note that there is no fix for +# this currently, as even performing fsync in a different thread will block +# our synchronous write(2) call. +# +# In order to mitigate this problem it's possible to use the following option +# that will prevent fsync() from being called in the main process while a +# BGSAVE or BGREWRITEAOF is in progress. +# +# This means that while another child is saving the durability of Redis is +# the same as "appendfsync none", that in pratical terms means that it is +# possible to lost up to 30 seconds of log in the worst scenario (with the +# default Linux settings). +# +# If you have latency problems turn this to "yes". Otherwise leave it as +# "no" that is the safest pick from the point of view of durability. +no-appendfsync-on-rewrite no + +################################ VIRTUAL MEMORY ############################### + +# Virtual Memory allows Redis to work with datasets bigger than the actual +# amount of RAM needed to hold the whole dataset in memory. +# In order to do so very used keys are taken in memory while the other keys +# are swapped into a swap file, similarly to what operating systems do +# with memory pages. +# +# To enable VM just set 'vm-enabled' to yes, and set the following three +# VM parameters accordingly to your needs. + +vm-enabled no +# vm-enabled yes + +# This is the path of the Redis swap file. As you can guess, swap files +# can't be shared by different Redis instances, so make sure to use a swap +# file for every redis process you are running. Redis will complain if the +# swap file is already in use. +# +# The best kind of storage for the Redis swap file (that's accessed at random) +# is a Solid State Disk (SSD). +# +# *** WARNING *** if you are using a shared hosting the default of putting +# the swap file under /tmp is not secure. Create a dir with access granted +# only to Redis user and configure Redis to create the swap file there. +vm-swap-file /var/lib/redis/redis.swap + +# vm-max-memory configures the VM to use at max the specified amount of +# RAM. Everything that deos not fit will be swapped on disk *if* possible, that +# is, if there is still enough contiguous space in the swap file. +# +# With vm-max-memory 0 the system will swap everything it can. Not a good +# default, just specify the max amount of RAM you can in bytes, but it's +# better to leave some margin. For instance specify an amount of RAM +# that's more or less between 60 and 80% of your free RAM. +vm-max-memory 0 + +# Redis swap files is split into pages. An object can be saved using multiple +# contiguous pages, but pages can't be shared between different objects. +# So if your page is too big, small objects swapped out on disk will waste +# a lot of space. If you page is too small, there is less space in the swap +# file (assuming you configured the same number of total swap file pages). +# +# If you use a lot of small objects, use a page size of 64 or 32 bytes. +# If you use a lot of big objects, use a bigger page size. +# If unsure, use the default :) +vm-page-size 32 + +# Number of total memory pages in the swap file. +# Given that the page table (a bitmap of free/used pages) is taken in memory, +# every 8 pages on disk will consume 1 byte of RAM. +# +# The total swap size is vm-page-size * vm-pages +# +# With the default of 32-bytes memory pages and 134217728 pages Redis will +# use a 4 GB swap file, that will use 16 MB of RAM for the page table. +# +# It's better to use the smallest acceptable value for your application, +# but the default is large in order to work in most conditions. +vm-pages 134217728 + +# Max number of VM I/O threads running at the same time. +# This threads are used to read/write data from/to swap file, since they +# also encode and decode objects from disk to memory or the reverse, a bigger +# number of threads can help with big objects even if they can't help with +# I/O itself as the physical device may not be able to couple with many +# reads/writes operations at the same time. +# +# The special value of 0 turn off threaded I/O and enables the blocking +# Virtual Memory implementation. +vm-max-threads 4 + +############################### ADVANCED CONFIG ############################### + +# Hashes are encoded in a special way (much more memory efficient) when they +# have at max a given numer of elements, and the biggest element does not +# exceed a given threshold. You can configure this limits with the following +# configuration directives. +hash-max-zipmap-entries 512 +hash-max-zipmap-value 64 + +# Similarly to hashes, small lists are also encoded in a special way in order +# to save a lot of space. The special representation is only used when +# you are under the following limits: +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +# Sets have a special encoding in just one case: when a set is composed +# of just strings that happens to be integers in radix 10 in the range +# of 64 bit signed integers. +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +set-max-intset-entries 512 + +# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in +# order to help rehashing the main Redis hash table (the one mapping top-level +# keys to values). The hash table implementation redis uses (see dict.c) +# performs a lazy rehashing: the more operation you run into an hash table +# that is rhashing, the more rehashing "steps" are performed, so if the +# server is idle the rehashing is never complete and some more memory is used +# by the hash table. +# +# The default is to use this millisecond 10 times every second in order to +# active rehashing the main dictionaries, freeing memory when possible. +# +# If unsure: +# use "activerehashing no" if you have hard latency requirements and it is +# not a good thing in your environment that Redis can reply form time to time +# to queries with 2 milliseconds delay. +# +# use "activerehashing yes" if you don't have such hard requirements but +# want to free memory asap when possible. +activerehashing yes + +################################## INCLUDES ################################### + +# Include one or more other config files here. This is useful if you +# have a standard template that goes to all redis server but also need +# to customize a few per-server settings. Include files can include +# other files, so use this wisely. +# +# include /path/to/local.conf +# include /path/to/other.conf diff --git a/stack.sh b/stack.sh index b1ff8af696..0dae05a3ab 100755 --- a/stack.sh +++ b/stack.sh @@ -980,7 +980,8 @@ if [ $ENABLE_CONTRAIL ]; then apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev apt_get install python-dev autoconf automake build-essential apt_get install libevent-dev libxml2-dev libxslt-dev - apt_get install tunctl + apt_get install uml-utilities + apt_get install redis-server else sudo yum -y install patch scons flex bison make vim sudo yum -y install expat-devel gettext-devel curl-devel @@ -990,6 +991,9 @@ if [ $ENABLE_CONTRAIL ]; then sudo yum -y install redis fi + # use contrail-specific configs. e.g. redis runs non-daemon on port 6382 + rsync -rv $TOP_DIR/contrail/etc/ /etc/contrail + # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 sudo easy_install -U distribute @@ -1010,14 +1014,6 @@ if [ $ENABLE_CONTRAIL ]; then scons cd ${contrail_cwd} - # setup redis - if [ -e /etc/redis.conf ]; then - grep -q 6382 /etc/redis.conf || - echo "Setting Redis listen port to 6382" - (sed 's/^port .*/port 6382/g' /etc/redis.conf > redis.conf.new && \ - sudo mv redis.conf.new /etc/redis.conf) - fi - # get cassandra if ! which cassandra > /dev/null 2>&1 ; then if is_ubuntu; then @@ -1074,18 +1070,17 @@ EOF cd ${contrail_cwd} fi - # create config files - # export passwords in a subshell so setup_contrail can pick them up but they won't leak later - (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && - python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE # --cfgm_ip $SERVICE_HOST - ) - # process gateway configuration if present contrail_gw_interface="" if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then contrail_gw_interface="--vgw_interface $CONTRAIL_VGW_INTERFACE --vgw_public_subnet $CONTRAIL_VGW_PUBLIC_SUBNET --vgw_public_network $CONTRAIL_VGW_PUBLIC_NETWORK" fi - python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST $contrail_gw_interface + + # create config files + # export passwords in a subshell so setup_contrail can pick them up but they won't leak later + (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && + python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface + ) # install contrail modules echo "Installing contrail modules" @@ -1555,8 +1550,8 @@ if [ $ENABLE_CONTRAIL ]; then screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" # launch ... + screen_it redis "sudo redis-server /etc/contrail/redis.conf" screen_it cass "sudo /usr/sbin/cassandra -f" - screen_it redis "sudo redis-server /etc/redis.conf" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 From 78f7dfd513118241778e583e42c12a86d9c377e8 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 25 Oct 2013 11:28:41 -0700 Subject: [PATCH 026/179] Combine two calls to setup_contrail.py --- stack.sh | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/stack.sh b/stack.sh index b1ff8af696..323c847960 100755 --- a/stack.sh +++ b/stack.sh @@ -1074,18 +1074,17 @@ EOF cd ${contrail_cwd} fi - # create config files - # export passwords in a subshell so setup_contrail can pick them up but they won't leak later - (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && - python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE # --cfgm_ip $SERVICE_HOST - ) - # process gateway configuration if present contrail_gw_interface="" if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then contrail_gw_interface="--vgw_interface $CONTRAIL_VGW_INTERFACE --vgw_public_subnet $CONTRAIL_VGW_PUBLIC_SUBNET --vgw_public_network $CONTRAIL_VGW_PUBLIC_NETWORK" fi - python $TOP_DIR/setup_contrail.py --cfgm_ip $SERVICE_HOST $contrail_gw_interface + + # create config files + # export passwords in a subshell so setup_contrail can pick them up but they won't leak later + (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && + python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface + ) # install contrail modules echo "Installing contrail modules" From 73a42656f21b8b4ff64f31f59eace8d64fe91951 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 25 Oct 2013 23:33:52 +0000 Subject: [PATCH 027/179] be root to rsync /etc/contrail --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index 0dae05a3ab..474e54d210 100755 --- a/stack.sh +++ b/stack.sh @@ -992,7 +992,7 @@ if [ $ENABLE_CONTRAIL ]; then fi # use contrail-specific configs. e.g. redis runs non-daemon on port 6382 - rsync -rv $TOP_DIR/contrail/etc/ /etc/contrail + sudo rsync -rv $TOP_DIR/contrail/etc/ /etc/contrail # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 From 966baca9c342beaf0adb7f2926261178fdd16579 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Sat, 26 Oct 2013 22:13:50 +0000 Subject: [PATCH 028/179] dsetia patch for multinode --- setup_contrail.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setup_contrail.py b/setup_contrail.py index 8ea074f5b7..cd52049b77 100755 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -166,16 +166,12 @@ def _parse_args(self, args_str): self._args = parser.parse_args(remaining_argv) - if self._args.physical_interface: - self._args.cfgm_ip = self.get_intf_ip(self._args.physical_interface) - print 'Using IP address %s' % self._args.cfgm_ip - # dsetia self._args.openstack_ip = self._args.cfgm_ip self._args.collector_ip = self._args.cfgm_ip self._args.discovery_ip = self._args.cfgm_ip self._args.control_ip = self._args.cfgm_ip - self._args.compute_ip = self._args.cfgm_ip + self._args.compute_ip = self.get_intf_ip(self._args.physical_interface) self._args.openstack_mgmt_ip = self._args.cfgm_ip self._args.database_listen_ip = self._args.cfgm_ip self._args.cassandra_ip_list = ['127.0.0.1'] From c06360030f86054b8d195ad885c5c5f22b26eb0f Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Sat, 26 Oct 2013 22:17:27 +0000 Subject: [PATCH 029/179] added localrc examples --- contrail/localrc-multinode-compute | 31 ++++++++++++++++++++++++++++++ contrail/localrc-multinode-server | 30 +++++++++++++++++++++++++++++ contrail/localrc-single | 25 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 contrail/localrc-multinode-compute create mode 100644 contrail/localrc-multinode-server create mode 100644 contrail/localrc-single diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute new file mode 100644 index 0000000000..8110542e1b --- /dev/null +++ b/contrail/localrc-multinode-compute @@ -0,0 +1,31 @@ +ENABLE_CONTRAIL=yes +PHYSICAL_INTERFACE=eth1 +MULTI_HOST=1 + +HOST_IP=172.18.4.15 # change this per compute node +SERVICE_HOST=172.18.4.14 + +ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent + +MYSQL_HOST=$SERVICE_HOST +RABBIT_HOST=$SERVICE_HOST +Q_HOST=$SERVICE_HOST +GLANCE_HOSTPORT=$SERVICE_HOST:9292 + +STACK_DIR=$(cd $(dirname $0) && pwd) + +LOG=True +DEBUG=True +LOGFILE=$STACK_DIR/log/stack.log +LOGDAYS=1 + +Q_PLUGIN=contrail +Q_USE_DEBUG_COMMAND=True +PHYSICAL_NETWORK=default + +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 +DATABASE_TYPE=mysql diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server new file mode 100644 index 0000000000..518e78638f --- /dev/null +++ b/contrail/localrc-multinode-server @@ -0,0 +1,30 @@ +# CONTRAIL MULTI_NODE master + +ENABLE_CONTRAIL=yes +PHYSICAL_INTERFACE=eth1 + +MULTI_HOST=1 +Q_PLUGIN=contrail + +STACK_DIR=$(cd $(dirname $0) && pwd) + +LOG=True +DEBUG=True +LOGFILE=$STACK_DIR/log/stack.log +LOGDAYS=1 + +disable_service n-net +enable_service q-svc +enable_service q-agt +enable_service q-dhcp +enable_service q-l3 +enable_service q-meta +enable_service neutron + +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 + + diff --git a/contrail/localrc-single b/contrail/localrc-single new file mode 100644 index 0000000000..dbc1c9e2e3 --- /dev/null +++ b/contrail/localrc-single @@ -0,0 +1,25 @@ +STACK_DIR=$(cd $(dirname $0) && pwd) + +LOG=True +DEBUG=True +LOGFILE=$STACK_DIR/log/stack.log +LOGDAYS=1 + +disable_service n-net +enable_service q-svc +enable_service q-agt +enable_service q-dhcp +enable_service q-l3 +enable_service q-meta +enable_service neutron + +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 + +ENABLE_CONTRAIL=yes +Q_PLUGIN=contrail +PHYSICAL_INTERFACE=eth1 + From a5ca56cadbd8f5ebb7c1707f58f12bb1a74f11ba Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 28 Oct 2013 17:44:02 -0700 Subject: [PATCH 030/179] Add sample localrc files --- contrail/README | 12 +++ contrail/localrc.compute | 36 ++++++++ contrail/localrc.master | 27 ++++++ contrail/provision_vrouter.py | 161 ++++++++++++++++++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 contrail/README create mode 100644 contrail/localrc.compute create mode 100644 contrail/localrc.master create mode 100755 contrail/provision_vrouter.py diff --git a/contrail/README b/contrail/README new file mode 100644 index 0000000000..1eb644506f --- /dev/null +++ b/contrail/README @@ -0,0 +1,12 @@ +Contrail directory includes some sample localrc files + +1) localrc.master - Use this on all-in-one system or master host +on a multi node system. Set PHYSICAL_INTERFACE to the interface that +Vrouter should bind to. Uncomment MULTI_HOST line if setup has +multiple compute nodes. + +2) localrc.compute - Use this on all compute nodes. Change the +following to suit your deployment: + PHYSICAL_INTERFACE + HOST_IP + SERVICE_HOST diff --git a/contrail/localrc.compute b/contrail/localrc.compute new file mode 100644 index 0000000000..b3ab73de2b --- /dev/null +++ b/contrail/localrc.compute @@ -0,0 +1,36 @@ +ENABLE_CONTRAIL=yes +PHYSICAL_INTERFACE=p4p1 +MULTI_HOST=1 + +# Change this per compute node +HOST_IP=10.84.13.34 + +# Set this to IP address of config (master) node +SERVICE_HOST=10.84.13.1 + +ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent + +MYSQL_HOST=$SERVICE_HOST +RABBIT_HOST=$SERVICE_HOST +Q_HOST=$SERVICE_HOST +GLANCE_HOSTPORT=$SERVICE_HOST:9292 + +STACK_DIR=$(cd $(dirname $0) && pwd) + +LOG=True +DEBUG=True +LOGFILE=$STACK_DIR/log/stack.log +LOGDAYS=1 + +NEUTRON_REPO=/opt/stack/neutron + +Q_PLUGIN=contrail +Q_USE_DEBUG_COMMAND=True +PHYSICAL_NETWORK=default + +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 +DATABASE_TYPE=mysql diff --git a/contrail/localrc.master b/contrail/localrc.master new file mode 100644 index 0000000000..0bd04314e4 --- /dev/null +++ b/contrail/localrc.master @@ -0,0 +1,27 @@ +# Enable Neutron +disable_service n-net +enable_service q-svc +enable_service q-agt +enable_service q-dhcp +enable_service q-l3 +enable_service q-meta +enable_service neutron + +# Set passwords +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 + +# Enable Contrail +ENABLE_CONTRAIL=yes + +# Use Contrail plugins for Nova and Neutron +Q_PLUGIN=contrail + +# Physical interface Vrouter binds too +PHYSICAL_INTERFACE=p6p1 + +# Enable multi node setup +# MULTI_HOST=1 diff --git a/contrail/provision_vrouter.py b/contrail/provision_vrouter.py new file mode 100755 index 0000000000..28db0dd2d6 --- /dev/null +++ b/contrail/provision_vrouter.py @@ -0,0 +1,161 @@ +#!/usr/bin/python +# +# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. +# + +import sys +import argparse +import ConfigParser + +from vnc_api.vnc_api import * + + +class VrouterProvisioner(object): + + def __init__(self, args_str=None): + self._args = None + if not args_str: + args_str = ' '.join(sys.argv[1:]) + self._parse_args(args_str) + + self._vnc_lib = VncApi( + self._args.admin_user, self._args.admin_password, + self._args.admin_tenant_name, + self._args.api_server_ip, + self._args.api_server_port, '/') + gsc_obj = self._vnc_lib.global_system_config_read( + fq_name=['default-global-system-config']) + self._global_system_config_obj = gsc_obj + + rt_inst_obj = self._vnc_lib.routing_instance_read( + fq_name=['default-domain', 'default-project', + 'ip-fabric', '__default__']) + self._fab_rt_inst_obj = rt_inst_obj + + if self._args.oper == 'add': + self.add_vrouter() + elif self._args.oper == 'del': + self.del_vrouter() + else: + print "Unknown operation %s. Only 'add' and 'del' supported"\ + % (self._args.oper) + + # end __init__ + + def _parse_args(self, args_str): + ''' + Eg. python provision_vrouter.py --host_name a3s30.contrail.juniper.net + --host_ip 10.1.1.1 + --api_server_ip 127.0.0.1 + --api_server_port 8082 + --oper + ''' + + # Source any specified config/ini file + # Turn off help, so we print all options in response to -h + conf_parser = argparse.ArgumentParser(add_help=False) + + conf_parser.add_argument("-c", "--conf_file", + help="Specify config file", metavar="FILE") + args, remaining_argv = conf_parser.parse_known_args(args_str.split()) + + defaults = { + 'api_server_ip': '127.0.0.1', + 'api_server_port': '8082', + 'oper': 'add', + 'control_names': [], + } + ksopts = { + 'admin_user': 'user1', + 'admin_password': 'password1', + 'admin_tenant_name': 'default-domain' + } + + if args.conf_file: + config = ConfigParser.SafeConfigParser() + config.read([args.conf_file]) + defaults.update(dict(config.items("DEFAULTS"))) + if 'KEYSTONE' in config.sections(): + ksopts.update(dict(config.items("KEYSTONE"))) + + # Override with CLI options + # Don't surpress add_help here so it will handle -h + parser = argparse.ArgumentParser( + # Inherit options from config_parser + parents=[conf_parser], + # print script description with -h/--help + description=__doc__, + # Don't mess with format of description + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + defaults.update(ksopts) + parser.set_defaults(**defaults) + + parser.add_argument( + "--host_name", help="hostname name of compute-node") + parser.add_argument("--host_ip", help="IP address of compute-node") + parser.add_argument( + "--control_names", + help="List of control-node names compute node connects to") + parser.add_argument( + "--api_server_ip", help="IP address of api server") + parser.add_argument("--api_server_port", help="Port of api server") + parser.add_argument( + "--oper", default='add', + help="Provision operation to be done(add or del)") + parser.add_argument( + "--admin_user", help="Name of keystone admin user") + parser.add_argument( + "--admin_password", help="Password of keystone admin user") + parser.add_argument( + "--admin_tenant_name", help="Tenamt name for keystone admin user") + + self._args = parser.parse_args(remaining_argv) + + # end _parse_args + + def add_vrouter(self): + gsc_obj = self._global_system_config_obj + + vrouter_obj = VirtualRouter( + self._args.host_name, gsc_obj, + virtual_router_ip_address=self._args.host_ip) + vrouter_exists = True + try: + vrouter_obj = self._vnc_lib.virtual_router_read( + fq_name=vrouter_obj.get_fq_name()) + vrouter_obj.set_bgp_router_list([]) + except NoIdError: + vrouter_exists = False + + for bgp in self._args.control_names: + bgp_router_fq_name = copy.deepcopy( + self._fab_rt_inst_obj.get_fq_name()) + bgp_router_fq_name.append(bgp) + bgp_router_obj = vnc_lib.bgp_router_read( + fq_name=bgp_router_fq_name) + vrouter_obj.add_bgp_router(bgp_router_obj) + + if vrouter_exists: + self._vnc_lib.virtual_router_update(vrouter_obj) + else: + self._vnc_lib.virtual_router_create(vrouter_obj) + + # end add_vrouter + + def del_vrouter(self): + gsc_obj = self._global_system_config_obj + vrouter_obj = VirtualRouter(self._args.host_name, gsc_obj) + self._vnc_lib.virtual_router_delete( + fq_name=vrouter_obj.get_fq_name()) + # end del_vrouter + +# end class VrouterProvisioner + + +def main(args_str=None): + VrouterProvisioner(args_str) +# end main + +if __name__ == "__main__": + main() From 59b2d885c3096813a7675f1e061b962f1f701406 Mon Sep 17 00:00:00 2001 From: stack Date: Sun, 27 Oct 2013 22:10:43 -0700 Subject: [PATCH 031/179] Update nova patch; move files to contrail sub directory --- neutron_v3.patch => contrail/neutron_v3.patch | 0 nova_v2.patch => contrail/nova_v3.patch | 110 +- neutron.patch | 4668 ---------------- neutron_v2.patch | 4705 ----------------- nova_v1.patch | 3238 ------------ stack.sh | 8 +- 6 files changed, 67 insertions(+), 12662 deletions(-) rename neutron_v3.patch => contrail/neutron_v3.patch (100%) rename nova_v2.patch => contrail/nova_v3.patch (96%) delete mode 100644 neutron.patch delete mode 100644 neutron_v2.patch delete mode 100644 nova_v1.patch diff --git a/neutron_v3.patch b/contrail/neutron_v3.patch similarity index 100% rename from neutron_v3.patch rename to contrail/neutron_v3.patch diff --git a/nova_v2.patch b/contrail/nova_v3.patch similarity index 96% rename from nova_v2.patch rename to contrail/nova_v3.patch index 282d29f3a3..a766f0afd8 100644 --- a/nova_v2.patch +++ b/contrail/nova_v3.patch @@ -11,7 +11,7 @@ index e11bfeb..a004cb4 100644 # Constant for max length of network interface names diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py -index 3e4004a..340b2fa 100644 +index 0e38345..32ef4bb 100644 --- nova/virt/libvirt/vif.py +++ nova/virt/libvirt/vif.py @@ -312,6 +312,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): @@ -44,8 +44,8 @@ index 3e4004a..340b2fa 100644 else: raise exception.NovaException( _("Unexpected vif_type=%s") % vif_type) -@@ -567,6 +583,28 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except exception.ProcessExecutionError: +@@ -567,6 +583,31 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except processutils.ProcessExecutionError: LOG.exception(_("Failed while plugging vif"), instance=instance) + def plug_contrail(self, instance, vif): @@ -54,26 +54,29 @@ index 3e4004a..340b2fa 100644 + super(LibvirtGenericVIFDriver, + self).plug(instance, vif) + dev = self.get_vif_devname(vif) -+ linux_net.create_tap_dev(dev) + iface_id = vif['id'] + from nova.virt import netutils + net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) -+ import sys -+ sys.path.append('/opt/stack/nova/plugins/contrail') -+ from config_parser import ContrailVifUpdate -+ ContrailVifUpdate(vif['id'], -+ dev, vif['network']['subnets'][0]['ips'][0]['address'], -+ instance['uuid'], vif['network']['id'], -+ vif['address'], -+ instance['display_name'], -+ instance['hostname'], -+ instance['host'], -+ prefix_len) ++ try: ++ linux_net.create_tap_dev(dev) ++ utils.execute('config_parser', 'create', ++ '--port_id', vif['id'], ++ '--tap_name', dev, ++ '--ip_address', vif['network']['subnets'][0]['ips'][0]['address'], ++ '--instance_id', instance['uuid'], ++ '--vn_id', vif['network']['id'], ++ '--mac_address', vif['address'], ++ '--display_name', instance['display_name'], ++ '--hostname', instance['hostname'], ++ '--host', instance['host'], ++ '--prefix_len', prefix_len) ++ except processutils.ProcessExecutionError: ++ LOG.exception(_("Failed while plugging vif"), instance=instance) + def plug(self, instance, vif): vif_type = vif['type'] -@@ -574,7 +612,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): +@@ -574,7 +615,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): 'vif=%(vif)s'), {'vif_type': vif_type, 'instance': instance, 'vif': vif}) @@ -81,7 +84,7 @@ index 3e4004a..340b2fa 100644 if vif_type is None: raise exception.NovaException( _("vif_type parameter must be present " -@@ -595,6 +632,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): +@@ -595,6 +635,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): self.plug_mlnx_direct(instance, vif) elif vif_type == network_model.VIF_TYPE_MIDONET: self.plug_midonet(instance, vif) @@ -90,8 +93,8 @@ index 3e4004a..340b2fa 100644 else: raise exception.NovaException( _("Unexpected vif_type=%s") % vif_type) -@@ -746,6 +785,18 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except exception.ProcessExecutionError: +@@ -746,6 +788,19 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except processutils.ProcessExecutionError: LOG.exception(_("Failed while unplugging vif"), instance=instance) + def unplug_contrail(self, instance, vif): @@ -100,16 +103,17 @@ index 3e4004a..340b2fa 100644 + super(LibvirtGenericVIFDriver, + self).unplug(instance, vif) + dev = self.get_vif_devname(vif) -+ import sys -+ sys.path.append('/opt/stack/nova/plugins/contrail') -+ from config_parser import ContrailVifDelete -+ ContrailVifDelete(vif['id']) -+ linux_net.delete_net_dev(dev) ++ try: ++ utils.execute('config_parser', 'delete', ++ '--port_id', vif['id']) ++ linux_net.delete_net_dev(dev) ++ except processutils.ProcessExecutionError: ++ LOG.exception(_("Failed while unplugging vif"), instance=instance) + def unplug(self, instance, vif): vif_type = vif['type'] -@@ -770,6 +821,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): +@@ -770,6 +825,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): self.unplug_ivs(instance, vif) elif vif_type == network_model.VIF_TYPE_IOVISOR: self.unplug_iovisor(instance, vif) @@ -119,11 +123,12 @@ index 3e4004a..340b2fa 100644 self.unplug_mlnx_direct(instance, vif) elif vif_type == network_model.VIF_TYPE_MIDONET: diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py -new file mode 100644 -index 0000000..043b77c +new file mode 100755 +index 0000000..acac9fb --- /dev/null +++ plugins/contrail/config_parser.py -@@ -0,0 +1,116 @@ +@@ -0,0 +1,126 @@ ++#! /usr/bin/env python +import os +import sys +import cgitb @@ -185,15 +190,18 @@ index 0000000..043b77c +# end ContrailVifUpdate + +def update_vif_file(args): -+ #import pdb; pdb.set_trace() -+ if (args.port_id and args.tap_name and -+ args.ip_address and args.instance_id and -+ args.vn_id and args.mac_address and -+ args.host and args.prefix_len): -+ ContrailVifUpdate(args.port_id, args.tap_name, -+ args.ip_address, args.instance_id, -+ args.vn_id, args.mac_address, args.display_name, -+ args.hostname, args.host, args.prefix_len) ++ if args.which is 'create': ++ if (args.port_id and args.tap_name and ++ args.ip_address and args.instance_id and ++ args.vn_id and args.mac_address and ++ args.host and args.prefix_len): ++ ContrailVifUpdate(args.port_id, args.tap_name, ++ args.ip_address, args.instance_id, ++ args.vn_id, args.mac_address, args.display_name, ++ args.hostname, args.host, args.prefix_len) ++ elif args.which is 'delete': ++ if args.port_id is not None: ++ ContrailVifDelete(args.port_id) + +# end update_vif_file + @@ -216,22 +224,28 @@ index 0000000..043b77c + #defaults.update(ksopts) + #parser.set_defaults(**defaults) + -+ parser.add_argument("--port_id", help = "port id") -+ parser.add_argument("--tap_name", help = "tap_name") -+ parser.add_argument("--ip_address", help = "ip_address") -+ parser.add_argument("--instance_id", help = "instance_id") -+ parser.add_argument("--vn_id", help = "vn_id") -+ parser.add_argument("--mac_address", help = "mac_address") -+ parser.add_argument("--display_name", help = "display_name") -+ parser.add_argument("--hostname", help = "hostname") -+ parser.add_argument("--host", help = "host") -+ parser.add_argument("--prefix_len", help = "prefix_len") ++ subparsers = parser.add_subparsers(help='commands') ++ create_parser = subparsers.add_parser('create', help='Create/Modify vif') ++ create_parser.set_defaults(which='create') ++ create_parser.add_argument("--port_id", help = "port id") ++ create_parser.add_argument("--tap_name", help = "tap_name") ++ create_parser.add_argument("--ip_address", help = "ip_address") ++ create_parser.add_argument("--instance_id", help = "instance_id") ++ create_parser.add_argument("--vn_id", help = "vn_id") ++ create_parser.add_argument("--mac_address", help = "mac_address") ++ create_parser.add_argument("--display_name", help = "display_name") ++ create_parser.add_argument("--hostname", help = "hostname") ++ create_parser.add_argument("--host", help = "host") ++ create_parser.add_argument("--prefix_len", help = "prefix_len") ++ delete_parser = subparsers.add_parser('delete', help='Delete vif') ++ delete_parser.set_defaults(which='delete') ++ delete_parser.add_argument("--port_id", help = "port id") ++ print parser.parse_args() + args = parser.parse_args(remaining_argv) + update_vif_file(args) +# end parse_args + +def main(args_str=None): -+ #import pdb; pdb.set_trace() + if not args_str: + args_str = ' '.join(sys.argv[1:]) + args = parse_args(args_str) diff --git a/neutron.patch b/neutron.patch deleted file mode 100644 index 9f1ed60402..0000000000 --- a/neutron.patch +++ /dev/null @@ -1,4668 +0,0 @@ -diff --git etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini -new file mode 100644 -index 0000000..ba1afba ---- /dev/null -+++ etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini -@@ -0,0 +1,4 @@ -+# Juniper plugin specific configuration -+ -+# JunosVContrail specifc configuration for plugin -+[JunosVContrail] -diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py -new file mode 100644 -index 0000000..5d610b3 ---- /dev/null -+++ neutron/extensions/ipam.py -@@ -0,0 +1,140 @@ -+from abc import abstractmethod -+ -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron.api import extensions -+from neutron import manager -+from oslo.config import cfg -+ -+ -+# Ipam Exceptions -+class IpamNotFound(qexception.NotFound): -+ message = _("IPAM %(id)s could not be found") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'ipams': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:regex': attr.UUID_PATTERN}, -+ 'is_visible': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'fq_name': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ 'mgmt': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': None}, -+ 'nets_using': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True, 'default': ''} -+ }, -+} -+ -+# TODO should this be tied to ipam extension? -+EXTENDED_ATTRIBUTES_2_0 = { -+ 'networks': { -+ 'contrail:fq_name': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:policys': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ 'contrail:subnet_ipam': {'allow_post': False, -+ 'allow_put': False, -+ 'default': '', -+ 'is_visible': True}, -+ }, -+ 'subnets': { -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:ipam_fq_name': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ } -+} -+ -+ -+class Ipam(object): -+ -+ @classmethod -+ def get_name(cls): -+ return "Network IP Address Management" -+ -+ @classmethod -+ def get_alias(cls): -+ return "ipam" -+ -+ @classmethod -+ def get_description(cls): -+ return ("Configuration object for holding common to a set of" -+ " IP address blocks") -+ -+ @classmethod -+ def get_namespace(cls): -+ return "http://docs.openstack.org/TODO" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2012-07-20T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ exts = [] -+ plugin = manager.QuantumManager.get_plugin() -+ for resource_name in ['ipam']: -+ collection_name = resource_name + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) -+ -+ member_actions = {} -+ -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, -+ member_actions=member_actions) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ member_actions=member_actions) -+ exts.append(ex) -+ -+ return exts -+ -+ def get_extended_resources(self, version): -+ if version == "2.0": -+ return EXTENDED_ATTRIBUTES_2_0 -+ else: -+ return {} -+#end class Ipam -+ -+ -+class IpamPluginBase(object): -+ -+ @abstractmethod -+ def create_ipam(self, context, ipam): -+ pass -+ -+ @abstractmethod -+ def update_ipam(self, context, id, ipam): -+ pass -+ -+ @abstractmethod -+ def get_ipam(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def delete_ipam(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_ipams(self, context, filters=None, fields=None): -+ pass -+#end class IpamPluginBase -diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py -new file mode 100644 -index 0000000..cb64c50 ---- /dev/null -+++ neutron/plugins/juniper/contrail/contrailplugin.py -@@ -0,0 +1,1160 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+ -+import ConfigParser -+import logging -+from pprint import pformat -+ -+#from neutron.manager import NeutronManager -+from neutron.common import exceptions as exc -+from neutron.db import db_base_plugin_v2 -+from neutron.extensions import l3 -+from neutron.extensions import securitygroup -+#from neutron.extensions import vpcroutetable -+ -+import cgitb -+from httplib2 import Http -+from oslo.config import cfg -+import re -+import string -+import sys -+ -+import ctdb.config_db -+ -+LOG = logging.getLogger(__name__) -+ -+vnc_opts = [ -+ cfg.StrOpt('api_server_ip', default='127.0.0.1'), -+ cfg.StrOpt('api_server_port', default='8082'), -+] -+ -+ -+def _read_cfg(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.get(section, option) -+ except (AttributeError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+def _read_cfg_boolean(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.getboolean(section, option) -+ except (AttributeError, ValueError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, -+ l3.RouterPluginBase, -+ securitygroup.SecurityGroupPluginBase): -+#vpcroutetable.RouteTablePluginBase): -+ -+ supported_extension_aliases = ["ipam", "policy", "security-group", -+ "router", "route-table", "port-security"] -+ __native_bulk_support = False -+ _cfgdb = None -+ _args = None -+ _tenant_id_dict = {} -+ _tenant_name_dict = {} -+ -+ @classmethod -+ def _parse_class_args(cls, cfg_parser): -+ cfg_parser.read("/etc/neutron/plugins/juniper/" -+ "contrail/ContrailPlugin.ini" -+ ) -+ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', -+ 'multi_tenancy', False) -+ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') -+ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') -+ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', -+ 'user1') -+ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_password', 'password1') -+ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_tenant_name', -+ 'default-domain') -+ cls._tenants_api = '%s/tenants' % (cls._auth_url) -+ pass -+ -+ @classmethod -+ def _connect_to_db(cls): -+ """ -+ Many instantiations of plugin (base + extensions) but need to have -+ only one config db conn (else error from ifmap-server) -+ """ -+ cls._cfgdb_map = {} -+ if cls._cfgdb is None: -+ sip = cfg.CONF.APISERVER.api_server_ip -+ sport = cfg.CONF.APISERVER.api_server_port -+ # Initialize connection to DB and add default entries -+ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, -+ cls._admin_password, -+ cls._admin_tenant_name, -+ sip, sport) -+ cls._cfgdb.manager = cls -+ -+ @classmethod -+ def _get_user_cfgdb(cls, context): -+ if not cls._multi_tenancy: -+ return cls._cfgdb -+ user_id = context.user_id -+ role = string.join(context.roles, ",") -+ if user_id not in cls._cfgdb_map: -+ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( -+ cls._admin_user, cls._admin_password, cls._admin_tenant_name, -+ cfg.CONF.APISERVER.api_server_ip, -+ cfg.CONF.APISERVER.api_server_port, -+ user_info={'user_id': user_id, 'role': role}) -+ cls._cfgdb_map[user_id].manager = cls -+ -+ return cls._cfgdb_map[user_id] -+ -+ @classmethod -+ def _tenant_list_from_keystone(cls): -+ # get all tenants -+ hdrs = {'X-Auth-Token': cls._admin_token, -+ 'Content-Type': 'application/json'} -+ try: -+ rsp, content = Http().request(cls._tenants_api, -+ method="GET", headers=hdrs) -+ if rsp.status != 200: -+ return -+ except Exception: -+ return -+ -+ # transform needed for python compatibility -+ content = re.sub('true', 'True', content) -+ content = re.sub('null', 'None', content) -+ content = eval(content) -+ -+ # bail if response is unexpected -+ if 'tenants' not in content: -+ return -+ -+ # create a dictionary for id->name and name->id mapping -+ for tenant in content['tenants']: -+ print 'Adding tenant %s:%s to cache' % (tenant['name'], -+ tenant['id']) -+ cls._tenant_id_dict[tenant['id']] = tenant['name'] -+ cls._tenant_name_dict[tenant['name']] = tenant['id'] -+ -+ def update_security_group(self, context, id, security_group): -+ pass -+ -+ def __init__(self): -+ cfg.CONF.register_opts(vnc_opts, 'APISERVER') -+ -+ cfg_parser = ConfigParser.ConfigParser() -+ ContrailPlugin._parse_class_args(cfg_parser) -+ -+ ContrailPlugin._connect_to_db() -+ self._cfgdb = ContrailPlugin._cfgdb -+ -+ ContrailPlugin._tenant_list_from_keystone() -+ -+ @classmethod -+ def tenant_id_to_name(cls, id): -+ # bail if we never built the list successfully -+ if len(cls._tenant_id_dict) == 0: -+ return id -+ # check cache -+ if id in cls._tenant_id_dict: -+ return cls._tenant_id_dict[id] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id -+ -+ @classmethod -+ def tenant_name_to_id(cls, name): -+ # bail if we never built the list successfully -+ if len(cls._tenant_name_dict) == 0: -+ return name -+ # check cache -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ else: -+ return name -+ -+ # Network API handlers -+ def create_network(self, context, network): -+ """ -+ Creates a new Virtual Network, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_create(network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("create_network(): " + pformat(net_dict) + "\n") -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_network(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_read(id, fields) -+ -+ # verify transformation is conforming to api -+ if not fields: -+ # should return all fields -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ fields, False) -+ net_dict.update(net_info['q_extra_data']) -+ else: -+ net_dict = net_info['q_api_data'] -+ -+ LOG.debug("get_network(): " + pformat(net_dict)) -+ return self._fields(net_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_network(self, context, net_id, network): -+ """ -+ Updates the attributes of a particular Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_update(net_id, network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("update_network(): " + pformat(net_dict)) -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_network(self, context, net_id): -+ """ -+ Deletes the network with the specified network identifier -+ belonging to the specified tenant. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.network_delete(net_id) -+ LOG.debug("delete_network(): " + pformat(net_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_info = cfgdb.network_list(filters) -+ -+ nets_dicts = [] -+ for n_info in nets_info: -+ # verify transformation is conforming to api -+ n_dict = self._make_network_dict(n_info['q_api_data'], fields, -+ False) -+ -+ n_dict.update(n_info['q_extra_data']) -+ nets_dicts.append(n_dict) -+ -+ LOG.debug( -+ "get_networks(): filters: " + pformat(filters) + " data: " -+ + pformat(nets_dicts)) -+ return nets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_count = cfgdb.network_count(filters) -+ LOG.debug("get_networks_count(): " + str(nets_count)) -+ return nets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Subnet API handlers -+ def create_subnet(self, context, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_create(subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("create_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnet(self, context, subnet_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_read(subnet_id) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], -+ fields) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("get_subnet(): " + pformat(subnet_dict)) -+ return self._fields(subnet_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_subnet(self, context, subnet_id, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("update_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_subnet(self, context, subnet_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.subnet_delete(subnet_id) -+ -+ LOG.debug("delete_subnet(): " + pformat(subnet_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets(self, context, filters=None, fields=None): -+ """ -+ Called from Neutron API -> get_ -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_info = cfgdb.subnets_list(filters) -+ -+ subnets_dicts = [] -+ for sn_info in subnets_info: -+ # verify transformation is conforming to api -+ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) -+ -+ sn_dict.update(sn_info['q_extra_data']) -+ subnets_dicts.append(sn_dict) -+ -+ LOG.debug( -+ "get_subnets(): filters: " + pformat(filters) + " data: " -+ + pformat(subnets_dicts)) -+ return subnets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_count = cfgdb.subnets_count(filters) -+ LOG.debug("get_subnets_count(): " + str(subnets_count)) -+ return subnets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Ipam API handlers -+ def create_ipam(self, context, ipam): -+ """ -+ Creates a new IPAM, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_create(ipam['ipam']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("create_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipam(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("get_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_ipam(self, context, id, ipam): -+ """ -+ Updates the attributes of a particular IPAM. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_update(id, ipam) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("update_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_ipam(self, context, ipam_id): -+ """ -+ Deletes the ipam with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.ipam_delete(ipam_id) -+ -+ LOG.debug("delete_ipam(): " + pformat(ipam_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_info = cfgdb.ipam_list(filters) -+ -+ ipams_dicts = [] -+ for ipam_info in ipams_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ ipams_dicts.append(ipam_dict) -+ -+ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) -+ return ipams_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_count = cfgdb.ipams_count(filters) -+ LOG.debug("get_ipams_count(): " + str(ipams_count)) -+ return ipams_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Policy API handlers -+ def create_policy(self, context, policy): -+ """ -+ Creates a new Policy, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_create(policy['policy']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("create_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("get_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_policy(self, context, id, policy): -+ """ -+ Updates the attributes of a particular Policy. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_update(id, policy) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("update_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_policy(self, context, policy_id): -+ """ -+ Deletes the Policy with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.policy_delete(policy_id) -+ -+ LOG.debug("delete_policy(): " + pformat(policy_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policys(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policys_info = cfgdb.policy_list(filters) -+ -+ policys_dicts = [] -+ for policy_info in policys_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ policys_dicts.append(policy_dict) -+ -+ LOG.debug("get_policys(): " + pformat(policys_dicts)) -+ return policys_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_count = cfgdb.policy_count(filters) -+ LOG.debug("get_policy_count(): " + str(policy_count)) -+ return policy_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Floating IP API handlers -+ def _make_floatingip_dict(self, floatingip, fields=None): -+ res = {'id': floatingip['id'], -+ 'tenant_id': floatingip['tenant_id'], -+ 'floating_ip_address': floatingip['floating_ip_address'], -+ 'floating_network_id': floatingip['floating_network_id'], -+ 'router_id': floatingip['router_id'], -+ 'port_id': floatingip['fixed_port_id'], -+ 'fixed_ip_address': floatingip['fixed_ip_address']} -+ return self._fields(res, fields) -+ -+ def create_floatingip(self, context, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("create_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_floatingip(self, context, fip_id, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_update(fip_id, -+ floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("update_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingip(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_read(id) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("get_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_floatingip(self, context, fip_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.floatingip_delete(fip_id) -+ LOG.debug("delete_floating(): " + pformat(fip_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fips_info = cfgdb.floatingip_list(filters) -+ -+ fips_dicts = [] -+ for fip_info in fips_info: -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ fips_dicts.append(fip_dict) -+ -+ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) -+ return fips_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ floatingips_count = cfgdb.floatingip_count(filters) -+ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) -+ return floatingips_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Port API handlers -+ def create_port(self, context, port): -+ """ -+ Creates a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_create(port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("create_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_port(self, context, port_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_read(port_id) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data'], fields) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("get_port(): " + pformat(port_dict)) -+ return self._fields(port_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_port(self, context, port_id, port): -+ """ -+ Updates the attributes of a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_update(port_id, port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("update_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_port(self, context, port_id): -+ """ -+ Deletes a port on a specified Virtual Network, -+ if the port contains a remote interface attachment, -+ the remote interface is first un-plugged and then the port -+ is deleted. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.port_delete(port_id) -+ LOG.debug("delete_port(): " + pformat(port_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports(self, context, filters=None, fields=None): -+ """ -+ Retrieves all port identifiers belonging to the -+ specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_info = cfgdb.port_list(filters) -+ -+ ports_dicts = [] -+ for p_info in ports_info: -+ # verify transformation is conforming to api -+ p_dict = self._make_port_dict(p_info['q_api_data'], fields) -+ -+ p_dict.update(p_info['q_extra_data']) -+ ports_dicts.append(p_dict) -+ -+ LOG.debug( -+ "get_ports(): filter: " + pformat(filters) + 'data: ' -+ + pformat(ports_dicts)) -+ return ports_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_count = cfgdb.port_count(filters) -+ LOG.debug("get_ports_count(): " + str(ports_count)) -+ return ports_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): -+ """ -+ Attaches a remote interface to the specified port on the -+ specified Virtual Network. -+ """ -+ port = self._get_port(tenant_id, net_id, port_id) -+ # Validate attachment -+ self._validate_attachment(tenant_id, net_id, port_id, -+ remote_interface_id) -+ if port['interface_id']: -+ raise exc.PortInUse(net_id=net_id, port_id=port_id, -+ att_id=port['interface_id']) -+ -+ def unplug_interface(self, tenant_id, net_id, port_id): -+ """ -+ Detaches a remote interface from the specified port on the -+ specified Virtual Network. -+ """ -+ self._get_port(tenant_id, net_id, port_id) -+ -+ # VPC route table handlers -+ def _make_route_table_routes_dict(self, route_table_route, fields=None): -+ res = {'prefix': route_table_route['prefix'], -+ 'next_hop': route_table_route['next_hop']} -+ -+ return self._fields(res, fields) -+ -+ def _make_route_table_dict(self, route_table, fields=None): -+ res = {'id': route_table['id'], -+ 'name': route_table['name'], -+ 'fq_name': route_table['fq_name'], -+ 'tenant_id': route_table['tenant_id']} -+ if route_table['routes']: -+ res['routes'] = [self._make_route_table_routes_dict(r) -+ for r in route_table['routes']['route']] -+ return self._fields(res, fields) -+ -+ def create_route_table(self, context, route_table): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_create( -+ route_table['route_table']) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_route_table(self, context, id, route_table): -+ """ -+ Updates the attributes of a particular route table. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_update(id, route_table['route_table']) -+ -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_route_table(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.route_table_delete(id) -+ LOG.debug("delete_route_table(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_tables(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ route_tables_info = cfgdb.route_table_list(context, filters) -+ -+ route_tables_dicts = [] -+ for rt_info in route_tables_info: -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ route_tables_dicts.append(rt_dict) -+ -+ LOG.debug( -+ "get_route_tables(): filter: " + pformat(filters) -+ + 'data: ' + pformat(route_tables_dicts)) -+ return route_tables_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_table(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_read(id) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ -+ LOG.debug("get_route_table(): " + pformat(rt_dict)) -+ return self._fields(rt_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # VPC route table svc instance handlers -+ def _make_svc_instance_dict(self, svc_instance, fields=None): -+ res = {'id': svc_instance['id'], -+ 'name': svc_instance['name'], -+ 'tenant_id': svc_instance['tenant_id']} -+ if svc_instance['internal_net']: -+ res['internal_net'] = svc_instance['internal_net'] -+ if svc_instance['external_net']: -+ res['external_net'] = svc_instance['external_net'] -+ return self._fields(res, fields) -+ -+ def create_nat_instance(self, context, nat_instance): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_create( -+ nat_instance['nat_instance']) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("create_nat_instance(): " + pformat(si_dict)) -+ return si_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_nat_instance(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.svc_instance_delete(id) -+ LOG.debug("delete_nat_instance(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instances(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ svc_instances_info = cfgdb.svc_instance_list(context, filters) -+ -+ svc_instances_dicts = [] -+ for si_info in svc_instances_info: -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ svc_instances_dicts.append(si_dict) -+ -+ LOG.debug( -+ "get_nat_instances(): filter: " + pformat(filters) -+ + 'data: ' + pformat(svc_instances_dicts)) -+ return svc_instances_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instance(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_read(id) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("get_nat_instance(): " + pformat(si_dict)) -+ return self._fields(si_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Security Group handlers -+ def _make_security_group_rule_dict(self, security_group_rule, fields=None): -+ res = {'id': security_group_rule['id'], -+ 'tenant_id': security_group_rule['tenant_id'], -+ 'security_group_id': security_group_rule['security_group_id'], -+ 'ethertype': security_group_rule['ethertype'], -+ 'direction': security_group_rule['direction'], -+ 'protocol': security_group_rule['protocol'], -+ 'port_range_min': security_group_rule['port_range_min'], -+ 'port_range_max': security_group_rule['port_range_max'], -+ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], -+ 'remote_group_id': security_group_rule['remote_group_id']} -+ -+ return self._fields(res, fields) -+ -+ def _make_security_group_dict(self, security_group, fields=None): -+ res = {'id': security_group['id'], -+ 'name': security_group['name'], -+ 'tenant_id': security_group['tenant_id'], -+ 'description': security_group['description']} -+ res['security_group_rules'] = [self._make_security_group_rule_dict(r) -+ for r in security_group['rules']] -+ return self._fields(res, fields) -+ -+ def create_security_group(self, context, security_group): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_create( -+ security_group['security_group']) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("create_security_group(): " + pformat(sg_dict)) -+ return sg_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_delete(id) -+ LOG.debug("delete_security_group(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_groups(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_groups_info = cfgdb.security_group_list(context, filters) -+ -+ security_groups_dicts = [] -+ for sg_info in security_groups_info: -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ security_groups_dicts.append(sg_dict) -+ -+ LOG.debug( -+ "get_security_groups(): filter: " + pformat(filters) -+ + 'data: ' + pformat(security_groups_dicts)) -+ return security_groups_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_read(id) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("get_security_group(): " + pformat(sg_dict)) -+ return self._fields(sg_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def create_security_group_rule(self, context, security_group_rule): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_create( -+ security_group_rule['security_group_rule']) -+ -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data']) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) -+ return sgr_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group_rule(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_rule_delete(id) -+ LOG.debug("delete_security_group_rule(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rules(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_group_rules_info = cfgdb.security_group_rule_list(filters) -+ -+ security_group_rules_dicts = [] -+ for sgr_info in security_group_rules_info: -+ for sgr in sgr_info: -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr['q_api_data'], fields) -+ sgr_dict.update(sgr['q_extra_data']) -+ security_group_rules_dicts.append(sgr_dict) -+ -+ LOG.debug( -+ "get_security_group_rules(): filter: " + pformat(filters) + -+ 'data: ' + pformat(security_group_rules_dicts)) -+ return security_group_rules_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rule(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_read(id) -+ -+ # verify transformation is conforming to api -+ sgr_dict = {} -+ if sgr_info != {}: -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data'], fields) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) -+ return self._fields(sgr_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py -new file mode 100644 -index 0000000..a69dda1 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/config_db.py -@@ -0,0 +1,2235 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+import json -+import re -+import requests -+import socket -+import time -+import uuid -+from netaddr import IPNetwork, IPSet, IPAddress -+ -+from neutron.api.v2 import attributes as attr -+from neutron.common import constants -+from neutron.common import exceptions -+from vnc_api.common import exceptions as vnc_exc -+from vnc_api import vnc_api -+ -+_DEFAULT_HEADERS = { -+ 'Content-type': 'application/json; charset="UTF-8"', } -+ -+CREATE = 1 -+READ = 2 -+UPDATE = 3 -+DELETE = 4 -+ -+ -+class DBInterface(object): -+ """ -+ An instance of this class forwards requests to vnc cfg api (web)server -+ """ -+ Q_URL_PREFIX = '/extensions/ct' -+ -+ def __init__(self, admin_name, admin_password, admin_tenant_name, -+ api_srvr_ip, api_srvr_port, user_info=None): -+ self._api_srvr_ip = api_srvr_ip -+ self._api_srvr_port = api_srvr_port -+ -+ self._db_cache = {} -+ self._db_cache['q_networks'] = {} -+ self._db_cache['q_subnets'] = {} -+ self._db_cache['q_subnet_maps'] = {} -+ self._db_cache['q_policies'] = {} -+ self._db_cache['q_ipams'] = {} -+ self._db_cache['q_floatingips'] = {} -+ self._db_cache['q_ports'] = {} -+ self._db_cache['q_fixed_ip_to_subnet'] = {} -+ #obj-uuid to tenant-uuid mapping -+ self._db_cache['q_obj_to_tenant'] = {} -+ #port count per tenant-id -+ self._db_cache['q_tenant_port_count'] = {} -+ self._db_cache['vnc_networks'] = {} -+ self._db_cache['vnc_ports'] = {} -+ self._db_cache['vnc_projects'] = {} -+ self._db_cache['vnc_instance_ips'] = {} -+ -+ # Retry till a api-server is up -+ connected = False -+ while not connected: -+ try: -+ self._vnc_lib = vnc_api.VncApi( -+ admin_name, admin_password, -+ admin_tenant_name, api_srvr_ip, -+ api_srvr_port, '/', user_info=user_info) -+ connected = True -+ except requests.exceptions.RequestException: -+ time.sleep(3) -+ -+ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key -+ subnet_map = self._vnc_lib.kv_retrieve(key=None) -+ for kv_dict in subnet_map: -+ key = kv_dict['key'] -+ if len(key.split()) == 1: -+ subnet_id = key -+ # uuid key, fixup value portion to 'net_id pfx/len' format -+ # if not already so -+ if len(kv_dict['value'].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ net_fq_name = kv_dict['value'].split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ self._vnc_lib.kv_delete(subnet_id) -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, -+ kv_dict['value'].split()[1]) -+ self._vnc_lib.kv_store(subnet_id, new_subnet_key) -+ else: # subnet key -+ if len(key.split()[0].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ # delete old key, convert to new key format and save -+ old_subnet_key = key -+ self._vnc_lib.kv_delete(old_subnet_key) -+ -+ subnet_id = kv_dict['value'] -+ net_fq_name = key.split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) -+ self._vnc_lib.kv_store(new_subnet_key, subnet_id) -+ -+ # Helper routines -+ def _request_api_server(self, url, method, data=None, headers=None): -+ if method == 'GET': -+ return requests.get(url) -+ if method == 'POST': -+ return requests.post(url, data=data, headers=headers) -+ if method == 'DELETE': -+ return requests.delete(url) -+ -+ def _relay_request(self, request): -+ """ -+ Send received request to api server -+ """ -+ # chop neutron parts of url and add api server address -+ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) -+ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, -+ url_path) -+ -+ return self._request_api_server( -+ url, request.environ['REQUEST_METHOD'], -+ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) -+ -+ def _obj_to_json(self, obj): -+ return dict((k, v) for k, v in obj.__dict__.iteritems()) -+ -+ def _ensure_instance_exists(self, instance_id): -+ instance_name = instance_id -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ try: -+ id = self._vnc_lib.obj_to_id(instance_obj) -+ instance_obj = self._vnc_lib.virtual_machine_read(id=id) -+ except vnc_exc.NoIdError: # instance doesn't exist, create it -+ instance_obj.uuid = instance_id -+ self._vnc_lib.virtual_machine_create(instance_obj) -+ -+ return instance_obj -+ -+ def _ensure_default_security_group_exists(self, proj_id): -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ sg_groups = proj_obj.get_security_groups() -+ for sg_group in sg_groups or []: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) -+ if sg_obj.name == 'default': -+ return -+ -+ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) -+ self._vnc_lib.security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ #allow ingress traffic from within default security group -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'ingress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ def _get_obj_tenant_id(self, q_type, obj_uuid): -+ # Get the mapping from cache, else seed cache and return -+ try: -+ return self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except KeyError: -+ # Seed the cache and return -+ if q_type == 'port': -+ port_obj = self._virtual_machine_interface_read(obj_uuid) -+ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] -+ # recurse up type-hierarchy -+ tenant_id = self._get_obj_tenant_id('network', net_id) -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ if q_type == 'network': -+ net_obj = self._virtual_network_read(net_id=obj_uuid) -+ tenant_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ return None -+ -+ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): -+ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid -+ -+ def _del_obj_tenant_id(self, obj_uuid): -+ try: -+ del self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except Exception: -+ pass -+ -+ def _project_read(self, proj_id=None, fq_name=None): -+ if proj_id: -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][proj_id] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ fq_name_str = json.dumps(proj_obj.get_fq_name()) -+ self._db_cache['vnc_projects'][proj_id] = proj_obj -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ return proj_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][fq_name_str] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj -+ return proj_obj -+ -+ def _security_group_rule_create(self, sg_id, sg_rule): -+ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) -+ rules = sg_vnc.get_security_group_entries() -+ if rules is None: -+ rules = vnc_api.PolicyEntriesType([sg_rule]) -+ else: -+ rules.add_policy_rule(sg_rule) -+ -+ sg_vnc.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_vnc) -+ return -+ -+ def _security_group_rule_find(self, sgr_id): -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ -+ for sg in project_sgs: -+ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) -+ sgr_entries = sg_obj.get_security_group_entries() -+ if sgr_entries is None: -+ continue -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ if sg_rule.get_rule_uuid() == sgr_id: -+ return sg_obj, sg_rule -+ -+ return None, None -+ -+ def _security_group_rule_delete(self, sg_obj, sg_rule): -+ rules = sg_obj.get_security_group_entries() -+ rules.get_policy_rule().remove(sg_rule) -+ sg_obj.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_obj) -+ return -+ -+ def _security_group_create(self, sg_obj): -+ sg_uuid = self._vnc_lib.security_group_create(sg_obj) -+ return sg_uuid -+ -+ def _security_group_delete(self, sg_id): -+ self._vnc_lib.security_group_delete(id=sg_id) -+ -+ def _svc_instance_create(self, si_obj): -+ si_uuid = self._vnc_lib.service_instance_create(si_obj) -+ st_fq_name = ['default-domain', 'nat-template'] -+ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) -+ si_obj.set_service_template(st_obj) -+ self._vnc_lib.service_instance_update(si_obj) -+ -+ return si_uuid -+ -+ def _svc_instance_delete(self, si_id): -+ self._vnc_lib.service_instance_delete(id=si_id) -+ -+ def _route_table_create(self, rt_obj): -+ rt_uuid = self._vnc_lib.route_table_create(rt_obj) -+ return rt_uuid -+ -+ def _route_table_delete(self, rt_id): -+ self._vnc_lib.route_table_delete(id=rt_id) -+ -+ def _virtual_network_create(self, net_obj): -+ net_uuid = self._vnc_lib.virtual_network_create(net_obj) -+ -+ return net_uuid -+ -+ def _virtual_network_read(self, net_id=None, fq_name=None): -+ if net_id: -+ try: -+ # return self._db_cache['vnc_networks'][net_id] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(id=net_id) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ self._db_cache['vnc_networks'][net_id] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ return net_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_networks'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ return net_obj -+ -+ def _virtual_network_update(self, net_obj): -+ self._vnc_lib.virtual_network_update(net_obj) -+ # read back to get subnet gw allocated by api-server -+ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ -+ def _virtual_network_delete(self, net_id): -+ fq_name_str = None -+ try: -+ net_obj = self._db_cache['vnc_networks'][net_id] -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_network_delete(id=net_id) -+ -+ try: -+ del self._db_cache['vnc_networks'][net_id] -+ if fq_name_str: -+ del self._db_cache['vnc_networks'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _virtual_machine_interface_create(self, port_obj): -+ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) -+ -+ return port_uuid -+ -+ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): -+ if port_id: -+ try: -+ # return self._db_cache['vnc_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ id=port_id) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ self._db_cache['vnc_ports'][port_id] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ return port_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_ports'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ fq_name=fq_name) -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ return port_obj -+ -+ def _virtual_machine_interface_update(self, port_obj): -+ self._vnc_lib.virtual_machine_interface_update(port_obj) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ -+ def _virtual_machine_interface_delete(self, port_id): -+ fq_name_str = None -+ try: -+ port_obj = self._db_cache['vnc_ports'][port_id] -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_machine_interface_delete(id=port_id) -+ -+ try: -+ del self._db_cache['vnc_ports'][port_id] -+ if fq_name_str: -+ del self._db_cache['vnc_ports'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _instance_ip_create(self, iip_obj): -+ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) -+ -+ return iip_uuid -+ -+ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): -+ if instance_ip_id: -+ try: -+ # return self._db_cache['vnc_instance_ips'][instance_ip_id] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ return iip_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_instance_ips'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ return iip_obj -+ -+ def _instance_ip_update(self, iip_obj): -+ self._vnc_lib.instance_ip_update(iip_obj) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ -+ def _instance_ip_delete(self, instance_ip_id): -+ fq_name_str = None -+ try: -+ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.instance_ip_delete(id=instance_ip_id) -+ -+ try: -+ del self._db_cache['vnc_instance_ips'][instance_ip_id] -+ if fq_name_str: -+ del self._db_cache['vnc_instance_ips'][fq_name_str] -+ except KeyError: -+ pass -+ -+ # find projects on a given domain -+ def _project_list_domain(self, domain_id): -+ fq_name = ['default-domain'] -+ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) -+ -+ return resp_dict['projects'] -+ -+ # find network ids on a given project -+ def _network_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) -+ -+ return resp_dict['virtual-networks'] -+ -+ def _ipam_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) -+ -+ return resp_dict['network-ipams'] -+ -+ def _security_group_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ self._ensure_default_security_group_exists(project_uuid) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _security_group_entries_list_sg(self, sg_id): -+ try: -+ sg_uuid = str(uuid.UUID(sg_id)) -+ except Exception: -+ print "Error in converting SG uuid %s" % (sg_id) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _route_table_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) -+ -+ return resp_dict['route-tables'] -+ -+ def _svc_instance_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) -+ -+ return resp_dict['service-instances'] -+ -+ def _policy_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) -+ -+ return resp_dict['network-policys'] -+ -+ # find floating ip pools a project has access to -+ def _fip_pool_refs_project(self, project_id): -+ project_uuid = str(uuid.UUID(project_id)) -+ project_obj = self._project_read(proj_id=project_uuid) -+ -+ return project_obj.get_floating_ip_pool_refs() -+ -+ # find networks of floating ip pools project has access to -+ def _fip_pool_ref_networks(self, project_id): -+ ret_nets = [] -+ -+ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) -+ if not proj_fip_pool_refs: -+ return ret_nets -+ -+ for fip_pool_ref in proj_fip_pool_refs: -+ fip_uuid = fip_pool_ref['uuid'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) -+ net_uuid = fip_pool_obj.parent_uuid -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ ret_nets.append({'uuid': net_obj.uuid, -+ 'fq_name': net_obj.get_fq_name()}) -+ -+ return ret_nets -+ -+ # find floating ip pools defined by network -+ def _fip_pool_list_network(self, net_id): -+ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) -+ -+ return resp_dict['floating-ip-pools'] -+ -+ # find port ids on a given network -+ def _port_list_network(self, network_id): -+ ret_list = [] -+ -+ try: -+ net_obj = self._virtual_network_read(net_id=network_id) -+ except vnc_exc.NoIdError: -+ return ret_list -+ -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ for port_back_ref in port_back_refs: -+ ret_list.append({'id': port_back_ref['uuid']}) -+ -+ return ret_list -+ -+ # find port ids on a given project -+ def _port_list_project(self, project_id): -+ ret_list = [] -+ project_nets = self._network_list_project(project_id) -+ for net in project_nets: -+ net_ports = self._port_list_network(net['uuid']) -+ ret_list.extend(net_ports) -+ -+ return ret_list -+ -+ # Returns True if -+ # * no filter is specified -+ # OR -+ # * search-param is not present in filters -+ # OR -+ # * 1. search-param is present in filters AND -+ # 2. resource matches param-list AND -+ # 3. shared parameter in filters is False -+ def _filters_is_present(self, filters, key_name, match_value): -+ if filters: -+ if key_name in filters: -+ try: -+ if ('shared' in filters and -+ filters['shared'][0] is True): -+ # yuck, q-api has shared as list always of 1 elem -+ return False # no shared-resource support -+ except ValueError: # not in requested list -+ return False -+ elif len(filters.keys()) == 1: -+ shared_val = filters.get('shared', None) -+ if shared_val and shared_val[0] is True: -+ return False -+ -+ return True -+ -+ def _network_read(self, net_uuid): -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ return net_obj -+ -+ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): -+ #import pdb; pdb.set_trace() -+ self._vnc_lib.kv_store(subnet_id, subnet_key) -+ self._vnc_lib.kv_store(subnet_key, subnet_id) -+ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key -+ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id -+ -+ def _subnet_vnc_read_mapping(self, id=None, key=None): -+ if id: -+ try: -+ return self._db_cache['q_subnet_maps'][id] -+ #raise KeyError -+ except KeyError: -+ subnet_key = self._vnc_lib.kv_retrieve(id) -+ self._db_cache['q_subnet_maps'][id] = subnet_key -+ return subnet_key -+ if key: -+ try: -+ return self._db_cache['q_subnet_maps'][key] -+ #raise KeyError -+ except KeyError: -+ subnet_id = self._vnc_lib.kv_retrieve(key) -+ self._db_cache['q_subnet_maps'][key] = subnet_id -+ return subnet_id -+ -+ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): -+ if id: -+ return self._subnet_vnc_read_mapping(id=id) -+ -+ # if subnet was created outside of neutron handle it and create -+ # neutron representation now (lazily) -+ try: -+ return self._subnet_vnc_read_mapping(key=key) -+ except vnc_exc.NoIdError: -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, key) -+ return self._subnet_vnc_read_mapping(key=key) -+ -+ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): -+ self._vnc_lib.kv_delete(subnet_id) -+ self._vnc_lib.kv_delete(subnet_key) -+ try: -+ del self._db_cache['q_subnet_maps'][subnet_id] -+ del self._db_cache['q_subnet_maps'][subnet_key] -+ except KeyError: -+ pass -+ -+ def _subnet_vnc_get_key(self, subnet_vnc, net_id): -+ pfx = subnet_vnc.subnet.get_ip_prefix() -+ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() -+ -+ return '%s %s/%s' % (net_id, pfx, pfx_len) -+ -+ def _subnet_read(self, net_uuid, subnet_key): -+ try: -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ except vnc_exc.NoIdError: -+ return None -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if not ipam_refs: -+ return None -+ -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_uuid) == subnet_key: -+ return subnet_vnc -+ -+ return None -+ -+ def _ip_address_to_subnet_id(self, ip_addr, net_obj): -+ # find subnet-id for ip-addr, called when instance-ip created -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ if IPAddress(ip_addr) in IPSet([cidr]): -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, -+ net_obj.uuid) -+ subnet_id = self._subnet_vnc_read_mapping( -+ key=subnet_key) -+ return subnet_id -+ -+ return None -+ -+ # Conversion routines between VNC and Quantum objects -+ def _svc_instance_neutron_to_vnc(self, si_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(si_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ net_id = si_q['internal_net'] -+ int_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ net_id = si_q['external_net'] -+ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, -+ auto_scale=False) -+ si_prop = vnc_api.ServiceInstanceType( -+ auto_policy=True, left_virtual_network=int_vn.name, -+ right_virtual_network=ext_vn.name, scale_out=scale_out) -+ si_prop.set_scale_out(scale_out) -+ si_vnc = vnc_api.ServiceInstance( -+ name=si_q['name'], -+ parent_obj=project_obj, -+ service_instance_properties=si_prop) -+ -+ return si_vnc -+ -+ def _svc_instance_vnc_to_neutron(self, si_obj): -+ si_q_dict = json.loads(json.dumps(si_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ si_q_dict['id'] = si_obj.uuid -+ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') -+ si_q_dict['name'] = si_obj.name -+ si_props = si_obj.get_service_instance_properties() -+ if si_props: -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_left_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_right_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ -+ return {'q_api_data': si_q_dict, -+ 'q_extra_data': {}} -+ -+ def _route_table_neutron_to_vnc(self, rt_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(rt_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], -+ parent_obj=project_obj) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ else: -+ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ -+ return rt_vnc -+ -+ def _route_table_vnc_to_neutron(self, rt_obj): -+ rt_q_dict = json.loads(json.dumps(rt_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ rt_q_dict['id'] = rt_obj.uuid -+ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') -+ rt_q_dict['name'] = rt_obj.name -+ rt_q_dict['fq_name'] = rt_obj.fq_name -+ -+ # get route table routes -+ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) -+ return {'q_api_data': rt_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_vnc_to_neutron(self, sg_obj): -+ sg_q_dict = json.loads(json.dumps(sg_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ sg_q_dict['id'] = sg_obj.uuid -+ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sg_q_dict['name'] = sg_obj.name -+ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() -+ -+ # get security group rules -+ sg_q_dict['rules'] = [] -+ rule_list = self.security_group_rules_read(sg_obj.uuid) -+ if rule_list: -+ for rule in rule_list: -+ sg_q_dict['rules'].append(rule['q_api_data']) -+ -+ return {'q_api_data': sg_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_neutron_to_vnc(self, sg_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(sg_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType( -+ enable=True, description=sg_q['description']) -+ sg_vnc = vnc_api.SecurityGroup( -+ name=sg_q['name'], parent_obj=project_obj, -+ id_perms=id_perms) -+ -+ return sg_vnc -+ -+ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): -+ sgr_q_dict = {} -+ if sg_id is None: -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ direction = 'egress' -+ if sg_rule.get_direction() == '<': -+ direction = 'ingress' -+ -+ remote_cidr = '' -+ remote_sg_uuid = '' -+ if direction == 'ingress': -+ addr = sg_rule.get_src_addresses()[0] -+ else: -+ addr = sg_rule.get_dst_addresses()[0] -+ -+ if addr.get_subnet(): -+ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), -+ addr.get_subnet().get_ip_prefix_len()) -+ elif addr.get_security_group(): -+ if (addr.get_security_group() != 'any') and \ -+ (addr.get_security_group() != 'local'): -+ remote_sg = addr.get_security_group() -+ try: -+ remote_sg_obj = self._vnc_lib.security_group_read( -+ fq_name_str=remote_sg) -+ remote_sg_uuid = remote_sg_obj.uuid -+ except vnc_exc.NoIdError: -+ pass -+ -+ sgr_q_dict['id'] = sg_rule.get_rule_uuid() -+ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sgr_q_dict['security_group_id'] = sg_obj.uuid -+ sgr_q_dict['ethertype'] = 'IPv4' -+ sgr_q_dict['direction'] = direction -+ sgr_q_dict['protocol'] = sg_rule.get_protocol() -+ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ -+ get_start_port() -+ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ -+ get_end_port() -+ sgr_q_dict['remote_ip_prefix'] = remote_cidr -+ sgr_q_dict['remote_group_id'] = remote_sg_uuid -+ -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): -+ if oper == CREATE: -+ port_min = 0 -+ port_max = 65535 -+ if sgr_q['port_range_min']: -+ port_min = sgr_q['port_range_min'] -+ if sgr_q['port_range_max']: -+ port_max = sgr_q['port_range_max'] -+ -+ endpt = [vnc_api.AddressType(security_group='any')] -+ if sgr_q['remote_ip_prefix']: -+ cidr = sgr_q['remote_ip_prefix'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ endpt = [vnc_api.AddressType( -+ subnet=vnc_api.SubnetType(pfx, pfx_len))] -+ elif sgr_q['remote_group_id']: -+ sg_obj = self._vnc_lib.security_group_read( -+ id=sgr_q['remote_group_id']) -+ endpt = [vnc_api.AddressType( -+ security_group=sg_obj.get_fq_name_str())] -+ -+ if sgr_q['direction'] == 'ingress': -+ dir = '<' -+ local = endpt -+ remote = [vnc_api.AddressType(security_group='local')] -+ else: -+ dir = '>' -+ remote = endpt -+ local = [vnc_api.AddressType(security_group='local')] -+ -+ if not sgr_q['protocol']: -+ sgr_q['protocol'] = 'any' -+ -+ sgr_uuid = str(uuid.uuid4()) -+ -+ rule = vnc_api.PolicyRuleType( -+ rule_uuid=sgr_uuid, -+ direction=dir, -+ protocol=sgr_q['protocol'], -+ src_addresses=local, -+ src_ports=[vnc_api.PortType(0, 65535)], -+ dst_addresses=remote, -+ dst_ports=[vnc_api.PortType(port_min, port_max)]) -+ return rule -+ -+ def _network_neutron_to_vnc(self, network_q, oper): -+ net_name = network_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(network_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType(enable=True) -+ net_obj = vnc_api.VirtualNetwork( -+ net_name, project_obj, id_perms=id_perms) -+ else: # READ/UPDATE/DELETE -+ net_obj = self._virtual_network_read(net_id=network_q['id']) -+ -+ id_perms = net_obj.get_id_perms() -+ if 'admin_state_up' in network_q: -+ id_perms.enable = network_q['admin_state_up'] -+ net_obj.set_id_perms(id_perms) -+ -+ if 'contrail:policys' in network_q: -+ policy_fq_names = network_q['contrail:policys'] -+ # reset and add with newly specified list -+ net_obj.set_network_policy_list([], []) -+ seq = 0 -+ for p_fq_name in policy_fq_names: -+ domain_name, project_name, policy_name = p_fq_name -+ -+ domain_obj = vnc_api.Domain(domain_name) -+ project_obj = vnc_api.Project(project_name, domain_obj) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ -+ net_obj.add_network_policy( -+ policy_obj, -+ vnc_api.VirtualNetworkPolicyType( -+ sequence=vnc_api.SequenceType(seq, 0))) -+ seq = seq + 1 -+ -+ if 'vpc:route_table' in network_q: -+ rt_fq_name = network_q['vpc:route_table'] -+ if rt_fq_name: -+ try: -+ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) -+ net_obj.set_route_table(rt_obj) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) -+ -+ return net_obj -+ -+ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): -+ net_q_dict = {} -+ extra_dict = {} -+ -+ net_q_dict['id'] = net_obj.uuid -+ net_q_dict['name'] = net_obj.name -+ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() -+ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable -+ net_q_dict['shared'] = False -+ net_q_dict['status'] = constants.NET_STATUS_ACTIVE -+ -+ if net_repr == 'SHOW': -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ #if port_back_refs: -+ # net_q_dict['ports'] = [] -+ # for port_back_ref in port_back_refs: -+ # fq_name = port_back_ref['to'] -+ # try: -+ # port_obj = self._virtual_machine_interface_read( -+ # port_id = fq_name[-1]) -+ # except NoIdError: -+ # continue -+ # -+ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) -+ # port_dict = port_info['q_api_data'] -+ # port_dict.update(port_info['q_extra_data']) -+ # -+ # net_q_dict['ports'].append(port_dict) -+ -+ extra_dict['contrail:instance_count'] = 0 -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ net_policy_refs = net_obj.get_network_policy_refs() -+ if net_policy_refs: -+ extra_dict['contrail:policys'] = \ -+ [np_ref['to'] for np_ref in net_policy_refs] -+ -+ elif net_repr == 'LIST': -+ extra_dict['contrail:instance_count'] = 0 -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ net_q_dict['subnets'] = [] -+ if ipam_refs: -+ extra_dict['contrail:subnet_ipam'] = [] -+ for ipam_ref in ipam_refs: -+ subnets = ipam_ref['attr'].get_ipam_subnets() -+ for subnet in subnets: -+ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, -+ ipam_ref['to']) -+ sn_dict = sn_info['q_api_data'] -+ sn_dict.update(sn_info['q_extra_data']) -+ net_q_dict['subnets'].append(sn_dict) -+ sn_ipam = {} -+ sn_ipam['subnet_cidr'] = sn_dict['cidr'] -+ sn_ipam['ipam_fq_name'] = ipam_ref['to'] -+ extra_dict['contrail:subnet_ipam'].append(sn_ipam) -+ -+ return {'q_api_data': net_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _subnet_neutron_to_vnc(self, subnet_q): -+ cidr = subnet_q['cidr'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: -+ default_gw = subnet_q['gateway_ip'] -+ else: -+ # Assigned by address manager -+ default_gw = None -+ sub_net = vnc_api.SubnetType(ip_prefix=pfx, -+ ip_prefix_len=pfx_len) -+ #subnet_vnc = vnc_api.IpamSubnetType( -+ #subnet=vnc_api.SubnetType(pfx, pfx_len), -+ #default_gateway=default_gw) -+ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, -+ default_gateway=default_gw) -+ return subnet_vnc -+ -+ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): -+ sn_q_dict = {} -+ sn_q_dict['name'] = '' -+ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ sn_q_dict['network_id'] = net_obj.uuid -+ sn_q_dict['ip_version'] = 4 -+ -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ sn_q_dict['cidr'] = cidr -+ -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) -+ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) -+ -+ sn_q_dict['id'] = sn_id -+ -+ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway -+ -+ first_ip = str(IPNetwork(cidr).network + 1) -+ last_ip = str(IPNetwork(cidr).broadcast - 2) -+ sn_q_dict['allocation_pools'] = \ -+ [{'id': 'TODO-allocation_pools-id', -+ 'subnet_id': sn_id, -+ 'first_ip': first_ip, -+ 'last_ip': last_ip, -+ 'available_ranges': {}}] -+ -+ sn_q_dict['enable_dhcp'] = False -+ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['routes'] = [{'destination': 'TODO-destination', -+ 'nexthop': 'TODO-nexthop', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['shared'] = False -+ -+ extra_dict = {} -+ extra_dict['contrail:instance_count'] = 0 -+ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name -+ -+ return {'q_api_data': sn_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _ipam_neutron_to_vnc(self, ipam_q, oper): -+ ipam_name = ipam_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(ipam_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) -+ -+ if ipam_q['mgmt']: -+ ipam_obj.set_network_ipam_mgmt( -+ vnc_api.IpamType.factory(**ipam_q['mgmt'])) -+ -+ return ipam_obj -+ -+ def _ipam_vnc_to_neutron(self, ipam_obj): -+ ipam_q_dict = json.loads(json.dumps(ipam_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') -+ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') -+ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) -+ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ ipam_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ ipam_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': ipam_q_dict, -+ 'q_extra_data': {}} -+ -+ def _policy_neutron_to_vnc(self, policy_q, oper): -+ policy_name = policy_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(policy_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) -+ -+ policy_obj.set_network_policy_entries( -+ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) -+ -+ return policy_obj -+ -+ def _policy_vnc_to_neutron(self, policy_obj): -+ policy_q_dict = json.loads(json.dumps(policy_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ policy_q_dict['id'] = policy_q_dict.pop('uuid') -+ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') -+ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', -+ None) -+ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ policy_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ policy_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': policy_q_dict, -+ 'q_extra_data': {}} -+ -+ def _floatingip_neutron_to_vnc(self, fip_q, oper): -+ if oper == CREATE: -+ # use first available pool on net -+ net_id = fip_q['floating_network_id'] -+ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) -+ fip_name = str(uuid.uuid4()) -+ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) -+ fip_obj.uuid = fip_name -+ -+ proj_id = str(uuid.UUID(fip_q['tenant_id'])) -+ proj_obj = self._project_read(proj_id=proj_id) -+ fip_obj.set_project(proj_obj) -+ else: # READ/UPDATE/DELETE -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) -+ -+ if fip_q['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=fip_q['port_id']) -+ fip_obj.set_virtual_machine_interface(port_obj) -+ else: -+ fip_obj.set_virtual_machine_interface_list([]) -+ -+ return fip_obj -+ -+ def _floatingip_vnc_to_neutron(self, fip_obj): -+ fip_q_dict = {} -+ extra_dict = {} -+ -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( -+ id=fip_obj.parent_uuid) -+ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) -+ -+ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') -+ -+ port_id = None -+ port_refs = fip_obj.get_virtual_machine_interface_refs() -+ if port_refs: -+ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] -+ -+ fip_q_dict['id'] = fip_obj.uuid -+ fip_q_dict['tenant_id'] = tenant_id -+ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() -+ fip_q_dict['floating_network_id'] = net_obj.uuid -+ fip_q_dict['router_id'] = None -+ fip_q_dict['fixed_port_id'] = port_id -+ fip_q_dict['fixed_ip_address'] = None -+ -+ return {'q_api_data': fip_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _port_neutron_to_vnc(self, port_q, net_obj, oper): -+ if oper == CREATE: -+ port_name = str(uuid.uuid4()) -+ instance_name = port_q['device_id'] -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ -+ id_perms = vnc_api.IdPermsType(enable=True) -+ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, -+ id_perms=id_perms) -+ port_obj.uuid = port_name -+ port_obj.set_virtual_network(net_obj) -+ -+ else: # READ/UPDATE/DELETE -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_q['id']) -+ -+ port_obj.set_security_group_list([]) -+ if ('security_groups' in port_q and -+ port_q['security_groups'].__class__ is not object): -+ for sg_id in port_q['security_groups']: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ port_obj.add_security_group(sg_obj) -+ -+ id_perms = port_obj.get_id_perms() -+ if 'admin_state_up' in port_q: -+ id_perms.enable = port_q['admin_state_up'] -+ port_obj.set_id_perms(id_perms) -+ -+ return port_obj -+ -+ def _port_vnc_to_neutron(self, port_obj, net_obj=None): -+ port_q_dict = {} -+ port_q_dict['name'] = port_obj.uuid -+ port_q_dict['id'] = port_obj.uuid -+ -+ if not net_obj: -+ net_refs = port_obj.get_virtual_network_refs() -+ if net_refs: -+ net_id = net_refs[0]['uuid'] -+ else: -+ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) -+ -+ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) -+ proj_id = None -+ if not proj_id: -+ # not in cache, get by reading VN obj, and populate cache -+ net_obj = self._virtual_network_read(net_id=net_id) -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(port_obj.uuid, proj_id) -+ else: -+ net_id = net_obj.uuid -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ -+ port_q_dict['tenant_id'] = proj_id -+ port_q_dict['network_id'] = net_id -+ -+ port_q_dict['mac_address'] = '' -+ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() -+ if mac_refs: -+ port_q_dict['mac_address'] = mac_refs.mac_address[0] -+ -+ port_q_dict['fixed_ips'] = [] -+ ip_back_refs = port_obj.get_instance_ip_back_refs() -+ if ip_back_refs: -+ for ip_back_ref in ip_back_refs: -+ try: -+ ip_obj = self._instance_ip_read( -+ instance_ip_id=ip_back_ref['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ -+ ip_addr = ip_obj.get_instance_ip_address() -+ -+ ip_q_dict = {} -+ ip_q_dict['port_id'] = port_obj.uuid -+ ip_q_dict['ip_address'] = ip_addr -+ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, -+ net_obj) -+ ip_q_dict['net_id'] = net_id -+ -+ port_q_dict['fixed_ips'].append(ip_q_dict) -+ -+ sg_dict = {'port_security_enabled': True} -+ sg_dict['security_groups'] = [] -+ sg_refs = port_obj.get_security_group_refs() -+ for sg_ref in sg_refs or []: -+ sg_dict['security_groups'].append(sg_ref['uuid']) -+ -+ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable -+ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE -+ port_q_dict['device_id'] = port_obj.parent_name -+ port_q_dict['device_owner'] = 'TODO-device-owner' -+ -+ return {'q_api_data': port_q_dict, -+ 'q_extra_data': sg_dict} -+ -+ # public methods -+ # network api handlers -+ def network_create(self, network_q): -+ #self._ensure_project_exists(network_q['tenant_id']) -+ -+ net_obj = self._network_neutron_to_vnc(network_q, CREATE) -+ net_uuid = self._virtual_network_create(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_uuid] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_read(self, net_uuid, fields=None): -+ # see if we can return fast... -+ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': -+ tenant_id = self._get_obj_tenant_id('network', net_uuid) -+ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} -+ -+ try: -+ # return self._db_cache['q_networks']['net_uuid'] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ try: -+ net_obj = self._network_read(net_uuid) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_uuid) -+ -+ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ -+ def network_update(self, net_id, network_q): -+ network_q['id'] = net_id -+ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) -+ self._virtual_network_update(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_id] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_delete(self, net_id): -+ self._virtual_network_delete(net_id=net_id) -+ try: -+ del self._db_cache['q_networks'][net_id] -+ except KeyError: -+ pass -+ -+ def network_list(self, filters=None): -+ ret_list = [] -+ -+ if filters and 'shared' in filters: -+ if filters['shared'][0] is True: -+ # no support for shared networks -+ return ret_list -+ -+ # collect phase -+ all_nets = [] # all n/ws in all projects -+ if filters and 'tenant_id' in filters: -+ # project-id is present -+ if 'id' in filters: -+ # required networks are also specified, -+ # just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in project, and prune below -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ if 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(p_id)) -+ else: -+ project_nets = self._network_list_project(p_id) -+ all_nets.append(project_nets) -+ elif filters and 'id' in filters: -+ # required networks are specified, just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in all projects -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ if filters and 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(proj_id)) -+ else: -+ project_nets = self._network_list_project(proj_id) -+ all_nets.append(project_nets) -+ -+ # prune phase -+ for project_nets in all_nets: -+ for proj_net in project_nets: -+ proj_net_id = proj_net['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_net_id): -+ continue -+ -+ proj_net_fq_name = unicode(proj_net['fq_name']) -+ if not self._filters_is_present(filters, 'contrail:fq_name', -+ proj_net_fq_name): -+ continue -+ -+ try: -+ net_obj = self._network_read(proj_net['uuid']) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ except vnc_exc.NoIdError: -+ continue -+ ret_list.append(net_info) -+ -+ return ret_list -+ -+ def network_count(self, filters=None): -+ nets_info = self.network_list(filters) -+ return len(nets_info) -+ -+ # subnet api handlers -+ def subnet_create(self, subnet_q): -+ net_id = subnet_q['network_id'] -+ net_obj = self._virtual_network_read(net_id=net_id) -+ -+ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] -+ if ipam_fq_name != '': -+ domain_name, project_name, ipam_name = ipam_fq_name -+ -+ project_obj = vnc_api.Project(project_name) -+ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # link subnet with default ipam -+ project_obj = vnc_api.Project(net_obj.parent_name) -+ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) -+ ipam_fq_name = netipam_obj.get_fq_name() -+ -+ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) -+ -+ # Locate list of subnets to which this subnet has to be appended -+ net_ipam_ref = None -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ if ipam_ref['to'] == ipam_fq_name: -+ net_ipam_ref = ipam_ref -+ break -+ -+ if not net_ipam_ref: -+ # First link from net to this ipam -+ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) -+ net_obj.add_network_ipam(netipam_obj, vnsn_data) -+ else: # virtual-network already linked to this ipam -+ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): -+ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): -+ # duplicate !! -+ subnet_info = self._subnet_vnc_to_neutron(subnet, -+ net_obj, -+ ipam_fq_name) -+ return subnet_info -+ vnsn_data = net_ipam_ref['attr'] -+ vnsn_data.ipam_subnets.append(subnet_vnc) -+ -+ self._virtual_network_update(net_obj) -+ -+ # allocate an id to the subnet and store mapping with -+ # api-server -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, subnet_key) -+ -+ # Read in subnet from server to get updated values for gw etc. -+ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) -+ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, -+ ipam_fq_name) -+ -+ #self._db_cache['q_subnets'][subnet_id] = subnet_info -+ -+ return subnet_info -+ -+ def subnet_read(self, subnet_id): -+ try: -+ # return self._db_cache['q_subnets'][subnet_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_id) == subnet_key: -+ ret_subnet_q = self._subnet_vnc_to_neutron( -+ subnet_vnc, net_obj, ipam_ref['to']) -+ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q -+ return ret_subnet_q -+ -+ return {} -+ -+ def subnet_delete(self, subnet_id): -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ orig_subnets = ipam_ref['attr'].get_ipam_subnets() -+ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets -+ if self._subnet_vnc_get_key(subnet_vnc, net_id) -+ != subnet_key] -+ if len(orig_subnets) != len(new_subnets): -+ # matched subnet to be deleted -+ ipam_ref['attr'].set_ipam_subnets(new_subnets) -+ self._virtual_network_update(net_obj) -+ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) -+ try: -+ del self._db_cache['q_subnets'][subnet_id] -+ except KeyError: -+ pass -+ -+ return -+ -+ def subnets_list(self, filters=None): -+ ret_subnets = [] -+ -+ if filters and 'id' in filters: -+ # required subnets are specified, -+ # just read in corresponding net_ids -+ net_ids = set([]) -+ for subnet_id in filters['id']: -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ net_ids.add(net_id) -+ else: -+ nets_info = self.network_list() -+ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] -+ -+ for net_id in net_ids: -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, -+ net_obj, -+ ipam_ref['to']) -+ sn_id = sn_info['q_api_data']['id'] -+ sn_proj_id = sn_info['q_api_data']['tenant_id'] -+ sn_net_id = sn_info['q_api_data']['network_id'] -+ -+ if filters: -+ if not self._filters_is_present(filters, 'id', -+ sn_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'tenant_id', -+ sn_proj_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'network_id', -+ sn_net_id): -+ continue -+ -+ ret_subnets.append(sn_info) -+ -+ return ret_subnets -+ -+ def subnets_count(self, filters=None): -+ subnets_info = self.subnets_list(filters) -+ return len(subnets_info) -+ -+ # ipam api handlers -+ def ipam_create(self, ipam_q): -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) -+ self._vnc_lib.network_ipam_create(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_read(self, ipam_id): -+ try: -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=ipam_id) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_update(self, ipam_id, ipam): -+ ipam_q = ipam['ipam'] -+ ipam_q['id'] = ipam_id -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) -+ self._vnc_lib.network_ipam_update(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_delete(self, ipam_id): -+ self._vnc_lib.network_ipam_delete(id=ipam_id) -+ -+ def ipam_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_ipams = [] # all ipams in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_ipams = self._ipam_list_project(p_id) -+ all_ipams.append(project_ipams) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_ipams = self._ipam_list_project(proj_id) -+ all_ipams.append(project_ipams) -+ -+ # prune phase -+ for project_ipams in all_ipams: -+ for proj_ipam in project_ipams: -+ proj_ipam_id = proj_ipam['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_ipam_id): -+ continue -+ ipam_info = self.ipam_read(proj_ipam['uuid']) -+ ret_list.append(ipam_info) -+ -+ return ret_list -+ -+ def ipam_count(self, filters=None): -+ ipam_info = self.ipam_list(filters) -+ return len(ipam_info) -+ -+ # policy api handlers -+ def policy_create(self, policy_q): -+ -+ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) -+ self._vnc_lib.network_policy_create(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_read(self, policy_id): -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_update(self, policy_id, policy): -+ policy_q = policy['policy'] -+ policy_q['id'] = policy_id -+ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) -+ self._vnc_lib.network_policy_update(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_delete(self, policy_id): -+ self._vnc_lib.network_policy_delete(id=policy_id) -+ -+ def policy_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_policys = [] # all policys in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_policys = self._policy_list_project(p_id) -+ all_policys.append(project_policys) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_policys = self._policy_list_project(proj_id) -+ all_policys.append(project_policys) -+ -+ # prune phase -+ for project_policys in all_policys: -+ for proj_policy in project_policys: -+ proj_policy_id = proj_policy['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_policy_id): -+ continue -+ policy_info = self.policy_read(proj_policy['uuid']) -+ ret_list.append(policy_info) -+ -+ return ret_list -+ -+ def policy_count(self, filters=None): -+ policy_info = self.policy_list(filters) -+ return len(policy_info) -+ -+ # floatingip api handlers -+ def floatingip_create(self, fip_q): -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) -+ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_read(self, fip_uuid): -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_update(self, fip_id, fip_q): -+ fip_q['id'] = fip_id -+ fip_obj = self._floatingip_neutron(fip_q, UPDATE) -+ self._vnc_lib.floating_ip_update(fip_obj) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_delete(self, fip_id): -+ self._vnc_lib.floating_ip_delete(id=fip_id) -+ -+ def floatingip_list(self, filters=None): -+ # Find networks, get floatingip backrefs and return -+ ret_list = [] -+ -+ if filters: -+ if 'tenant_id' in filters: -+ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] -+ elif 'port_id' in filters: -+ # required ports are specified, just read and populate ret_list -+ # prune is skipped because proj_objs is empty -+ proj_ids = [] -+ for port_id in filters['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_id) -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron( -+ fip_obj)) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ proj_ids = [proj['uuid'] for proj in dom_projects] -+ -+ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] -+ -+ for proj_obj in proj_objs: -+ fip_back_refs = proj_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) -+ -+ return ret_list -+ -+ def floatingip_count(self, filters=None): -+ floatingip_info = self.floatingip_list(filters) -+ return len(floatingip_info) -+ -+ # port api handlers -+ def port_create(self, port_q): -+ net_id = port_q['network_id'] -+ net_obj = self._network_read(net_id) -+ proj_id = net_obj.parent_uuid -+ -+ self._ensure_instance_exists(port_q['device_id']) -+ -+ # initialize port object -+ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) -+ -+ # if ip address passed then use it -+ ip_addr = None -+ ip_obj = None -+ if port_q['fixed_ips'].__class__ is not object: -+ ip_addr = port_q['fixed_ips'][0]['ip_address'] -+ ip_name = '%s %s' % (net_id, ip_addr) -+ try: -+ ip_obj = self._instance_ip_read(fq_name=[ip_name]) -+ #ip_id = ip_obj.uuid -+ except Exception as e: -+ ip_obj = None -+ -+ # create the object -+ port_id = self._virtual_machine_interface_create(port_obj) -+ -+ # initialize ip object -+ if ip_obj is None: -+ ip_name = str(uuid.uuid4()) -+ ip_obj = vnc_api.InstanceIp(name=ip_name) -+ ip_obj.uuid = ip_name -+ ip_obj.set_virtual_machine_interface(port_obj) -+ ip_obj.set_virtual_network(net_obj) -+ if ip_addr: -+ ip_obj.set_instance_ip_address(ip_addr) -+ try: -+ self._instance_ip_create(ip_obj) -+ except Exception as e: -+ # ResourceExhaustionError, resources are not available -+ self._virtual_machine_interface_delete(port_id=port_id) -+ raise e -+ # shared ip address -+ else: -+ if ip_addr == ip_obj.get_instance_ip_address(): -+ ip_obj.add_virtual_machine_interface(port_obj) -+ self._instance_ip_update(ip_obj) -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) -+ #self._db_cache['q_ports'][port_id] = ret_port_q -+ self._set_obj_tenant_id(port_id, proj_id) -+ -+ # update cache on successful creation -+ tenant_id = proj_id.replace('-', '') -+ if tenant_id not in self._db_cache['q_tenant_port_count']: -+ ncurports = self.port_count({'tenant_id': tenant_id}) -+ else: -+ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] -+ -+ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 -+ -+ return ret_port_q -+ -+ def port_read(self, port_id): -+ try: -+ # return self._db_cache['q_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_update(self, port_id, port_q): -+ port_q['id'] = port_id -+ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) -+ self._virtual_machine_interface_update(port_obj) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_delete(self, port_id): -+ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) -+ instance_id = port_obj.parent_uuid -+ -+ # release instance IP address -+ iip_back_refs = port_obj.get_instance_ip_back_refs() -+ if iip_back_refs: -+ for iip_back_ref in iip_back_refs: -+ # if name contains IP address then this is shared ip -+ iip_obj = self._vnc_lib.instance_ip_read( -+ id=iip_back_ref['uuid']) -+ name = iip_obj.name -+ if len(name.split(' ')) > 1: -+ name = name.split(' ')[1] -+ -+ # in case of shared ip only delete the link to the VMI -+ try: -+ socket.inet_aton(name) -+ iip_obj.del_virtual_machine_interface(port_obj) -+ self._instance_ip_update(iip_obj) -+ except socket.error: -+ self._instance_ip_delete( -+ instance_ip_id=iip_back_ref['uuid']) -+ -+ # disassociate any floating IP used by instance -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if fip_back_refs: -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ self.floatingip_update(fip_obj.uuid, {'port_id': None}) -+ -+ self._virtual_machine_interface_delete(port_id=port_id) -+ -+ # delete instance if this was the last port -+ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) -+ inst_intfs = inst_obj.get_virtual_machine_interfaces() -+ if not inst_intfs: -+ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) -+ -+ try: -+ del self._db_cache['q_ports'][port_id] -+ except KeyError: -+ pass -+ -+ # update cache on successful deletion -+ try: -+ tenant_id = self._get_obj_tenant_id('port', port_id) -+ self._db_cache['q_tenant_port_count'][tenant_id] = \ -+ self._db_cache['q_tenant_port_count'][tenant_id] - 1 -+ except KeyError: -+ pass -+ -+ self._del_obj_tenant_id(port_id) -+ -+ def port_list(self, filters=None): -+ ret_q_ports = [] -+ all_project_ids = [] -+ -+ if 'device_owner' in filters: -+ return ret_q_ports -+ -+ if 'device_id' not in filters: -+ # Listing from back references -+ if not filters: -+ # no filters => return all ports! -+ all_projects = self._project_list_domain(None) -+ all_project_ids = [project['uuid'] for project in all_projects] -+ elif 'tenant_id' in filters: -+ all_project_ids = filters.get('tenant_id') -+ -+ for proj_id in all_project_ids: -+ proj_ports = self._port_list_project(proj_id) -+ for port in proj_ports: -+ try: -+ port_info = self.port_read(port['id']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ for net_id in filters.get('network_id', []): -+ net_ports = self._port_list_network(net_id) -+ for port in net_ports: -+ port_info = self.port_read(port['id']) -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ # Listing from parent to children -+ virtual_machine_ids = filters['device_id'] -+ for vm_id in virtual_machine_ids: -+ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( -+ parent_id=vm_id) -+ vm_intf_ids = resp_dict['virtual-machine-interfaces'] -+ for vm_intf in vm_intf_ids: -+ try: -+ port_info = self.port_read(vm_intf['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ def port_count(self, filters=None): -+ if 'device_owner' in filters: -+ return 0 -+ -+ if 'tenant_id' in filters: -+ project_id = filters['tenant_id'][0] -+ try: -+ return self._db_cache['q_tenant_port_count'][project_id] -+ except KeyError: -+ # do it the hard way but remember for next time -+ nports = len(self._port_list_project(project_id)) -+ self._db_cache['q_tenant_port_count'][project_id] = nports -+ else: -+ # across all projects -+ # get only a count from api-server! -+ nports = len(self.port_list(filters)) -+ -+ return nports -+ -+ # security group api handlers -+ def security_group_create(self, sg_q): -+ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) -+ sg_uuid = self._security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_uuid, rule) -+ -+ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) -+ return ret_sg_q -+ -+ def security_group_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return self._security_group_vnc_to_neutron(sg_obj) -+ -+ def security_group_delete(self, sg_id): -+ self._security_group_delete(sg_id) -+ -+ def security_group_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] # all sgs in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sg_info = self.security_group_read(proj_sg_id) -+ if not self._filters_is_present(filters, 'name', -+ sg_info['q_api_data']['name']): -+ continue -+ ret_list.append(sg_info) -+ -+ return ret_list -+ -+ def security_group_rule_create(self, sgr_q): -+ sg_id = sgr_q['security_group_id'] -+ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) -+ self._security_group_rule_create(sg_id, sg_rule) -+ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, -+ sg_rule) -+ -+ return ret_sg_rule_q -+ -+ def security_group_rule_read(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ -+ return {} -+ -+ def security_group_rule_delete(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_delete(sg_obj, sg_rule) -+ -+ def security_group_rules_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ sgr_entries = sg_obj.get_security_group_entries() -+ sg_rules = [] -+ if sgr_entries is None: -+ return -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ sg_rules.append(sg_info) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return sg_rules -+ -+ def security_group_rule_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sgr_info = self.security_group_rules_read(proj_sg_id) -+ if sgr_info: -+ ret_list.append(sgr_info) -+ -+ return ret_list -+ -+ #route table api handlers -+ def route_table_create(self, rt_q): -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) -+ self._route_table_create(rt_obj) -+ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) -+ return ret_rt_q -+ -+ def route_table_read(self, rt_id): -+ try: -+ rt_obj = self._vnc_lib.route_table_read(id=rt_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=rt_id) -+ -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_update(self, rt_id, rt_q): -+ rt_q['id'] = rt_id -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) -+ self._vnc_lib.route_table_update(rt_obj) -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_delete(self, rt_id): -+ self._route_table_delete(rt_id) -+ -+ def route_table_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_rts = [] # all rts in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_rts = self._route_table_list_project(proj_id) -+ all_rts.append(project_rts) -+ -+ # prune phase -+ for project_rts in all_rts: -+ for proj_rt in project_rts: -+ proj_rt_id = proj_rt['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_rt_id): -+ continue -+ rt_info = self.route_table_read(proj_rt_id) -+ if not self._filters_is_present(filters, 'name', -+ rt_info['q_api_data']['name']): -+ continue -+ ret_list.append(rt_info) -+ -+ return ret_list -+ -+ #service instance api handlers -+ def svc_instance_create(self, si_q): -+ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) -+ self._svc_instance_create(si_obj) -+ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) -+ return ret_si_q -+ -+ def svc_instance_read(self, si_id): -+ try: -+ si_obj = self._vnc_lib.service_instance_read(id=si_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=si_id) -+ -+ return self._svc_instance_vnc_to_neutron(si_obj) -+ -+ def svc_instance_delete(self, si_id): -+ self._svc_instance_delete(si_id) -+ -+ def svc_instance_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sis = [] # all sis in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sis = self._svc_instance_list_project(proj_id) -+ all_sis.append(project_sis) -+ -+ # prune phase -+ for project_sis in all_sis: -+ for proj_si in project_sis: -+ proj_si_id = proj_si['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_si_id): -+ continue -+ si_info = self.svc_instance_read(proj_si_id) -+ if not self._filters_is_present(filters, 'name', -+ si_info['q_api_data']['name']): -+ continue -+ ret_list.append(si_info) -+ -+ return ret_list -diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py -new file mode 100644 -index 0000000..72bebec ---- /dev/null -+++ neutron/tests/unit/juniper/__init__.py -@@ -0,0 +1,14 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py -new file mode 100644 -index 0000000..decf79e ---- /dev/null -+++ neutron/tests/unit/juniper/test_contrail_plugin.py -@@ -0,0 +1,998 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -+ -+import datetime -+import mock -+import neutron.db.api -+from neutron.manager import NeutronManager -+from neutron.tests.unit import test_db_plugin as test_plugin -+import sys -+import uuid -+ -+subnet_obj = {u'subnet': -+ {'name': '', 'enable_dhcp': True, -+ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', -+ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', -+ 'dns_nameservers': '', -+ u'contrail:ipam_fq_name': -+ [u'default-domain', u'admin', u'default-network-ipam'], -+ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, -+ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} -+ -+vn_list = [] -+GlobalProjects = [] -+ -+ -+class MockVncApi(mock.MagicMock): -+ def __init__(self, *args, **kwargs): -+ pass -+ -+ def kv_retrieve(self, *args, **kwargs): -+ return [] -+ -+ def kv_store(self, *args, **kwargs): -+ return -+ -+ def kv_delete(self, *args, **kwargs): -+ return -+ -+ def project_read(self, *args, **kwargs): -+ #return MockProject('dummy-proj') -+ return GlobalProjects[0] -+ -+ def virtual_network_create(self, net_obj): -+ net_id = unicode(str(uuid.uuid4())) -+ net_obj.set_uuid(net_id) -+ vn_list.append(net_obj) -+ return net_id -+ -+ def virtual_network_read(self, id, *args, **kwargs): -+ if len(vn_list): -+ for index in range(len(vn_list)): -+ if ((vn_list[index].get_uuid()) == id): -+ return vn_list[index] -+ -+ #return a mock object if it is not created so far -+ return MockVirtualNetwork('dummy-net', MockProject()) -+ -+ def virtual_network_delete(self, *args, **kwargs): -+ return -+ -+ def virtual_network_update(self, *args, **kwargs): -+ return -+ -+ def virtual_networks_list(self, *args, **kwargs): -+ return vn_list -+ -+ -+class MockVncObject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ if not parent_obj: -+ self._fq_name = [name] -+ else: -+ self._fq_name = parent_obj.get_fq_name() + [name] -+ -+ self._ipam_refs = [{'to': [u'default-domain', u'admin', -+ u'default-network-ipam']}] -+ self.uuid = None -+ self.name = name -+ self.network_ipam_refs = [] -+ -+ def set_uuid(self, uuid): -+ self.uuid = uuid -+ -+ def get_uuid(self): -+ return self.uuid -+ -+ def get_fq_name(self): -+ return self._fq_name -+ -+ def get_network_ipam_refs(self): -+ return getattr(self, 'network_ipam_refs', None) -+ -+ def add_network_ipam(self, ref_obj, ref_data): -+ refs = getattr(self, 'network_ipam_refs', []) -+ if not refs: -+ self.network_ipam_refs = [] -+ -+ # if ref already exists, update any attr with it -+ for ref in refs: -+ if ref['to'] == ref_obj.get_fq_name(): -+ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref['uuid'] = ref_obj.uuid -+ return -+ -+ # ref didn't exist before -+ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref_info['uuid'] = ref_obj.uuid -+ -+ self.network_ipam_refs.append(ref_info) -+ -+ -+class MockVirtualNetwork(MockVncObject): -+ pass -+ -+ -+class MockSubnetType(mock.MagicMock): -+ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ip_prefix = ip_prefix -+ self.ip_prefix_len = ip_prefix_len -+ -+ def get_ip_prefix(self): -+ return self.ip_prefix -+ -+ def set_ip_prefix(self, ip_prefix): -+ self.ip_prefix = ip_prefix -+ -+ def get_ip_prefix_len(self): -+ return self.ip_prefix_len -+ -+ def set_ip_prefix_len(self, ip_prefix_len): -+ self.ip_prefix_len = ip_prefix_len -+ -+ -+class MockIpamSubnetType(mock.MagicMock): -+ def __init__(self, name=None, subnet=None, default_gateway=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.subnet = subnet -+ self.default_gateway = default_gateway -+ -+ def get_subnet(self): -+ return self.subnet -+ -+ def set_subnet(self, subnet): -+ self.subnet = subnet -+ -+ def get_default_gateway(self): -+ return self.default_gateway -+ -+ def set_default_gateway(self, default_gateway): -+ self.default_gateway = default_gateway -+ -+ def validate_IpAddressType(self, value): -+ pass -+ -+ -+class MockVnSubnetsType(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ipam_subnets = [] -+ if ipam_subnets: -+ #self.ipam_subnets = copy.deepcopy(ipam_subnets) -+ self.ipam_subnets = ipam_subnets -+ -+ def get_ipam_subnets(self): -+ return self.ipam_subnets -+ -+ def set_ipam_subnets(self, ipam_subnets): -+ self.ipam_subnets = ipam_subnets -+ -+ def add_ipam_subnets(self, value): -+ self.ipam_subnets.append(value) -+ -+ def insert_ipam_subnets(self, index, value): -+ self.ipam_subnets[index] = value -+ -+ def delete_ipam_subnets(self, value): -+ self.ipam_subnets.remove(value) -+ -+ -+class MockNetworkIpam(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, -+ network_ipam_mgmt=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'default-network-ipam' -+ self.name = name -+ self.uuid = None -+ if parent_obj: -+ self.parent_type = parent_obj._type -+ # copy parent's fq_name -+ self.fq_name = list(parent_obj.fq_name) -+ self.fq_name.append(name) -+ if not parent_obj.get_network_ipams(): -+ parent_obj.network_ipams = [] -+ parent_obj.network_ipams.append(self) -+ else: # No parent obj specified -+ self.parent_type = 'project' -+ self.fq_name = [u'default-domain', u'default-project'] -+ self.fq_name.append(name) -+ -+ # property fields -+ if network_ipam_mgmt: -+ self.network_ipam_mgmt = network_ipam_mgmt -+ if id_perms: -+ self.id_perms = id_perms -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+class MockProject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'project' -+ self.uuid = None -+ self.parent_type = 'domain' -+ self.fq_name = [u'default-domain'] -+ self.fq_name.append(name) -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+def GlobalProjectApi(project_name): -+ if not GlobalProjects: -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ return GlobalProjects[0] -+ -+ -+# Mock definations for different pkgs, modules and VncApi -+mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) -+mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') -+mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork -+mock_vnc_api_mod.SubnetType = MockSubnetType -+mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType -+mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType -+mock_vnc_api_mod.NetworkIpam = MockNetworkIpam -+mock_vnc_api_mod.Project = GlobalProjectApi -+ -+mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') -+mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') -+mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ -+ mock_vnc_api_pkg -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ -+ mock_vnc_api_mod -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ -+ mock_vnc_common_mod -+sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' -+ 'exceptions')] = \ -+ mock_vnc_exception_mod -+ -+CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" -+ -+ -+class RouterInstance(object): -+ def __init__(self): -+ self._name = 'rounter_instance' -+ -+ -+class Context(object): -+ def __init__(self, tenant_id=''): -+ self.read_only = False -+ self.show_deleted = False -+ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] -+ self._read_deleted = 'no' -+ self.timestamp = datetime.datetime.now() -+ self.auth_token = None -+ self._session = None -+ self._is_admin = True -+ self.admin = uuid.uuid4().hex.decode() -+ self.request_id = 'req-' + str(uuid.uuid4()) -+ self.tenant = tenant_id -+ -+ -+class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): -+ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) -+ -+ def setUp(self): -+ -+ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod -+ -+ mock_vnc_api_mod.common = mock_vnc_common_mod -+ mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+ -+ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+ -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ neutron.db.api._ENGINE = mock.MagicMock() -+ -+ def teardown(self): -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ -+ -+class TestContrailNetworks(test_plugin.TestNetworksV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ if 'contrail:fq_name' not in net.keys(): -+ assert False -+ else: -+ assert True -+ -+ def test_delete_network(self): -+ # First create the network and request to delete the same -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ -+ plugin_obj.delete_network(context_obj, net_id) -+ mock_vnc_api_cls.virtual_network_delete.assert_called_once() -+ -+ def test_update_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ # change one of the attribute and update the network -+ network['admin_state_up'] = 'False' -+ new_dict = plugin_obj.update_network(context_obj, net_id, -+ networks_req) -+ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): -+ assert False -+ else: -+ assert True -+ -+ # Not supported test cases in the this TestClass -+ def test_create_networks_bulk_emulated(self): -+ pass -+ -+ def test_create_networks_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_public_network(self): -+ pass -+ -+ def test_create_networks_bulk_wrong_input(self): -+ pass -+ -+ def test_update_shared_network_noadmin_returns_403(self): -+ pass -+ -+ def test_update_network_set_shared(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_single_tenant(self): -+ pass -+ -+ def test_update_network_set_not_shared_other_tenant_returns_409(self): -+ pass -+ -+ def test_update_network_with_subnet_set_shared(self): -+ pass -+ -+ def test_show_network(self): -+ pass -+ -+ def test_show_network_with_subnet(self): -+ pass -+ -+ def test_list_networks(self): -+ pass -+ -+ def test_list_shared_networks_with_non_admin_user(self): -+ pass -+ -+ def test_list_networks_with_parameters(self): -+ pass -+ -+ def test_list_networks_with_fields(self): -+ pass -+ -+ def test_list_networks_with_parameters_invalid_values(self): -+ pass -+ -+ def test_list_networks_with_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_without_pk_in_fields_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_with_sort_emulated(self): -+ pass -+ -+ def test_list_networks_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_invalid_admin_status(self): -+ pass -+ -+ -+class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: -+ assert False -+ else: -+ assert True -+ -+ def test_delete_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ subnet_id = subnet_dict['id'] -+ plugin_obj.delete_subnet(context_obj, subnet_id) -+ -+ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_delete_network(self): -+ pass -+ -+ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet_adding_additional_host_routes_and_dns(self): -+ pass -+ -+ def test_update_subnet_no_gateway(self): -+ pass -+ -+ def test_create_subnet_bad_cidr(self): -+ pass -+ -+ def test_create_subnet_gw_of_network_force_on_returns_400(self): -+ pass -+ -+ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_create_two_subnets(self): -+ pass -+ -+ def test_create_two_subnets_same_cidr_returns_400(self): -+ pass -+ -+ def test_create_subnet_bad_V4_cidr(self): -+ pass -+ -+ def test_create_subnet_bad_V6_cidr(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): -+ pass -+ -+ def test_create_subnets_bulk_native(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_subnets_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_network(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_other(self): -+ pass -+ -+ def test_create_subnet_bad_tenant(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version_null(self): -+ pass -+ -+ def test_create_subnet_bad_uuid(self): -+ pass -+ -+ def test_create_subnet_bad_boolean(self): -+ pass -+ -+ def test_create_subnet_bad_pools(self): -+ pass -+ -+ def test_create_subnet_bad_nameserver(self): -+ pass -+ -+ def test_create_subnet_bad_hostroutes(self): -+ pass -+ -+ def test_create_subnet_defaults(self): -+ pass -+ -+ def test_create_subnet_gw_values(self): -+ pass -+ -+ def test_create_force_subnet_gw_values(self): -+ pass -+ -+ def test_create_subnet_with_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_fully_allocated(self): -+ pass -+ -+ def test_subnet_with_allocation_range(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_v6_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_large_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_multiple_allocation_pools(self): -+ pass -+ -+ def test_create_subnet_with_dhcp_disabled(self): -+ pass -+ -+ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( -+ self): -+ pass -+ -+ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_create_subnet_overlapping_allocation_pools_returns_409(self): -+ pass -+ -+ def test_create_subnet_invalid_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_shared_returns_400(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_cidrv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_cidrv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_dns_v4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): -+ pass -+ -+ def test_create_subnet_gw_bcast_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet(self): -+ pass -+ -+ def test_update_subnet_shared_returns_400(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_dns_v6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): -+ pass -+ -+ def test_show_subnet(self): -+ pass -+ -+ def test_list_subnets(self): -+ pass -+ -+ def test_list_subnets_shared(self): -+ pass -+ -+ def test_list_subnets_with_parameter(self): -+ pass -+ -+ def test_invalid_ip_version(self): -+ pass -+ -+ def test_invalid_subnet(self): -+ pass -+ -+ def test_invalid_ip_address(self): -+ pass -+ -+ def test_invalid_uuid(self): -+ pass -+ -+ def test_create_subnet_with_one_dns(self): -+ pass -+ -+ def test_create_subnet_with_two_dns(self): -+ pass -+ -+ def test_create_subnet_with_too_many_dns(self): -+ pass -+ -+ def test_create_subnet_with_one_host_route(self): -+ pass -+ -+ def test_create_subnet_with_two_host_routes(self): -+ pass -+ -+ def test_create_subnet_with_too_many_routes(self): -+ pass -+ -+ def test_update_subnet_dns(self): -+ pass -+ -+ def test_update_subnet_dns_to_None(self): -+ pass -+ -+ def test_update_subnet_dns_with_too_many_entries(self): -+ pass -+ -+ def test_update_subnet_route(self): -+ pass -+ -+ def test_update_subnet_route_to_None(self): -+ pass -+ -+ def test_update_subnet_route_with_too_many_entries(self): -+ pass -+ -+ def test_delete_subnet_with_dns(self): -+ pass -+ -+ def test_delete_subnet_with_route(self): -+ pass -+ -+ def test_delete_subnet_with_dns_and_route(self): -+ pass -+ -+ def test_list_subnets_with_pagination_emulated(self): -+ pass -+ -+ def test_list_subnets_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_subnets_with_sort_emulated(self): -+ pass -+ -+ def test_validate_subnet_host_routes_exhausted(self): -+ pass -+ -+ def test_validate_subnet_dns_nameservers_exhausted(self): -+ pass -+ -+ -+class TestContrailPortsV2(test_plugin.TestPortsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_port_json(self): -+ pass -+ -+ def test_create_port_bad_tenant(self): -+ pass -+ -+ def test_create_port_public_network(self): -+ pass -+ -+ def test_create_port_public_network_with_ip(self): -+ pass -+ -+ def test_create_ports_bulk_native(self): -+ pass -+ -+ def test_create_ports_bulk_emulated(self): -+ pass -+ -+ def test_create_ports_bulk_wrong_input(self): -+ pass -+ -+ def test_create_ports_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_ports_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_list_ports(self): -+ pass -+ -+ def test_list_ports_filtered_by_fixed_ip(self): -+ pass -+ -+ def test_list_ports_public_network(self): -+ pass -+ -+ def test_show_port(self): -+ pass -+ -+ def test_delete_port(self): -+ pass -+ -+ def test_delete_port_public_network(self): -+ pass -+ -+ def test_update_port(self): -+ pass -+ -+ def test_update_device_id_null(self): -+ pass -+ -+ def test_delete_network_if_port_exists(self): -+ pass -+ -+ def test_delete_network_port_exists_owned_by_network(self): -+ pass -+ -+ def test_update_port_delete_ip(self): -+ pass -+ -+ def test_no_more_port_exception(self): -+ pass -+ -+ def test_update_port_update_ip(self): -+ pass -+ -+ def test_update_port_update_ip_address_only(self): -+ pass -+ -+ def test_update_port_update_ips(self): -+ pass -+ -+ def test_update_port_add_additional_ip(self): -+ pass -+ -+ def test_requested_duplicate_mac(self): -+ pass -+ -+ def test_mac_generation(self): -+ pass -+ -+ def test_mac_generation_4octet(self): -+ pass -+ -+ def test_bad_mac_format(self): -+ pass -+ -+ def test_mac_exhaustion(self): -+ pass -+ -+ def test_requested_duplicate_ip(self): -+ pass -+ -+ def test_requested_subnet_delete(self): -+ pass -+ -+ def test_requested_subnet_id(self): -+ pass -+ -+ def test_requested_subnet_id_not_on_network(self): -+ pass -+ -+ def test_overlapping_subnets(self): -+ pass -+ -+ def test_requested_subnet_id_v4_and_v6(self): -+ pass -+ -+ def test_range_allocation(self): -+ pass -+ -+ def test_requested_invalid_fixed_ips(self): -+ pass -+ -+ def test_invalid_ip(self): -+ pass -+ -+ def test_requested_split(self): -+ pass -+ -+ def test_duplicate_ips(self): -+ pass -+ -+ def test_fixed_ip_invalid_subnet_id(self): -+ pass -+ -+ def test_fixed_ip_invalid_ip(self): -+ pass -+ -+ def test_requested_ips_only(self): -+ pass -+ -+ def test_recycling(self): -+ pass -+ -+ def test_invalid_admin_state(self): -+ pass -+ -+ def test_invalid_mac_address(self): -+ pass -+ -+ def test_default_allocation_expiration(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration(self): -+ pass -+ -+ def test_port_delete_holds_ip(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration_invalid_address(self): -+ pass -+ -+ def test_hold_ip_address(self): -+ pass -+ -+ def test_recycle_held_ip_address(self): -+ pass -+ -+ def test_recycle_expired_previously_run_within_context(self): -+ pass -+ -+ def test_update_port_not_admin(self): -+ pass -+ -+ def test_list_ports_with_pagination_emulated(self): -+ pass -+ -+ def test_list_ports_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_ports_with_sort_emulated(self): -+ pass -+ -+ def test_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_update_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_recycle_ip_address_without_allocation_pool(self): -+ pass -diff --git setup.cfg setup.cfg -index 4876309..9fc01a2 100644 ---- setup.cfg -+++ setup.cfg -@@ -61,6 +61,7 @@ data_files = - etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini - etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini - etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini -+ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini - scripts = - bin/quantum-rootwrap - bin/neutron-rootwrap diff --git a/neutron_v2.patch b/neutron_v2.patch deleted file mode 100644 index 2a294ddab9..0000000000 --- a/neutron_v2.patch +++ /dev/null @@ -1,4705 +0,0 @@ -diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py -new file mode 100644 -index 0000000..5d610b3 ---- /dev/null -+++ neutron/extensions/ipam.py -@@ -0,0 +1,140 @@ -+from abc import abstractmethod -+ -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron.api import extensions -+from neutron import manager -+from oslo.config import cfg -+ -+ -+# Ipam Exceptions -+class IpamNotFound(qexception.NotFound): -+ message = _("IPAM %(id)s could not be found") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'ipams': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:regex': attr.UUID_PATTERN}, -+ 'is_visible': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'fq_name': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ 'mgmt': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': None}, -+ 'nets_using': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True, 'default': ''} -+ }, -+} -+ -+# TODO should this be tied to ipam extension? -+EXTENDED_ATTRIBUTES_2_0 = { -+ 'networks': { -+ 'contrail:fq_name': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:policys': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ 'contrail:subnet_ipam': {'allow_post': False, -+ 'allow_put': False, -+ 'default': '', -+ 'is_visible': True}, -+ }, -+ 'subnets': { -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:ipam_fq_name': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ } -+} -+ -+ -+class Ipam(object): -+ -+ @classmethod -+ def get_name(cls): -+ return "Network IP Address Management" -+ -+ @classmethod -+ def get_alias(cls): -+ return "ipam" -+ -+ @classmethod -+ def get_description(cls): -+ return ("Configuration object for holding common to a set of" -+ " IP address blocks") -+ -+ @classmethod -+ def get_namespace(cls): -+ return "http://docs.openstack.org/TODO" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2012-07-20T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ exts = [] -+ plugin = manager.QuantumManager.get_plugin() -+ for resource_name in ['ipam']: -+ collection_name = resource_name + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) -+ -+ member_actions = {} -+ -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, -+ member_actions=member_actions) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ member_actions=member_actions) -+ exts.append(ex) -+ -+ return exts -+ -+ def get_extended_resources(self, version): -+ if version == "2.0": -+ return EXTENDED_ATTRIBUTES_2_0 -+ else: -+ return {} -+#end class Ipam -+ -+ -+class IpamPluginBase(object): -+ -+ @abstractmethod -+ def create_ipam(self, context, ipam): -+ pass -+ -+ @abstractmethod -+ def update_ipam(self, context, id, ipam): -+ pass -+ -+ @abstractmethod -+ def get_ipam(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def delete_ipam(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_ipams(self, context, filters=None, fields=None): -+ pass -+#end class IpamPluginBase -diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py -index 425f8dc..69f1202 100644 ---- neutron/extensions/portbindings.py -+++ neutron/extensions/portbindings.py -@@ -44,10 +44,11 @@ VIF_TYPE_BRIDGE = 'bridge' - VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_HYPERV = 'hyperv' -+VIF_TYPE_CONTRAIL = 'contrail' - VIF_TYPE_OTHER = 'other' - VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, - VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, -- VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_OTHER] -+ VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_CONTRAIL, VIF_TYPE_OTHER] - - - EXTENDED_ATTRIBUTES_2_0 = { -diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py -new file mode 100644 -index 0000000..8028b32 ---- /dev/null -+++ neutron/plugins/juniper/contrail/contrailplugin.py -@@ -0,0 +1,1187 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+ -+import ConfigParser -+import logging -+from pprint import pformat -+ -+#from neutron.manager import NeutronManager -+from neutron.common import exceptions as exc -+from neutron.db import db_base_plugin_v2 -+from neutron.db import portbindings_base -+from neutron.extensions import l3 -+from neutron.extensions import securitygroup -+from neutron.extensions import portbindings -+#from neutron.extensions import vpcroutetable -+ -+import cgitb -+from httplib2 import Http -+from oslo.config import cfg -+import re -+import string -+import sys -+ -+import ctdb.config_db -+ -+LOG = logging.getLogger(__name__) -+ -+vnc_opts = [ -+ cfg.StrOpt('api_server_ip', default='127.0.0.1'), -+ cfg.StrOpt('api_server_port', default='8082'), -+] -+ -+ -+def _read_cfg(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.get(section, option) -+ except (AttributeError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+def _read_cfg_boolean(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.getboolean(section, option) -+ except (AttributeError, ValueError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, -+ l3.RouterPluginBase, -+ securitygroup.SecurityGroupPluginBase, -+ portbindings_base.PortBindingBaseMixin): -+#vpcroutetable.RouteTablePluginBase): -+ -+ supported_extension_aliases = ["ipam", "policy", "security-group", -+ "router", "route-table", "port-security", -+ "binding",] -+ __native_bulk_support = False -+ _cfgdb = None -+ _args = None -+ _tenant_id_dict = {} -+ _tenant_name_dict = {} -+ -+ @classmethod -+ def _parse_class_args(cls, cfg_parser): -+ cfg_parser.read("/etc/neutron/plugins/juniper/" -+ "contrail/ContrailPlugin.ini" -+ ) -+ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', -+ 'multi_tenancy', False) -+ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') -+ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') -+ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', -+ 'user1') -+ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_password', 'password1') -+ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_tenant_name', -+ 'default-domain') -+ cls._tenants_api = '%s/tenants' % (cls._auth_url) -+ pass -+ -+ @classmethod -+ def _connect_to_db(cls): -+ """ -+ Many instantiations of plugin (base + extensions) but need to have -+ only one config db conn (else error from ifmap-server) -+ """ -+ cls._cfgdb_map = {} -+ if cls._cfgdb is None: -+ sip = cfg.CONF.APISERVER.api_server_ip -+ sport = cfg.CONF.APISERVER.api_server_port -+ # Initialize connection to DB and add default entries -+ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, -+ cls._admin_password, -+ cls._admin_tenant_name, -+ sip, sport) -+ cls._cfgdb.manager = cls -+ -+ @classmethod -+ def _get_user_cfgdb(cls, context): -+ if not cls._multi_tenancy: -+ return cls._cfgdb -+ user_id = context.user_id -+ role = string.join(context.roles, ",") -+ if user_id not in cls._cfgdb_map: -+ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( -+ cls._admin_user, cls._admin_password, cls._admin_tenant_name, -+ cfg.CONF.APISERVER.api_server_ip, -+ cfg.CONF.APISERVER.api_server_port, -+ user_info={'user_id': user_id, 'role': role}) -+ cls._cfgdb_map[user_id].manager = cls -+ -+ return cls._cfgdb_map[user_id] -+ -+ @classmethod -+ def _tenant_list_from_keystone(cls): -+ # get all tenants -+ hdrs = {'X-Auth-Token': cls._admin_token, -+ 'Content-Type': 'application/json'} -+ try: -+ rsp, content = Http().request(cls._tenants_api, -+ method="GET", headers=hdrs) -+ if rsp.status != 200: -+ return -+ except Exception: -+ return -+ -+ # transform needed for python compatibility -+ content = re.sub('true', 'True', content) -+ content = re.sub('null', 'None', content) -+ content = eval(content) -+ -+ # bail if response is unexpected -+ if 'tenants' not in content: -+ return -+ -+ # create a dictionary for id->name and name->id mapping -+ for tenant in content['tenants']: -+ print 'Adding tenant %s:%s to cache' % (tenant['name'], -+ tenant['id']) -+ cls._tenant_id_dict[tenant['id']] = tenant['name'] -+ cls._tenant_name_dict[tenant['name']] = tenant['id'] -+ -+ def update_security_group(self, context, id, security_group): -+ pass -+ -+ def __init__(self): -+ cfg.CONF.register_opts(vnc_opts, 'APISERVER') -+ -+ cfg_parser = ConfigParser.ConfigParser() -+ ContrailPlugin._parse_class_args(cfg_parser) -+ -+ ContrailPlugin._connect_to_db() -+ self._cfgdb = ContrailPlugin._cfgdb -+ -+ ContrailPlugin._tenant_list_from_keystone() -+ self.base_binding_dict = self._get_base_binding_dict() -+ portbindings_base.register_port_dict_function() -+ -+ def _get_base_binding_dict(self): -+ binding = { -+ portbindings.VIF_TYPE: portbindings.VIF_TYPE_CONTRAIL, -+ portbindings.CAPABILITIES: { -+ portbindings.CAP_PORT_FILTER: -+ 'security-group' in self.supported_extension_aliases}} -+ return binding -+ -+ @classmethod -+ def tenant_id_to_name(cls, id): -+ # bail if we never built the list successfully -+ if len(cls._tenant_id_dict) == 0: -+ return id -+ # check cache -+ if id in cls._tenant_id_dict: -+ return cls._tenant_id_dict[id] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id -+ -+ @classmethod -+ def tenant_name_to_id(cls, name): -+ # bail if we never built the list successfully -+ if len(cls._tenant_name_dict) == 0: -+ return name -+ # check cache -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ else: -+ return name -+ -+ # Network API handlers -+ def create_network(self, context, network): -+ """ -+ Creates a new Virtual Network, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_create(network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("create_network(): " + pformat(net_dict) + "\n") -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_network(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_read(id, fields) -+ -+ # verify transformation is conforming to api -+ if not fields: -+ # should return all fields -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ fields, False) -+ net_dict.update(net_info['q_extra_data']) -+ else: -+ net_dict = net_info['q_api_data'] -+ -+ LOG.debug("get_network(): " + pformat(net_dict)) -+ return self._fields(net_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_network(self, context, net_id, network): -+ """ -+ Updates the attributes of a particular Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_update(net_id, network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("update_network(): " + pformat(net_dict)) -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_network(self, context, net_id): -+ """ -+ Deletes the network with the specified network identifier -+ belonging to the specified tenant. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.network_delete(net_id) -+ LOG.debug("delete_network(): " + pformat(net_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_info = cfgdb.network_list(filters) -+ -+ nets_dicts = [] -+ for n_info in nets_info: -+ # verify transformation is conforming to api -+ n_dict = self._make_network_dict(n_info['q_api_data'], fields, -+ False) -+ -+ n_dict.update(n_info['q_extra_data']) -+ nets_dicts.append(n_dict) -+ -+ LOG.debug( -+ "get_networks(): filters: " + pformat(filters) + " data: " -+ + pformat(nets_dicts)) -+ return nets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_count = cfgdb.network_count(filters) -+ LOG.debug("get_networks_count(): " + str(nets_count)) -+ return nets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Subnet API handlers -+ def create_subnet(self, context, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_create(subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("create_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnet(self, context, subnet_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_read(subnet_id) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], -+ fields) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("get_subnet(): " + pformat(subnet_dict)) -+ return self._fields(subnet_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_subnet(self, context, subnet_id, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("update_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_subnet(self, context, subnet_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.subnet_delete(subnet_id) -+ -+ LOG.debug("delete_subnet(): " + pformat(subnet_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets(self, context, filters=None, fields=None): -+ """ -+ Called from Neutron API -> get_ -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_info = cfgdb.subnets_list(filters) -+ -+ subnets_dicts = [] -+ for sn_info in subnets_info: -+ # verify transformation is conforming to api -+ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) -+ -+ sn_dict.update(sn_info['q_extra_data']) -+ subnets_dicts.append(sn_dict) -+ -+ LOG.debug( -+ "get_subnets(): filters: " + pformat(filters) + " data: " -+ + pformat(subnets_dicts)) -+ return subnets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_count = cfgdb.subnets_count(filters) -+ LOG.debug("get_subnets_count(): " + str(subnets_count)) -+ return subnets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Ipam API handlers -+ def create_ipam(self, context, ipam): -+ """ -+ Creates a new IPAM, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_create(ipam['ipam']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("create_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipam(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("get_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_ipam(self, context, id, ipam): -+ """ -+ Updates the attributes of a particular IPAM. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_update(id, ipam) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("update_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_ipam(self, context, ipam_id): -+ """ -+ Deletes the ipam with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.ipam_delete(ipam_id) -+ -+ LOG.debug("delete_ipam(): " + pformat(ipam_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_info = cfgdb.ipam_list(filters) -+ -+ ipams_dicts = [] -+ for ipam_info in ipams_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ ipams_dicts.append(ipam_dict) -+ -+ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) -+ return ipams_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_count = cfgdb.ipams_count(filters) -+ LOG.debug("get_ipams_count(): " + str(ipams_count)) -+ return ipams_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Policy API handlers -+ def create_policy(self, context, policy): -+ """ -+ Creates a new Policy, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_create(policy['policy']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("create_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("get_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_policy(self, context, id, policy): -+ """ -+ Updates the attributes of a particular Policy. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_update(id, policy) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("update_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_policy(self, context, policy_id): -+ """ -+ Deletes the Policy with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.policy_delete(policy_id) -+ -+ LOG.debug("delete_policy(): " + pformat(policy_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policys(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policys_info = cfgdb.policy_list(filters) -+ -+ policys_dicts = [] -+ for policy_info in policys_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ policys_dicts.append(policy_dict) -+ -+ LOG.debug("get_policys(): " + pformat(policys_dicts)) -+ return policys_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_count = cfgdb.policy_count(filters) -+ LOG.debug("get_policy_count(): " + str(policy_count)) -+ return policy_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Floating IP API handlers -+ def _make_floatingip_dict(self, floatingip, fields=None): -+ res = {'id': floatingip['id'], -+ 'tenant_id': floatingip['tenant_id'], -+ 'floating_ip_address': floatingip['floating_ip_address'], -+ 'floating_network_id': floatingip['floating_network_id'], -+ 'router_id': floatingip['router_id'], -+ 'port_id': floatingip['fixed_port_id'], -+ 'fixed_ip_address': floatingip['fixed_ip_address']} -+ return self._fields(res, fields) -+ -+ def create_floatingip(self, context, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("create_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_floatingip(self, context, fip_id, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_update(fip_id, -+ floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("update_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingip(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_read(id) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("get_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_floatingip(self, context, fip_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.floatingip_delete(fip_id) -+ LOG.debug("delete_floating(): " + pformat(fip_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fips_info = cfgdb.floatingip_list(filters) -+ -+ fips_dicts = [] -+ for fip_info in fips_info: -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ fips_dicts.append(fip_dict) -+ -+ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) -+ return fips_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ floatingips_count = cfgdb.floatingip_count(filters) -+ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) -+ return floatingips_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Port API handlers -+ def create_port(self, context, port): -+ """ -+ Creates a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_create(port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ -+ LOG.debug("create_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_port(self, context, port_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_read(port_id) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ port_info, -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("get_port(): " + pformat(port_dict)) -+ return self._fields(port_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_port(self, context, port_id, port): -+ """ -+ Updates the attributes of a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_update(port_id, port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("update_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_port(self, context, port_id): -+ """ -+ Deletes a port on a specified Virtual Network, -+ if the port contains a remote interface attachment, -+ the remote interface is first un-plugged and then the port -+ is deleted. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.port_delete(port_id) -+ LOG.debug("delete_port(): " + pformat(port_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports(self, context, filters=None, fields=None): -+ """ -+ Retrieves all port identifiers belonging to the -+ specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_info = cfgdb.port_list(filters) -+ -+ ports_dicts = [] -+ for p_info in ports_info: -+ # verify transformation is conforming to api -+ p_dict = self._make_port_dict(p_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ p_info, -+ p_dict) -+ -+ p_dict.update(p_info['q_extra_data']) -+ ports_dicts.append(p_dict) -+ -+ LOG.debug( -+ "get_ports(): filter: " + pformat(filters) + 'data: ' -+ + pformat(ports_dicts)) -+ return ports_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_count = cfgdb.port_count(filters) -+ LOG.debug("get_ports_count(): " + str(ports_count)) -+ return ports_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): -+ """ -+ Attaches a remote interface to the specified port on the -+ specified Virtual Network. -+ """ -+ port = self._get_port(tenant_id, net_id, port_id) -+ # Validate attachment -+ self._validate_attachment(tenant_id, net_id, port_id, -+ remote_interface_id) -+ if port['interface_id']: -+ raise exc.PortInUse(net_id=net_id, port_id=port_id, -+ att_id=port['interface_id']) -+ -+ def unplug_interface(self, tenant_id, net_id, port_id): -+ """ -+ Detaches a remote interface from the specified port on the -+ specified Virtual Network. -+ """ -+ self._get_port(tenant_id, net_id, port_id) -+ -+ # VPC route table handlers -+ def _make_route_table_routes_dict(self, route_table_route, fields=None): -+ res = {'prefix': route_table_route['prefix'], -+ 'next_hop': route_table_route['next_hop']} -+ -+ return self._fields(res, fields) -+ -+ def _make_route_table_dict(self, route_table, fields=None): -+ res = {'id': route_table['id'], -+ 'name': route_table['name'], -+ 'fq_name': route_table['fq_name'], -+ 'tenant_id': route_table['tenant_id']} -+ if route_table['routes']: -+ res['routes'] = [self._make_route_table_routes_dict(r) -+ for r in route_table['routes']['route']] -+ return self._fields(res, fields) -+ -+ def create_route_table(self, context, route_table): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_create( -+ route_table['route_table']) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_route_table(self, context, id, route_table): -+ """ -+ Updates the attributes of a particular route table. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_update(id, route_table['route_table']) -+ -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_route_table(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.route_table_delete(id) -+ LOG.debug("delete_route_table(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_tables(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ route_tables_info = cfgdb.route_table_list(context, filters) -+ -+ route_tables_dicts = [] -+ for rt_info in route_tables_info: -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ route_tables_dicts.append(rt_dict) -+ -+ LOG.debug( -+ "get_route_tables(): filter: " + pformat(filters) -+ + 'data: ' + pformat(route_tables_dicts)) -+ return route_tables_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_table(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_read(id) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ -+ LOG.debug("get_route_table(): " + pformat(rt_dict)) -+ return self._fields(rt_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # VPC route table svc instance handlers -+ def _make_svc_instance_dict(self, svc_instance, fields=None): -+ res = {'id': svc_instance['id'], -+ 'name': svc_instance['name'], -+ 'tenant_id': svc_instance['tenant_id']} -+ if svc_instance['internal_net']: -+ res['internal_net'] = svc_instance['internal_net'] -+ if svc_instance['external_net']: -+ res['external_net'] = svc_instance['external_net'] -+ return self._fields(res, fields) -+ -+ def create_nat_instance(self, context, nat_instance): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_create( -+ nat_instance['nat_instance']) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("create_nat_instance(): " + pformat(si_dict)) -+ return si_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_nat_instance(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.svc_instance_delete(id) -+ LOG.debug("delete_nat_instance(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instances(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ svc_instances_info = cfgdb.svc_instance_list(context, filters) -+ -+ svc_instances_dicts = [] -+ for si_info in svc_instances_info: -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ svc_instances_dicts.append(si_dict) -+ -+ LOG.debug( -+ "get_nat_instances(): filter: " + pformat(filters) -+ + 'data: ' + pformat(svc_instances_dicts)) -+ return svc_instances_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instance(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_read(id) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("get_nat_instance(): " + pformat(si_dict)) -+ return self._fields(si_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Security Group handlers -+ def _make_security_group_rule_dict(self, security_group_rule, fields=None): -+ res = {'id': security_group_rule['id'], -+ 'tenant_id': security_group_rule['tenant_id'], -+ 'security_group_id': security_group_rule['security_group_id'], -+ 'ethertype': security_group_rule['ethertype'], -+ 'direction': security_group_rule['direction'], -+ 'protocol': security_group_rule['protocol'], -+ 'port_range_min': security_group_rule['port_range_min'], -+ 'port_range_max': security_group_rule['port_range_max'], -+ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], -+ 'remote_group_id': security_group_rule['remote_group_id']} -+ -+ return self._fields(res, fields) -+ -+ def _make_security_group_dict(self, security_group, fields=None): -+ res = {'id': security_group['id'], -+ 'name': security_group['name'], -+ 'tenant_id': security_group['tenant_id'], -+ 'description': security_group['description']} -+ res['security_group_rules'] = [self._make_security_group_rule_dict(r) -+ for r in security_group['rules']] -+ return self._fields(res, fields) -+ -+ def create_security_group(self, context, security_group): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_create( -+ security_group['security_group']) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("create_security_group(): " + pformat(sg_dict)) -+ return sg_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_delete(id) -+ LOG.debug("delete_security_group(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_groups(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_groups_info = cfgdb.security_group_list(context, filters) -+ -+ security_groups_dicts = [] -+ for sg_info in security_groups_info: -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ security_groups_dicts.append(sg_dict) -+ -+ LOG.debug( -+ "get_security_groups(): filter: " + pformat(filters) -+ + 'data: ' + pformat(security_groups_dicts)) -+ return security_groups_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_read(id) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("get_security_group(): " + pformat(sg_dict)) -+ return self._fields(sg_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def create_security_group_rule(self, context, security_group_rule): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_create( -+ security_group_rule['security_group_rule']) -+ -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data']) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) -+ return sgr_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group_rule(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_rule_delete(id) -+ LOG.debug("delete_security_group_rule(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rules(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_group_rules_info = cfgdb.security_group_rule_list(filters) -+ -+ security_group_rules_dicts = [] -+ for sgr_info in security_group_rules_info: -+ for sgr in sgr_info: -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr['q_api_data'], fields) -+ sgr_dict.update(sgr['q_extra_data']) -+ security_group_rules_dicts.append(sgr_dict) -+ -+ LOG.debug( -+ "get_security_group_rules(): filter: " + pformat(filters) + -+ 'data: ' + pformat(security_group_rules_dicts)) -+ return security_group_rules_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rule(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_read(id) -+ -+ # verify transformation is conforming to api -+ sgr_dict = {} -+ if sgr_info != {}: -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data'], fields) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) -+ return self._fields(sgr_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py -new file mode 100644 -index 0000000..4a87a41 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/config_db.py -@@ -0,0 +1,2238 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+import json -+import re -+import requests -+import socket -+import time -+import uuid -+from netaddr import IPNetwork, IPSet, IPAddress -+ -+from neutron.api.v2 import attributes as attr -+from neutron.common import constants -+from neutron.common import exceptions -+from neutron.extensions import portbindings -+from vnc_api.common import exceptions as vnc_exc -+from vnc_api import vnc_api -+ -+_DEFAULT_HEADERS = { -+ 'Content-type': 'application/json; charset="UTF-8"', } -+ -+CREATE = 1 -+READ = 2 -+UPDATE = 3 -+DELETE = 4 -+ -+ -+class DBInterface(object): -+ """ -+ An instance of this class forwards requests to vnc cfg api (web)server -+ """ -+ Q_URL_PREFIX = '/extensions/ct' -+ -+ def __init__(self, admin_name, admin_password, admin_tenant_name, -+ api_srvr_ip, api_srvr_port, user_info=None): -+ self._api_srvr_ip = api_srvr_ip -+ self._api_srvr_port = api_srvr_port -+ -+ self._db_cache = {} -+ self._db_cache['q_networks'] = {} -+ self._db_cache['q_subnets'] = {} -+ self._db_cache['q_subnet_maps'] = {} -+ self._db_cache['q_policies'] = {} -+ self._db_cache['q_ipams'] = {} -+ self._db_cache['q_floatingips'] = {} -+ self._db_cache['q_ports'] = {} -+ self._db_cache['q_fixed_ip_to_subnet'] = {} -+ #obj-uuid to tenant-uuid mapping -+ self._db_cache['q_obj_to_tenant'] = {} -+ #port count per tenant-id -+ self._db_cache['q_tenant_port_count'] = {} -+ self._db_cache['vnc_networks'] = {} -+ self._db_cache['vnc_ports'] = {} -+ self._db_cache['vnc_projects'] = {} -+ self._db_cache['vnc_instance_ips'] = {} -+ -+ # Retry till a api-server is up -+ connected = False -+ while not connected: -+ try: -+ self._vnc_lib = vnc_api.VncApi( -+ admin_name, admin_password, -+ admin_tenant_name, api_srvr_ip, -+ api_srvr_port, '/', user_info=user_info) -+ connected = True -+ except requests.exceptions.RequestException: -+ time.sleep(3) -+ -+ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key -+ subnet_map = self._vnc_lib.kv_retrieve(key=None) -+ for kv_dict in subnet_map: -+ key = kv_dict['key'] -+ if len(key.split()) == 1: -+ subnet_id = key -+ # uuid key, fixup value portion to 'net_id pfx/len' format -+ # if not already so -+ if len(kv_dict['value'].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ net_fq_name = kv_dict['value'].split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ self._vnc_lib.kv_delete(subnet_id) -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, -+ kv_dict['value'].split()[1]) -+ self._vnc_lib.kv_store(subnet_id, new_subnet_key) -+ else: # subnet key -+ if len(key.split()[0].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ # delete old key, convert to new key format and save -+ old_subnet_key = key -+ self._vnc_lib.kv_delete(old_subnet_key) -+ -+ subnet_id = kv_dict['value'] -+ net_fq_name = key.split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) -+ self._vnc_lib.kv_store(new_subnet_key, subnet_id) -+ -+ # Helper routines -+ def _request_api_server(self, url, method, data=None, headers=None): -+ if method == 'GET': -+ return requests.get(url) -+ if method == 'POST': -+ return requests.post(url, data=data, headers=headers) -+ if method == 'DELETE': -+ return requests.delete(url) -+ -+ def _relay_request(self, request): -+ """ -+ Send received request to api server -+ """ -+ # chop neutron parts of url and add api server address -+ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) -+ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, -+ url_path) -+ -+ return self._request_api_server( -+ url, request.environ['REQUEST_METHOD'], -+ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) -+ -+ def _obj_to_json(self, obj): -+ return dict((k, v) for k, v in obj.__dict__.iteritems()) -+ -+ def _ensure_instance_exists(self, instance_id): -+ instance_name = instance_id -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ try: -+ id = self._vnc_lib.obj_to_id(instance_obj) -+ instance_obj = self._vnc_lib.virtual_machine_read(id=id) -+ except Exception as e: -+ #except vnc_exc.NoIdError: # instance doesn't exist, create it -+ instance_obj.uuid = instance_id -+ self._vnc_lib.virtual_machine_create(instance_obj) -+ -+ return instance_obj -+ -+ def _ensure_default_security_group_exists(self, proj_id): -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ sg_groups = proj_obj.get_security_groups() -+ for sg_group in sg_groups or []: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) -+ if sg_obj.name == 'default': -+ return -+ -+ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) -+ self._vnc_lib.security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ #allow ingress traffic from within default security group -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'ingress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ def _get_obj_tenant_id(self, q_type, obj_uuid): -+ # Get the mapping from cache, else seed cache and return -+ try: -+ return self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except KeyError: -+ # Seed the cache and return -+ if q_type == 'port': -+ port_obj = self._virtual_machine_interface_read(obj_uuid) -+ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] -+ # recurse up type-hierarchy -+ tenant_id = self._get_obj_tenant_id('network', net_id) -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ if q_type == 'network': -+ net_obj = self._virtual_network_read(net_id=obj_uuid) -+ tenant_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ return None -+ -+ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): -+ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid -+ -+ def _del_obj_tenant_id(self, obj_uuid): -+ try: -+ del self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except Exception: -+ pass -+ -+ def _project_read(self, proj_id=None, fq_name=None): -+ if proj_id: -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][proj_id] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ fq_name_str = json.dumps(proj_obj.get_fq_name()) -+ self._db_cache['vnc_projects'][proj_id] = proj_obj -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ return proj_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][fq_name_str] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj -+ return proj_obj -+ -+ def _security_group_rule_create(self, sg_id, sg_rule): -+ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) -+ rules = sg_vnc.get_security_group_entries() -+ if rules is None: -+ rules = vnc_api.PolicyEntriesType([sg_rule]) -+ else: -+ rules.add_policy_rule(sg_rule) -+ -+ sg_vnc.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_vnc) -+ return -+ -+ def _security_group_rule_find(self, sgr_id): -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ -+ for sg in project_sgs: -+ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) -+ sgr_entries = sg_obj.get_security_group_entries() -+ if sgr_entries is None: -+ continue -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ if sg_rule.get_rule_uuid() == sgr_id: -+ return sg_obj, sg_rule -+ -+ return None, None -+ -+ def _security_group_rule_delete(self, sg_obj, sg_rule): -+ rules = sg_obj.get_security_group_entries() -+ rules.get_policy_rule().remove(sg_rule) -+ sg_obj.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_obj) -+ return -+ -+ def _security_group_create(self, sg_obj): -+ sg_uuid = self._vnc_lib.security_group_create(sg_obj) -+ return sg_uuid -+ -+ def _security_group_delete(self, sg_id): -+ self._vnc_lib.security_group_delete(id=sg_id) -+ -+ def _svc_instance_create(self, si_obj): -+ si_uuid = self._vnc_lib.service_instance_create(si_obj) -+ st_fq_name = ['default-domain', 'nat-template'] -+ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) -+ si_obj.set_service_template(st_obj) -+ self._vnc_lib.service_instance_update(si_obj) -+ -+ return si_uuid -+ -+ def _svc_instance_delete(self, si_id): -+ self._vnc_lib.service_instance_delete(id=si_id) -+ -+ def _route_table_create(self, rt_obj): -+ rt_uuid = self._vnc_lib.route_table_create(rt_obj) -+ return rt_uuid -+ -+ def _route_table_delete(self, rt_id): -+ self._vnc_lib.route_table_delete(id=rt_id) -+ -+ def _virtual_network_create(self, net_obj): -+ net_uuid = self._vnc_lib.virtual_network_create(net_obj) -+ -+ return net_uuid -+ -+ def _virtual_network_read(self, net_id=None, fq_name=None): -+ if net_id: -+ try: -+ # return self._db_cache['vnc_networks'][net_id] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(id=net_id) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ self._db_cache['vnc_networks'][net_id] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ return net_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_networks'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ return net_obj -+ -+ def _virtual_network_update(self, net_obj): -+ self._vnc_lib.virtual_network_update(net_obj) -+ # read back to get subnet gw allocated by api-server -+ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ -+ def _virtual_network_delete(self, net_id): -+ fq_name_str = None -+ try: -+ net_obj = self._db_cache['vnc_networks'][net_id] -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_network_delete(id=net_id) -+ -+ try: -+ del self._db_cache['vnc_networks'][net_id] -+ if fq_name_str: -+ del self._db_cache['vnc_networks'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _virtual_machine_interface_create(self, port_obj): -+ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) -+ -+ return port_uuid -+ -+ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): -+ if port_id: -+ try: -+ # return self._db_cache['vnc_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ id=port_id) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ self._db_cache['vnc_ports'][port_id] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ return port_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_ports'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ fq_name=fq_name) -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ return port_obj -+ -+ def _virtual_machine_interface_update(self, port_obj): -+ self._vnc_lib.virtual_machine_interface_update(port_obj) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ -+ def _virtual_machine_interface_delete(self, port_id): -+ fq_name_str = None -+ try: -+ port_obj = self._db_cache['vnc_ports'][port_id] -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_machine_interface_delete(id=port_id) -+ -+ try: -+ del self._db_cache['vnc_ports'][port_id] -+ if fq_name_str: -+ del self._db_cache['vnc_ports'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _instance_ip_create(self, iip_obj): -+ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) -+ -+ return iip_uuid -+ -+ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): -+ if instance_ip_id: -+ try: -+ # return self._db_cache['vnc_instance_ips'][instance_ip_id] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ return iip_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_instance_ips'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ return iip_obj -+ -+ def _instance_ip_update(self, iip_obj): -+ self._vnc_lib.instance_ip_update(iip_obj) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ -+ def _instance_ip_delete(self, instance_ip_id): -+ fq_name_str = None -+ try: -+ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.instance_ip_delete(id=instance_ip_id) -+ -+ try: -+ del self._db_cache['vnc_instance_ips'][instance_ip_id] -+ if fq_name_str: -+ del self._db_cache['vnc_instance_ips'][fq_name_str] -+ except KeyError: -+ pass -+ -+ # find projects on a given domain -+ def _project_list_domain(self, domain_id): -+ fq_name = ['default-domain'] -+ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) -+ -+ return resp_dict['projects'] -+ -+ # find network ids on a given project -+ def _network_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) -+ -+ return resp_dict['virtual-networks'] -+ -+ def _ipam_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) -+ -+ return resp_dict['network-ipams'] -+ -+ def _security_group_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ self._ensure_default_security_group_exists(project_uuid) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _security_group_entries_list_sg(self, sg_id): -+ try: -+ sg_uuid = str(uuid.UUID(sg_id)) -+ except Exception: -+ print "Error in converting SG uuid %s" % (sg_id) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _route_table_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) -+ -+ return resp_dict['route-tables'] -+ -+ def _svc_instance_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) -+ -+ return resp_dict['service-instances'] -+ -+ def _policy_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) -+ -+ return resp_dict['network-policys'] -+ -+ # find floating ip pools a project has access to -+ def _fip_pool_refs_project(self, project_id): -+ project_uuid = str(uuid.UUID(project_id)) -+ project_obj = self._project_read(proj_id=project_uuid) -+ -+ return project_obj.get_floating_ip_pool_refs() -+ -+ # find networks of floating ip pools project has access to -+ def _fip_pool_ref_networks(self, project_id): -+ ret_nets = [] -+ -+ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) -+ if not proj_fip_pool_refs: -+ return ret_nets -+ -+ for fip_pool_ref in proj_fip_pool_refs: -+ fip_uuid = fip_pool_ref['uuid'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) -+ net_uuid = fip_pool_obj.parent_uuid -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ ret_nets.append({'uuid': net_obj.uuid, -+ 'fq_name': net_obj.get_fq_name()}) -+ -+ return ret_nets -+ -+ # find floating ip pools defined by network -+ def _fip_pool_list_network(self, net_id): -+ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) -+ -+ return resp_dict['floating-ip-pools'] -+ -+ # find port ids on a given network -+ def _port_list_network(self, network_id): -+ ret_list = [] -+ -+ try: -+ net_obj = self._virtual_network_read(net_id=network_id) -+ except vnc_exc.NoIdError: -+ return ret_list -+ -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ for port_back_ref in port_back_refs: -+ ret_list.append({'id': port_back_ref['uuid']}) -+ -+ return ret_list -+ -+ # find port ids on a given project -+ def _port_list_project(self, project_id): -+ ret_list = [] -+ project_nets = self._network_list_project(project_id) -+ for net in project_nets: -+ net_ports = self._port_list_network(net['uuid']) -+ ret_list.extend(net_ports) -+ -+ return ret_list -+ -+ # Returns True if -+ # * no filter is specified -+ # OR -+ # * search-param is not present in filters -+ # OR -+ # * 1. search-param is present in filters AND -+ # 2. resource matches param-list AND -+ # 3. shared parameter in filters is False -+ def _filters_is_present(self, filters, key_name, match_value): -+ if filters: -+ if key_name in filters: -+ try: -+ if ('shared' in filters and -+ filters['shared'][0] is True): -+ # yuck, q-api has shared as list always of 1 elem -+ return False # no shared-resource support -+ except ValueError: # not in requested list -+ return False -+ elif len(filters.keys()) == 1: -+ shared_val = filters.get('shared', None) -+ if shared_val and shared_val[0] is True: -+ return False -+ -+ return True -+ -+ def _network_read(self, net_uuid): -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ return net_obj -+ -+ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): -+ #import pdb; pdb.set_trace() -+ self._vnc_lib.kv_store(subnet_id, subnet_key) -+ self._vnc_lib.kv_store(subnet_key, subnet_id) -+ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key -+ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id -+ -+ def _subnet_vnc_read_mapping(self, id=None, key=None): -+ if id: -+ try: -+ return self._db_cache['q_subnet_maps'][id] -+ #raise KeyError -+ except KeyError: -+ subnet_key = self._vnc_lib.kv_retrieve(id) -+ self._db_cache['q_subnet_maps'][id] = subnet_key -+ return subnet_key -+ if key: -+ try: -+ return self._db_cache['q_subnet_maps'][key] -+ #raise KeyError -+ except KeyError: -+ subnet_id = self._vnc_lib.kv_retrieve(key) -+ self._db_cache['q_subnet_maps'][key] = subnet_id -+ return subnet_id -+ -+ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): -+ if id: -+ return self._subnet_vnc_read_mapping(id=id) -+ -+ # if subnet was created outside of neutron handle it and create -+ # neutron representation now (lazily) -+ try: -+ return self._subnet_vnc_read_mapping(key=key) -+ except vnc_exc.NoIdError: -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, key) -+ return self._subnet_vnc_read_mapping(key=key) -+ -+ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): -+ self._vnc_lib.kv_delete(subnet_id) -+ self._vnc_lib.kv_delete(subnet_key) -+ try: -+ del self._db_cache['q_subnet_maps'][subnet_id] -+ del self._db_cache['q_subnet_maps'][subnet_key] -+ except KeyError: -+ pass -+ -+ def _subnet_vnc_get_key(self, subnet_vnc, net_id): -+ pfx = subnet_vnc.subnet.get_ip_prefix() -+ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() -+ -+ return '%s %s/%s' % (net_id, pfx, pfx_len) -+ -+ def _subnet_read(self, net_uuid, subnet_key): -+ try: -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ except vnc_exc.NoIdError: -+ return None -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if not ipam_refs: -+ return None -+ -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_uuid) == subnet_key: -+ return subnet_vnc -+ -+ return None -+ -+ def _ip_address_to_subnet_id(self, ip_addr, net_obj): -+ # find subnet-id for ip-addr, called when instance-ip created -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ if IPAddress(ip_addr) in IPSet([cidr]): -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, -+ net_obj.uuid) -+ subnet_id = self._subnet_vnc_read_mapping( -+ key=subnet_key) -+ return subnet_id -+ -+ return None -+ -+ # Conversion routines between VNC and Quantum objects -+ def _svc_instance_neutron_to_vnc(self, si_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(si_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ net_id = si_q['internal_net'] -+ int_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ net_id = si_q['external_net'] -+ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, -+ auto_scale=False) -+ si_prop = vnc_api.ServiceInstanceType( -+ auto_policy=True, left_virtual_network=int_vn.name, -+ right_virtual_network=ext_vn.name, scale_out=scale_out) -+ si_prop.set_scale_out(scale_out) -+ si_vnc = vnc_api.ServiceInstance( -+ name=si_q['name'], -+ parent_obj=project_obj, -+ service_instance_properties=si_prop) -+ -+ return si_vnc -+ -+ def _svc_instance_vnc_to_neutron(self, si_obj): -+ si_q_dict = json.loads(json.dumps(si_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ si_q_dict['id'] = si_obj.uuid -+ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') -+ si_q_dict['name'] = si_obj.name -+ si_props = si_obj.get_service_instance_properties() -+ if si_props: -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_left_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_right_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ -+ return {'q_api_data': si_q_dict, -+ 'q_extra_data': {}} -+ -+ def _route_table_neutron_to_vnc(self, rt_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(rt_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], -+ parent_obj=project_obj) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ else: -+ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ -+ return rt_vnc -+ -+ def _route_table_vnc_to_neutron(self, rt_obj): -+ rt_q_dict = json.loads(json.dumps(rt_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ rt_q_dict['id'] = rt_obj.uuid -+ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') -+ rt_q_dict['name'] = rt_obj.name -+ rt_q_dict['fq_name'] = rt_obj.fq_name -+ -+ # get route table routes -+ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) -+ return {'q_api_data': rt_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_vnc_to_neutron(self, sg_obj): -+ sg_q_dict = json.loads(json.dumps(sg_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ sg_q_dict['id'] = sg_obj.uuid -+ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sg_q_dict['name'] = sg_obj.name -+ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() -+ -+ # get security group rules -+ sg_q_dict['rules'] = [] -+ rule_list = self.security_group_rules_read(sg_obj.uuid) -+ if rule_list: -+ for rule in rule_list: -+ sg_q_dict['rules'].append(rule['q_api_data']) -+ -+ return {'q_api_data': sg_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_neutron_to_vnc(self, sg_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(sg_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType( -+ enable=True, description=sg_q['description']) -+ sg_vnc = vnc_api.SecurityGroup( -+ name=sg_q['name'], parent_obj=project_obj, -+ id_perms=id_perms) -+ -+ return sg_vnc -+ -+ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): -+ sgr_q_dict = {} -+ if sg_id is None: -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ direction = 'egress' -+ if sg_rule.get_direction() == '<': -+ direction = 'ingress' -+ -+ remote_cidr = '' -+ remote_sg_uuid = '' -+ if direction == 'ingress': -+ addr = sg_rule.get_src_addresses()[0] -+ else: -+ addr = sg_rule.get_dst_addresses()[0] -+ -+ if addr.get_subnet(): -+ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), -+ addr.get_subnet().get_ip_prefix_len()) -+ elif addr.get_security_group(): -+ if (addr.get_security_group() != 'any') and \ -+ (addr.get_security_group() != 'local'): -+ remote_sg = addr.get_security_group() -+ try: -+ remote_sg_obj = self._vnc_lib.security_group_read( -+ fq_name_str=remote_sg) -+ remote_sg_uuid = remote_sg_obj.uuid -+ except vnc_exc.NoIdError: -+ pass -+ -+ sgr_q_dict['id'] = sg_rule.get_rule_uuid() -+ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sgr_q_dict['security_group_id'] = sg_obj.uuid -+ sgr_q_dict['ethertype'] = 'IPv4' -+ sgr_q_dict['direction'] = direction -+ sgr_q_dict['protocol'] = sg_rule.get_protocol() -+ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ -+ get_start_port() -+ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ -+ get_end_port() -+ sgr_q_dict['remote_ip_prefix'] = remote_cidr -+ sgr_q_dict['remote_group_id'] = remote_sg_uuid -+ -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): -+ if oper == CREATE: -+ port_min = 0 -+ port_max = 65535 -+ if sgr_q['port_range_min']: -+ port_min = sgr_q['port_range_min'] -+ if sgr_q['port_range_max']: -+ port_max = sgr_q['port_range_max'] -+ -+ endpt = [vnc_api.AddressType(security_group='any')] -+ if sgr_q['remote_ip_prefix']: -+ cidr = sgr_q['remote_ip_prefix'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ endpt = [vnc_api.AddressType( -+ subnet=vnc_api.SubnetType(pfx, pfx_len))] -+ elif sgr_q['remote_group_id']: -+ sg_obj = self._vnc_lib.security_group_read( -+ id=sgr_q['remote_group_id']) -+ endpt = [vnc_api.AddressType( -+ security_group=sg_obj.get_fq_name_str())] -+ -+ if sgr_q['direction'] == 'ingress': -+ dir = '<' -+ local = endpt -+ remote = [vnc_api.AddressType(security_group='local')] -+ else: -+ dir = '>' -+ remote = endpt -+ local = [vnc_api.AddressType(security_group='local')] -+ -+ if not sgr_q['protocol']: -+ sgr_q['protocol'] = 'any' -+ -+ sgr_uuid = str(uuid.uuid4()) -+ -+ rule = vnc_api.PolicyRuleType( -+ rule_uuid=sgr_uuid, -+ direction=dir, -+ protocol=sgr_q['protocol'], -+ src_addresses=local, -+ src_ports=[vnc_api.PortType(0, 65535)], -+ dst_addresses=remote, -+ dst_ports=[vnc_api.PortType(port_min, port_max)]) -+ return rule -+ -+ def _network_neutron_to_vnc(self, network_q, oper): -+ net_name = network_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(network_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType(enable=True) -+ net_obj = vnc_api.VirtualNetwork( -+ net_name, project_obj, id_perms=id_perms) -+ else: # READ/UPDATE/DELETE -+ net_obj = self._virtual_network_read(net_id=network_q['id']) -+ -+ id_perms = net_obj.get_id_perms() -+ if 'admin_state_up' in network_q: -+ id_perms.enable = network_q['admin_state_up'] -+ net_obj.set_id_perms(id_perms) -+ -+ if 'contrail:policys' in network_q: -+ policy_fq_names = network_q['contrail:policys'] -+ # reset and add with newly specified list -+ net_obj.set_network_policy_list([], []) -+ seq = 0 -+ for p_fq_name in policy_fq_names: -+ domain_name, project_name, policy_name = p_fq_name -+ -+ domain_obj = vnc_api.Domain(domain_name) -+ project_obj = vnc_api.Project(project_name, domain_obj) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ -+ net_obj.add_network_policy( -+ policy_obj, -+ vnc_api.VirtualNetworkPolicyType( -+ sequence=vnc_api.SequenceType(seq, 0))) -+ seq = seq + 1 -+ -+ if 'vpc:route_table' in network_q: -+ rt_fq_name = network_q['vpc:route_table'] -+ if rt_fq_name: -+ try: -+ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) -+ net_obj.set_route_table(rt_obj) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) -+ -+ return net_obj -+ -+ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): -+ net_q_dict = {} -+ extra_dict = {} -+ -+ net_q_dict['id'] = net_obj.uuid -+ net_q_dict['name'] = net_obj.name -+ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() -+ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable -+ net_q_dict['shared'] = False -+ net_q_dict['status'] = constants.NET_STATUS_ACTIVE -+ -+ if net_repr == 'SHOW': -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ #if port_back_refs: -+ # net_q_dict['ports'] = [] -+ # for port_back_ref in port_back_refs: -+ # fq_name = port_back_ref['to'] -+ # try: -+ # port_obj = self._virtual_machine_interface_read( -+ # port_id = fq_name[-1]) -+ # except NoIdError: -+ # continue -+ # -+ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) -+ # port_dict = port_info['q_api_data'] -+ # port_dict.update(port_info['q_extra_data']) -+ # -+ # net_q_dict['ports'].append(port_dict) -+ -+ extra_dict['contrail:instance_count'] = 0 -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ net_policy_refs = net_obj.get_network_policy_refs() -+ if net_policy_refs: -+ extra_dict['contrail:policys'] = \ -+ [np_ref['to'] for np_ref in net_policy_refs] -+ -+ elif net_repr == 'LIST': -+ extra_dict['contrail:instance_count'] = 0 -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ net_q_dict['subnets'] = [] -+ if ipam_refs: -+ extra_dict['contrail:subnet_ipam'] = [] -+ for ipam_ref in ipam_refs: -+ subnets = ipam_ref['attr'].get_ipam_subnets() -+ for subnet in subnets: -+ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, -+ ipam_ref['to']) -+ sn_dict = sn_info['q_api_data'] -+ sn_dict.update(sn_info['q_extra_data']) -+ net_q_dict['subnets'].append(sn_dict) -+ sn_ipam = {} -+ sn_ipam['subnet_cidr'] = sn_dict['cidr'] -+ sn_ipam['ipam_fq_name'] = ipam_ref['to'] -+ extra_dict['contrail:subnet_ipam'].append(sn_ipam) -+ -+ return {'q_api_data': net_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _subnet_neutron_to_vnc(self, subnet_q): -+ cidr = subnet_q['cidr'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: -+ default_gw = subnet_q['gateway_ip'] -+ else: -+ # Assigned by address manager -+ default_gw = None -+ sub_net = vnc_api.SubnetType(ip_prefix=pfx, -+ ip_prefix_len=pfx_len) -+ #subnet_vnc = vnc_api.IpamSubnetType( -+ #subnet=vnc_api.SubnetType(pfx, pfx_len), -+ #default_gateway=default_gw) -+ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, -+ default_gateway=default_gw) -+ return subnet_vnc -+ -+ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): -+ sn_q_dict = {} -+ sn_q_dict['name'] = '' -+ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ sn_q_dict['network_id'] = net_obj.uuid -+ sn_q_dict['ip_version'] = 4 -+ -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ sn_q_dict['cidr'] = cidr -+ -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) -+ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) -+ -+ sn_q_dict['id'] = sn_id -+ -+ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway -+ -+ first_ip = str(IPNetwork(cidr).network + 1) -+ last_ip = str(IPNetwork(cidr).broadcast - 2) -+ sn_q_dict['allocation_pools'] = \ -+ [{'id': 'TODO-allocation_pools-id', -+ 'subnet_id': sn_id, -+ 'first_ip': first_ip, -+ 'last_ip': last_ip, -+ 'available_ranges': {}}] -+ -+ sn_q_dict['enable_dhcp'] = False -+ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['routes'] = [{'destination': 'TODO-destination', -+ 'nexthop': 'TODO-nexthop', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['shared'] = False -+ -+ extra_dict = {} -+ extra_dict['contrail:instance_count'] = 0 -+ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name -+ -+ return {'q_api_data': sn_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _ipam_neutron_to_vnc(self, ipam_q, oper): -+ ipam_name = ipam_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(ipam_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) -+ -+ if ipam_q['mgmt']: -+ ipam_obj.set_network_ipam_mgmt( -+ vnc_api.IpamType.factory(**ipam_q['mgmt'])) -+ -+ return ipam_obj -+ -+ def _ipam_vnc_to_neutron(self, ipam_obj): -+ ipam_q_dict = json.loads(json.dumps(ipam_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') -+ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') -+ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) -+ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ ipam_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ ipam_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': ipam_q_dict, -+ 'q_extra_data': {}} -+ -+ def _policy_neutron_to_vnc(self, policy_q, oper): -+ policy_name = policy_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(policy_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) -+ -+ policy_obj.set_network_policy_entries( -+ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) -+ -+ return policy_obj -+ -+ def _policy_vnc_to_neutron(self, policy_obj): -+ policy_q_dict = json.loads(json.dumps(policy_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ policy_q_dict['id'] = policy_q_dict.pop('uuid') -+ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') -+ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', -+ None) -+ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ policy_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ policy_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': policy_q_dict, -+ 'q_extra_data': {}} -+ -+ def _floatingip_neutron_to_vnc(self, fip_q, oper): -+ if oper == CREATE: -+ # use first available pool on net -+ net_id = fip_q['floating_network_id'] -+ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) -+ fip_name = str(uuid.uuid4()) -+ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) -+ fip_obj.uuid = fip_name -+ -+ proj_id = str(uuid.UUID(fip_q['tenant_id'])) -+ proj_obj = self._project_read(proj_id=proj_id) -+ fip_obj.set_project(proj_obj) -+ else: # READ/UPDATE/DELETE -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) -+ -+ if fip_q['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=fip_q['port_id']) -+ fip_obj.set_virtual_machine_interface(port_obj) -+ else: -+ fip_obj.set_virtual_machine_interface_list([]) -+ -+ return fip_obj -+ -+ def _floatingip_vnc_to_neutron(self, fip_obj): -+ fip_q_dict = {} -+ extra_dict = {} -+ -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( -+ id=fip_obj.parent_uuid) -+ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) -+ -+ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') -+ -+ port_id = None -+ port_refs = fip_obj.get_virtual_machine_interface_refs() -+ if port_refs: -+ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] -+ -+ fip_q_dict['id'] = fip_obj.uuid -+ fip_q_dict['tenant_id'] = tenant_id -+ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() -+ fip_q_dict['floating_network_id'] = net_obj.uuid -+ fip_q_dict['router_id'] = None -+ fip_q_dict['fixed_port_id'] = port_id -+ fip_q_dict['fixed_ip_address'] = None -+ -+ return {'q_api_data': fip_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _port_neutron_to_vnc(self, port_q, net_obj, oper): -+ if oper == CREATE: -+ port_name = str(uuid.uuid4()) -+ instance_name = port_q['device_id'] -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ -+ id_perms = vnc_api.IdPermsType(enable=True) -+ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, -+ id_perms=id_perms) -+ port_obj.uuid = port_name -+ port_obj.set_virtual_network(net_obj) -+ -+ else: # READ/UPDATE/DELETE -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_q['id']) -+ -+ port_obj.set_security_group_list([]) -+ if ('security_groups' in port_q and -+ port_q['security_groups'].__class__ is not object): -+ for sg_id in port_q['security_groups']: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ port_obj.add_security_group(sg_obj) -+ -+ id_perms = port_obj.get_id_perms() -+ if 'admin_state_up' in port_q: -+ id_perms.enable = port_q['admin_state_up'] -+ port_obj.set_id_perms(id_perms) -+ -+ return port_obj -+ -+ def _port_vnc_to_neutron(self, port_obj, net_obj=None): -+ port_q_dict = {} -+ port_q_dict['name'] = port_obj.uuid -+ port_q_dict['id'] = port_obj.uuid -+ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_CONTRAIL -+ -+ if not net_obj: -+ net_refs = port_obj.get_virtual_network_refs() -+ if net_refs: -+ net_id = net_refs[0]['uuid'] -+ else: -+ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) -+ -+ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) -+ proj_id = None -+ if not proj_id: -+ # not in cache, get by reading VN obj, and populate cache -+ net_obj = self._virtual_network_read(net_id=net_id) -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(port_obj.uuid, proj_id) -+ else: -+ net_id = net_obj.uuid -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ -+ port_q_dict['tenant_id'] = proj_id -+ port_q_dict['network_id'] = net_id -+ -+ port_q_dict['mac_address'] = '' -+ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() -+ if mac_refs: -+ port_q_dict['mac_address'] = mac_refs.mac_address[0] -+ -+ port_q_dict['fixed_ips'] = [] -+ ip_back_refs = port_obj.get_instance_ip_back_refs() -+ if ip_back_refs: -+ for ip_back_ref in ip_back_refs: -+ try: -+ ip_obj = self._instance_ip_read( -+ instance_ip_id=ip_back_ref['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ -+ ip_addr = ip_obj.get_instance_ip_address() -+ -+ ip_q_dict = {} -+ ip_q_dict['port_id'] = port_obj.uuid -+ ip_q_dict['ip_address'] = ip_addr -+ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, -+ net_obj) -+ ip_q_dict['net_id'] = net_id -+ -+ port_q_dict['fixed_ips'].append(ip_q_dict) -+ -+ sg_dict = {'port_security_enabled': True} -+ sg_dict['security_groups'] = [] -+ sg_refs = port_obj.get_security_group_refs() -+ for sg_ref in sg_refs or []: -+ sg_dict['security_groups'].append(sg_ref['uuid']) -+ -+ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable -+ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE -+ port_q_dict['device_id'] = port_obj.parent_name -+ port_q_dict['device_owner'] = 'TODO-device-owner' -+ -+ return {'q_api_data': port_q_dict, -+ 'q_extra_data': sg_dict} -+ -+ # public methods -+ # network api handlers -+ def network_create(self, network_q): -+ #self._ensure_project_exists(network_q['tenant_id']) -+ -+ net_obj = self._network_neutron_to_vnc(network_q, CREATE) -+ net_uuid = self._virtual_network_create(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_uuid] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_read(self, net_uuid, fields=None): -+ # see if we can return fast... -+ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': -+ tenant_id = self._get_obj_tenant_id('network', net_uuid) -+ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} -+ -+ try: -+ # return self._db_cache['q_networks']['net_uuid'] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ try: -+ net_obj = self._network_read(net_uuid) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_uuid) -+ -+ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ -+ def network_update(self, net_id, network_q): -+ network_q['id'] = net_id -+ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) -+ self._virtual_network_update(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_id] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_delete(self, net_id): -+ self._virtual_network_delete(net_id=net_id) -+ try: -+ del self._db_cache['q_networks'][net_id] -+ except KeyError: -+ pass -+ -+ def network_list(self, filters=None): -+ ret_list = [] -+ -+ if filters and 'shared' in filters: -+ if filters['shared'][0] is True: -+ # no support for shared networks -+ return ret_list -+ -+ # collect phase -+ all_nets = [] # all n/ws in all projects -+ if filters and 'tenant_id' in filters: -+ # project-id is present -+ if 'id' in filters: -+ # required networks are also specified, -+ # just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in project, and prune below -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ if 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(p_id)) -+ else: -+ project_nets = self._network_list_project(p_id) -+ all_nets.append(project_nets) -+ elif filters and 'id' in filters: -+ # required networks are specified, just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in all projects -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ if filters and 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(proj_id)) -+ else: -+ project_nets = self._network_list_project(proj_id) -+ all_nets.append(project_nets) -+ -+ # prune phase -+ for project_nets in all_nets: -+ for proj_net in project_nets: -+ proj_net_id = proj_net['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_net_id): -+ continue -+ -+ proj_net_fq_name = unicode(proj_net['fq_name']) -+ if not self._filters_is_present(filters, 'contrail:fq_name', -+ proj_net_fq_name): -+ continue -+ -+ try: -+ net_obj = self._network_read(proj_net['uuid']) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ except vnc_exc.NoIdError: -+ continue -+ ret_list.append(net_info) -+ -+ return ret_list -+ -+ def network_count(self, filters=None): -+ nets_info = self.network_list(filters) -+ return len(nets_info) -+ -+ # subnet api handlers -+ def subnet_create(self, subnet_q): -+ net_id = subnet_q['network_id'] -+ net_obj = self._virtual_network_read(net_id=net_id) -+ -+ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] -+ if ipam_fq_name != '': -+ domain_name, project_name, ipam_name = ipam_fq_name -+ -+ project_obj = vnc_api.Project(project_name) -+ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # link subnet with default ipam -+ project_obj = vnc_api.Project(net_obj.parent_name) -+ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) -+ ipam_fq_name = netipam_obj.get_fq_name() -+ -+ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) -+ -+ # Locate list of subnets to which this subnet has to be appended -+ net_ipam_ref = None -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ if ipam_ref['to'] == ipam_fq_name: -+ net_ipam_ref = ipam_ref -+ break -+ -+ if not net_ipam_ref: -+ # First link from net to this ipam -+ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) -+ net_obj.add_network_ipam(netipam_obj, vnsn_data) -+ else: # virtual-network already linked to this ipam -+ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): -+ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): -+ # duplicate !! -+ subnet_info = self._subnet_vnc_to_neutron(subnet, -+ net_obj, -+ ipam_fq_name) -+ return subnet_info -+ vnsn_data = net_ipam_ref['attr'] -+ vnsn_data.ipam_subnets.append(subnet_vnc) -+ -+ self._virtual_network_update(net_obj) -+ -+ # allocate an id to the subnet and store mapping with -+ # api-server -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, subnet_key) -+ -+ # Read in subnet from server to get updated values for gw etc. -+ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) -+ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, -+ ipam_fq_name) -+ -+ #self._db_cache['q_subnets'][subnet_id] = subnet_info -+ -+ return subnet_info -+ -+ def subnet_read(self, subnet_id): -+ try: -+ # return self._db_cache['q_subnets'][subnet_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_id) == subnet_key: -+ ret_subnet_q = self._subnet_vnc_to_neutron( -+ subnet_vnc, net_obj, ipam_ref['to']) -+ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q -+ return ret_subnet_q -+ -+ return {} -+ -+ def subnet_delete(self, subnet_id): -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ orig_subnets = ipam_ref['attr'].get_ipam_subnets() -+ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets -+ if self._subnet_vnc_get_key(subnet_vnc, net_id) -+ != subnet_key] -+ if len(orig_subnets) != len(new_subnets): -+ # matched subnet to be deleted -+ ipam_ref['attr'].set_ipam_subnets(new_subnets) -+ self._virtual_network_update(net_obj) -+ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) -+ try: -+ del self._db_cache['q_subnets'][subnet_id] -+ except KeyError: -+ pass -+ -+ return -+ -+ def subnets_list(self, filters=None): -+ ret_subnets = [] -+ -+ if filters and 'id' in filters: -+ # required subnets are specified, -+ # just read in corresponding net_ids -+ net_ids = set([]) -+ for subnet_id in filters['id']: -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ net_ids.add(net_id) -+ else: -+ nets_info = self.network_list() -+ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] -+ -+ for net_id in net_ids: -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, -+ net_obj, -+ ipam_ref['to']) -+ sn_id = sn_info['q_api_data']['id'] -+ sn_proj_id = sn_info['q_api_data']['tenant_id'] -+ sn_net_id = sn_info['q_api_data']['network_id'] -+ -+ if filters: -+ if not self._filters_is_present(filters, 'id', -+ sn_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'tenant_id', -+ sn_proj_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'network_id', -+ sn_net_id): -+ continue -+ -+ ret_subnets.append(sn_info) -+ -+ return ret_subnets -+ -+ def subnets_count(self, filters=None): -+ subnets_info = self.subnets_list(filters) -+ return len(subnets_info) -+ -+ # ipam api handlers -+ def ipam_create(self, ipam_q): -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) -+ self._vnc_lib.network_ipam_create(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_read(self, ipam_id): -+ try: -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=ipam_id) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_update(self, ipam_id, ipam): -+ ipam_q = ipam['ipam'] -+ ipam_q['id'] = ipam_id -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) -+ self._vnc_lib.network_ipam_update(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_delete(self, ipam_id): -+ self._vnc_lib.network_ipam_delete(id=ipam_id) -+ -+ def ipam_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_ipams = [] # all ipams in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_ipams = self._ipam_list_project(p_id) -+ all_ipams.append(project_ipams) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_ipams = self._ipam_list_project(proj_id) -+ all_ipams.append(project_ipams) -+ -+ # prune phase -+ for project_ipams in all_ipams: -+ for proj_ipam in project_ipams: -+ proj_ipam_id = proj_ipam['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_ipam_id): -+ continue -+ ipam_info = self.ipam_read(proj_ipam['uuid']) -+ ret_list.append(ipam_info) -+ -+ return ret_list -+ -+ def ipam_count(self, filters=None): -+ ipam_info = self.ipam_list(filters) -+ return len(ipam_info) -+ -+ # policy api handlers -+ def policy_create(self, policy_q): -+ -+ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) -+ self._vnc_lib.network_policy_create(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_read(self, policy_id): -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_update(self, policy_id, policy): -+ policy_q = policy['policy'] -+ policy_q['id'] = policy_id -+ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) -+ self._vnc_lib.network_policy_update(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_delete(self, policy_id): -+ self._vnc_lib.network_policy_delete(id=policy_id) -+ -+ def policy_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_policys = [] # all policys in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_policys = self._policy_list_project(p_id) -+ all_policys.append(project_policys) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_policys = self._policy_list_project(proj_id) -+ all_policys.append(project_policys) -+ -+ # prune phase -+ for project_policys in all_policys: -+ for proj_policy in project_policys: -+ proj_policy_id = proj_policy['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_policy_id): -+ continue -+ policy_info = self.policy_read(proj_policy['uuid']) -+ ret_list.append(policy_info) -+ -+ return ret_list -+ -+ def policy_count(self, filters=None): -+ policy_info = self.policy_list(filters) -+ return len(policy_info) -+ -+ # floatingip api handlers -+ def floatingip_create(self, fip_q): -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) -+ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_read(self, fip_uuid): -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_update(self, fip_id, fip_q): -+ fip_q['id'] = fip_id -+ fip_obj = self._floatingip_neutron(fip_q, UPDATE) -+ self._vnc_lib.floating_ip_update(fip_obj) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_delete(self, fip_id): -+ self._vnc_lib.floating_ip_delete(id=fip_id) -+ -+ def floatingip_list(self, filters=None): -+ # Find networks, get floatingip backrefs and return -+ ret_list = [] -+ -+ if filters: -+ if 'tenant_id' in filters: -+ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] -+ elif 'port_id' in filters: -+ # required ports are specified, just read and populate ret_list -+ # prune is skipped because proj_objs is empty -+ proj_ids = [] -+ for port_id in filters['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_id) -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron( -+ fip_obj)) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ proj_ids = [proj['uuid'] for proj in dom_projects] -+ -+ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] -+ -+ for proj_obj in proj_objs: -+ fip_back_refs = proj_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) -+ -+ return ret_list -+ -+ def floatingip_count(self, filters=None): -+ floatingip_info = self.floatingip_list(filters) -+ return len(floatingip_info) -+ -+ # port api handlers -+ def port_create(self, port_q): -+ net_id = port_q['network_id'] -+ net_obj = self._network_read(net_id) -+ proj_id = net_obj.parent_uuid -+ -+ self._ensure_instance_exists(port_q['device_id']) -+ -+ # initialize port object -+ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) -+ -+ # if ip address passed then use it -+ ip_addr = None -+ ip_obj = None -+ if port_q['fixed_ips'].__class__ is not object: -+ ip_addr = port_q['fixed_ips'][0]['ip_address'] -+ ip_name = '%s %s' % (net_id, ip_addr) -+ try: -+ ip_obj = self._instance_ip_read(fq_name=[ip_name]) -+ #ip_id = ip_obj.uuid -+ except Exception as e: -+ ip_obj = None -+ -+ # create the object -+ port_id = self._virtual_machine_interface_create(port_obj) -+ -+ # initialize ip object -+ if ip_obj is None: -+ ip_name = str(uuid.uuid4()) -+ ip_obj = vnc_api.InstanceIp(name=ip_name) -+ ip_obj.uuid = ip_name -+ ip_obj.set_virtual_machine_interface(port_obj) -+ ip_obj.set_virtual_network(net_obj) -+ if ip_addr: -+ ip_obj.set_instance_ip_address(ip_addr) -+ try: -+ self._instance_ip_create(ip_obj) -+ except Exception as e: -+ # ResourceExhaustionError, resources are not available -+ self._virtual_machine_interface_delete(port_id=port_id) -+ raise e -+ # shared ip address -+ else: -+ if ip_addr == ip_obj.get_instance_ip_address(): -+ ip_obj.add_virtual_machine_interface(port_obj) -+ self._instance_ip_update(ip_obj) -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) -+ #self._db_cache['q_ports'][port_id] = ret_port_q -+ self._set_obj_tenant_id(port_id, proj_id) -+ -+ # update cache on successful creation -+ tenant_id = proj_id.replace('-', '') -+ if tenant_id not in self._db_cache['q_tenant_port_count']: -+ ncurports = self.port_count({'tenant_id': tenant_id}) -+ else: -+ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] -+ -+ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 -+ -+ return ret_port_q -+ -+ def port_read(self, port_id): -+ try: -+ # return self._db_cache['q_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_update(self, port_id, port_q): -+ port_q['id'] = port_id -+ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) -+ self._virtual_machine_interface_update(port_obj) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_delete(self, port_id): -+ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) -+ instance_id = port_obj.parent_uuid -+ -+ # release instance IP address -+ iip_back_refs = port_obj.get_instance_ip_back_refs() -+ if iip_back_refs: -+ for iip_back_ref in iip_back_refs: -+ # if name contains IP address then this is shared ip -+ iip_obj = self._vnc_lib.instance_ip_read( -+ id=iip_back_ref['uuid']) -+ name = iip_obj.name -+ if len(name.split(' ')) > 1: -+ name = name.split(' ')[1] -+ -+ # in case of shared ip only delete the link to the VMI -+ try: -+ socket.inet_aton(name) -+ iip_obj.del_virtual_machine_interface(port_obj) -+ self._instance_ip_update(iip_obj) -+ except socket.error: -+ self._instance_ip_delete( -+ instance_ip_id=iip_back_ref['uuid']) -+ -+ # disassociate any floating IP used by instance -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if fip_back_refs: -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ self.floatingip_update(fip_obj.uuid, {'port_id': None}) -+ -+ self._virtual_machine_interface_delete(port_id=port_id) -+ -+ # delete instance if this was the last port -+ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) -+ inst_intfs = inst_obj.get_virtual_machine_interfaces() -+ if not inst_intfs: -+ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) -+ -+ try: -+ del self._db_cache['q_ports'][port_id] -+ except KeyError: -+ pass -+ -+ # update cache on successful deletion -+ try: -+ tenant_id = self._get_obj_tenant_id('port', port_id) -+ self._db_cache['q_tenant_port_count'][tenant_id] = \ -+ self._db_cache['q_tenant_port_count'][tenant_id] - 1 -+ except KeyError: -+ pass -+ -+ self._del_obj_tenant_id(port_id) -+ -+ def port_list(self, filters=None): -+ ret_q_ports = [] -+ all_project_ids = [] -+ -+ if 'device_owner' in filters: -+ return ret_q_ports -+ -+ if 'device_id' not in filters: -+ # Listing from back references -+ if not filters: -+ # no filters => return all ports! -+ all_projects = self._project_list_domain(None) -+ all_project_ids = [project['uuid'] for project in all_projects] -+ elif 'tenant_id' in filters: -+ all_project_ids = filters.get('tenant_id') -+ -+ for proj_id in all_project_ids: -+ proj_ports = self._port_list_project(proj_id) -+ for port in proj_ports: -+ try: -+ port_info = self.port_read(port['id']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ for net_id in filters.get('network_id', []): -+ net_ports = self._port_list_network(net_id) -+ for port in net_ports: -+ port_info = self.port_read(port['id']) -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ # Listing from parent to children -+ virtual_machine_ids = filters['device_id'] -+ for vm_id in virtual_machine_ids: -+ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( -+ parent_id=vm_id) -+ vm_intf_ids = resp_dict['virtual-machine-interfaces'] -+ for vm_intf in vm_intf_ids: -+ try: -+ port_info = self.port_read(vm_intf['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ def port_count(self, filters=None): -+ if 'device_owner' in filters: -+ return 0 -+ -+ if 'tenant_id' in filters: -+ project_id = filters['tenant_id'][0] -+ try: -+ return self._db_cache['q_tenant_port_count'][project_id] -+ except KeyError: -+ # do it the hard way but remember for next time -+ nports = len(self._port_list_project(project_id)) -+ self._db_cache['q_tenant_port_count'][project_id] = nports -+ else: -+ # across all projects -+ # get only a count from api-server! -+ nports = len(self.port_list(filters)) -+ -+ return nports -+ -+ # security group api handlers -+ def security_group_create(self, sg_q): -+ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) -+ sg_uuid = self._security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_uuid, rule) -+ -+ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) -+ return ret_sg_q -+ -+ def security_group_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return self._security_group_vnc_to_neutron(sg_obj) -+ -+ def security_group_delete(self, sg_id): -+ self._security_group_delete(sg_id) -+ -+ def security_group_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] # all sgs in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sg_info = self.security_group_read(proj_sg_id) -+ if not self._filters_is_present(filters, 'name', -+ sg_info['q_api_data']['name']): -+ continue -+ ret_list.append(sg_info) -+ -+ return ret_list -+ -+ def security_group_rule_create(self, sgr_q): -+ sg_id = sgr_q['security_group_id'] -+ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) -+ self._security_group_rule_create(sg_id, sg_rule) -+ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, -+ sg_rule) -+ -+ return ret_sg_rule_q -+ -+ def security_group_rule_read(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ -+ return {} -+ -+ def security_group_rule_delete(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_delete(sg_obj, sg_rule) -+ -+ def security_group_rules_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ sgr_entries = sg_obj.get_security_group_entries() -+ sg_rules = [] -+ if sgr_entries is None: -+ return -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ sg_rules.append(sg_info) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return sg_rules -+ -+ def security_group_rule_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sgr_info = self.security_group_rules_read(proj_sg_id) -+ if sgr_info: -+ ret_list.append(sgr_info) -+ -+ return ret_list -+ -+ #route table api handlers -+ def route_table_create(self, rt_q): -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) -+ self._route_table_create(rt_obj) -+ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) -+ return ret_rt_q -+ -+ def route_table_read(self, rt_id): -+ try: -+ rt_obj = self._vnc_lib.route_table_read(id=rt_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=rt_id) -+ -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_update(self, rt_id, rt_q): -+ rt_q['id'] = rt_id -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) -+ self._vnc_lib.route_table_update(rt_obj) -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_delete(self, rt_id): -+ self._route_table_delete(rt_id) -+ -+ def route_table_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_rts = [] # all rts in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_rts = self._route_table_list_project(proj_id) -+ all_rts.append(project_rts) -+ -+ # prune phase -+ for project_rts in all_rts: -+ for proj_rt in project_rts: -+ proj_rt_id = proj_rt['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_rt_id): -+ continue -+ rt_info = self.route_table_read(proj_rt_id) -+ if not self._filters_is_present(filters, 'name', -+ rt_info['q_api_data']['name']): -+ continue -+ ret_list.append(rt_info) -+ -+ return ret_list -+ -+ #service instance api handlers -+ def svc_instance_create(self, si_q): -+ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) -+ self._svc_instance_create(si_obj) -+ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) -+ return ret_si_q -+ -+ def svc_instance_read(self, si_id): -+ try: -+ si_obj = self._vnc_lib.service_instance_read(id=si_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=si_id) -+ -+ return self._svc_instance_vnc_to_neutron(si_obj) -+ -+ def svc_instance_delete(self, si_id): -+ self._svc_instance_delete(si_id) -+ -+ def svc_instance_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sis = [] # all sis in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sis = self._svc_instance_list_project(proj_id) -+ all_sis.append(project_sis) -+ -+ # prune phase -+ for project_sis in all_sis: -+ for proj_si in project_sis: -+ proj_si_id = proj_si['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_si_id): -+ continue -+ si_info = self.svc_instance_read(proj_si_id) -+ if not self._filters_is_present(filters, 'name', -+ si_info['q_api_data']['name']): -+ continue -+ ret_list.append(si_info) -+ -+ return ret_list -diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py -new file mode 100644 -index 0000000..72bebec ---- /dev/null -+++ neutron/tests/unit/juniper/__init__.py -@@ -0,0 +1,14 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py -new file mode 100644 -index 0000000..decf79e ---- /dev/null -+++ neutron/tests/unit/juniper/test_contrail_plugin.py -@@ -0,0 +1,998 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -+ -+import datetime -+import mock -+import neutron.db.api -+from neutron.manager import NeutronManager -+from neutron.tests.unit import test_db_plugin as test_plugin -+import sys -+import uuid -+ -+subnet_obj = {u'subnet': -+ {'name': '', 'enable_dhcp': True, -+ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', -+ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', -+ 'dns_nameservers': '', -+ u'contrail:ipam_fq_name': -+ [u'default-domain', u'admin', u'default-network-ipam'], -+ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, -+ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} -+ -+vn_list = [] -+GlobalProjects = [] -+ -+ -+class MockVncApi(mock.MagicMock): -+ def __init__(self, *args, **kwargs): -+ pass -+ -+ def kv_retrieve(self, *args, **kwargs): -+ return [] -+ -+ def kv_store(self, *args, **kwargs): -+ return -+ -+ def kv_delete(self, *args, **kwargs): -+ return -+ -+ def project_read(self, *args, **kwargs): -+ #return MockProject('dummy-proj') -+ return GlobalProjects[0] -+ -+ def virtual_network_create(self, net_obj): -+ net_id = unicode(str(uuid.uuid4())) -+ net_obj.set_uuid(net_id) -+ vn_list.append(net_obj) -+ return net_id -+ -+ def virtual_network_read(self, id, *args, **kwargs): -+ if len(vn_list): -+ for index in range(len(vn_list)): -+ if ((vn_list[index].get_uuid()) == id): -+ return vn_list[index] -+ -+ #return a mock object if it is not created so far -+ return MockVirtualNetwork('dummy-net', MockProject()) -+ -+ def virtual_network_delete(self, *args, **kwargs): -+ return -+ -+ def virtual_network_update(self, *args, **kwargs): -+ return -+ -+ def virtual_networks_list(self, *args, **kwargs): -+ return vn_list -+ -+ -+class MockVncObject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ if not parent_obj: -+ self._fq_name = [name] -+ else: -+ self._fq_name = parent_obj.get_fq_name() + [name] -+ -+ self._ipam_refs = [{'to': [u'default-domain', u'admin', -+ u'default-network-ipam']}] -+ self.uuid = None -+ self.name = name -+ self.network_ipam_refs = [] -+ -+ def set_uuid(self, uuid): -+ self.uuid = uuid -+ -+ def get_uuid(self): -+ return self.uuid -+ -+ def get_fq_name(self): -+ return self._fq_name -+ -+ def get_network_ipam_refs(self): -+ return getattr(self, 'network_ipam_refs', None) -+ -+ def add_network_ipam(self, ref_obj, ref_data): -+ refs = getattr(self, 'network_ipam_refs', []) -+ if not refs: -+ self.network_ipam_refs = [] -+ -+ # if ref already exists, update any attr with it -+ for ref in refs: -+ if ref['to'] == ref_obj.get_fq_name(): -+ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref['uuid'] = ref_obj.uuid -+ return -+ -+ # ref didn't exist before -+ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref_info['uuid'] = ref_obj.uuid -+ -+ self.network_ipam_refs.append(ref_info) -+ -+ -+class MockVirtualNetwork(MockVncObject): -+ pass -+ -+ -+class MockSubnetType(mock.MagicMock): -+ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ip_prefix = ip_prefix -+ self.ip_prefix_len = ip_prefix_len -+ -+ def get_ip_prefix(self): -+ return self.ip_prefix -+ -+ def set_ip_prefix(self, ip_prefix): -+ self.ip_prefix = ip_prefix -+ -+ def get_ip_prefix_len(self): -+ return self.ip_prefix_len -+ -+ def set_ip_prefix_len(self, ip_prefix_len): -+ self.ip_prefix_len = ip_prefix_len -+ -+ -+class MockIpamSubnetType(mock.MagicMock): -+ def __init__(self, name=None, subnet=None, default_gateway=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.subnet = subnet -+ self.default_gateway = default_gateway -+ -+ def get_subnet(self): -+ return self.subnet -+ -+ def set_subnet(self, subnet): -+ self.subnet = subnet -+ -+ def get_default_gateway(self): -+ return self.default_gateway -+ -+ def set_default_gateway(self, default_gateway): -+ self.default_gateway = default_gateway -+ -+ def validate_IpAddressType(self, value): -+ pass -+ -+ -+class MockVnSubnetsType(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ipam_subnets = [] -+ if ipam_subnets: -+ #self.ipam_subnets = copy.deepcopy(ipam_subnets) -+ self.ipam_subnets = ipam_subnets -+ -+ def get_ipam_subnets(self): -+ return self.ipam_subnets -+ -+ def set_ipam_subnets(self, ipam_subnets): -+ self.ipam_subnets = ipam_subnets -+ -+ def add_ipam_subnets(self, value): -+ self.ipam_subnets.append(value) -+ -+ def insert_ipam_subnets(self, index, value): -+ self.ipam_subnets[index] = value -+ -+ def delete_ipam_subnets(self, value): -+ self.ipam_subnets.remove(value) -+ -+ -+class MockNetworkIpam(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, -+ network_ipam_mgmt=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'default-network-ipam' -+ self.name = name -+ self.uuid = None -+ if parent_obj: -+ self.parent_type = parent_obj._type -+ # copy parent's fq_name -+ self.fq_name = list(parent_obj.fq_name) -+ self.fq_name.append(name) -+ if not parent_obj.get_network_ipams(): -+ parent_obj.network_ipams = [] -+ parent_obj.network_ipams.append(self) -+ else: # No parent obj specified -+ self.parent_type = 'project' -+ self.fq_name = [u'default-domain', u'default-project'] -+ self.fq_name.append(name) -+ -+ # property fields -+ if network_ipam_mgmt: -+ self.network_ipam_mgmt = network_ipam_mgmt -+ if id_perms: -+ self.id_perms = id_perms -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+class MockProject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'project' -+ self.uuid = None -+ self.parent_type = 'domain' -+ self.fq_name = [u'default-domain'] -+ self.fq_name.append(name) -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+def GlobalProjectApi(project_name): -+ if not GlobalProjects: -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ return GlobalProjects[0] -+ -+ -+# Mock definations for different pkgs, modules and VncApi -+mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) -+mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') -+mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork -+mock_vnc_api_mod.SubnetType = MockSubnetType -+mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType -+mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType -+mock_vnc_api_mod.NetworkIpam = MockNetworkIpam -+mock_vnc_api_mod.Project = GlobalProjectApi -+ -+mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') -+mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') -+mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ -+ mock_vnc_api_pkg -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ -+ mock_vnc_api_mod -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ -+ mock_vnc_common_mod -+sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' -+ 'exceptions')] = \ -+ mock_vnc_exception_mod -+ -+CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" -+ -+ -+class RouterInstance(object): -+ def __init__(self): -+ self._name = 'rounter_instance' -+ -+ -+class Context(object): -+ def __init__(self, tenant_id=''): -+ self.read_only = False -+ self.show_deleted = False -+ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] -+ self._read_deleted = 'no' -+ self.timestamp = datetime.datetime.now() -+ self.auth_token = None -+ self._session = None -+ self._is_admin = True -+ self.admin = uuid.uuid4().hex.decode() -+ self.request_id = 'req-' + str(uuid.uuid4()) -+ self.tenant = tenant_id -+ -+ -+class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): -+ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) -+ -+ def setUp(self): -+ -+ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod -+ -+ mock_vnc_api_mod.common = mock_vnc_common_mod -+ mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+ -+ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+ -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ neutron.db.api._ENGINE = mock.MagicMock() -+ -+ def teardown(self): -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ -+ -+class TestContrailNetworks(test_plugin.TestNetworksV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ if 'contrail:fq_name' not in net.keys(): -+ assert False -+ else: -+ assert True -+ -+ def test_delete_network(self): -+ # First create the network and request to delete the same -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ -+ plugin_obj.delete_network(context_obj, net_id) -+ mock_vnc_api_cls.virtual_network_delete.assert_called_once() -+ -+ def test_update_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ # change one of the attribute and update the network -+ network['admin_state_up'] = 'False' -+ new_dict = plugin_obj.update_network(context_obj, net_id, -+ networks_req) -+ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): -+ assert False -+ else: -+ assert True -+ -+ # Not supported test cases in the this TestClass -+ def test_create_networks_bulk_emulated(self): -+ pass -+ -+ def test_create_networks_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_public_network(self): -+ pass -+ -+ def test_create_networks_bulk_wrong_input(self): -+ pass -+ -+ def test_update_shared_network_noadmin_returns_403(self): -+ pass -+ -+ def test_update_network_set_shared(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_single_tenant(self): -+ pass -+ -+ def test_update_network_set_not_shared_other_tenant_returns_409(self): -+ pass -+ -+ def test_update_network_with_subnet_set_shared(self): -+ pass -+ -+ def test_show_network(self): -+ pass -+ -+ def test_show_network_with_subnet(self): -+ pass -+ -+ def test_list_networks(self): -+ pass -+ -+ def test_list_shared_networks_with_non_admin_user(self): -+ pass -+ -+ def test_list_networks_with_parameters(self): -+ pass -+ -+ def test_list_networks_with_fields(self): -+ pass -+ -+ def test_list_networks_with_parameters_invalid_values(self): -+ pass -+ -+ def test_list_networks_with_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_without_pk_in_fields_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_with_sort_emulated(self): -+ pass -+ -+ def test_list_networks_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_invalid_admin_status(self): -+ pass -+ -+ -+class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: -+ assert False -+ else: -+ assert True -+ -+ def test_delete_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ subnet_id = subnet_dict['id'] -+ plugin_obj.delete_subnet(context_obj, subnet_id) -+ -+ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_delete_network(self): -+ pass -+ -+ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet_adding_additional_host_routes_and_dns(self): -+ pass -+ -+ def test_update_subnet_no_gateway(self): -+ pass -+ -+ def test_create_subnet_bad_cidr(self): -+ pass -+ -+ def test_create_subnet_gw_of_network_force_on_returns_400(self): -+ pass -+ -+ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_create_two_subnets(self): -+ pass -+ -+ def test_create_two_subnets_same_cidr_returns_400(self): -+ pass -+ -+ def test_create_subnet_bad_V4_cidr(self): -+ pass -+ -+ def test_create_subnet_bad_V6_cidr(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): -+ pass -+ -+ def test_create_subnets_bulk_native(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_subnets_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_network(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_other(self): -+ pass -+ -+ def test_create_subnet_bad_tenant(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version_null(self): -+ pass -+ -+ def test_create_subnet_bad_uuid(self): -+ pass -+ -+ def test_create_subnet_bad_boolean(self): -+ pass -+ -+ def test_create_subnet_bad_pools(self): -+ pass -+ -+ def test_create_subnet_bad_nameserver(self): -+ pass -+ -+ def test_create_subnet_bad_hostroutes(self): -+ pass -+ -+ def test_create_subnet_defaults(self): -+ pass -+ -+ def test_create_subnet_gw_values(self): -+ pass -+ -+ def test_create_force_subnet_gw_values(self): -+ pass -+ -+ def test_create_subnet_with_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_fully_allocated(self): -+ pass -+ -+ def test_subnet_with_allocation_range(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_v6_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_large_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_multiple_allocation_pools(self): -+ pass -+ -+ def test_create_subnet_with_dhcp_disabled(self): -+ pass -+ -+ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( -+ self): -+ pass -+ -+ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_create_subnet_overlapping_allocation_pools_returns_409(self): -+ pass -+ -+ def test_create_subnet_invalid_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_shared_returns_400(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_cidrv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_cidrv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_dns_v4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): -+ pass -+ -+ def test_create_subnet_gw_bcast_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet(self): -+ pass -+ -+ def test_update_subnet_shared_returns_400(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_dns_v6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): -+ pass -+ -+ def test_show_subnet(self): -+ pass -+ -+ def test_list_subnets(self): -+ pass -+ -+ def test_list_subnets_shared(self): -+ pass -+ -+ def test_list_subnets_with_parameter(self): -+ pass -+ -+ def test_invalid_ip_version(self): -+ pass -+ -+ def test_invalid_subnet(self): -+ pass -+ -+ def test_invalid_ip_address(self): -+ pass -+ -+ def test_invalid_uuid(self): -+ pass -+ -+ def test_create_subnet_with_one_dns(self): -+ pass -+ -+ def test_create_subnet_with_two_dns(self): -+ pass -+ -+ def test_create_subnet_with_too_many_dns(self): -+ pass -+ -+ def test_create_subnet_with_one_host_route(self): -+ pass -+ -+ def test_create_subnet_with_two_host_routes(self): -+ pass -+ -+ def test_create_subnet_with_too_many_routes(self): -+ pass -+ -+ def test_update_subnet_dns(self): -+ pass -+ -+ def test_update_subnet_dns_to_None(self): -+ pass -+ -+ def test_update_subnet_dns_with_too_many_entries(self): -+ pass -+ -+ def test_update_subnet_route(self): -+ pass -+ -+ def test_update_subnet_route_to_None(self): -+ pass -+ -+ def test_update_subnet_route_with_too_many_entries(self): -+ pass -+ -+ def test_delete_subnet_with_dns(self): -+ pass -+ -+ def test_delete_subnet_with_route(self): -+ pass -+ -+ def test_delete_subnet_with_dns_and_route(self): -+ pass -+ -+ def test_list_subnets_with_pagination_emulated(self): -+ pass -+ -+ def test_list_subnets_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_subnets_with_sort_emulated(self): -+ pass -+ -+ def test_validate_subnet_host_routes_exhausted(self): -+ pass -+ -+ def test_validate_subnet_dns_nameservers_exhausted(self): -+ pass -+ -+ -+class TestContrailPortsV2(test_plugin.TestPortsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_port_json(self): -+ pass -+ -+ def test_create_port_bad_tenant(self): -+ pass -+ -+ def test_create_port_public_network(self): -+ pass -+ -+ def test_create_port_public_network_with_ip(self): -+ pass -+ -+ def test_create_ports_bulk_native(self): -+ pass -+ -+ def test_create_ports_bulk_emulated(self): -+ pass -+ -+ def test_create_ports_bulk_wrong_input(self): -+ pass -+ -+ def test_create_ports_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_ports_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_list_ports(self): -+ pass -+ -+ def test_list_ports_filtered_by_fixed_ip(self): -+ pass -+ -+ def test_list_ports_public_network(self): -+ pass -+ -+ def test_show_port(self): -+ pass -+ -+ def test_delete_port(self): -+ pass -+ -+ def test_delete_port_public_network(self): -+ pass -+ -+ def test_update_port(self): -+ pass -+ -+ def test_update_device_id_null(self): -+ pass -+ -+ def test_delete_network_if_port_exists(self): -+ pass -+ -+ def test_delete_network_port_exists_owned_by_network(self): -+ pass -+ -+ def test_update_port_delete_ip(self): -+ pass -+ -+ def test_no_more_port_exception(self): -+ pass -+ -+ def test_update_port_update_ip(self): -+ pass -+ -+ def test_update_port_update_ip_address_only(self): -+ pass -+ -+ def test_update_port_update_ips(self): -+ pass -+ -+ def test_update_port_add_additional_ip(self): -+ pass -+ -+ def test_requested_duplicate_mac(self): -+ pass -+ -+ def test_mac_generation(self): -+ pass -+ -+ def test_mac_generation_4octet(self): -+ pass -+ -+ def test_bad_mac_format(self): -+ pass -+ -+ def test_mac_exhaustion(self): -+ pass -+ -+ def test_requested_duplicate_ip(self): -+ pass -+ -+ def test_requested_subnet_delete(self): -+ pass -+ -+ def test_requested_subnet_id(self): -+ pass -+ -+ def test_requested_subnet_id_not_on_network(self): -+ pass -+ -+ def test_overlapping_subnets(self): -+ pass -+ -+ def test_requested_subnet_id_v4_and_v6(self): -+ pass -+ -+ def test_range_allocation(self): -+ pass -+ -+ def test_requested_invalid_fixed_ips(self): -+ pass -+ -+ def test_invalid_ip(self): -+ pass -+ -+ def test_requested_split(self): -+ pass -+ -+ def test_duplicate_ips(self): -+ pass -+ -+ def test_fixed_ip_invalid_subnet_id(self): -+ pass -+ -+ def test_fixed_ip_invalid_ip(self): -+ pass -+ -+ def test_requested_ips_only(self): -+ pass -+ -+ def test_recycling(self): -+ pass -+ -+ def test_invalid_admin_state(self): -+ pass -+ -+ def test_invalid_mac_address(self): -+ pass -+ -+ def test_default_allocation_expiration(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration(self): -+ pass -+ -+ def test_port_delete_holds_ip(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration_invalid_address(self): -+ pass -+ -+ def test_hold_ip_address(self): -+ pass -+ -+ def test_recycle_held_ip_address(self): -+ pass -+ -+ def test_recycle_expired_previously_run_within_context(self): -+ pass -+ -+ def test_update_port_not_admin(self): -+ pass -+ -+ def test_list_ports_with_pagination_emulated(self): -+ pass -+ -+ def test_list_ports_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_ports_with_sort_emulated(self): -+ pass -+ -+ def test_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_update_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_recycle_ip_address_without_allocation_pool(self): -+ pass -diff --git setup.cfg setup.cfg -index af52a4d..27ef0ce 100644 ---- setup.cfg -+++ setup.cfg -@@ -61,6 +61,7 @@ data_files = - etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini - etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini - etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini -+ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini - scripts = - bin/quantum-rootwrap - bin/neutron-rootwrap diff --git a/nova_v1.patch b/nova_v1.patch deleted file mode 100644 index b0bc529a93..0000000000 --- a/nova_v1.patch +++ /dev/null @@ -1,3238 +0,0 @@ -diff --git nova/network/model.py nova/network/model.py -index b8905a5..e50f75f 100644 ---- nova/network/model.py -+++ nova/network/model.py -@@ -37,6 +37,7 @@ VIF_TYPE_BRIDGE = 'bridge' - VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' -+VIF_TYPE_CONTRAIL = 'contrail' - VIF_TYPE_OTHER = 'other' - - # Constant for max length of network interface names -diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py -index 1bb8f62..9a8b0e9 100644 ---- nova/virt/libvirt/vif.py -+++ nova/virt/libvirt/vif.py -@@ -301,6 +301,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - - return conf - -+ def get_config_contrail(self, instance, vif, image_meta, -+ inst_type): -+ conf = super(LibvirtGenericVIFDriver, -+ self).get_config(instance, vif, -+ image_meta, inst_type) -+ -+ dev = self.get_vif_devname(vif) -+ designer.set_vif_host_backend_ethernet_config(conf, dev) -+ -+ return conf -+ - def get_config_mlnx_direct(self, instance, vif, image_meta, - inst_type): - conf = super(LibvirtGenericVIFDriver, -@@ -359,6 +370,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - vif, - image_meta, - inst_type) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ return self.get_config_contrail(instance, -+ vif, -+ image_meta, -+ inst_type) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -535,6 +551,28 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except exception.ProcessExecutionError: - LOG.exception(_("Failed while plugging vif"), instance=instance) - -+ def plug_contrail(self, instance, vif): -+ """Plug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).plug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ linux_net.create_tap_dev(dev) -+ iface_id = vif['id'] -+ from nova.virt import netutils -+ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) -+ import sys -+ sys.path.append('/opt/stack/nova/plugins/contrail') -+ from config_parser import ContrailVifUpdate -+ ContrailVifUpdate(vif['id'], -+ dev, vif['network']['subnets'][0]['ips'][0]['address'], -+ instance['uuid'], vif['network']['id'], -+ vif['address'], -+ instance['display_name'], -+ instance['hostname'], -+ instance['host'], -+ prefix_len) -+ - def plug(self, instance, vif): - vif_type = vif['type'] - -@@ -542,7 +580,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - 'vif=%(vif)s'), - {'vif_type': vif_type, 'instance': instance, - 'vif': vif}) -- - if vif_type is None: - raise exception.NovaException( - _("vif_type parameter must be present " -@@ -561,6 +598,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.plug_iovisor(instance, vif) - elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: - self.plug_mlnx_direct(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ self.plug_contrail(instance, vif) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -696,6 +735,18 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except exception.ProcessExecutionError: - LOG.exception(_("Failed while unplugging vif"), instance=instance) - -+ def unplug_contrail(self, instance, vif): -+ """Unplug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).unplug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ import sys -+ sys.path.append('/opt/stack/nova/plugins/contrail') -+ from config_parser import ContrailVifDelete -+ ContrailVifDelete(vif['id']) -+ linux_net.delete_net_dev(dev) -+ - def unplug(self, instance, vif): - vif_type = vif['type'] - -@@ -720,6 +771,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.unplug_ivs(instance, vif) - elif vif_type == network_model.VIF_TYPE_IOVISOR: - self.unplug_iovisor(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ self.unplug_contrail(instance, vif) - elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: - self.unplug_mlnx_direct(instance, vif) - else: -diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py -new file mode 100644 -index 0000000..043b77c ---- /dev/null -+++ plugins/contrail/config_parser.py -@@ -0,0 +1,116 @@ -+import os -+import sys -+import cgitb -+import argparse -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' -+ -+class ContrailVifDelete(object): -+ def __init__(self, port_id): -+ if os.path.exists(VIF_DIR+port_id): -+ os.remove(VIF_DIR+port_id) -+ #end __init__ -+# end ContrailVifDelete -+ -+class ContrailVifUpdate(object): -+ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, -+ hostname, host, prefix_len): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ self.__update_vif(port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, display_name, -+ hostname, host, prefix_len) -+ -+ # end __init__ -+ -+ def __update_vif(self, port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, -+ display_name, -+ hostname, -+ host, prefix_len): -+ if (port_id and tap_name and -+ ip_address and instance_id and -+ vn_id and mac_address and -+ host and prefix_len): -+ import ConfigParser -+ config = ConfigParser.RawConfigParser() -+ config.add_section('Vif') -+ config.set('Vif', 'port_id', port_id) -+ config.set('Vif', 'tap_name', tap_name) -+ config.set('Vif', 'ip_address', ip_address) -+ config.set('Vif', 'instance_id', instance_id) -+ config.set('Vif', 'vn_id', vn_id) -+ config.set('Vif', 'mac_address', mac_address) -+ config.set('Vif', 'display_name', display_name) -+ config.set('Vif', 'hostname', hostname) -+ config.set('Vif', 'host', host) -+ config.set('Vif', 'prefix_len', prefix_len) -+ with open(VIF_DIR + port_id, 'wb') as configfile: -+ config.write(configfile) -+ -+ # end __update_vif -+# end ContrailVifUpdate -+ -+def update_vif_file(args): -+ #import pdb; pdb.set_trace() -+ if (args.port_id and args.tap_name and -+ args.ip_address and args.instance_id and -+ args.vn_id and args.mac_address and -+ args.host and args.prefix_len): -+ ContrailVifUpdate(args.port_id, args.tap_name, -+ args.ip_address, args.instance_id, -+ args.vn_id, args.mac_address, args.display_name, -+ args.hostname, args.host, args.prefix_len) -+ -+# end update_vif_file -+ -+def parse_args(args_str): -+ ''' -+ ''' -+ # Source any specified config/ini file -+ # Turn off help, so we all options in response to -h -+ conf_parser = argparse.ArgumentParser(add_help=False) -+ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) -+ parser = argparse.ArgumentParser( -+ # Inherit options from config_parser -+ parents=[conf_parser], -+ # print script description with -h/--help -+ description=__doc__, -+ # Don't mess with format of description -+ formatter_class=argparse.RawDescriptionHelpFormatter, -+ ) -+ #defaults.update(secopts) -+ #defaults.update(ksopts) -+ #parser.set_defaults(**defaults) -+ -+ parser.add_argument("--port_id", help = "port id") -+ parser.add_argument("--tap_name", help = "tap_name") -+ parser.add_argument("--ip_address", help = "ip_address") -+ parser.add_argument("--instance_id", help = "instance_id") -+ parser.add_argument("--vn_id", help = "vn_id") -+ parser.add_argument("--mac_address", help = "mac_address") -+ parser.add_argument("--display_name", help = "display_name") -+ parser.add_argument("--hostname", help = "hostname") -+ parser.add_argument("--host", help = "host") -+ parser.add_argument("--prefix_len", help = "prefix_len") -+ args = parser.parse_args(remaining_argv) -+ update_vif_file(args) -+# end parse_args -+ -+def main(args_str=None): -+ #import pdb; pdb.set_trace() -+ if not args_str: -+ args_str = ' '.join(sys.argv[1:]) -+ args = parse_args(args_str) -+# end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py -new file mode 100644 -index 0000000..7d004a0 ---- /dev/null -+++ plugins/contrail/contrail_vif.py -@@ -0,0 +1,298 @@ -+# -+# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. -+# -+ -+""" -+contril vif plug, communicate with contrail agent -+""" -+import os -+import pyinotify -+import sys -+import socket -+import cgitb -+from nova import utils -+from nova import exception -+from nova.openstack.common import log as logging -+from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent -+import gevent -+from gevent import monkey; monkey.patch_time() -+ -+LOG = logging.getLogger(__name__) -+ -+''' -+struct Port { -+ 1:required tuuid port_id, -+ 2:required tuuid instance_id, -+ 3:required string tap_name, -+ 4:required string ip_address, -+ 5:required tuuid vn_id, -+ 6:required string mac_address, -+ 7:optional string display_name, -+ 8:optional string hostname, -+ 9:optional string host; -+ 10: optional byte prefix_len; -+} -+''' -+ -+class ContrailVifPlug(object): -+ "" -+ "" -+ def __init__(self): -+ self._agent_alive = False -+ self._agent_connected = False -+ self._port_dict = {} -+ self._protocol = None -+ self._notifier = None -+ #end __init__ -+ -+ def _agent_connect(self, protocol): -+ # Agent connect for first time -+ if protocol != None: -+ from instance_service import InstanceService -+ service = InstanceService.Client(protocol) -+ return service.Connect() -+ else: -+ return False -+ #end __agent_connect -+ -+ def _keep_alive(self): -+ try: -+ if self._agent_alive == False: -+ self._protocol = self._agent_conn_open() -+ if self._protocol == None: -+ return -+ from instance_service import InstanceService -+ service = InstanceService.Client(self._protocol) -+ aa_latest = service.KeepAliveCheck() -+ if self._agent_alive == False and aa_latest == True: -+ port_l = [v for k, v in self._port_dict.iteritems()] -+ service.AddPort(port_l) -+ self._agent_alive = True -+ return -+ if self._agent_alive == True and aa_latest == False: -+ self._agent_alive = False -+ return -+ except: -+ self._agent_alive = False -+ #end _keep_alive -+ -+ def _agent_conn_open(self): -+ import socket -+ import sys -+ import uuid -+ from thrift.transport import TTransport, TSocket -+ from thrift.transport.TTransport import TTransportException -+ from thrift.protocol import TBinaryProtocol, TProtocol -+ from instance_service import InstanceService -+ from instance_service import ttypes -+ try: -+ socket = TSocket.TSocket("127.0.0.1", 9090) -+ transport = TTransport.TFramedTransport(socket) -+ transport.open() -+ protocol = TBinaryProtocol.TBinaryProtocol(transport) -+ self._agent_connected = self._agent_connect(protocol) -+ return protocol -+ except TTransportException: -+ return None -+ #end _agent_conn_open -+ -+ def get_dev_name(self, iface_id): -+ return "tap" + iface_id[0:11] -+ #end get_dev_name -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _agent_inform_port_add(self, port, port_id): -+ # First add to the port list -+ self._port_dict[port_id] = port -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.AddPort([port]) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_add -+ -+ def _agent_inform_port_delete(self, port_id): -+ # First add to the port list -+ if port_id in self._port_dict: -+ del_port_id = self._port_dict[port_id].port_id -+ del self._port_dict[port_id] -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.DeletePort(del_port_id) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_delete -+ -+ -+#end class ContrailVifPlug -+ -+def launch_interval_looping(contrail_vif_plug): -+ while True: -+ contrail_vif_plug._keep_alive() -+ gevent.sleep(2) -+#end launch_internal_looping -+ -+ -+class ContrailVifDir(ProcessEvent): -+ def __init__(self, contrail_vif, vif_dir): -+ self._create_port_list(contrail_vif, vif_dir) -+ self._contrail_vif_plug = contrail_vif -+ #end __init__ -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _create_port_list(self, contrail_vif, vif_dir): -+ import os -+ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] -+ for f in files: -+ print f -+ file_name = os.path.join(vif_dir, f) -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ contrail_vif._agent_inform_port_add(port, port_id) -+ #end create_port_list -+ -+ def _get_port_info(self, config): -+ import ConfigParser -+ #import pdb; pdb.set_trace() -+ from instance_service import ttypes -+ try: -+ vif = 'Vif' -+ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), -+ self._convert_to_bl(config.get(vif, 'instance_id')), -+ config.get(vif, 'tap_name'), -+ config.get(vif, 'ip_address'), -+ self._convert_to_bl(config.get(vif, 'vn_id')), -+ config.get(vif, 'mac_address'), -+ config.get(vif, 'display_name'), -+ config.get(vif, 'hostname'), -+ config.get(vif, 'host')) -+ #print config.get(vif, 'prefix_len') -+ return port -+ except: -+ return None -+ -+ def _print_port_info(self, config): -+ import ConfigParser -+ try: -+ vif = 'Vif' -+ print config.get(vif, 'port_id') -+ print config.get(vif, 'instance_id') -+ print config.get(vif, 'tap_name') -+ print config.get(vif, 'ip_address') -+ print config.get(vif, 'vn_id') -+ print config.get(vif, 'mac_address') -+ print config.get(vif, 'display_name') -+ print config.get(vif, 'hostname') -+ print config.get(vif, 'host') -+ print config.get(vif, 'prefix_len') -+ except: -+ return -+ #end __print_port_into -+ -+ def _read_port_info_from_file(self, file_name): -+ import ConfigParser -+ config = ConfigParser.ConfigParser() -+ config.read(file_name) -+ self._print_port_info(config) -+ port = self._get_port_info(config) -+ if port is not None: -+ return port, config.get('Vif', 'port_id') -+ else: -+ return None, None -+ #end _read_port_info_from_file -+ -+ def _is_allowed(self, file_name): -+ ret = True -+ if (file_name[0] == '.' or file_name[-1] == '~'): -+ ret = False -+ return ret -+ #end _is_allowed -+ -+ def process_IN_CREATE(self, event): -+ file_name = os.path.join(event.path, event.name) -+ if not self._is_allowed(event.name): -+ return -+ print "Create: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In create: %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ -+ #end process_IN_CREATE -+ -+ def process_IN_DELETE(self, event): -+ if not self._is_allowed(event.name): -+ return -+ print "Remove: %s" % os.path.join(event.path, event.name) -+ file_name = os.path.join(event.path, event.name) -+ #import pdb; pdb.set_trace() -+ if self._is_allowed(event.name): -+ self._contrail_vif_plug._agent_inform_port_delete(event.name) -+ return -+ -+ #end process_IN_DELETE -+ -+ def process_IN_MODIFY(self, event): -+ if not self._is_allowed(event.name): -+ return -+ file_name = os.path.join(event.path, event.name) -+ print "Modify: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In modify %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ #end process_IN_MODIFY -+#end ContrilVifDir -+ -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' -+def contrail_vif_dir_monitor(contrail_vif_plug): -+ #import pdb; pdb.set_trace() -+ wm = WatchManager() -+ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) -+ contrail_vif_plug._notifier = notifier -+ # watched events -+ mask = pyinotify.IN_DELETE | \ -+ pyinotify.IN_CREATE | \ -+ pyinotify.IN_MODIFY | \ -+ pyinotify.IN_ISDIR -+ wm.add_watch(VIF_DIR, mask, quiet=False) -+ notifier.start() -+#end contrail_vif_dir_monitor -+ -+def main(args_str = None): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ contrail_vif_plug = ContrailVifPlug() -+ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) -+ #import pdb; pdb.set_trace() -+ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) -+ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) -+#end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote -new file mode 100644 -index 0000000..76626d4 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService-remote -@@ -0,0 +1,165 @@ -+#!/usr/bin/env python -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+import sys -+import pprint -+from urlparse import urlparse -+from thrift.transport import TTransport -+from thrift.transport import TSocket -+from thrift.transport import THttpClient -+from thrift.protocol import TBinaryProtocol -+ -+import InstanceService -+from ttypes import * -+ -+if len(sys.argv) <= 1 or sys.argv[1] == '--help': -+ print '' -+ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' -+ print '' -+ print 'Functions:' -+ print ' bool AddPort(PortList port_list)' -+ print ' bool KeepAliveCheck()' -+ print ' bool Connect()' -+ print ' bool DeletePort(tuuid port_id)' -+ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' -+ print ' bool AddHostRoute(string ip_address, string vrf_name)' -+ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' -+ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool CreateVrf(string vrf_name)' -+ print '' -+ sys.exit(0) -+ -+pp = pprint.PrettyPrinter(indent = 2) -+host = 'localhost' -+port = 9090 -+uri = '' -+framed = False -+http = False -+argi = 1 -+ -+if sys.argv[argi] == '-h': -+ parts = sys.argv[argi+1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ argi += 2 -+ -+if sys.argv[argi] == '-u': -+ url = urlparse(sys.argv[argi+1]) -+ parts = url[1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ else: -+ port = 80 -+ uri = url[2] -+ if url[4]: -+ uri += '?%s' % url[4] -+ http = True -+ argi += 2 -+ -+if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': -+ framed = True -+ argi += 1 -+ -+cmd = sys.argv[argi] -+args = sys.argv[argi+1:] -+ -+if http: -+ transport = THttpClient.THttpClient(host, port, uri) -+else: -+ socket = TSocket.TSocket(host, port) -+ if framed: -+ transport = TTransport.TFramedTransport(socket) -+ else: -+ transport = TTransport.TBufferedTransport(socket) -+protocol = TBinaryProtocol.TBinaryProtocol(transport) -+client = InstanceService.Client(protocol) -+transport.open() -+ -+if cmd == 'AddPort': -+ if len(args) != 1: -+ print 'AddPort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.AddPort(eval(args[0]),)) -+ -+elif cmd == 'KeepAliveCheck': -+ if len(args) != 0: -+ print 'KeepAliveCheck requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.KeepAliveCheck()) -+ -+elif cmd == 'Connect': -+ if len(args) != 0: -+ print 'Connect requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.Connect()) -+ -+elif cmd == 'DeletePort': -+ if len(args) != 1: -+ print 'DeletePort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.DeletePort(eval(args[0]),)) -+ -+elif cmd == 'TunnelNHEntryAdd': -+ if len(args) != 3: -+ print 'TunnelNHEntryAdd requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) -+ -+elif cmd == 'TunnelNHEntryDelete': -+ if len(args) != 3: -+ print 'TunnelNHEntryDelete requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) -+ -+elif cmd == 'RouteEntryAdd': -+ if len(args) != 4: -+ print 'RouteEntryAdd requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'RouteEntryDelete': -+ if len(args) != 2: -+ print 'RouteEntryDelete requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) -+ -+elif cmd == 'AddHostRoute': -+ if len(args) != 2: -+ print 'AddHostRoute requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.AddHostRoute(args[0],args[1],)) -+ -+elif cmd == 'AddLocalVmRoute': -+ if len(args) != 4: -+ print 'AddLocalVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'AddRemoteVmRoute': -+ if len(args) != 4: -+ print 'AddRemoteVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'CreateVrf': -+ if len(args) != 1: -+ print 'CreateVrf requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.CreateVrf(args[0],)) -+ -+else: -+ print 'Unrecognized method %s' % cmd -+ sys.exit(1) -+ -+transport.close() -diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py -new file mode 100644 -index 0000000..2219045 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService.py -@@ -0,0 +1,2275 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+from thrift.Thrift import TProcessor -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+class Iface: -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ pass -+ -+ def KeepAliveCheck(self, ): -+ pass -+ -+ def Connect(self, ): -+ pass -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ pass -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ pass -+ -+ -+class Client(Iface): -+ def __init__(self, iprot, oprot=None): -+ self._iprot = self._oprot = iprot -+ if oprot is not None: -+ self._oprot = oprot -+ self._seqid = 0 -+ -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ self.send_AddPort(port_list) -+ return self.recv_AddPort() -+ -+ def send_AddPort(self, port_list): -+ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) -+ args = AddPort_args() -+ args.port_list = port_list -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddPort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddPort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); -+ -+ def KeepAliveCheck(self, ): -+ self.send_KeepAliveCheck() -+ return self.recv_KeepAliveCheck() -+ -+ def send_KeepAliveCheck(self, ): -+ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) -+ args = KeepAliveCheck_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_KeepAliveCheck(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = KeepAliveCheck_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); -+ -+ def Connect(self, ): -+ self.send_Connect() -+ return self.recv_Connect() -+ -+ def send_Connect(self, ): -+ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) -+ args = Connect_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_Connect(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = Connect_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ self.send_DeletePort(port_id) -+ return self.recv_DeletePort() -+ -+ def send_DeletePort(self, port_id): -+ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) -+ args = DeletePort_args() -+ args.port_id = port_id -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_DeletePort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = DeletePort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryAdd() -+ -+ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryAdd_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryDelete() -+ -+ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryDelete_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) -+ return self.recv_RouteEntryAdd() -+ -+ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) -+ args = RouteEntryAdd_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_RouteEntryDelete(ip_address, vrf_name) -+ return self.recv_RouteEntryDelete() -+ -+ def send_RouteEntryDelete(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) -+ args = RouteEntryDelete_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_AddHostRoute(ip_address, vrf_name) -+ return self.recv_AddHostRoute() -+ -+ def send_AddHostRoute(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) -+ args = AddHostRoute_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddHostRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddHostRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) -+ return self.recv_AddLocalVmRoute() -+ -+ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) -+ args = AddLocalVmRoute_args() -+ args.ip_address = ip_address -+ args.intf_uuid = intf_uuid -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddLocalVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddLocalVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) -+ return self.recv_AddRemoteVmRoute() -+ -+ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) -+ args = AddRemoteVmRoute_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddRemoteVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddRemoteVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ self.send_CreateVrf(vrf_name) -+ return self.recv_CreateVrf() -+ -+ def send_CreateVrf(self, vrf_name): -+ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) -+ args = CreateVrf_args() -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_CreateVrf(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = CreateVrf_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); -+ -+ -+class Processor(Iface, TProcessor): -+ def __init__(self, handler): -+ self._handler = handler -+ self._processMap = {} -+ self._processMap["AddPort"] = Processor.process_AddPort -+ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck -+ self._processMap["Connect"] = Processor.process_Connect -+ self._processMap["DeletePort"] = Processor.process_DeletePort -+ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd -+ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete -+ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd -+ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete -+ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute -+ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute -+ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute -+ self._processMap["CreateVrf"] = Processor.process_CreateVrf -+ -+ def process(self, iprot, oprot): -+ (name, type, seqid) = iprot.readMessageBegin() -+ if name not in self._processMap: -+ iprot.skip(TType.STRUCT) -+ iprot.readMessageEnd() -+ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) -+ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) -+ x.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ return -+ else: -+ self._processMap[name](self, seqid, iprot, oprot) -+ return True -+ -+ def process_AddPort(self, seqid, iprot, oprot): -+ args = AddPort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddPort_result() -+ result.success = self._handler.AddPort(args.port_list) -+ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_KeepAliveCheck(self, seqid, iprot, oprot): -+ args = KeepAliveCheck_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = KeepAliveCheck_result() -+ result.success = self._handler.KeepAliveCheck() -+ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_Connect(self, seqid, iprot, oprot): -+ args = Connect_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = Connect_result() -+ result.success = self._handler.Connect() -+ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_DeletePort(self, seqid, iprot, oprot): -+ args = DeletePort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = DeletePort_result() -+ result.success = self._handler.DeletePort(args.port_id) -+ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): -+ args = TunnelNHEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryAdd_result() -+ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): -+ args = TunnelNHEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryDelete_result() -+ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryAdd(self, seqid, iprot, oprot): -+ args = RouteEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryAdd_result() -+ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryDelete(self, seqid, iprot, oprot): -+ args = RouteEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryDelete_result() -+ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddHostRoute(self, seqid, iprot, oprot): -+ args = AddHostRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddHostRoute_result() -+ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddLocalVmRoute(self, seqid, iprot, oprot): -+ args = AddLocalVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddLocalVmRoute_result() -+ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): -+ args = AddRemoteVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddRemoteVmRoute_result() -+ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_CreateVrf(self, seqid, iprot, oprot): -+ args = CreateVrf_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = CreateVrf_result() -+ result.success = self._handler.CreateVrf(args.vrf_name) -+ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ -+# HELPER FUNCTIONS AND STRUCTURES -+ -+class AddPort_args: -+ """ -+ Attributes: -+ - port_list -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_list=None,): -+ self.port_list = port_list -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_list = [] -+ (_etype24, _size21) = iprot.readListBegin() -+ for _i25 in xrange(_size21): -+ _elem26 = Port() -+ _elem26.read(iprot) -+ self.port_list.append(_elem26) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_args') -+ if self.port_list is not None: -+ oprot.writeFieldBegin('port_list', TType.LIST, -1) -+ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) -+ for iter27 in self.port_list: -+ iter27.write(oprot) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddPort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_args: -+ """ -+ Attributes: -+ - port_id -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_id=None,): -+ self.port_id = port_id -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype31, _size28) = iprot.readListBegin() -+ for _i32 in xrange(_size28): -+ _elem33 = iprot.readI16(); -+ self.port_id.append(_elem33) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_args') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, -1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter34 in self.port_id: -+ oprot.writeI16(iter34) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.intf_uuid = intf_uuid -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.intf_uuid = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.intf_uuid is not None: -+ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) -+ oprot.writeString(self.intf_uuid) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.intf_uuid is None: -+ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_args: -+ """ -+ Attributes: -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'vrf_name', None, None, ), # 1 -+ ) -+ -+ def __init__(self, vrf_name=None,): -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_args') -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py -new file mode 100644 -index 0000000..f34ead4 ---- /dev/null -+++ plugins/contrail/instance_service/__init__.py -@@ -0,0 +1 @@ -+__all__ = ['ttypes', 'constants', 'InstanceService'] -diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py -new file mode 100644 -index 0000000..73f07fe ---- /dev/null -+++ plugins/contrail/instance_service/constants.py -@@ -0,0 +1,11 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+ -diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py -new file mode 100644 -index 0000000..564f82e ---- /dev/null -+++ plugins/contrail/instance_service/ttypes.py -@@ -0,0 +1,210 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+ -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+ -+class Port: -+ """ -+ Attributes: -+ - port_id -+ - instance_id -+ - tap_name -+ - ip_address -+ - vn_id -+ - mac_address -+ - display_name -+ - hostname -+ - host -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 -+ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 -+ (3, TType.STRING, 'tap_name', None, None, ), # 3 -+ (4, TType.STRING, 'ip_address', None, None, ), # 4 -+ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 -+ (6, TType.STRING, 'mac_address', None, None, ), # 6 -+ (7, TType.STRING, 'display_name', None, None, ), # 7 -+ (8, TType.STRING, 'hostname', None, None, ), # 8 -+ (9, TType.STRING, 'host', None, None, ), # 9 -+ ) -+ -+ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): -+ self.port_id = port_id -+ self.instance_id = instance_id -+ self.tap_name = tap_name -+ self.ip_address = ip_address -+ self.vn_id = vn_id -+ self.mac_address = mac_address -+ self.display_name = display_name -+ self.hostname = hostname -+ self.host = host -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype3, _size0) = iprot.readListBegin() -+ for _i4 in xrange(_size0): -+ _elem5 = iprot.readI16(); -+ self.port_id.append(_elem5) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.LIST: -+ self.instance_id = [] -+ (_etype9, _size6) = iprot.readListBegin() -+ for _i10 in xrange(_size6): -+ _elem11 = iprot.readI16(); -+ self.instance_id.append(_elem11) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.tap_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 5: -+ if ftype == TType.LIST: -+ self.vn_id = [] -+ (_etype15, _size12) = iprot.readListBegin() -+ for _i16 in xrange(_size12): -+ _elem17 = iprot.readI16(); -+ self.vn_id.append(_elem17) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 6: -+ if ftype == TType.STRING: -+ self.mac_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 7: -+ if ftype == TType.STRING: -+ self.display_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 8: -+ if ftype == TType.STRING: -+ self.hostname = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 9: -+ if ftype == TType.STRING: -+ self.host = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Port') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, 1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter18 in self.port_id: -+ oprot.writeI16(iter18) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.instance_id is not None: -+ oprot.writeFieldBegin('instance_id', TType.LIST, 2) -+ oprot.writeListBegin(TType.I16, len(self.instance_id)) -+ for iter19 in self.instance_id: -+ oprot.writeI16(iter19) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.tap_name is not None: -+ oprot.writeFieldBegin('tap_name', TType.STRING, 3) -+ oprot.writeString(self.tap_name) -+ oprot.writeFieldEnd() -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 4) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vn_id is not None: -+ oprot.writeFieldBegin('vn_id', TType.LIST, 5) -+ oprot.writeListBegin(TType.I16, len(self.vn_id)) -+ for iter20 in self.vn_id: -+ oprot.writeI16(iter20) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.mac_address is not None: -+ oprot.writeFieldBegin('mac_address', TType.STRING, 6) -+ oprot.writeString(self.mac_address) -+ oprot.writeFieldEnd() -+ if self.display_name is not None: -+ oprot.writeFieldBegin('display_name', TType.STRING, 7) -+ oprot.writeString(self.display_name) -+ oprot.writeFieldEnd() -+ if self.hostname is not None: -+ oprot.writeFieldBegin('hostname', TType.STRING, 8) -+ oprot.writeString(self.hostname) -+ oprot.writeFieldEnd() -+ if self.host is not None: -+ oprot.writeFieldBegin('host', TType.STRING, 9) -+ oprot.writeString(self.host) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.port_id is None: -+ raise TProtocol.TProtocolException(message='Required field port_id is unset!') -+ if self.instance_id is None: -+ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') -+ if self.tap_name is None: -+ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vn_id is None: -+ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') -+ if self.mac_address is None: -+ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) diff --git a/stack.sh b/stack.sh index 323c847960..e27e4d71bc 100755 --- a/stack.sh +++ b/stack.sh @@ -687,7 +687,7 @@ function test_install_neutron_patch() { patch_name="neutron_v3.patch" contrail_cwd=$(pwd) cd $DEST/neutron - patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null + patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null if [ $? == 0 ]; then # patch is missing echo "Installing neutron patch" @@ -697,14 +697,16 @@ function test_install_neutron_patch() { } function test_install_nova_patch() { - patch_name="nova_v2.patch" + patch_name="nova_v3.patch" contrail_cwd=$(pwd) cd $DEST/nova - patch -p0 -N --dry-run --silent < $TOP_DIR/$patch_name &> /dev/null + patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null if [ $? == 0 ]; then # patch is missing echo "Installing nova patch" patch -p0 < $TOP_DIR/$patch_name + sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser + sudo chmod +x /usr/bin/config_parser fi cd ${contrail_cwd} } From 2452ef22c1955ddce89acb39c9e1a38f66a884ff Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 28 Oct 2013 19:23:38 +0000 Subject: [PATCH 032/179] fixed localrc-compute --- contrail/localrc-multinode-compute | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 8110542e1b..9824e66f55 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,16 +1,10 @@ -ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=eth1 -MULTI_HOST=1 - HOST_IP=172.18.4.15 # change this per compute node SERVICE_HOST=172.18.4.14 -ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent +PHYSICAL_INTERFACE=eth1 -MYSQL_HOST=$SERVICE_HOST -RABBIT_HOST=$SERVICE_HOST -Q_HOST=$SERVICE_HOST -GLANCE_HOSTPORT=$SERVICE_HOST:9292 +ENABLE_CONTRAIL=yes +Q_PLUGIN=contrail STACK_DIR=$(cd $(dirname $0) && pwd) @@ -19,10 +13,16 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -Q_PLUGIN=contrail +ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent + Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default +MYSQL_HOST=$SERVICE_HOST +RABBIT_HOST=$SERVICE_HOST +Q_HOST=$SERVICE_HOST +GLANCE_HOSTPORT=$SERVICE_HOST:9292 + DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 SERVICE_TOKEN=contrail123 From a5c4dbe38547bcb6316c06f79cd7ec4bfb640e8b Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 28 Oct 2013 20:14:55 +0000 Subject: [PATCH 033/179] testing new master localrc --- contrail/localrc-multinode-server | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 518e78638f..7f635bb631 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,9 +1,11 @@ # CONTRAIL MULTI_NODE master +HOST_IP=172.18.3.6 # change this per compute node ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=eth1 +PHYSICAL_INTERFACE=eth0:1 +FLAT_INTERFACE=eth0:1 -MULTI_HOST=1 +MULTI_HOST=True Q_PLUGIN=contrail STACK_DIR=$(cd $(dirname $0) && pwd) @@ -20,6 +22,7 @@ enable_service q-dhcp enable_service q-l3 enable_service q-meta enable_service neutron +enable_service rabbit DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 From 38b8026f1f9bc198db34c55c398a484b7b959784 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 29 Oct 2013 05:59:23 +0000 Subject: [PATCH 034/179] get link addr from alias ifaces like eth0:0 --- contrail/localrc-multinode-server | 4 ++-- setup_contrail.py | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 7f635bb631..9cdab99eee 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -2,8 +2,8 @@ HOST_IP=172.18.3.6 # change this per compute node ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=eth0:1 -FLAT_INTERFACE=eth0:1 +PHYSICAL_INTERFACE=eth0:0 +FLAT_INTERFACE=eth0:0 MULTI_HOST=True Q_PLUGIN=contrail diff --git a/setup_contrail.py b/setup_contrail.py index cd52049b77..d7e6774172 100755 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -698,20 +698,26 @@ def fixup_config_files(self): mac = None if dev and dev != 'vhost0' : - mac = netifaces.ifaddresses (dev)[netifaces.AF_LINK][0][ - 'addr'] + ifaddresses = netifaces.ifaddresses(dev) + if netifaces.AF_LINK not in ifaddresses: + # kludge - if dev is an alias like "eth0:0", + # ifaddresses doesn't get the link address, so get + # it from the parent interface, "eth0" + i = dev.find(":") + if i > 0: + ifaddresses = netifaces.ifaddresses(dev[0:i]) + mac = ifaddresses[netifaces.AF_LINK][0]['addr'] if mac: with open ('%s/default_pmac' % temp_dir_name, 'w') as f: f.write (mac) self.run_shell("sudo mv %s/default_pmac /etc/contrail/default_pmac" % (temp_dir_name)) else: raise KeyError, 'Interface %s Mac %s' % (str (dev), str (mac)) - netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0][ - 'netmask'] + netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0]['netmask'] if multi_net: gateway= non_mgmt_gw else: - gateway = self.find_gateway (dev) + gateway = self.find_gateway(dev) cidr = str (netaddr.IPNetwork('%s/%s' % (vhost_ip, netmask))) template_vals = { From ccbb3c24b0a89fb269e8c0fdedfae06b5b05cd12 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 29 Oct 2013 05:59:23 +0000 Subject: [PATCH 035/179] get link addr from alias ifaces like eth0:0 --- contrail/localrc-multinode-server | 4 ++-- setup_contrail.py | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 7f635bb631..9cdab99eee 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -2,8 +2,8 @@ HOST_IP=172.18.3.6 # change this per compute node ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=eth0:1 -FLAT_INTERFACE=eth0:1 +PHYSICAL_INTERFACE=eth0:0 +FLAT_INTERFACE=eth0:0 MULTI_HOST=True Q_PLUGIN=contrail diff --git a/setup_contrail.py b/setup_contrail.py index cd52049b77..d7e6774172 100755 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -698,20 +698,26 @@ def fixup_config_files(self): mac = None if dev and dev != 'vhost0' : - mac = netifaces.ifaddresses (dev)[netifaces.AF_LINK][0][ - 'addr'] + ifaddresses = netifaces.ifaddresses(dev) + if netifaces.AF_LINK not in ifaddresses: + # kludge - if dev is an alias like "eth0:0", + # ifaddresses doesn't get the link address, so get + # it from the parent interface, "eth0" + i = dev.find(":") + if i > 0: + ifaddresses = netifaces.ifaddresses(dev[0:i]) + mac = ifaddresses[netifaces.AF_LINK][0]['addr'] if mac: with open ('%s/default_pmac' % temp_dir_name, 'w') as f: f.write (mac) self.run_shell("sudo mv %s/default_pmac /etc/contrail/default_pmac" % (temp_dir_name)) else: raise KeyError, 'Interface %s Mac %s' % (str (dev), str (mac)) - netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0][ - 'netmask'] + netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0]['netmask'] if multi_net: gateway= non_mgmt_gw else: - gateway = self.find_gateway (dev) + gateway = self.find_gateway(dev) cidr = str (netaddr.IPNetwork('%s/%s' % (vhost_ip, netmask))) template_vals = { From 4dd9ce47d5d987fa638d6e82c438e16d7031c95f Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 29 Oct 2013 06:47:06 +0000 Subject: [PATCH 036/179] support alias interfaces like eth0:0 --- setup_contrail.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/setup_contrail.py b/setup_contrail.py index d7e6774172..92ef722204 100755 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -305,6 +305,20 @@ def _is_string_in_file(self, string, filename): return found #end _is_string_in_file + def get_mac_addr(self, dev): + ifaddresses = netifaces.ifaddresses(dev) + if netifaces.AF_LINK not in ifaddresses: + # kludge - if dev is an alias like "eth0:0", ifaddresses + # doesn't get the link address, so get it from the parent + # interface, "eth0" + i = dev.find(":") + if i > 0: + ifaddresses = netifaces.ifaddresses(dev[0:i]) + mac = None + if netifaces.AF_LINK in ifaddresses: + mac = ifaddresses[netifaces.AF_LINK][0]['addr'] + return mac + def _rewrite_ifcfg_file(self, filename, dev, prsv_cfg): bond = False mac = '' @@ -314,8 +328,8 @@ def _rewrite_ifcfg_file(self, filename, dev, prsv_cfg): bond = True # end if os.path.isdir... - mac = netifaces.ifaddresses(dev)[netifaces.AF_LINK][0]['addr'] - ifcfg_file='/etc/sysconfig/network-scripts/ifcfg-%s' %(dev) + mac = self.get_mac_addr(dev) + ifcfg_file='/etc/sysconfig/network-scripts/ifcfg-%s' % (dev) if not os.path.isfile( ifcfg_file ): ifcfg_file = temp_dir_name + 'ifcfg-' + dev with open (ifcfg_file, 'w') as f: @@ -698,15 +712,7 @@ def fixup_config_files(self): mac = None if dev and dev != 'vhost0' : - ifaddresses = netifaces.ifaddresses(dev) - if netifaces.AF_LINK not in ifaddresses: - # kludge - if dev is an alias like "eth0:0", - # ifaddresses doesn't get the link address, so get - # it from the parent interface, "eth0" - i = dev.find(":") - if i > 0: - ifaddresses = netifaces.ifaddresses(dev[0:i]) - mac = ifaddresses[netifaces.AF_LINK][0]['addr'] + mac = self.get_mac_addr(dev) if mac: with open ('%s/default_pmac' % temp_dir_name, 'w') as f: f.write (mac) From 43c5d4de38d95a7f80b2f48c2c6c96a412486906 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 30 Oct 2013 00:47:33 +0000 Subject: [PATCH 037/179] got vhost0 to work with eth0 --- contrail/localrc-multinode-server | 3 +-- stack.sh | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 9cdab99eee..c8482d7c37 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -2,8 +2,7 @@ HOST_IP=172.18.3.6 # change this per compute node ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=eth0:0 -FLAT_INTERFACE=eth0:0 +PHYSICAL_INTERFACE=eth0 MULTI_HOST=True Q_PLUGIN=contrail diff --git a/stack.sh b/stack.sh index 474e54d210..333c3581f2 100755 --- a/stack.sh +++ b/stack.sh @@ -1503,14 +1503,33 @@ function insert_vrouter() { || echo "Error adding $dev to vrouter" if is_ubuntu; then - cat > /tmp/interfaces </tmp/interfaces + + # bring down the old interface + # and bring it back up with no IP address sudo ifdown $dev + sudo ifconfig $dev 0 up + + # bring up vhost0 sudo ifup -i /tmp/interfaces $DEVICE echo "Sleeping 10 seconds to allow link state to settle" sleep 10 From e5665ae1697fdfbf0da942c93947f549308d3c79 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 30 Oct 2013 18:37:08 +0000 Subject: [PATCH 038/179] compute host works. remote VMs get attached to contrail's vhost0 --- contrail/localrc-multinode-compute | 8 ++++---- stack.sh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 9824e66f55..46efe29358 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,7 +1,7 @@ -HOST_IP=172.18.4.15 # change this per compute node -SERVICE_HOST=172.18.4.14 +HOST_IP=172.18.3.5 # change this per compute node +SERVICE_HOST=172.18.3.6 -PHYSICAL_INTERFACE=eth1 +PHYSICAL_INTERFACE=eth0 ENABLE_CONTRAIL=yes Q_PLUGIN=contrail @@ -13,7 +13,7 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent +ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,q-agt,agent,vif Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default diff --git a/stack.sh b/stack.sh index 333c3581f2..1b3e9aab4b 100755 --- a/stack.sh +++ b/stack.sh @@ -1010,7 +1010,7 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - python third_party/fetch_packages.py + #python third_party/fetch_packages.py scons cd ${contrail_cwd} From 297421e57d8bd47cf4386b6c2cc3add8a5a63788 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 30 Oct 2013 20:15:29 +0000 Subject: [PATCH 039/179] reverted support for alias interfaces like eth0:0. Alias interfaces don't work for other reasons --- setup_contrail.py | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) mode change 100755 => 100644 setup_contrail.py diff --git a/setup_contrail.py b/setup_contrail.py old mode 100755 new mode 100644 index 92ef722204..cd52049b77 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -305,20 +305,6 @@ def _is_string_in_file(self, string, filename): return found #end _is_string_in_file - def get_mac_addr(self, dev): - ifaddresses = netifaces.ifaddresses(dev) - if netifaces.AF_LINK not in ifaddresses: - # kludge - if dev is an alias like "eth0:0", ifaddresses - # doesn't get the link address, so get it from the parent - # interface, "eth0" - i = dev.find(":") - if i > 0: - ifaddresses = netifaces.ifaddresses(dev[0:i]) - mac = None - if netifaces.AF_LINK in ifaddresses: - mac = ifaddresses[netifaces.AF_LINK][0]['addr'] - return mac - def _rewrite_ifcfg_file(self, filename, dev, prsv_cfg): bond = False mac = '' @@ -328,8 +314,8 @@ def _rewrite_ifcfg_file(self, filename, dev, prsv_cfg): bond = True # end if os.path.isdir... - mac = self.get_mac_addr(dev) - ifcfg_file='/etc/sysconfig/network-scripts/ifcfg-%s' % (dev) + mac = netifaces.ifaddresses(dev)[netifaces.AF_LINK][0]['addr'] + ifcfg_file='/etc/sysconfig/network-scripts/ifcfg-%s' %(dev) if not os.path.isfile( ifcfg_file ): ifcfg_file = temp_dir_name + 'ifcfg-' + dev with open (ifcfg_file, 'w') as f: @@ -712,18 +698,20 @@ def fixup_config_files(self): mac = None if dev and dev != 'vhost0' : - mac = self.get_mac_addr(dev) + mac = netifaces.ifaddresses (dev)[netifaces.AF_LINK][0][ + 'addr'] if mac: with open ('%s/default_pmac' % temp_dir_name, 'w') as f: f.write (mac) self.run_shell("sudo mv %s/default_pmac /etc/contrail/default_pmac" % (temp_dir_name)) else: raise KeyError, 'Interface %s Mac %s' % (str (dev), str (mac)) - netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0]['netmask'] + netmask = netifaces.ifaddresses (dev)[netifaces.AF_INET][0][ + 'netmask'] if multi_net: gateway= non_mgmt_gw else: - gateway = self.find_gateway(dev) + gateway = self.find_gateway (dev) cidr = str (netaddr.IPNetwork('%s/%s' % (vhost_ip, netmask))) template_vals = { From 9f9687adb1e9f90e24721088a777d6eeb7aea787 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 30 Oct 2013 20:52:07 +0000 Subject: [PATCH 040/179] re-enable fetch_packages --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index d07cb5b4b0..3d52310080 100755 --- a/stack.sh +++ b/stack.sh @@ -1012,7 +1012,7 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - #python third_party/fetch_packages.py + python third_party/fetch_packages.py scons cd ${contrail_cwd} From 00b69f94b066ab1f21591f559cb23415b0598f1c Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 31 Oct 2013 18:58:49 +0000 Subject: [PATCH 041/179] removed HOST_IP added comments --- contrail/localrc-multinode-compute | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 46efe29358..3d8e289ac8 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,6 +1,7 @@ -HOST_IP=172.18.3.5 # change this per compute node -SERVICE_HOST=172.18.3.6 +# change this to your master node's ip +SERVICE_HOST=172.18.3.6 +# the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 ENABLE_CONTRAIL=yes From 96c284927dfd4212dd52a991314f2a9bc40e7d31 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 31 Oct 2013 18:59:41 +0000 Subject: [PATCH 042/179] use launchpad_getkeys instead of keyserver to get apt repository keys for cassandra --- stack.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/stack.sh b/stack.sh index 3d52310080..9afd0c68cc 100755 --- a/stack.sh +++ b/stack.sh @@ -1009,6 +1009,8 @@ if [ $ENABLE_CONTRAIL ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC if [ ! -d $CONTRAIL_SRC/.repo ]; then + git config --global --get user.name || git config --global user.name "Anonymous" + git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" repo init -u git@github.com:Juniper/contrail-vnc fi repo sync @@ -1019,14 +1021,13 @@ if [ $ENABLE_CONTRAIL ]; then # get cassandra if ! which cassandra > /dev/null 2>&1 ; then if is_ubuntu; then + sudo add-apt-repository ppa:nilarimogard/webupd8 + sudo apt-get update + sudo apt-get install launchpad-getkeys + echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | sudo tee /etc/apt/sources.list.d/cassandra.list - gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D - gpg --export --armor F758CE318D77295D | sudo apt-key add - - gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 - gpg --export --armor 2B5C1B00 | sudo apt-key add - - apt_get update apt_get install cassandra # don't start cassandra at boot From 4dbdb800c5f562ddd56d75181684eb37bbe96525 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 1 Nov 2013 17:45:28 +0000 Subject: [PATCH 043/179] fixed application of nova_v3.patch --- stack.sh | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/stack.sh b/stack.sh index 9afd0c68cc..04b29f8374 100755 --- a/stack.sh +++ b/stack.sh @@ -700,14 +700,10 @@ function test_install_nova_patch() { patch_name="nova_v3.patch" contrail_cwd=$(pwd) cd $DEST/nova - patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing nova patch" - patch -p0 < $TOP_DIR/$patch_name - sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser - sudo chmod +x /usr/bin/config_parser - fi + echo "Installing nova patch" + patch -p0 -N < $TOP_DIR/contrail/$patch_name + sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser + sudo chmod +x /usr/bin/config_parser cd ${contrail_cwd} } @@ -1014,7 +1010,7 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - python third_party/fetch_packages.py + #python third_party/fetch_packages.py scons cd ${contrail_cwd} From 7138aa25bf08eeaccd1892bdc497610c60d7e101 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 1 Nov 2013 17:47:06 +0000 Subject: [PATCH 044/179] enable fetch_packages --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index 04b29f8374..7ea8e1a7ce 100755 --- a/stack.sh +++ b/stack.sh @@ -1010,7 +1010,7 @@ if [ $ENABLE_CONTRAIL ]; then repo init -u git@github.com:Juniper/contrail-vnc fi repo sync - #python third_party/fetch_packages.py + python third_party/fetch_packages.py scons cd ${contrail_cwd} From a4b7887cd2edb05931756146585ff1093bd89d7d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 1 Nov 2013 12:14:39 -0700 Subject: [PATCH 045/179] Fix patch path after reorg of files into contrail subdirs --- stack.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stack.sh b/stack.sh index 9afd0c68cc..6f5b0e90eb 100755 --- a/stack.sh +++ b/stack.sh @@ -691,7 +691,7 @@ function test_install_neutron_patch() { if [ $? == 0 ]; then # patch is missing echo "Installing neutron patch" - patch -p0 < $TOP_DIR/$patch_name + patch -p0 < $TOP_DIR/contrail/$patch_name fi cd ${contrail_cwd} } @@ -704,7 +704,7 @@ function test_install_nova_patch() { if [ $? == 0 ]; then # patch is missing echo "Installing nova patch" - patch -p0 < $TOP_DIR/$patch_name + patch -p0 < $TOP_DIR/contrail/$patch_name sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser sudo chmod +x /usr/bin/config_parser fi From 49afe976a4df23f511058462c21d20f641abfd95 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 1 Nov 2013 22:19:54 +0000 Subject: [PATCH 046/179] fix cassandra install on fresh build --- contrail/localrc-multinode-server | 1 - stack.sh | 25 +++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index c8482d7c37..a8cbe48499 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,5 +1,4 @@ # CONTRAIL MULTI_NODE master -HOST_IP=172.18.3.6 # change this per compute node ENABLE_CONTRAIL=yes PHYSICAL_INTERFACE=eth0 diff --git a/stack.sh b/stack.sh index 7ea8e1a7ce..aac7a8796a 100755 --- a/stack.sh +++ b/stack.sh @@ -691,7 +691,7 @@ function test_install_neutron_patch() { if [ $? == 0 ]; then # patch is missing echo "Installing neutron patch" - patch -p0 < $TOP_DIR/$patch_name + patch -p0 < $TOP_DIR/contrail/$patch_name fi cd ${contrail_cwd} } @@ -1017,15 +1017,24 @@ if [ $ENABLE_CONTRAIL ]; then # get cassandra if ! which cassandra > /dev/null 2>&1 ; then if is_ubuntu; then - sudo add-apt-repository ppa:nilarimogard/webupd8 - sudo apt-get update - sudo apt-get install launchpad-getkeys - - echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | - sudo tee /etc/apt/sources.list.d/cassandra.list + apt_get install python-software-properties + sudo add-apt-repository -y ppa:nilarimogard/webupd8 + apt_get update + apt_get install launchpad-getkeys + # use oracle Java 7 instead of OpenJDK + sudo add-apt-repository -y ppa:webupd8team/java + apt_get update + echo debconf shared/accepted-oracle-license-v1-1 select true | \ + sudo debconf-set-selections + echo debconf shared/accepted-oracle-license-v1-1 seen true | \ + sudo debconf-set-selections + yes | apt_get install oracle-java7-installer + + echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | \ + sudo tee /etc/apt/sources.list.d/cassandra.list apt_get update - apt_get install cassandra + apt_get install --force-yes cassandra # don't start cassandra at boot sudo update-rc.d -f cassandra remove else From a07cb2346fc1bc3c1f44d03a1cf32c29340251a9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 1 Nov 2013 23:02:36 +0000 Subject: [PATCH 047/179] add patch to fix cassandra's heap space issues --- contrail/cassandra-env.sh.patch | 34 +++++++++++++++++++++++++++++++++ stack.sh | 7 ++++++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 contrail/cassandra-env.sh.patch diff --git a/contrail/cassandra-env.sh.patch b/contrail/cassandra-env.sh.patch new file mode 100644 index 0000000000..e16e64c1c4 --- /dev/null +++ b/contrail/cassandra-env.sh.patch @@ -0,0 +1,34 @@ +--- cassandra-env.sh-orig 2013-11-01 22:39:23.899752001 +0000 ++++ cassandra-env.sh 2013-11-01 22:39:58.067752000 +0000 +@@ -72,8 +72,8 @@ + # times. If in doubt, and if you do not particularly want to tweak, go with + # 100 MB per physical CPU core. + +-#MAX_HEAP_SIZE="4G" +-#HEAP_NEWSIZE="800M" ++MAX_HEAP_SIZE="4G" ++HEAP_NEWSIZE="800M" + + if [ "x$MAX_HEAP_SIZE" = "x" ] && [ "x$HEAP_NEWSIZE" = "x" ]; then + calculate_heap_sizes +@@ -124,13 +124,13 @@ + JVM_OPTS="$JVM_OPTS -XX:HeapDumpPath=$CASSANDRA_HEAPDUMP_DIR/cassandra-`date +%s`-pid$$.hprof" + fi + +-if [ "`uname`" = "Linux" ] ; then +- # reduce the per-thread stack size to minimize the impact of Thrift +- # thread-per-client. (Best practice is for client connections to +- # be pooled anyway.) Only do so on Linux where it is known to be +- # supported. +- JVM_OPTS="$JVM_OPTS -Xss128k" +-fi ++#if [ "`uname`" = "Linux" ] ; then ++# # reduce the per-thread stack size to minimize the impact of Thrift ++# # thread-per-client. (Best practice is for client connections to ++# # be pooled anyway.) Only do so on Linux where it is known to be ++# # supported. ++# JVM_OPTS="$JVM_OPTS -Xss128k" ++#fi + + # GC tuning options + JVM_OPTS="$JVM_OPTS -XX:+UseParNewGC" diff --git a/stack.sh b/stack.sh index 27506d1de6..26998ae168 100755 --- a/stack.sh +++ b/stack.sh @@ -1039,7 +1039,12 @@ if [ $ENABLE_CONTRAIL ]; then sudo tee /etc/apt/sources.list.d/cassandra.list apt_get update apt_get install --force-yes cassandra - # don't start cassandra at boot + + # fix cassandra's stack size issues + sudo patch -N -r - -d /etc/cassandra < $TOP_DIR/contrail/cassandra-env.sh.patch + + # don't start cassandra at boot. I'll screen_it later + sudo service cassandra stop sudo update-rc.d -f cassandra remove else cat << EOF > datastax.repo From 60e39c0a0d4bbdb2e13d137e10aa3cfa8450d5f3 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 1 Nov 2013 18:46:38 -0700 Subject: [PATCH 048/179] Restore original interface state --- unstack.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/unstack.sh b/unstack.sh index 39f56aecf7..2d01d4701c 100755 --- a/unstack.sh +++ b/unstack.sh @@ -148,8 +148,14 @@ if [ $? == 0 ]; then cmd=$(sudo rmmod vrouter) if [ $? == 0 ]; then source /etc/contrail/agent_param - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-$dev - sudo rm -f /etc/sysconfig/network-scripts/ifcfg-vhost0 + if is_ubuntu; then + sudo ifdown $dev + sudo ifup $dev + sudo ifdown vhost0 + else + sudo rm -f /etc/sysconfig/network-scripts/ifcfg-$dev + sudo rm -f /etc/sysconfig/network-scripts/ifcfg-vhost0 + fi fi fi if [ $CONTRAIL_VGW_PUBLIC_SUBNET ]; then From d4b0a57766826578542e088f8af48492dc4cd35d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 11 Nov 2013 11:51:38 -0800 Subject: [PATCH 049/179] Assorted fixed from Pedro --- contrail_config_templates.py | 1 + exercises/neutron-adv-test.sh | 4 ++-- lib/neutron_plugins/contrail | 2 +- setup_contrail.py | 17 ++++++++++++----- stack.sh | 9 +++------ 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/contrail_config_templates.py b/contrail_config_templates.py index 2d8534488e..4e7c5c6984 100644 --- a/contrail_config_templates.py +++ b/contrail_config_templates.py @@ -7,6 +7,7 @@ ifmap_server_port=$__contrail_ifmap_server_port__ ifmap_username=$__contrail_ifmap_username__ ifmap_password=$__contrail_ifmap_password__ +redis_server_port=6379 cassandra_server_list=$__contrail_cassandra_server_list__ listen_ip_addr=$__contrail_listen_ip_addr__ listen_port=$__contrail_listen_port__ diff --git a/exercises/neutron-adv-test.sh b/exercises/neutron-adv-test.sh index abb29cf333..85a2adfa2f 100755 --- a/exercises/neutron-adv-test.sh +++ b/exercises/neutron-adv-test.sh @@ -234,7 +234,7 @@ function create_network { source $TOP_DIR/openrc $TENANT $TENANT local NET_ID=$(neutron net-create --tenant_id $TENANT_ID $NET_NAME $EXTRA| grep ' id ' | awk '{print $4}' ) neutron subnet-create --ip_version 4 --tenant_id $TENANT_ID --gateway $GATEWAY $NET_ID $CIDR - neutron-debug probe-create --device-owner compute $NET_ID + # neutron-debug probe-create --device-owner compute $NET_ID source $TOP_DIR/openrc demo demo } @@ -321,7 +321,7 @@ function delete_network { #TODO(nati) comment out until l3-agent merged #for res in port subnet net router;do for net_id in `neutron net-list -c id -c name | grep $NET_NAME | awk '{print $2}'`;do - delete_probe $net_id + # delete_probe $net_id neutron subnet-list | grep $net_id | awk '{print $2}' | xargs -I% neutron subnet-delete % neutron net-delete $net_id done diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index 1f41a276a6..8c97520e4b 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -40,7 +40,7 @@ function has_neutron_plugin_security_group() { } function neutron_plugin_check_adv_test_requirements() { - is_service_enabled q-agt && is_service_enabled q-dhcp && return 0 + return 0 } # Restore xtrace $MY_XTRACE diff --git a/setup_contrail.py b/setup_contrail.py index cd52049b77..a99c26f311 100644 --- a/setup_contrail.py +++ b/setup_contrail.py @@ -25,12 +25,12 @@ # Get Environment Stuff password = os.environ.get('ADMIN_PASSWORD', 'contrail123') admin_username = os.environ.get('CONTRAIL_ADMIN_USERNAME', 'admin') -admin_token = os.environ.get('SERVICE_TOKEN', 'contrail123') +admin_passwd = os.environ.get('ADMIN_PASSWORD', 'contrail123') admin_tenant = os.environ.get('CONTRAIL_ADMIN_TENANT', 'admin') # TODO following keystone credentials hardcoded ks_admin_user = admin_username -ks_admin_password = admin_token +ks_admin_password = admin_passwd ks_admin_tenant_name = admin_tenant from contrail_config_templates import * @@ -171,7 +171,7 @@ def _parse_args(self, args_str): self._args.collector_ip = self._args.cfgm_ip self._args.discovery_ip = self._args.cfgm_ip self._args.control_ip = self._args.cfgm_ip - self._args.compute_ip = self.get_intf_ip(self._args.physical_interface) + self._args.compute_ip = self.get_management_ip(self._args.physical_interface) self._args.openstack_mgmt_ip = self._args.cfgm_ip self._args.database_listen_ip = self._args.cfgm_ip self._args.cassandra_ip_list = ['127.0.0.1'] @@ -274,6 +274,14 @@ def get_intf_ip (self, intf): raise RuntimeError, '%s not configured' % intf # end + def get_management_ip(self, physical_interface): + if 'vhost0' in netifaces.interfaces(): + ipaddr = netifaces.ifaddresses('vhost0') + else: + ipaddr = netifaces.ifaddresses(physical_interface) + return ipaddr[netifaces.AF_INET][0]['addr'] + # end get_management_ip + def get_device_by_ip (self, ip): for i in netifaces.interfaces (): try: @@ -448,7 +456,7 @@ def fixup_config_files(self): self.run_shell("echo 'SERVICE_TOKEN=%s' >> %s/ctrl-details" %(self.service_token, temp_dir_name)) - self.run_shell("echo 'ADMIN_TOKEN=%s' >> %s/ctrl-details" %(ks_admin_password, temp_dir_name)) + self.run_shell("echo 'ADMIN_PASSWORD=%s' >> %s/ctrl-details" %(ks_admin_password, temp_dir_name)) self.run_shell("echo 'CONTROLLER=%s' >> %s/ctrl-details" %(openstack_ip, temp_dir_name)) self.run_shell("echo 'QUANTUM=%s' >> %s/ctrl-details" %(cfgm_ip, temp_dir_name)) self.run_shell("echo 'COMPUTE=%s' >> %s/ctrl-details" %(compute_ip, temp_dir_name)) @@ -493,7 +501,6 @@ def fixup_config_files(self): '__contrail_api_server_port__': '8082', '__contrail_multi_tenancy__': self._args.multi_tenancy, '__contrail_keystone_ip__': '127.0.0.1', - '__contrail_admin_token__': ks_admin_password, '__contrail_admin_user__': ks_admin_user, '__contrail_admin_password__': ks_admin_password, '__contrail_admin_tenant_name__': ks_admin_tenant_name, diff --git a/stack.sh b/stack.sh index 26998ae168..d2945f5fde 100755 --- a/stack.sh +++ b/stack.sh @@ -993,12 +993,9 @@ if [ $ENABLE_CONTRAIL ]; then sudo yum -y install redis fi - # use contrail-specific configs. e.g. redis runs non-daemon on port 6382 - sudo rsync -rv $TOP_DIR/contrail/etc/ /etc/contrail - # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 - sudo easy_install -U distribute + # sudo easy_install -U distribute sudo pip install gevent geventhttpclient==1.0a thrift sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient @@ -1055,7 +1052,7 @@ enabled = 1 gpgcheck = 0 EOF sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install dsc20 + sudo yum -y install cassandra20 fi fi @@ -1586,7 +1583,7 @@ if [ $ENABLE_CONTRAIL ]; then screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" # launch ... - screen_it redis "sudo redis-server /etc/contrail/redis.conf" + screen_it redis "sudo redis-server /etc/redis.conf" screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" From edad37ff790bcd9af75f0a110104d90916aabac3 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 11 Nov 2013 22:48:46 -0800 Subject: [PATCH 050/179] Restored test code related to probe --- exercises/neutron-adv-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/neutron-adv-test.sh b/exercises/neutron-adv-test.sh index 85a2adfa2f..abb29cf333 100755 --- a/exercises/neutron-adv-test.sh +++ b/exercises/neutron-adv-test.sh @@ -234,7 +234,7 @@ function create_network { source $TOP_DIR/openrc $TENANT $TENANT local NET_ID=$(neutron net-create --tenant_id $TENANT_ID $NET_NAME $EXTRA| grep ' id ' | awk '{print $4}' ) neutron subnet-create --ip_version 4 --tenant_id $TENANT_ID --gateway $GATEWAY $NET_ID $CIDR - # neutron-debug probe-create --device-owner compute $NET_ID + neutron-debug probe-create --device-owner compute $NET_ID source $TOP_DIR/openrc demo demo } @@ -321,7 +321,7 @@ function delete_network { #TODO(nati) comment out until l3-agent merged #for res in port subnet net router;do for net_id in `neutron net-list -c id -c name | grep $NET_NAME | awk '{print $2}'`;do - # delete_probe $net_id + delete_probe $net_id neutron subnet-list | grep $net_id | awk '{print $2}' | xargs -I% neutron subnet-delete % neutron net-delete $net_id done From e85010528495e722c890684dbc3035459ec9cde7 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 12 Nov 2013 02:28:13 -0800 Subject: [PATCH 051/179] Updated README --- contrail/README | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/contrail/README b/contrail/README index 1eb644506f..2096c3002f 100644 --- a/contrail/README +++ b/contrail/README @@ -1,5 +1,15 @@ -Contrail directory includes some sample localrc files +This fork of devstack brings up all in one openstack + opencontrail +system. Run stack.sh as usual to setup OpenStack + contrail modules. +Notes: +1) You will need to install kernel-devel package to compile OpenContrail + Vrouter module +2) Stack.sh will create an additional screen "contrail" for contrail modules. +3) This fork includes Neutron and Nova patches. These patches have been + seperately submitted for review. +4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 + +Contrail directory also includes some sample localrc files. 1) localrc.master - Use this on all-in-one system or master host on a multi node system. Set PHYSICAL_INTERFACE to the interface that Vrouter should bind to. Uncomment MULTI_HOST line if setup has @@ -7,6 +17,6 @@ multiple compute nodes. 2) localrc.compute - Use this on all compute nodes. Change the following to suit your deployment: - PHYSICAL_INTERFACE - HOST_IP - SERVICE_HOST + PHYSICAL_INTERFACE -- external interface Vrouter should bind to + SERVICE_HOST -- IP address of master + From dedb6efd0b02a04ab891ce479b246ae9f7d93ff0 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 12 Nov 2013 23:00:34 +0000 Subject: [PATCH 052/179] use contrail0 --- contrail/localrc-multinode-compute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 3d8e289ac8..6b5a023cfb 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,5 +1,5 @@ # change this to your master node's ip -SERVICE_HOST=172.18.3.6 +SERVICE_HOST=172.18.3.10 # contrail0 # the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 From c968ea0ec0d8a171442a7de076df6c6300e7f6f0 Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Thu, 14 Nov 2013 18:21:22 +0200 Subject: [PATCH 053/179] Fix issue with libthriftasio not being generated --- stack.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stack.sh b/stack.sh index d2945f5fde..a280976c59 100755 --- a/stack.sh +++ b/stack.sh @@ -1012,6 +1012,10 @@ if [ $ENABLE_CONTRAIL ]; then fi repo sync python third_party/fetch_packages.py + cd third_party/thrift-* + touch configure.ac + autoreconf --force --install + cd ../.. scons cd ${contrail_cwd} From 4722f710c2b3a39c1fb1be1854a4345852cbb287 Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Thu, 14 Nov 2013 18:26:03 +0200 Subject: [PATCH 054/179] Missing dependency (libtool) --- stack.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stack.sh b/stack.sh index d2945f5fde..008c78eebd 100755 --- a/stack.sh +++ b/stack.sh @@ -980,14 +980,14 @@ if [ $ENABLE_CONTRAIL ]; then if is_ubuntu; then apt_get install patch scons flex bison make vim apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev - apt_get install python-dev autoconf automake build-essential + apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities apt_get install redis-server else sudo yum -y install patch scons flex bison make vim sudo yum -y install expat-devel gettext-devel curl-devel - sudo yum -y install gcc-c++ python-devel autoconf automake + sudo yum -y install gcc-c++ python-devel autoconf automake libtool sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel sudo yum -y install tunctl sudo yum -y install redis From 1029ad173b06fd8668a8bb9f0076752f61b73cb7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 14 Nov 2013 22:51:23 +0000 Subject: [PATCH 055/179] merged dsetia --- contrail/localrc-multinode-server | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index a8cbe48499..601018eb68 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,4 +1,5 @@ # CONTRAIL MULTI_NODE master +HOST_IP=172.18.4.18 ENABLE_CONTRAIL=yes PHYSICAL_INTERFACE=eth0 @@ -15,13 +16,16 @@ LOGDAYS=1 disable_service n-net enable_service q-svc -enable_service q-agt enable_service q-dhcp -enable_service q-l3 enable_service q-meta enable_service neutron enable_service rabbit +#enable_service q-l3 +#enable_service q-agt +disable_service q-l3 +disable_service q-agt + DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 SERVICE_TOKEN=contrail123 From 938b8aac521ff3b31965bf313ee31a48e76c93a2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 14 Nov 2013 22:54:43 +0000 Subject: [PATCH 056/179] disabled q-l3 and q-agt. They're not used by contrail --- contrail/localrc-multinode-server | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 601018eb68..7c49d2cafe 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -20,9 +20,7 @@ enable_service q-dhcp enable_service q-meta enable_service neutron enable_service rabbit - -#enable_service q-l3 -#enable_service q-agt +# not used by contrail disable_service q-l3 disable_service q-agt From 64a44453300a7b25bb82a88313238e7f07ecca54 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 14 Nov 2013 23:43:29 +0000 Subject: [PATCH 057/179] trying contrail floating ips --- contrail/localrc-multinode-compute | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 6b5a023cfb..47bbd87eee 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,5 +1,12 @@ +HOST_IP=172.18.4.10 # publicly routable ip to me + # change this to your master node's ip -SERVICE_HOST=172.18.3.10 # contrail0 +SERVICE_HOST=172.18.4.18 # contrail0 + +# allow floating ips from 172.18.4.240 to 172.18.4.255 +CONTRAIL_VGW_INTERFACE=vgw +CONTRAIL_VGW_PUBLIC_SUBNET=172.18.4.240/28 # .240 to .255 +CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public # the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 From 2ce8d63c029f809c818ea6e789995421b4563887 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Nov 2013 00:18:45 +0000 Subject: [PATCH 058/179] don't always rebuild contrail --- contrail/localrc-multinode-server | 5 +++++ stack.sh | 2 ++ 2 files changed, 7 insertions(+) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 7c49d2cafe..441a43229e 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,6 +1,11 @@ # CONTRAIL MULTI_NODE master HOST_IP=172.18.4.18 +# allow floating ips from 172.18.4.240 to 172.18.4.255 +CONTRAIL_VGW_INTERFACE=vgw +CONTRAIL_VGW_PUBLIC_SUBNET=172.18.4.240/28 # .240 to .255 +CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public + ENABLE_CONTRAIL=yes PHYSICAL_INTERFACE=eth0 diff --git a/stack.sh b/stack.sh index f6e1630d20..13109c25ae 100755 --- a/stack.sh +++ b/stack.sh @@ -1002,6 +1002,7 @@ if [ $ENABLE_CONTRAIL ]; then sudo pip install kazoo pyinotify CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} + if [ "$CONTRAIL_REBUILD" ] || ! [ -e "$CONTRAIL_SRC" ] ; then mkdir -p $CONTRAIL_SRC contrail_cwd=$(pwd) cd $CONTRAIL_SRC @@ -1017,6 +1018,7 @@ if [ $ENABLE_CONTRAIL ]; then autoreconf --force --install cd ../.. scons + fi # CONTRAIL_REBUILD cd ${contrail_cwd} # get cassandra From 2a53051c41902c2715545161c0bf0932a7914227 Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Fri, 15 Nov 2013 08:00:31 +0200 Subject: [PATCH 059/179] touch missing files --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index f6e1630d20..4ed33a7570 100755 --- a/stack.sh +++ b/stack.sh @@ -1013,7 +1013,7 @@ if [ $ENABLE_CONTRAIL ]; then repo sync python third_party/fetch_packages.py cd third_party/thrift-* - touch configure.ac + touch configure.ac README ChangeLog autoreconf --force --install cd ../.. scons From b15dcd960a56c72eaa8c82210c06b0e309f85a51 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 15 Nov 2013 07:03:50 +0000 Subject: [PATCH 060/179] Copy contrail in-line code to a seperate file. Clean stack.sh/unstack.sh in next step --- lib/neutron_thirdparty/contrail | 382 ++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 lib/neutron_thirdparty/contrail diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail new file mode 100644 index 0000000000..b689ca7462 --- /dev/null +++ b/lib/neutron_thirdparty/contrail @@ -0,0 +1,382 @@ +# Contrail NFV +# ------------ + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set -o xtrace + +BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80} +BS_FL_OF_PORT=${BS_FL_OF_PORT:-6633} + +function install_contrail() { + sudo mkdir -p /var/log/contrail + sudo chmod 777 /var/log/contrail + + # basic dependencies + if ! which repo > /dev/null 2>&1 ; then + wget http://commondatastorage.googleapis.com/git-repo-downloads/repo + chmod 0755 repo + sudo mv repo /usr/bin + fi + + # dependencies + if is_ubuntu; then + apt_get install patch scons flex bison make vim + apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev + apt_get install python-dev autoconf automake build-essential libtool + apt_get install libevent-dev libxml2-dev libxslt-dev + apt_get install uml-utilities + apt_get install redis-server + else + sudo yum -y install patch scons flex bison make vim + sudo yum -y install expat-devel gettext-devel curl-devel + sudo yum -y install gcc-c++ python-devel autoconf automake libtool + sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel + sudo yum -y install tunctl + sudo yum -y install redis + fi + + # api server requirements + # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 + # sudo easy_install -U distribute + # sudo pip install --upgrade setuptools + sudo pip install gevent geventhttpclient==1.0a thrift + sudo pip install netifaces fabric argparse + sudo pip install stevedore xmltodict python-keystoneclient + sudo pip install kazoo pyinotify + + CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} + mkdir -p $CONTRAIL_SRC + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC + if [ ! -d $CONTRAIL_SRC/.repo ]; then + git config --global --get user.name || git config --global user.name "Anonymous" + git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" + repo init -u git@github.com:Juniper/contrail-vnc + fi + repo sync + python third_party/fetch_packages.py + (cd third_party/thrift-*; touch configure.ac; autoreconf --force --install) + scons + cd ${contrail_cwd} + + # install contrail modules + echo "Installing contrail modules" + sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + + # install neutron patch after VNC api is built and installed + test_install_neutron_patch + + # get cassandra + if ! which cassandra > /dev/null 2>&1 ; then + if is_ubuntu; then + apt_get install python-software-properties + sudo add-apt-repository -y ppa:nilarimogard/webupd8 + apt_get update + apt_get install launchpad-getkeys + + # use oracle Java 7 instead of OpenJDK + sudo add-apt-repository -y ppa:webupd8team/java + apt_get update + echo debconf shared/accepted-oracle-license-v1-1 select true | \ + sudo debconf-set-selections + echo debconf shared/accepted-oracle-license-v1-1 seen true | \ + sudo debconf-set-selections + yes | apt_get install oracle-java7-installer + + echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | \ + sudo tee /etc/apt/sources.list.d/cassandra.list + apt_get update + apt_get install --force-yes cassandra + + # fix cassandra's stack size issues + sudo patch -N -r - -d /etc/cassandra < $TOP_DIR/contrail/cassandra-env.sh.patch + + # don't start cassandra at boot. I'll screen_it later + sudo service cassandra stop + sudo update-rc.d -f cassandra remove + else + cat << EOF > datastax.repo +[datastax] +name = DataStax Repo for Apache Cassandra +baseurl = http://rpm.datastax.com/community +enabled = 1 +gpgcheck = 0 +EOF + sudo mv datastax.repo /etc/yum.repos.d/ + sudo yum -y install cassandra20 + fi + fi + + # get ifmap + if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + unzip irond-0.3.0-bin.zip + cd ${contrail_cwd} + fi + + if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz + tar xvzf zookeeper-3.4.5.tar.gz + cd zookeeper-3.4.5 + cp conf/zoo_sample.cfg conf/zoo.cfg + cd ${contrail_cwd} + fi + + # ncclient + if ! python -c 'import ncclient' >/dev/null 2>&1; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + sudo pip install ncclient-v0.3.2.tar.gz + cd ${contrail_cwd} + fi + + # process gateway configuration if present + contrail_gw_interface="" + if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then + contrail_gw_interface="--vgw_interface $CONTRAIL_VGW_INTERFACE --vgw_public_subnet $CONTRAIL_VGW_PUBLIC_SUBNET --vgw_public_network $CONTRAIL_VGW_PUBLIC_NETWORK" + fi + + # create config files + # export passwords in a subshell so setup_contrail can pick them up but they won't leak later + (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && + python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface + ) + +} + +function test_install_neutron_patch() { + patch_name="neutron_v3.patch" + contrail_cwd=$(pwd) + cd $DEST/neutron + patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null + if [ $? == 0 ]; then + # patch is missing + echo "Installing neutron patch" + patch -p0 < $TOP_DIR/contrail/$patch_name + fi + cd ${contrail_cwd} +} + +function test_install_nova_patch() { + patch_name="nova_v3.patch" + contrail_cwd=$(pwd) + cd $DEST/nova + patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null + if [ $? == 0 ]; then + # patch is missing + echo "Installing nova patch" + patch -p0 < $TOP_DIR/contrail/$patch_name + sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser + sudo chmod +x /usr/bin/config_parser + fi + cd ${contrail_cwd} +} + +# take over physical interface +function insert_vrouter() { + source /etc/contrail/agent_param + EXT_DEV=$dev + if [ -e $VHOST_CFG ]; then + source $VHOST_CFG + else + DEVICE=vhost0 + IPADDR=$(ifconfig $EXT_DEV | sed -ne 's/.*inet *addr[: ]*\([0-9.]*\).*/\1/i p') + NETMASK=$(ifconfig $EXT_DEV | sed -ne 's/.*mask[: *]\([0-9.]*\).*/\1/i p') + fi + # don't die in small memory environments + sudo insmod $CONTRAIL_SRC/$kmod vr_flow_entries=4096 vr_oflow_entries=512 + + echo "Creating vhost interface: $DEVICE." + VIF=$CONTRAIL_SRC/build/debug/vrouter/utils/vif + DEV_MAC=$(cat /sys/class/net/$dev/address) + sudo $VIF --create $DEVICE --mac $DEV_MAC \ + || echo "Error creating interface: $DEVICE" + + echo "Adding $DEVICE to vrouter" + sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost \ + || echo "Error adding $DEVICE to vrouter" + + echo "Adding $dev to vrouter" + sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical \ + || echo "Error adding $dev to vrouter" + + if is_ubuntu; then + + # copy eth0 interface params, routes, and dns to a new + # interfaces file for vhost0 + ( + cat </tmp/interfaces + + # bring down the old interface + # and bring it back up with no IP address + sudo ifdown $dev + sudo ifconfig $dev 0 up + + # bring up vhost0 + sudo ifup -i /tmp/interfaces $DEVICE + echo "Sleeping 10 seconds to allow link state to settle" + sleep 10 + sudo ifup -i /tmp/interfaces $dev + else + echo "Sleeping 10 seconds to allow link state to settle" + sudo ifup $DEVICE + sudo cp /etc/contrail/ifcfg-$dev /etc/sysconfig/network-scripts + sleep 10 + echo "Restarting network service" + sudo service network restart + fi +} + +function test_insert_vrouter () +{ + if lsmod | grep -q vrouter; then + echo "vrouter module already inserted." + else + insert_vrouter + echo "vrouter kernel module inserted." + fi +} + +function pywhere() { + module=$1 + python -c "import $module; import os; print os.path.dirname($module.__file__)" +} + +function start_contrail() { + # save screen settings + SAVED_SCREEN_NAME=$SCREEN_NAME + SCREEN_NAME="contrail" + screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash + sleep 1 + # Set a reasonable status bar + screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" + + # launch ... + screen_it redis "sudo redis-server /etc/redis.conf" + screen_it cass "sudo /usr/sbin/cassandra -f" + screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" + screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" + sleep 2 + + + screen_it disco "python $(pywhere discovery)/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" + sleep 2 + + # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" + echo "Waiting for api-server to start..." + if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then + echo "api-server did not start" + exit 1 + fi + sleep 2 + screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" + + source /etc/contrail/control_param + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + + # vrouter + test_insert_vrouter + + # agent + if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then + sudo sysctl -w net.ipv4.ip_forward=1 + sudo /opt/stack/contrail/build/debug/vrouter/utils/vif --create vgw --mac 00:01:00:5e:00:00 + sudo ifconfig vgw up + sudo route add -net $CONTRAIL_VGW_PUBLIC_SUBNET dev vgw + fi + source /etc/contrail/agent_param + #sudo mkdir -p $(dirname $VROUTER_LOGFILE) + mkdir -p $TOP_DIR/bin + + # make a fake contrail-version when contrail isn't installed by yum + if ! contrail-version >/dev/null 2>&1; then + cat >$TOP_DIR/bin/contrail-version < $TOP_DIR/bin/vnsw.hlpr < Date: Fri, 15 Nov 2013 07:06:38 +0000 Subject: [PATCH 061/179] Clean up stack.sh and unstack.sh; move in-line contrail specific code to third part area --- contrail/README | 11 +- contrail/localrc-multinode-server | 1 + contrail/localrc-single | 1 + contrail/localrc.master | 1 + lib/neutron_thirdparty/contrail | 2 +- stack.sh | 347 ------------------------------ unstack.sh | 30 --- 7 files changed, 8 insertions(+), 385 deletions(-) diff --git a/contrail/README b/contrail/README index 2096c3002f..22bd743c2e 100644 --- a/contrail/README +++ b/contrail/README @@ -10,13 +10,10 @@ Notes: 4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 Contrail directory also includes some sample localrc files. -1) localrc.master - Use this on all-in-one system or master host -on a multi node system. Set PHYSICAL_INTERFACE to the interface that -Vrouter should bind to. Uncomment MULTI_HOST line if setup has -multiple compute nodes. +1) localrc-single: for all-in-one system +2) localrc-multinode-server: master host on a multi node system. +3) localrc-multinode-compute: all compute nodes. -2) localrc.compute - Use this on all compute nodes. Change the -following to suit your deployment: +Change the following to suit your deployment: PHYSICAL_INTERFACE -- external interface Vrouter should bind to SERVICE_HOST -- IP address of master - diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index a8cbe48499..600dc731c5 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -21,6 +21,7 @@ enable_service q-l3 enable_service q-meta enable_service neutron enable_service rabbit +enable_service contrail DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 diff --git a/contrail/localrc-single b/contrail/localrc-single index dbc1c9e2e3..5893b0544b 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -12,6 +12,7 @@ enable_service q-dhcp enable_service q-l3 enable_service q-meta enable_service neutron +enable_service contrail DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 diff --git a/contrail/localrc.master b/contrail/localrc.master index 0bd04314e4..c6242c41ac 100644 --- a/contrail/localrc.master +++ b/contrail/localrc.master @@ -6,6 +6,7 @@ enable_service q-dhcp enable_service q-l3 enable_service q-meta enable_service neutron +enable_service contrail # Set passwords DATABASE_PASSWORD=contrail123 diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index b689ca7462..347156afb3 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -56,7 +56,7 @@ function install_contrail() { fi repo sync python third_party/fetch_packages.py - (cd third_party/thrift-*; touch configure.ac; autoreconf --force --install) + (cd third_party/thrift-*; touch configure.ac README ChangeLog; autoreconf --force --install) scons cd ${contrail_cwd} diff --git a/stack.sh b/stack.sh index 4ed33a7570..88d55e1ac8 100755 --- a/stack.sh +++ b/stack.sh @@ -436,11 +436,6 @@ if is_service_enabled s-proxy; then read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH." fi -if [ $ENABLE_CONTRAIL ]; then - read_password PHYSICAL_INTERFACE "ENTER PHYSICAL INTERFACE TO USE FOR FOR VROUTER" -fi - - # Configure logging # ----------------- @@ -683,53 +678,14 @@ if is_service_enabled cinder; then configure_cinder fi -function test_install_neutron_patch() { - patch_name="neutron_v3.patch" - contrail_cwd=$(pwd) - cd $DEST/neutron - patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing neutron patch" - patch -p0 < $TOP_DIR/contrail/$patch_name - fi - cd ${contrail_cwd} -} - -function test_install_nova_patch() { - patch_name="nova_v3.patch" - contrail_cwd=$(pwd) - cd $DEST/nova - patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing nova patch" - patch -p0 < $TOP_DIR/contrail/$patch_name - sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser - sudo chmod +x /usr/bin/config_parser - fi - cd ${contrail_cwd} -} - -function command_exists() { - hash "$1" &> /dev/null ; -} - - if is_service_enabled neutron; then install_neutron install_neutron_third_party - if [ $ENABLE_CONTRAIL ]; then - test_install_neutron_patch - fi fi if is_service_enabled nova; then # compute service install_nova - if [ $ENABLE_CONTRAIL ]; then - test_install_nova_patch - fi cleanup_nova configure_nova fi @@ -963,148 +919,6 @@ if is_service_enabled ir-api ir-cond; then init_ironic fi -# Contrail -# -------- -if [ $ENABLE_CONTRAIL ]; then - sudo mkdir -p /var/log/contrail - sudo chmod 777 /var/log/contrail - - # basic dependencies - if ! which repo > /dev/null 2>&1 ; then - wget http://commondatastorage.googleapis.com/git-repo-downloads/repo - chmod 0755 repo - sudo mv repo /usr/bin - fi - - # dependencies - if is_ubuntu; then - apt_get install patch scons flex bison make vim - apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev - apt_get install python-dev autoconf automake build-essential libtool - apt_get install libevent-dev libxml2-dev libxslt-dev - apt_get install uml-utilities - apt_get install redis-server - else - sudo yum -y install patch scons flex bison make vim - sudo yum -y install expat-devel gettext-devel curl-devel - sudo yum -y install gcc-c++ python-devel autoconf automake libtool - sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel - sudo yum -y install tunctl - sudo yum -y install redis - fi - - # api server requirements - # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 - # sudo easy_install -U distribute - sudo pip install gevent geventhttpclient==1.0a thrift - sudo pip install netifaces fabric argparse - sudo pip install stevedore xmltodict python-keystoneclient - sudo pip install kazoo pyinotify - - CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} - mkdir -p $CONTRAIL_SRC - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC - if [ ! -d $CONTRAIL_SRC/.repo ]; then - git config --global --get user.name || git config --global user.name "Anonymous" - git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" - repo init -u git@github.com:Juniper/contrail-vnc - fi - repo sync - python third_party/fetch_packages.py - cd third_party/thrift-* - touch configure.ac README ChangeLog - autoreconf --force --install - cd ../.. - scons - cd ${contrail_cwd} - - # get cassandra - if ! which cassandra > /dev/null 2>&1 ; then - if is_ubuntu; then - apt_get install python-software-properties - sudo add-apt-repository -y ppa:nilarimogard/webupd8 - apt_get update - apt_get install launchpad-getkeys - - # use oracle Java 7 instead of OpenJDK - sudo add-apt-repository -y ppa:webupd8team/java - apt_get update - echo debconf shared/accepted-oracle-license-v1-1 select true | \ - sudo debconf-set-selections - echo debconf shared/accepted-oracle-license-v1-1 seen true | \ - sudo debconf-set-selections - yes | apt_get install oracle-java7-installer - - echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | \ - sudo tee /etc/apt/sources.list.d/cassandra.list - apt_get update - apt_get install --force-yes cassandra - - # fix cassandra's stack size issues - sudo patch -N -r - -d /etc/cassandra < $TOP_DIR/contrail/cassandra-env.sh.patch - - # don't start cassandra at boot. I'll screen_it later - sudo service cassandra stop - sudo update-rc.d -f cassandra remove - else - cat << EOF > datastax.repo -[datastax] -name = DataStax Repo for Apache Cassandra -baseurl = http://rpm.datastax.com/community -enabled = 1 -gpgcheck = 0 -EOF - sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install cassandra20 - fi - fi - - # get ifmap - if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip - unzip irond-0.3.0-bin.zip - cd ${contrail_cwd} - fi - - if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz - tar xvzf zookeeper-3.4.5.tar.gz - cd zookeeper-3.4.5 - cp conf/zoo_sample.cfg conf/zoo.cfg - cd ${contrail_cwd} - fi - - # ncclient - if ! python -c 'import ncclient' >/dev/null 2>&1; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz - sudo pip install ncclient-v0.3.2.tar.gz - cd ${contrail_cwd} - fi - - # process gateway configuration if present - contrail_gw_interface="" - if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then - contrail_gw_interface="--vgw_interface $CONTRAIL_VGW_INTERFACE --vgw_public_subnet $CONTRAIL_VGW_PUBLIC_SUBNET --vgw_public_network $CONTRAIL_VGW_PUBLIC_NETWORK" - fi - - # create config files - # export passwords in a subshell so setup_contrail can pick them up but they won't leak later - (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && - python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface - ) - - # install contrail modules - echo "Installing contrail modules" - sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) -fi - # Neutron # ------- @@ -1492,167 +1306,6 @@ fi # Check the status of running services service_check -# Contrail -function insert_vrouter() { - source /etc/contrail/agent_param - EXT_DEV=$dev - if [ -e $VHOST_CFG ]; then - source $VHOST_CFG - else - DEVICE=vhost0 - IPADDR=$(ifconfig $EXT_DEV | sed -ne 's/.*inet *addr[: ]*\([0-9.]*\).*/\1/i p') - NETMASK=$(ifconfig $EXT_DEV | sed -ne 's/.*mask[: *]\([0-9.]*\).*/\1/i p') - fi - # don't die in small memory environments - sudo insmod $CONTRAIL_SRC/$kmod vr_flow_entries=4096 vr_oflow_entries=512 - - echo "Creating vhost interface: $DEVICE." - VIF=$CONTRAIL_SRC/build/debug/vrouter/utils/vif - DEV_MAC=$(cat /sys/class/net/$dev/address) - sudo $VIF --create $DEVICE --mac $DEV_MAC \ - || echo "Error creating interface: $DEVICE" - - echo "Adding $DEVICE to vrouter" - sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost \ - || echo "Error adding $DEVICE to vrouter" - - echo "Adding $dev to vrouter" - sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical \ - || echo "Error adding $dev to vrouter" - - if is_ubuntu; then - - # copy eth0 interface params, routes, and dns to a new - # interfaces file for vhost0 - ( - cat </tmp/interfaces - - # bring down the old interface - # and bring it back up with no IP address - sudo ifdown $dev - sudo ifconfig $dev 0 up - - # bring up vhost0 - sudo ifup -i /tmp/interfaces $DEVICE - echo "Sleeping 10 seconds to allow link state to settle" - sleep 10 - sudo ifup -i /tmp/interfaces $dev - else - echo "Sleeping 10 seconds to allow link state to settle" - sudo ifup $DEVICE - sudo cp /etc/contrail/ifcfg-$dev /etc/sysconfig/network-scripts - sleep 10 - echo "Restarting network service" - sudo service network restart - fi -} - -function test_insert_vrouter () -{ - if lsmod | grep -q vrouter; then - echo "vrouter module already inserted." - else - insert_vrouter - echo "vrouter kernel module inserted." - fi -} - -function pywhere() { - module=$1 - python -c "import $module; import os; print os.path.dirname($module.__file__)" -} - -if [ $ENABLE_CONTRAIL ]; then - # save screen settings - SAVED_SCREEN_NAME=$SCREEN_NAME - SCREEN_NAME="contrail" - screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash - sleep 1 - # Set a reasonable status bar - screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" - - # launch ... - screen_it redis "sudo redis-server /etc/redis.conf" - screen_it cass "sudo /usr/sbin/cassandra -f" - screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" - screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" - sleep 2 - - - screen_it disco "python $(pywhere discovery)/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" - sleep 2 - - # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" - echo "Waiting for api-server to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then - echo "api-server did not start" - exit 1 - fi - sleep 2 - screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" - - source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" - - # vrouter - test_insert_vrouter - - # agent - if [ $CONTRAIL_VGW_INTERFACE -a $CONTRAIL_VGW_PUBLIC_SUBNET -a $CONTRAIL_VGW_PUBLIC_NETWORK ]; then - sudo sysctl -w net.ipv4.ip_forward=1 - sudo /opt/stack/contrail/build/debug/vrouter/utils/vif --create vgw --mac 00:01:00:5e:00:00 - sudo ifconfig vgw up - sudo route add -net $CONTRAIL_VGW_PUBLIC_SUBNET dev vgw - fi - source /etc/contrail/agent_param - #sudo mkdir -p $(dirname $VROUTER_LOGFILE) - mkdir -p $TOP_DIR/bin - - # make a fake contrail-version when contrail isn't installed by yum - if ! contrail-version >/dev/null 2>&1; then - cat >$TOP_DIR/bin/contrail-version < $TOP_DIR/bin/vnsw.hlpr < Date: Fri, 15 Nov 2013 08:43:56 +0000 Subject: [PATCH 062/179] use redis with /etc/contrail/redis.conf --- stack.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.sh b/stack.sh index 13109c25ae..12d72aff49 100755 --- a/stack.sh +++ b/stack.sh @@ -1589,7 +1589,7 @@ if [ $ENABLE_CONTRAIL ]; then screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" # launch ... - screen_it redis "sudo redis-server /etc/redis.conf" + screen_it redis "sudo redis-server /etc/contrail/redis.conf" screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" From 7b36f490ff98be21b9e621b4c7c949241e7fca59 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 15 Nov 2013 15:53:32 -0800 Subject: [PATCH 063/179] move contrail files under contrail directory --- .../contrail_config_templates.py | 9 +++++++++ setup_contrail.py => contrail/setup_contrail.py | 10 ++++++++++ lib/neutron_thirdparty/contrail | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) rename contrail_config_templates.py => contrail/contrail_config_templates.py (97%) rename setup_contrail.py => contrail/setup_contrail.py (98%) diff --git a/contrail_config_templates.py b/contrail/contrail_config_templates.py similarity index 97% rename from contrail_config_templates.py rename to contrail/contrail_config_templates.py index 4e7c5c6984..5634f36321 100644 --- a/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -315,3 +315,12 @@ admin_password=$__contrail_admin_password__ admin_tenant_name=$__contrail_admin_tenant_name__ """) + +openstackrc_template = string.Template(""" +export OS_USERNAME=$__contrail_admin_user__ +export OS_PASSWORD=$__contrail_admin_password__ +export OS_TENANT_NAME=$__contrail_admin_tenant_name__ +export OS_AUTH_URL=http://$__contrail_keystone_ip__:5000/v2.0/ +export OS_NO_CACHE=1 +""") + diff --git a/setup_contrail.py b/contrail/setup_contrail.py similarity index 98% rename from setup_contrail.py rename to contrail/setup_contrail.py index a99c26f311..6297751982 100644 --- a/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -591,6 +591,16 @@ def fixup_config_files(self): self.run_shell("sudo cp %s/ContrailPlugin.ini /opt/stack/neutron/etc/neutron/plugins/juniper/contrail/" %(temp_dir_name)) self.run_shell("sudo mv %s/ContrailPlugin.ini /etc/contrail/" %(temp_dir_name)) + template_vals = { + '__contrail_keystone_ip__': cfgm_ip, + '__contrail_admin_user__': ks_admin_user, + '__contrail_admin_password__': ks_admin_password, + '__contrail_admin_tenant_name__': ks_admin_tenant_name, + } + self._template_substitute_write(openstackrc_template, + template_vals, temp_dir_name + '/openstackrc') + self.run_shell("sudo mv %s/openstackrc /etc/contrail/openstackrc" %(temp_dir_name)) + if 'control' in self._args.role: control_ip = self._args.control_ip certdir = '/var/lib/puppet/ssl' if self._args.puppet_server else '/etc/contrail/ssl' diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 347156afb3..d56c6f86e1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -145,7 +145,7 @@ EOF # create config files # export passwords in a subshell so setup_contrail can pick them up but they won't leak later (export ADMIN_PASSWORD CONTRAIL_ADMIN_USERNAME SERVICE_TOKEN CONTRAIL_ADMIN_TENANT && - python $TOP_DIR/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface + python $TOP_DIR/contrail/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface ) } From 3e524b81229ae9c299354f6affedf07289f7bd2f Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Sun, 17 Nov 2013 08:53:05 +0200 Subject: [PATCH 064/179] Missing sudo's --- lib/neutron_thirdparty/contrail | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index d56c6f86e1..f1d5abfdd6 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -186,8 +186,8 @@ function insert_vrouter() { source $VHOST_CFG else DEVICE=vhost0 - IPADDR=$(ifconfig $EXT_DEV | sed -ne 's/.*inet *addr[: ]*\([0-9.]*\).*/\1/i p') - NETMASK=$(ifconfig $EXT_DEV | sed -ne 's/.*mask[: *]\([0-9.]*\).*/\1/i p') + IPADDR=$(sudo ifconfig $EXT_DEV | sed -ne 's/.*inet *addr[: ]*\([0-9.]*\).*/\1/i p') + NETMASK=$(sudo ifconfig $EXT_DEV | sed -ne 's/.*mask[: *]\([0-9.]*\).*/\1/i p') fi # don't die in small memory environments sudo insmod $CONTRAIL_SRC/$kmod vr_flow_entries=4096 vr_oflow_entries=512 @@ -216,13 +216,13 @@ iface $dev inet manual iface $DEVICE inet static EOF - ifconfig $dev | perl -ne ' + sudo ifconfig $dev | perl -ne ' /HWaddr\s*([a-f\d:]+)/i && print(" hwaddr $1\n"); /inet addr:\s*([\d.]+)/i && print(" address $1\n"); /Bcast:\s*([\d.]+)/i && print(" broadcast $1\n"); /Mask:\s*([\d.]+)/i && print(" netmask $1\n"); ' - route -n | perl -ane '$F[7]=="'$dev'" && ($F[3] =~ /G/) && print(" gateway $F[1]\n")' + sudo route -n | perl -ane '$F[7]=="'$dev'" && ($F[3] =~ /G/) && print(" gateway $F[1]\n")' perl -ne '/^nameserver ([\d.]+)/ && push(@dns, $1); END { @dns && print(" dns-nameservers ", join(" ", @dns), "\n") }' /etc/resolv.conf From 7688df60c924b23f28093c28cb54befa326141a1 Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Mon, 18 Nov 2013 12:11:00 +0200 Subject: [PATCH 065/179] Patch Cassandra in a better way. patch -N returns != is the patch is already applied, so stack.sh thinks it's an error and stops. --- lib/neutron_thirdparty/contrail | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index d56c6f86e1..8ad5d61d2e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -90,7 +90,7 @@ function install_contrail() { apt_get install --force-yes cassandra # fix cassandra's stack size issues - sudo patch -N -r - -d /etc/cassandra < $TOP_DIR/contrail/cassandra-env.sh.patch + test_install_cassandra_patch # don't start cassandra at boot. I'll screen_it later sudo service cassandra stop @@ -150,6 +150,16 @@ EOF } +function test_install_cassandra_patch() { + patch_name="cassandra-env.sh.patch" + patch -p0 -N -d /etc/cassandra --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null + if [ $? == 0 ]; then + # patch is missing + echo "Installing neutron patch" + patch -p0 -d /etc/cassandra < $TOP_DIR/contrail/$patch_name + fi +} + function test_install_neutron_patch() { patch_name="neutron_v3.patch" contrail_cwd=$(pwd) From 709af7827038ff25541b9f1d3eedafd96750690b Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 18 Nov 2013 09:22:06 -0800 Subject: [PATCH 066/179] Minor edit to a cassandra comment --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 7236e29de9..5785140c45 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -155,7 +155,7 @@ function test_install_cassandra_patch() { patch -p0 -N -d /etc/cassandra --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null if [ $? == 0 ]; then # patch is missing - echo "Installing neutron patch" + echo "Installing cassandra patch" patch -p0 -d /etc/cassandra < $TOP_DIR/contrail/$patch_name fi } From df989703ddee3ff112b512f08aebfe55852b5555 Mon Sep 17 00:00:00 2001 From: Frank Borkin Date: Tue, 19 Nov 2013 17:19:30 +0200 Subject: [PATCH 067/179] Add missing sudo's --- lib/neutron_thirdparty/contrail | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 5785140c45..e8aea09124 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -152,11 +152,11 @@ EOF function test_install_cassandra_patch() { patch_name="cassandra-env.sh.patch" - patch -p0 -N -d /etc/cassandra --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null + sudo patch -p0 -N -d /etc/cassandra --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null if [ $? == 0 ]; then # patch is missing echo "Installing cassandra patch" - patch -p0 -d /etc/cassandra < $TOP_DIR/contrail/$patch_name + sudo patch -p0 -d /etc/cassandra < $TOP_DIR/contrail/$patch_name fi } From 3d217cafcbb45550c5b90ef8b044cfdc456585dc Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 19 Nov 2013 17:36:22 +0000 Subject: [PATCH 068/179] enable screen logging to log/screens. Add --assume-yes to apt_get --- contrail/localrc-multinode-server | 8 +++++--- functions | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 441a43229e..aa0583af08 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,9 +1,9 @@ # CONTRAIL MULTI_NODE master -HOST_IP=172.18.4.18 +HOST_IP=192.168.122.251 -# allow floating ips from 172.18.4.240 to 172.18.4.255 +# allow floating ips from 192.168.122.240 to 192.168.122.255 CONTRAIL_VGW_INTERFACE=vgw -CONTRAIL_VGW_PUBLIC_SUBNET=172.18.4.240/28 # .240 to .255 +CONTRAIL_VGW_PUBLIC_SUBNET=192.168.122.240/28 # .240 to .255 CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public ENABLE_CONTRAIL=yes @@ -14,6 +14,8 @@ Q_PLUGIN=contrail STACK_DIR=$(cd $(dirname $0) && pwd) +# log all screen output to this directory +SCREEN_LOGDIR=$STACK_DIR/log/screens LOG=True DEBUG=True LOGFILE=$STACK_DIR/log/stack.log diff --git a/functions b/functions index 83826f9327..baeeed49b6 100644 --- a/functions +++ b/functions @@ -63,7 +63,7 @@ function apt_get() { $sudo DEBIAN_FRONTEND=noninteractive \ http_proxy=$http_proxy https_proxy=$https_proxy \ no_proxy=$no_proxy \ - apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@" + apt-get --option "Dpkg::Options::=--force-confold" --force-yes --assume-yes "$@" } From a21582950051984bd1cf69b0625f32b16b01b11b Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 19 Nov 2013 23:06:14 +0000 Subject: [PATCH 069/179] create /etc/contrail/redis.conf --- contrail/redis.conf.patch | 21 +++++++++++++++++++++ stack.sh | 12 +++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 contrail/redis.conf.patch diff --git a/contrail/redis.conf.patch b/contrail/redis.conf.patch new file mode 100644 index 0000000000..be2d750b10 --- /dev/null +++ b/contrail/redis.conf.patch @@ -0,0 +1,21 @@ +--- /etc/redis/redis.conf 2011-07-27 17:26:50.000000000 +0000 ++++ redis.conf 2013-11-19 19:28:06.266187000 +0000 +@@ -14,7 +14,7 @@ + + # By default Redis does not run as a daemon. Use 'yes' if you need it. + # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +-daemonize yes ++#daemonize yes + + # When running daemonized, Redis writes a pid file in /var/run/redis.pid by + # default. You can specify a custom pid file location here. +@@ -22,7 +22,8 @@ + + # Accept connections on the specified port, default is 6379. + # If port 0 is specified Redis will not listen on a TCP socket. +-port 6379 ++# contrail uses redis on 6382 ++port 6382 + + # If you want you can bind a single interface, if the bind option is not + # specified all the interfaces will listen for incoming connections. diff --git a/stack.sh b/stack.sh index 12d72aff49..6b5a5afcbf 100755 --- a/stack.sh +++ b/stack.sh @@ -1025,7 +1025,7 @@ if [ $ENABLE_CONTRAIL ]; then if ! which cassandra > /dev/null 2>&1 ; then if is_ubuntu; then apt_get install python-software-properties - sudo add-apt-repository -y ppa:nilarimogard/webupd8 + sudo add-apt-repository ppa:nilarimogard/webupd8 apt_get update apt_get install launchpad-getkeys @@ -1589,7 +1589,17 @@ if [ $ENABLE_CONTRAIL ]; then screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" # launch ... + + # rebuild /etc/contrail/redis.conf to listen on port 6382 + rm -f /etc/contrail/redis.conf + for f in /etc/redis.conf /etc/redis/redis.conf; do + if [ -e $f ]; then + cp -f $f /etc/contrail/redis.conf + fi + done + patch -p0 -N -r - -d /etc/contrail < $TOP_DIR/contrail/redis.conf.patch screen_it redis "sudo redis-server /etc/contrail/redis.conf" + screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" From 8f1f239fc536a60d527ca91cbcb0c112482f5ac7 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 20 Nov 2013 01:33:25 +0000 Subject: [PATCH 070/179] use redis.conf in /etc/contrail. /etc/redis.conf doesn't work in ubuntu --- lib/neutron_thirdparty/contrail | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e8aea09124..764f0741a7 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -282,8 +282,17 @@ function start_contrail() { # Set a reasonable status bar screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" + # redis: rebuild /etc/contrail/redis.conf to listen on port 6382 + rm -f /etc/contrail/redis.conf + for f in /etc/redis.conf /etc/redis/redis.conf; do + if [ -e $f ]; then + cp -f $f /etc/contrail/redis.conf + fi + done + patch -p0 -N -r - -d /etc/contrail < $TOP_DIR/contrail/redis.conf.patch + # launch ... - screen_it redis "sudo redis-server /etc/redis.conf" + screen_it redis "sudo redis-server /etc/contrail/redis.conf" screen_it cass "sudo /usr/sbin/cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" From ede0c397c88da910a8f5eebb01f1e3d8da85a85e Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 20 Nov 2013 05:24:31 +0000 Subject: [PATCH 071/179] write nova.conf [keystone_authtoken] section to avoid ERROR: Unauthorized (HTTP 401) --- lib/nova | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/nova b/lib/nova index e5c78d8fe1..db98afee3f 100644 --- a/lib/nova +++ b/lib/nova @@ -566,6 +566,22 @@ function create_nova_conf() { iniset $NOVA_CONF DEFAULT ec2_dmz_host "$EC2_DMZ_HOST" iniset_rpc_backend nova $NOVA_CONF DEFAULT iniset $NOVA_CONF DEFAULT glance_api_servers "$GLANCE_HOSTPORT" + + # [keystone_authtoken] + # Host providing the admin Identity API endpoint + iniset $NOVA_CONF keystone_authtoken auth_host $KEYSTONE_SERVICE_HOST + # Port of the admin Identity API endpoint + iniset $NOVA_CONF keystone_authtoken auth_port $KEYSTONE_SERVICE_PORT + # Protocol of the admin Identity API endpoint + iniset $NOVA_CONF keystone_authtoken auth_protocol $KEYSTONE_SERVICE_PROTOCOL + # Keystone service account tenant name to validate user tokens + iniset $NOVA_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME + # Keystone account username + iniset $NOVA_CONF keystone_authtoken admin_user nova + # Keystone account password + iniset $NOVA_CONF keystone_authtoken admin_password $ADMIN_PASSWORD + iniset $NOVA_CONF keystone_authtoken auth_version v2.0 + } function init_nova_cells() { From 32e8e452463b419aa7474ee7ca14f32d597d8376 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 20 Nov 2013 05:25:19 +0000 Subject: [PATCH 072/179] support KEYSTONE_SERVICE_PROTOCOL=https in keystone.conf --- lib/keystone | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/keystone b/lib/keystone index 699b94abb5..4d09d29fbf 100755 --- a/lib/keystone +++ b/lib/keystone @@ -333,6 +333,18 @@ function init_keystone() { sudo chown $STACK_USER $KEYSTONE_AUTH_CACHE_DIR rm -f $KEYSTONE_AUTH_CACHE_DIR/* fi + + # Nova always speaks HTTPS, so keystone needs SSL certs + if [ ${KEYSTONE_SERVICE_PROTOCOL} == 'https' ]; then + $KEYSTONE_DIR/bin/keystone-manage ssl_setup + iniset $KEYSTONE_CONF ssl enable True + iniset $KEYSTONE_CONF ssl certfile ${KEYSTONE_CONF_DIR}/ssl/certs/keystone.pem + iniset $KEYSTONE_CONF ssl keyfile ${KEYSTONE_CONF_DIR}/ssl/private/keystonekey.pem + iniset $KEYSTONE_CONF ssl ca_certs ${KEYSTONE_CONF_DIR}/ssl/certs/ca.pem + iniset $KEYSTONE_CONF ssl ca_key ${KEYSTONE_CONF_DIR}/ssl/private/cakey.pem + else + iniset $KEYSTONE_CONF ssl enable False + fi } # install_keystoneclient() - Collect source and prepare @@ -372,7 +384,7 @@ function start_keystone() { fi echo "Waiting for keystone to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= curl -s http://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then + if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= curl -k -s ${KEYSTONE_SERVICE_PROTOCOL}://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then die $LINENO "keystone did not start" fi From fa41a4386251cf5d71f5226d72adc839ee02a953 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 20 Nov 2013 13:19:59 -0800 Subject: [PATCH 073/179] 1) Switch back to standard redis configuration and port 2) Use apache-cassandra for Fedora as datastax had become unreliable needed picking up openjdk also. --- lib/neutron_thirdparty/contrail | 38 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 764f0741a7..3a9be7c9db 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -34,6 +34,7 @@ function install_contrail() { sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel sudo yum -y install tunctl sudo yum -y install redis + sudo yum -y install java-1.7.0-openjdk fi # api server requirements @@ -95,17 +96,13 @@ function install_contrail() { # don't start cassandra at boot. I'll screen_it later sudo service cassandra stop sudo update-rc.d -f cassandra remove - else - cat << EOF > datastax.repo -[datastax] -name = DataStax Repo for Apache Cassandra -baseurl = http://rpm.datastax.com/community -enabled = 1 -gpgcheck = 0 -EOF - sudo mv datastax.repo /etc/yum.repos.d/ - sudo yum -y install cassandra20 - fi + elif [ ! -d $CONTRAIL_SRC/third_party/apache-cassandra-2.0.2-bin ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://www.bizdirusa.com/mirrors/apache/cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz + tar xvzf apache-cassandra-2.0.2-bin.tar.gz + cd ${contrail_cwd} + fi fi # get ifmap @@ -282,18 +279,17 @@ function start_contrail() { # Set a reasonable status bar screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" - # redis: rebuild /etc/contrail/redis.conf to listen on port 6382 - rm -f /etc/contrail/redis.conf - for f in /etc/redis.conf /etc/redis/redis.conf; do - if [ -e $f ]; then - cp -f $f /etc/contrail/redis.conf - fi - done - patch -p0 -N -r - -d /etc/contrail < $TOP_DIR/contrail/redis.conf.patch + if is_ubuntu; then + REDIS_CONF="/etc/redis/redis.conf" + CASS_PATH="/usr/sbin/cassandra" + else + REDIS_CONF="/etc/redis.conf" + CASS_PATH="$CONTRAIL_SRC/third_party/apache-cassandra-2.0.2/bin/cassandra" + fi # launch ... - screen_it redis "sudo redis-server /etc/contrail/redis.conf" - screen_it cass "sudo /usr/sbin/cassandra -f" + screen_it redis "sudo redis-server $REDIS_CONF" + screen_it cass "sudo $CASS_PATH -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 From 85a58f5240219b66dc66c3eda8e8cc6e7eae1a50 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 20 Nov 2013 14:09:41 -0800 Subject: [PATCH 074/179] merge https://github.com/dsetia/devstack/pull/15 request from frank-borkin --- contrail/localrc-multinode-compute | 2 +- contrail/localrc-multinode-server | 2 +- contrail/localrc-single | 6 +++--- contrail/localrc.compute | 2 +- contrail/localrc.master | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 47bbd87eee..e2729a3ee7 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -21,7 +21,7 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,q-agt,agent,vif +ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 17978873b0..2a660f6f8d 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -23,12 +23,12 @@ LOGDAYS=1 disable_service n-net enable_service q-svc -enable_service q-dhcp enable_service q-meta enable_service neutron enable_service rabbit # not used by contrail +disable_service q-dhcp disable_service q-l3 disable_service q-agt enable_service contrail diff --git a/contrail/localrc-single b/contrail/localrc-single index 5893b0544b..b44601aa05 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -7,9 +7,9 @@ LOGDAYS=1 disable_service n-net enable_service q-svc -enable_service q-agt -enable_service q-dhcp -enable_service q-l3 +disable_service q-agt +disable_service q-dhcp +disable_service q-l3 enable_service q-meta enable_service neutron enable_service contrail diff --git a/contrail/localrc.compute b/contrail/localrc.compute index b3ab73de2b..619e254895 100644 --- a/contrail/localrc.compute +++ b/contrail/localrc.compute @@ -8,7 +8,7 @@ HOST_IP=10.84.13.34 # Set this to IP address of config (master) node SERVICE_HOST=10.84.13.1 -ENABLED_SERVICES=n-cpu,rabbit,q-agt,agent +ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif MYSQL_HOST=$SERVICE_HOST RABBIT_HOST=$SERVICE_HOST diff --git a/contrail/localrc.master b/contrail/localrc.master index c6242c41ac..6b4816e8ee 100644 --- a/contrail/localrc.master +++ b/contrail/localrc.master @@ -1,9 +1,9 @@ # Enable Neutron disable_service n-net enable_service q-svc -enable_service q-agt -enable_service q-dhcp -enable_service q-l3 +disable_service q-agt +disable_service q-dhcp +disable_service q-l3 enable_service q-meta enable_service neutron enable_service contrail From 4e030aeeedc870364152d49bbaec639e56b06ae0 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 20 Nov 2013 14:12:04 -0800 Subject: [PATCH 075/179] get rid of redundant sample localrc files --- contrail/localrc.compute | 36 ------------------------------------ contrail/localrc.master | 28 ---------------------------- 2 files changed, 64 deletions(-) delete mode 100644 contrail/localrc.compute delete mode 100644 contrail/localrc.master diff --git a/contrail/localrc.compute b/contrail/localrc.compute deleted file mode 100644 index 619e254895..0000000000 --- a/contrail/localrc.compute +++ /dev/null @@ -1,36 +0,0 @@ -ENABLE_CONTRAIL=yes -PHYSICAL_INTERFACE=p4p1 -MULTI_HOST=1 - -# Change this per compute node -HOST_IP=10.84.13.34 - -# Set this to IP address of config (master) node -SERVICE_HOST=10.84.13.1 - -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif - -MYSQL_HOST=$SERVICE_HOST -RABBIT_HOST=$SERVICE_HOST -Q_HOST=$SERVICE_HOST -GLANCE_HOSTPORT=$SERVICE_HOST:9292 - -STACK_DIR=$(cd $(dirname $0) && pwd) - -LOG=True -DEBUG=True -LOGFILE=$STACK_DIR/log/stack.log -LOGDAYS=1 - -NEUTRON_REPO=/opt/stack/neutron - -Q_PLUGIN=contrail -Q_USE_DEBUG_COMMAND=True -PHYSICAL_NETWORK=default - -DATABASE_PASSWORD=contrail123 -RABBIT_PASSWORD=contrail123 -SERVICE_TOKEN=contrail123 -SERVICE_PASSWORD=contrail123 -ADMIN_PASSWORD=contrail123 -DATABASE_TYPE=mysql diff --git a/contrail/localrc.master b/contrail/localrc.master deleted file mode 100644 index 6b4816e8ee..0000000000 --- a/contrail/localrc.master +++ /dev/null @@ -1,28 +0,0 @@ -# Enable Neutron -disable_service n-net -enable_service q-svc -disable_service q-agt -disable_service q-dhcp -disable_service q-l3 -enable_service q-meta -enable_service neutron -enable_service contrail - -# Set passwords -DATABASE_PASSWORD=contrail123 -RABBIT_PASSWORD=contrail123 -SERVICE_TOKEN=contrail123 -SERVICE_PASSWORD=contrail123 -ADMIN_PASSWORD=contrail123 - -# Enable Contrail -ENABLE_CONTRAIL=yes - -# Use Contrail plugins for Nova and Neutron -Q_PLUGIN=contrail - -# Physical interface Vrouter binds too -PHYSICAL_INTERFACE=p6p1 - -# Enable multi node setup -# MULTI_HOST=1 From abb8ea9cef9920bfaa1bd556931c52cc5585aff4 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 21 Nov 2013 09:58:08 +0000 Subject: [PATCH 076/179] fixed contrail patching to apply if already partially applied and fail if any hunks fail --- lib/neutron_thirdparty/contrail | 55 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 764f0741a7..bf5742c408 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -1,3 +1,5 @@ +#! /bin/bash + # Contrail NFV # ------------ @@ -150,42 +152,35 @@ EOF } -function test_install_cassandra_patch() { - patch_name="cassandra-env.sh.patch" - sudo patch -p0 -N -d /etc/cassandra --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing cassandra patch" - sudo patch -p0 -d /etc/cassandra < $TOP_DIR/contrail/$patch_name +function apply_patch() { + local patch="$1" + local dir="$2" + + echo "Installing patch $(basename $patch) in $dir..." + + # run patch, ignore previously applied patches, and return an + # error if patch says "fail" + [ -d "$dir" ] || die "No such directory $dir" + [ -f "$patch" ] || die "No such patch file $patch" + if patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then + die "Failed tp apply $patch in $dir" + else + true fi } +function test_install_cassandra_patch() { + apply_patch $TOP_DIR/contrail/cassandra-env.sh.patch /etc/cassandra +} + function test_install_neutron_patch() { - patch_name="neutron_v3.patch" - contrail_cwd=$(pwd) - cd $DEST/neutron - patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing neutron patch" - patch -p0 < $TOP_DIR/contrail/$patch_name - fi - cd ${contrail_cwd} + apply_patch $TOP_DIR/contrail/neutron_v3.patch $DEST/neutron } function test_install_nova_patch() { - patch_name="nova_v3.patch" - contrail_cwd=$(pwd) - cd $DEST/nova - patch -p0 -N --dry-run --silent < $TOP_DIR/contrail/$patch_name &> /dev/null - if [ $? == 0 ]; then - # patch is missing - echo "Installing nova patch" - patch -p0 < $TOP_DIR/contrail/$patch_name - sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser - sudo chmod +x /usr/bin/config_parser - fi - cd ${contrail_cwd} + apply_patch $TOP_DIR/contrail/nova_v3.patch $DEST/nova + sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser + sudo chmod +x /usr/bin/config_parser } # take over physical interface @@ -289,7 +284,7 @@ function start_contrail() { cp -f $f /etc/contrail/redis.conf fi done - patch -p0 -N -r - -d /etc/contrail < $TOP_DIR/contrail/redis.conf.patch + apply_patch $TOP_DIR/contrail/redis.conf.patch /etc/contrail # launch ... screen_it redis "sudo redis-server /etc/contrail/redis.conf" From c4a0ffc4bb6c8e1e5ea7ea31cdfb000099c9b625 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 21 Nov 2013 10:24:28 +0000 Subject: [PATCH 077/179] touch a stamp file to avoid errors re-applying a patch --- lib/neutron_thirdparty/contrail | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 5f225a236c..2f08b9ce08 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -152,17 +152,22 @@ function install_contrail() { function apply_patch() { local patch="$1" local dir="$2" - - echo "Installing patch $(basename $patch) in $dir..." + local patch_applied="${dir}/$(basename ${patch}).appled" # run patch, ignore previously applied patches, and return an # error if patch says "fail" [ -d "$dir" ] || die "No such directory $dir" [ -f "$patch" ] || die "No such patch file $patch" - if patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then - die "Failed tp apply $patch in $dir" - else - true + if [ -e "$patch_applied" ]; then + echo "Patch $(basename $patch) was previously applied in $dir" + else5D + echo "Installing patch $(basename $patch) in $dir..." + if patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then + die "Failed to apply $patch in $dir" + else + sudo touch "$patch_applied" + true + fi fi } From dc78c55f26eaf8543f0ca93594ce61db8ef64dba Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 21 Nov 2013 14:13:20 -0800 Subject: [PATCH 078/179] Fix a couple of minor merge issues --- lib/neutron_thirdparty/contrail | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 2f08b9ce08..7583ae4e80 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -42,7 +42,7 @@ function install_contrail() { # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 # sudo easy_install -U distribute - # sudo pip install --upgrade setuptools + sudo pip install --upgrade setuptools sudo pip install gevent geventhttpclient==1.0a thrift sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient @@ -160,7 +160,7 @@ function apply_patch() { [ -f "$patch" ] || die "No such patch file $patch" if [ -e "$patch_applied" ]; then echo "Patch $(basename $patch) was previously applied in $dir" - else5D + else echo "Installing patch $(basename $patch) in $dir..." if patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then die "Failed to apply $patch in $dir" @@ -181,8 +181,10 @@ function test_install_neutron_patch() { function test_install_nova_patch() { apply_patch $TOP_DIR/contrail/nova_v3.patch $DEST/nova - sudo mv ./plugins/contrail/config_parser.py /usr/bin/config_parser - sudo chmod +x /usr/bin/config_parser + if [ -e $DEST/nova/plugins/contrail/config_parser.py ]; then + sudo mv $DEST/nova/plugins/contrail/config_parser.py /usr/bin/config_parser + sudo chmod +x /usr/bin/config_parser + fi } # take over physical interface From e79c8d8cc87502910a170e2344a1f30069111cae Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 21 Nov 2013 17:38:07 -0800 Subject: [PATCH 079/179] Fixed typo in neutron plugin --- contrail/neutron_v3.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrail/neutron_v3.patch b/contrail/neutron_v3.patch index 16d835bfe5..8f74cdb552 100644 --- a/contrail/neutron_v3.patch +++ b/contrail/neutron_v3.patch @@ -3163,7 +3163,7 @@ index 0000000..4a87a41 + + def floatingip_update(self, fip_id, fip_q): + fip_q['id'] = fip_id -+ fip_obj = self._floatingip_neutron(fip_q, UPDATE) ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, UPDATE) + self._vnc_lib.floating_ip_update(fip_obj) + + return self._floatingip_vnc_to_neutron(fip_obj) From 6797f58d37d6e9bbb8553fc53763cacfff082e2c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 22 Nov 2013 12:01:37 -0800 Subject: [PATCH 080/179] patch to /etc/cassandra needs sudo --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 7583ae4e80..8f65d1494c 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -162,7 +162,7 @@ function apply_patch() { echo "Patch $(basename $patch) was previously applied in $dir" else echo "Installing patch $(basename $patch) in $dir..." - if patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then + if sudo patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then die "Failed to apply $patch in $dir" else sudo touch "$patch_applied" From 1134ac3483236330d1e363ea59c7725d747228a7 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 25 Nov 2013 17:51:59 +0000 Subject: [PATCH 081/179] floating ips work on single host. clean out cassanddra and redis databases in stack.sh startup --- contrail/localrc-multinode-server | 8 ++++---- lib/neutron_thirdparty/contrail | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 2a660f6f8d..1c55621520 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -1,10 +1,10 @@ # CONTRAIL MULTI_NODE master -HOST_IP=192.168.122.251 +HOST_IP=192.168.56.119 -# allow floating ips from 192.168.122.240 to 192.168.122.255 +# allow floating ips from 10.99.99.0 CONTRAIL_VGW_INTERFACE=vgw -CONTRAIL_VGW_PUBLIC_SUBNET=192.168.122.240/28 # .240 to .255 -CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public +CONTRAIL_VGW_PUBLIC_SUBNET=10.99.99.0/24 # +CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:demo:public:public ENABLE_CONTRAIL=yes PHYSICAL_INTERFACE=eth0 diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 8f65d1494c..9131122a28 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -290,25 +290,29 @@ function start_contrail() { fi # launch ... + redis-cli flushall screen_it redis "sudo redis-server $REDIS_CONF" + screen_it cass "sudo $CASS_PATH -f" + screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" + screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 - screen_it disco "python $(pywhere discovery)/disc_server_zk.py --conf_file /etc/contrail/discovery.conf" + screen_it disco "python $(pywhere discovery)/disc_server_zk.py --reset_config --conf_file /etc/contrail/discovery.conf" sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --reset_config --conf_file /etc/contrail/api_server.conf" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" exit 1 fi sleep 2 - screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --conf_file /etc/contrail/schema_transformer.conf" + screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --reset_config --conf_file /etc/contrail/schema_transformer.conf" source /etc/contrail/control_param screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" From 7d56d7f4eb8178cace927d85aa73d106228da680 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 27 Nov 2013 07:45:23 +0000 Subject: [PATCH 082/179] added screen logging to localrc --- contrail/localrc-multinode-compute | 13 +++++-------- contrail/localrc-multinode-server | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index e2729a3ee7..f6b3279da2 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,12 +1,7 @@ -HOST_IP=172.18.4.10 # publicly routable ip to me +HOST_IP=192.168.56.103 # publicly routable ip to me # change this to your master node's ip -SERVICE_HOST=172.18.4.18 # contrail0 - -# allow floating ips from 172.18.4.240 to 172.18.4.255 -CONTRAIL_VGW_INTERFACE=vgw -CONTRAIL_VGW_PUBLIC_SUBNET=172.18.4.240/28 # .240 to .255 -CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:admin:public:public +SERVICE_HOST=172.18.4.119 # control1 # the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 @@ -16,12 +11,14 @@ Q_PLUGIN=contrail STACK_DIR=$(cd $(dirname $0) && pwd) +# log all screen output to this directory +SCREEN_LOGDIR=$STACK_DIR/log/screens LOG=True DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif +ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif,contrail Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 1c55621520..750d95648b 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -26,12 +26,12 @@ enable_service q-svc enable_service q-meta enable_service neutron enable_service rabbit +enable_service contrail # not used by contrail disable_service q-dhcp disable_service q-l3 disable_service q-agt -enable_service contrail DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 From 6249b409e07702d54698cb14944cd532ce4af0ab Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Tue, 26 Nov 2013 04:48:48 +0000 Subject: [PATCH 083/179] added test_network.sh script to test networks and floating ips --- contrail/test_network.sh | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 contrail/test_network.sh diff --git a/contrail/test_network.sh b/contrail/test_network.sh new file mode 100755 index 0000000000..a1eefc9661 --- /dev/null +++ b/contrail/test_network.sh @@ -0,0 +1,88 @@ +#! /bin/bash +# +# test_network.sh +# +# Set up a couple of test VMs distributed across a couple of devstack +# contrail nodes with floating ips. +# +# control1 - uses localrc-multinode-server +# compute1 - uses localrc-multinode-compute, with SERVICE_HOST=$IP_OF_CONTROL1 +# +# Devstack +# Contrail nodes VMS in Contrail nodes +# -------------- --------------------- +# +# control1 vm2 +# eth0 eth0 +# 192.168.56.119 10.1.0.252 +# vhost0 10.99.99.252 (floating) +# vgw +# +# +# compute1 vm1 +# eth0 eth0 +# 192.168.56.103 10.1.0.253 +# vhost0 10.99.99.253 (floating) +# + +set -eux + +. ./openrc admin demo + +# allow ping and ssh +nova secgroup-list +nova secgroup-list-rules default +nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 +nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +nova secgroup-list-rules default + +# net1 +eval $(neutron net-create -f shell -c id net1 | sed -ne '/^id=/p') +net1_id=$id +echo "net1_id=$net1_id" +neutron subnet-create --name net1-subnet1 $net1_id 10.1.0.0/24 + +# net2 (cloud) +eval $(neutron net-create -f shell -c id net2 | sed -ne '/^id=/p') +net2_id=$id +echo "net2_id=$net2_id" +neutron subnet-create --name net2-subnet1 $net2_id 10.2.0.0/24 + +# public +eval $(neutron net-create -f shell -c id public | sed -ne '/^id=/p') +public_id=$id +echo "public_id=$public_id" +neutron subnet-create --name public-subnet1 $public_id $CONTRAIL_VGW_PUBLIC_SUBNET --disable-dhcp +python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py --public_vn_name default-domain:demo:public --floating_ip_pool_name floatingip_pool +python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:demo --floating_ip_pool_name default-domain:demo:public:floatingip_pool + +# vms +image=cirros-0.3.1-x86_64-uec +flavor=m1.tiny +base="--image $image --flavor $flavor" + +# vm1: net1 +#nova boot $base --nic net-id=$net1_id --nic net-id=$net2_id vm1 +nova boot $base --nic net-id=$net1_id vm1 + +# vm2: net1 +nova boot $base --nic net-id=$net1_id vm2 + +# floatingip for vm1 +eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) +floatingip1_id=$id +vm1_net1_ip=$(nova show vm1 | sed -ne 's/^| net1 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') +port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm1_net1_ip"'.*/\1/p') +neutron floatingip-associate $floatingip1_id $port_id +neutron floatingip-show $floatingip1_id + +# floatingip for vm2 +eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) +floatingip2_id=$id +vm2_net1_ip=$(nova show vm2 | sed -ne 's/^| net1 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') +port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm2_net1_ip"'.*/\1/p') +neutron floatingip-associate $floatingip2_id $port_id +neutron floatingip-show $floatingip2_id + +# show where the vms ended up +nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host From 9c0f16b19421a901339637473d64a469cb003a39 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 4 Dec 2013 16:02:56 +0000 Subject: [PATCH 084/179] Prevent accidental overwrite of ifmap properties file --- lib/neutron_thirdparty/contrail | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 8f65d1494c..6f0dd7aee1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -113,6 +113,7 @@ function install_contrail() { cd $CONTRAIL_SRC/third_party wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip unzip irond-0.3.0-bin.zip + chmod -w irond-0.3.0-bin/ifmap.properties cd ${contrail_cwd} fi From 6da8e8350bdf0d315b7d08a4e1e311e27123c625 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 4 Dec 2013 16:04:12 +0000 Subject: [PATCH 085/179] Simple copy of file to help tracking patch content --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 6f0dd7aee1..1ad3959397 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -183,7 +183,7 @@ function test_install_neutron_patch() { function test_install_nova_patch() { apply_patch $TOP_DIR/contrail/nova_v3.patch $DEST/nova if [ -e $DEST/nova/plugins/contrail/config_parser.py ]; then - sudo mv $DEST/nova/plugins/contrail/config_parser.py /usr/bin/config_parser + sudo cp $DEST/nova/plugins/contrail/config_parser.py /usr/bin/config_parser sudo chmod +x /usr/bin/config_parser fi } From ec975bb99c229885e684392bc2f9e95fc8a3d60c Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 4 Dec 2013 13:33:14 -0800 Subject: [PATCH 086/179] added net_policy_join.py to use Contrail to create a routing policy between net1 and net2 --- contrail/net_policy_join.py | 93 +++++++++++++++++++++++++++++++++++++ contrail/test_network.sh | 42 +++++++++++++---- 2 files changed, 125 insertions(+), 10 deletions(-) create mode 100755 contrail/net_policy_join.py diff --git a/contrail/net_policy_join.py b/contrail/net_policy_join.py new file mode 100755 index 0000000000..bf925f89b8 --- /dev/null +++ b/contrail/net_policy_join.py @@ -0,0 +1,93 @@ +#! /usr/bin/env python +""" +net_policy_join.py [options] net1_uuid net2_uuid + +Calls Contrail API server to create a network policy to allow all +traffic between net1 and net2 + +""" + +# See contrail/build/debug/config/api-server/doc/build/html/tutorial_with_library.html + +import argparse +import os +from vnc_api import vnc_api + + +arg_defaults = {} + +# options from environment +for env_name, opt_name in ( + ('OS_TENANT_NAME', 'auth_tenant'), # demo + ('OS_USERNAME', 'auth_user'), + ('OS_PASSWORD', 'auth_password'), + ('OS_AUTH_URL', 'auth_url'), # 'http://192.168.56.119:5000/v2.0' + ('OS_IDENTITY_API_VERSION', 'auth_version') + ): + if env_name in os.environ: + arg_defaults[opt_name] = os.environ[env_name] + +# options from argv +parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, +) +parser.add_argument( + "--auth_url", default='http://127.0.0.1:5000/v2.0', + help="IP address of keystone server") +parser.add_argument( + "--auth_tenant", default='demo', + help="Tenant name for keystone admin user") +parser.add_argument( + "--auth_version", default='2.0', + help="Version of keystone server") +parser.add_argument( + "--auth_user", default='admin', + help="Name of keystone admin user") +parser.add_argument( + "--auth_password", default='contrail123', + help="Password of keystone admin user") +parser.add_argument( + "--api_host", default='127.0.0.1', + help="Hostnmae of api server") +parser.add_argument( + "--api_port", default=8082, + help="Port of api server") +parser.add_argument("net1_uuid", help="UUIDs of subnets to join") +parser.add_argument("net2_uuid") +parser.set_defaults(**arg_defaults) +args = parser.parse_args() + +vnc_lib = vnc_api.VncApi(api_server_host=args.api_host, + api_server_port=args.api_port, + ) + +net1 = vnc_lib.virtual_network_read(id = args.net1_uuid) +net2 = vnc_lib.virtual_network_read(id = args.net2_uuid) + +pol1 = vnc_api.NetworkPolicy( + 'policy-%s-%s-any' % (net1.get_fq_name_str(), net2.get_fq_name_str()), + network_policy_entries = vnc_api.PolicyEntriesType( + [vnc_api.PolicyRuleType( + direction = '<>', + action_list = vnc_api.ActionListType(simple_action='pass'), + protocol = 'any', + src_addresses = [ + vnc_api.AddressType(virtual_network = net1.get_fq_name_str()) + ], + src_ports = [vnc_api.PortType(-1, -1)], + dst_addresses = [ + vnc_api.AddressType(virtual_network = net2.get_fq_name_str()) + ], + dst_ports = [vnc_api.PortType(-1, -1)]) + ])) +vnc_lib.network_policy_create(pol1) + +net1.add_network_policy(pol1, vnc_api.VirtualNetworkPolicyType( + sequence = vnc_api.SequenceType(0, 0))) +vnc_lib.virtual_network_update(net1) + +net2.add_network_policy(pol1, vnc_api.VirtualNetworkPolicyType( + sequence = vnc_api.SequenceType(0, 0))) +vnc_lib.virtual_network_update(net2) + diff --git a/contrail/test_network.sh b/contrail/test_network.sh index a1eefc9661..2ec4178618 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -25,7 +25,7 @@ # vhost0 10.99.99.253 (floating) # -set -eux +set -ex . ./openrc admin demo @@ -57,32 +57,54 @@ python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py - python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:demo --floating_ip_pool_name default-domain:demo:public:floatingip_pool # vms -image=cirros-0.3.1-x86_64-uec + +image=cirros-0.3.1-x86_64-uec # default stock image +## try to use a test image instead of stock +#IMAGE_NAME=${IMAGE_NAME:-cirros-test} +#IMAGE_FILE=${IMAGE_FILE:-~/projects/piston/projects/cirros/cirros-0.3.1-x86_64-nbk.qcow2} +#if glance image-show $IMAGE_NAME > /dev/null 2>&1; then +# image=$IMAGE_NAME +#else +# if [ -e $IMAGE_FILE ] && +# glance image-create --name=$IMAGE_NAME --disk-format qcow2 --container-format=bare < $IMAGE_FILE; then +# image=$IMAGE_NAME +# fi +#fi + flavor=m1.tiny base="--image $image --flavor $flavor" # vm1: net1 -#nova boot $base --nic net-id=$net1_id --nic net-id=$net2_id vm1 nova boot $base --nic net-id=$net1_id vm1 -# vm2: net1 -nova boot $base --nic net-id=$net1_id vm2 +# vm2: net2 +nova boot $base --nic net-id=$net2_id vm2 # floatingip for vm1 eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) floatingip1_id=$id vm1_net1_ip=$(nova show vm1 | sed -ne 's/^| net1 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') -port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm1_net1_ip"'.*/\1/p') -neutron floatingip-associate $floatingip1_id $port_id +port1_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm1_net1_ip"'.*/\1/p') +neutron floatingip-associate $floatingip1_id $port1_id neutron floatingip-show $floatingip1_id # floatingip for vm2 eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) floatingip2_id=$id -vm2_net1_ip=$(nova show vm2 | sed -ne 's/^| net1 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') -port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm2_net1_ip"'.*/\1/p') -neutron floatingip-associate $floatingip2_id $port_id +vm2_net2_ip=$(nova show vm2 | sed -ne 's/^| net2 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') +port2_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm2_net2_ip"'.*/\1/p') +neutron floatingip-associate $floatingip2_id $port2_id neutron floatingip-show $floatingip2_id # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host + +# if the net_policy_join script exists, then use it to join net1 and net2 +THIS_DIR=$(dirname $0) +PATH=$THIS_DIR:$PATH +if which net_policy_join.py; then + net_policy_join.py $net1_id $net2_id +fi + + +set +ex \ No newline at end of file From 95847c374225fd7370737cb7f4c227106d39e97c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 5 Dec 2013 11:36:10 -0800 Subject: [PATCH 087/179] 1) Update Cassandra source 2) Update neutron and nova patches --- contrail/neutron_v4.patch | 3931 +++++++++++++++++++++++++++++++ contrail/nova_v4.patch | 3252 +++++++++++++++++++++++++ lib/neutron_thirdparty/contrail | 6 +- 3 files changed, 7186 insertions(+), 3 deletions(-) create mode 100644 contrail/neutron_v4.patch create mode 100644 contrail/nova_v4.patch diff --git a/contrail/neutron_v4.patch b/contrail/neutron_v4.patch new file mode 100644 index 0000000000..50bdbc8eba --- /dev/null +++ b/contrail/neutron_v4.patch @@ -0,0 +1,3931 @@ +diff --git etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini +new file mode 100644 +index 0000000..ab1cee6 +--- /dev/null ++++ etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini +@@ -0,0 +1,10 @@ ++ ++[APISERVER] ++api_server_ip=10.84.13.34 ++api_server_port=8082 ++multi_tenancy=False ++ ++[KEYSTONE] ++admin_user=admin ++admin_password=contrail123 ++admin_tenant_name=admin +diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py +new file mode 100644 +index 0000000..5d610b3 +--- /dev/null ++++ neutron/extensions/ipam.py +@@ -0,0 +1,140 @@ ++from abc import abstractmethod ++ ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron.api import extensions ++from neutron import manager ++from oslo.config import cfg ++ ++ ++# Ipam Exceptions ++class IpamNotFound(qexception.NotFound): ++ message = _("IPAM %(id)s could not be found") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'ipams': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:regex': attr.UUID_PATTERN}, ++ 'is_visible': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'fq_name': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ 'mgmt': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': None}, ++ 'nets_using': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True, 'default': ''} ++ }, ++} ++ ++# TODO should this be tied to ipam extension? ++EXTENDED_ATTRIBUTES_2_0 = { ++ 'networks': { ++ 'contrail:fq_name': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:policys': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ 'contrail:subnet_ipam': {'allow_post': False, ++ 'allow_put': False, ++ 'default': '', ++ 'is_visible': True}, ++ }, ++ 'subnets': { ++ 'contrail:instance_count': {'allow_post': False, ++ 'allow_put': False, ++ 'is_visible': True}, ++ 'contrail:ipam_fq_name': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ } ++} ++ ++ ++class Ipam(object): ++ ++ @classmethod ++ def get_name(cls): ++ return "Network IP Address Management" ++ ++ @classmethod ++ def get_alias(cls): ++ return "ipam" ++ ++ @classmethod ++ def get_description(cls): ++ return ("Configuration object for holding common to a set of" ++ " IP address blocks") ++ ++ @classmethod ++ def get_namespace(cls): ++ return "http://docs.openstack.org/TODO" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2012-07-20T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ exts = [] ++ plugin = manager.NeutronManager.get_plugin() ++ for resource_name in ['ipam']: ++ collection_name = resource_name + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) ++ ++ member_actions = {} ++ ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, ++ member_actions=member_actions) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ member_actions=member_actions) ++ exts.append(ex) ++ ++ return exts ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return EXTENDED_ATTRIBUTES_2_0 ++ else: ++ return {} ++#end class Ipam ++ ++ ++class IpamPluginBase(object): ++ ++ @abstractmethod ++ def create_ipam(self, context, ipam): ++ pass ++ ++ @abstractmethod ++ def update_ipam(self, context, id, ipam): ++ pass ++ ++ @abstractmethod ++ def get_ipam(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def delete_ipam(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_ipams(self, context, filters=None, fields=None): ++ pass ++#end class IpamPluginBase +diff --git neutron/extensions/policy.py neutron/extensions/policy.py +new file mode 100644 +index 0000000..59418e4 +--- /dev/null ++++ neutron/extensions/policy.py +@@ -0,0 +1,105 @@ ++from abc import abstractmethod ++ ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron.api import extensions ++from neutron import manager ++from oslo.config import cfg ++ ++ ++# Policy Exceptions ++class PolicyNotFound(qexception.NotFound): ++ message = _("Policy %(id)s could not be found") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'policys': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:regex': attr.UUID_PATTERN}, ++ 'is_visible': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'fq_name': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ 'entries': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': ''}, ++ 'nets_using': {'allow_post': False, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ }, ++} ++ ++ ++class Policy(object): ++ ++ @classmethod ++ def get_name(cls): ++ return "Network Policy" ++ ++ @classmethod ++ def get_alias(cls): ++ return "policy" ++ ++ @classmethod ++ def get_description(cls): ++ return ("Configuration object for Network Policies") ++ ++ @classmethod ++ def get_namespace(cls): ++ return "http://docs.openstack.org/TODO" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2012-07-20T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ exts = [] ++ plugin = manager.NeutronManager.get_plugin() ++ for resource_name in ['policy']: ++ collection_name = resource_name + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) ++ ++ member_actions = {} ++ ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, ++ member_actions=member_actions) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ member_actions=member_actions) ++ exts.append(ex) ++ ++ return exts ++ ++#end class Policy ++ ++ ++class PolicyPluginBase(object): ++ ++ @abstractmethod ++ def create_policy(self, context, policy): ++ pass ++ ++ @abstractmethod ++ def update_policy(self, context, id, policy): ++ pass ++ ++ @abstractmethod ++ def get_policy(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def delete_policy(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_policys(self, context, filters=None, fields=None): ++ pass ++#end class PolicyPluginBase +diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py +index dbef592..bbed97b 100644 +--- neutron/extensions/portbindings.py ++++ neutron/extensions/portbindings.py +@@ -45,11 +45,12 @@ VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_HYPERV = 'hyperv' + VIF_TYPE_MIDONET = 'midonet' ++VIF_TYPE_VROUTER = 'vrouter' + VIF_TYPE_OTHER = 'other' + VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, + VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, + VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_MIDONET, +- VIF_TYPE_OTHER] ++ VIF_TYPE_VROUTER, VIF_TYPE_OTHER] + + + EXTENDED_ATTRIBUTES_2_0 = { +diff --git neutron/extensions/vpcroutetable.py neutron/extensions/vpcroutetable.py +new file mode 100644 +index 0000000..ec1f720 +--- /dev/null ++++ neutron/extensions/vpcroutetable.py +@@ -0,0 +1,186 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++ ++# Copyright (c) 2012 OpenStack Foundation. ++# 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. ++ ++from abc import ABCMeta ++from abc import abstractmethod ++ ++from oslo.config import cfg ++ ++from neutron.api import extensions ++from neutron.api.v2 import attributes as attr ++from neutron.api.v2 import base ++from neutron.common import exceptions as qexception ++from neutron import manager ++from neutron.openstack.common import uuidutils ++from neutron import quota ++ ++ ++# Route table Exceptions ++class RouteTableNotFound(qexception.NotFound): ++ message = _("Route table %(id)s does not exist") ++ ++# Attribute Map ++RESOURCE_ATTRIBUTE_MAP = { ++ 'route_tables': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:uuid': None}, ++ 'is_visible': True, ++ 'primary_key': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': '', ++ 'validate': {'type:name_not_default': None}}, ++ 'fq_name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': '', ++ 'validate': {'type:name_not_default': None}}, ++ 'routes': {'allow_post': True, 'allow_put': True, ++ 'is_visible': True, 'default': ''}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ }, ++ 'nat_instances': { ++ 'id': {'allow_post': False, 'allow_put': False, ++ 'validate': {'type:uuid': None}, ++ 'is_visible': True, ++ 'primary_key': True}, ++ 'name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': '', ++ 'validate': {'type:name_not_default': None}}, ++ 'fq_name': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': '', ++ 'validate': {'type:name_not_default': None}}, ++ 'internal_net': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'internal_ip': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'external_net': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'external_ip': {'allow_post': True, 'allow_put': False, ++ 'is_visible': True, 'default': ''}, ++ 'tenant_id': {'allow_post': True, 'allow_put': False, ++ 'required_by_policy': True, ++ 'is_visible': True}, ++ }, ++} ++ ++EXTENDED_ATTRIBUTES_2_0 = { ++ 'networks': { ++ 'vpc:route_table': {'allow_post': True, ++ 'allow_put': True, ++ 'default': '', ++ 'is_visible': True}, ++ } ++} ++ ++ ++class Vpcroutetable(extensions.ExtensionDescriptor): ++ """ Route table extension""" ++ ++ @classmethod ++ def get_name(cls): ++ return "route-table" ++ ++ @classmethod ++ def get_alias(cls): ++ return "route-table" ++ ++ @classmethod ++ def get_description(cls): ++ return "VPC route tables extension." ++ ++ @classmethod ++ def get_namespace(cls): ++ # todo ++ return "http://docs.openstack.org/ext/routetables/api/v2.0" ++ ++ @classmethod ++ def get_updated(cls): ++ return "2013-07-24T10:00:00-00:00" ++ ++ @classmethod ++ def get_resources(cls): ++ """ Returns Ext Resources """ ++ my_plurals = [(key, key[:-1]) for key in RESOURCE_ATTRIBUTE_MAP.keys()] ++ attr.PLURALS.update(dict(my_plurals)) ++ exts = [] ++ plugin = manager.NeutronManager.get_plugin() ++ for resource_name in ['route_table', 'nat_instance']: ++ collection_name = resource_name.replace('_', '-') + "s" ++ params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict()) ++ quota.QUOTAS.register_resource_by_name(resource_name) ++ controller = base.create_resource(collection_name, ++ resource_name, ++ plugin, params, allow_bulk=True, ++ allow_pagination=True, ++ allow_sorting=True) ++ ++ ex = extensions.ResourceExtension(collection_name, ++ controller, ++ attr_map=params) ++ exts.append(ex) ++ ++ return exts ++ ++ def get_extended_resources(self, version): ++ if version == "2.0": ++ return EXTENDED_ATTRIBUTES_2_0 ++ else: ++ return {} ++ ++ ++class RouteTablePluginBase(object): ++ __metaclass__ = ABCMeta ++ ++ @abstractmethod ++ def create_route_table(self, context, route_table): ++ pass ++ ++ @abstractmethod ++ def delete_route_table(self, context, id): ++ pass ++ ++ @abstractmethod ++ def update_route_table(self, context, id, route_table): ++ pass ++ ++ @abstractmethod ++ def get_route_tables(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ pass ++ ++ @abstractmethod ++ def get_route_table(self, context, id, fields=None): ++ pass ++ ++ @abstractmethod ++ def create_nat_instance(self, context, nat_instance): ++ pass ++ ++ @abstractmethod ++ def delete_nat_instance(self, context, id): ++ pass ++ ++ @abstractmethod ++ def get_nat_instances(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ pass ++ ++ @abstractmethod ++ def get_nat_instance(self, context, id, fields=None): ++ pass +diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py +new file mode 100644 +index 0000000..01f37e2 +--- /dev/null ++++ neutron/plugins/juniper/contrail/contrailplugin.py +@@ -0,0 +1,600 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++import ctdb.config_db ++import httplib2 ++from oslo.config import cfg ++import re ++import string ++ ++from neutron.common import exceptions as exc ++from neutron.db import db_base_plugin_v2 ++from neutron.db import portbindings_base ++from neutron.extensions import l3 ++from neutron.extensions import securitygroup ++from neutron.extensions import portbindings ++from neutron.openstack.common import log as logging ++ ++ ++LOG = logging.getLogger(__name__) ++ ++vnc_opts = [ ++ cfg.StrOpt('api_server_ip', default='127.0.0.1'), ++ cfg.StrOpt('api_server_port', default='8082'), ++] ++ ++ ++def _read_cfg(multi_parser, section, option, default): ++ name_tuple = (section, option) ++ cfg_names = [] ++ cfg_names.append(name_tuple) ++ try: ++ val = multi_parser.get(names=cfg_names, multi=False) ++ except KeyError: ++ val = default ++ ++ return val ++ ++ ++class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, ++ l3.RouterPluginBase, ++ securitygroup.SecurityGroupPluginBase, ++ portbindings_base.PortBindingBaseMixin): ++ ++ # only floatingip part of router extension is supported. ++ supported_extension_aliases = ["ipam", "policy", "security-group", ++ "router", "route-table", "port-security", ++ "binding",] ++ __native_bulk_support = False ++ _cfgdb = None ++ _args = None ++ _tenant_id_dict = {} ++ _tenant_name_dict = {} ++ ++ @classmethod ++ def _parse_class_args(cls, multi_parser): ++ read_ok = multi_parser.read(cfg.CONF.config_file) ++ ++ if len(read_ok) != len(cfg.CONF.config_file): ++ raise cfg.Error("Some config files were not parsed properly") ++ ++ cls._multi_tenancy = _read_cfg(multi_parser, 'APISERVER', ++ 'multi_tenancy', False) ++ cls._max_retries = _read_cfg(multi_parser, 'APISERVER', ++ 'max_retries', -1) ++ cls._retry_interval = _read_cfg(multi_parser, 'APISERVER', ++ 'retry_interval', 3) ++ cls._admin_token = _read_cfg(multi_parser, 'KEYSTONE', ++ 'admin_token', '') ++ cls._auth_url = _read_cfg(multi_parser, 'KEYSTONE', 'auth_url', '') ++ cls._admin_user = _read_cfg(multi_parser, 'KEYSTONE', 'admin_user', ++ 'user1') ++ cls._admin_password = _read_cfg(multi_parser, 'KEYSTONE', ++ 'admin_password', 'password1') ++ cls._admin_tenant_name = _read_cfg(multi_parser, 'KEYSTONE', ++ 'admin_tenant_name', ++ 'default-domain') ++ cls._tenants_api = '%s/tenants' % (cls._auth_url) ++ ++ @classmethod ++ def _connect_to_db(cls): ++ """Connection to config db. ++ ++ Many instantiations of plugin (base + extensions) but need to have ++ only one config db conn (else error from ifmap-server) ++ """ ++ cls._cfgdb_map = {} ++ if cls._cfgdb is None: ++ sip = cfg.CONF.APISERVER.api_server_ip ++ sport = cfg.CONF.APISERVER.api_server_port ++ # Initialize connection to DB and add default entries ++ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, ++ cls._admin_password, ++ cls._admin_tenant_name, ++ sip, sport, ++ cls._max_retries, ++ cls._retry_interval) ++ cls._cfgdb.manager = cls ++ ++ @classmethod ++ def _get_user_cfgdb(cls, context): ++ if not cls._multi_tenancy: ++ return cls._cfgdb ++ user_id = context.user_id ++ role = string.join(context.roles, ",") ++ if user_id not in cls._cfgdb_map: ++ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( ++ cls._admin_user, cls._admin_password, cls._admin_tenant_name, ++ cfg.CONF.APISERVER.api_server_ip, ++ cfg.CONF.APISERVER.api_server_port, ++ cls._max_retries, cls._retry_interval, ++ user_info={'user_id': user_id, 'role': role}) ++ cls._cfgdb_map[user_id].manager = cls ++ ++ return cls._cfgdb_map[user_id] ++ ++ @classmethod ++ def _tenant_list_from_keystone(cls): ++ # get all tenants ++ hdrs = {'X-Auth-Token': cls._admin_token, ++ 'Content-Type': 'application/json'} ++ try: ++ rsp, content = httplib2.Http().request(cls._tenants_api, ++ method="GET", headers=hdrs) ++ if rsp.status != 200: ++ return ++ except Exception: ++ return ++ ++ # transform needed for python compatibility ++ content = re.sub('true', 'True', content) ++ content = re.sub('null', 'None', content) ++ content = eval(content) ++ ++ # bail if response is unexpected ++ if 'tenants' not in content: ++ return ++ ++ # create a dictionary for id->name and name->id mapping ++ for tenant in content['tenants']: ++ print 'Adding tenant %s:%s to cache' % (tenant['name'], ++ tenant['id']) ++ cls._tenant_id_dict[tenant['id']] = tenant['name'] ++ cls._tenant_name_dict[tenant['name']] = tenant['id'] ++ ++ def update_security_group(self, context, id, security_group): ++ pass ++ ++ def __init__(self): ++ cfg.CONF.register_opts(vnc_opts, 'APISERVER') ++ ++ multi_parser = cfg.MultiConfigParser() ++ ContrailPlugin._parse_class_args(multi_parser) ++ ++ ContrailPlugin._connect_to_db() ++ self._cfgdb = ContrailPlugin._cfgdb ++ ++ ContrailPlugin._tenant_list_from_keystone() ++ self.base_binding_dict = self._get_base_binding_dict() ++ portbindings_base.register_port_dict_function() ++ ++ def _get_base_binding_dict(self): ++ binding = { ++ portbindings.VIF_TYPE: portbindings.VIF_TYPE_VROUTER, ++ portbindings.CAPABILITIES: { ++ portbindings.CAP_PORT_FILTER: ++ 'security-group' in self.supported_extension_aliases}} ++ return binding ++ ++ # Network API handlers ++ def create_network(self, context, network): ++ """Creates a new Virtual Network, and assigns it a symbolic name.""" ++ cfgdb = self._get_user_cfgdb(context) ++ net_info = cfgdb.network_create(network['network']) ++ ++ # verify transformation is conforming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ LOG.debug(_("create_network(): %r"), net_dict) ++ return net_dict ++ ++ def get_network(self, context, id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ net_info = cfgdb.network_read(id, fields) ++ ++ # verify transformation is conforming to api ++ if not fields: ++ # should return all fields ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ fields, False) ++ else: ++ net_dict = net_info['q_api_data'] ++ ++ LOG.debug(_("get_network(): %r"), net_dict) ++ return self._fields(net_dict, fields) ++ ++ def update_network(self, context, net_id, network): ++ """Updates the attributes of a particular Virtual Network.""" ++ cfgdb = self._get_user_cfgdb(context) ++ net_info = cfgdb.network_update(net_id, network['network']) ++ ++ # verify transformation is confirming to api ++ net_dict = self._make_network_dict(net_info['q_api_data'], ++ None, False) ++ ++ LOG.debug(_("update_network(): %r"), net_dict) ++ return net_dict ++ ++ def delete_network(self, context, net_id): ++ """Network delete operation. ++ ++ Deletes the network with the specified network identifier ++ belonging to the specified tenant. ++ """ ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.network_delete(net_id) ++ LOG.debug(_("delete_network(): %r"), net_id) ++ ++ def get_networks(self, context, filters=None, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ nets_info = cfgdb.network_list(filters) ++ ++ nets_dicts = [] ++ for n_info in nets_info: ++ # verify transformation is conforming to api ++ n_dict = self._make_network_dict(n_info['q_api_data'], fields, ++ False) ++ ++ nets_dicts.append(n_dict) ++ ++ LOG.debug( ++ "get_networks(): filters: %r data: %r", filters, nets_dicts) ++ return nets_dicts ++ ++ def get_networks_count(self, context, filters=None): ++ cfgdb = self._get_user_cfgdb(context) ++ nets_count = cfgdb.network_count(filters) ++ LOG.debug(_("get_networks_count(): %r"), str(nets_count)) ++ return nets_count ++ ++ def create_subnet(self, context, subnet): ++ cfgdb = self._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_create(subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ LOG.debug(_("create_subnet(): %r"), subnet_dict) ++ return subnet_dict ++ ++ def get_subnet(self, context, subnet_id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_read(subnet_id) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], ++ fields) ++ ++ LOG.debug(_("get_subnet(): %r"), subnet_dict) ++ return self._fields(subnet_dict, fields) ++ ++ def update_subnet(self, context, subnet_id, subnet): ++ cfgdb = self._get_user_cfgdb(context) ++ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) ++ ++ # verify transformation is conforming to api ++ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) ++ ++ LOG.debug(_("update_subnet(): %r"), subnet_dict) ++ return subnet_dict ++ ++ def delete_subnet(self, context, subnet_id): ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.subnet_delete(subnet_id) ++ ++ LOG.debug(_("delete_subnet(): %r"), subnet_id) ++ ++ def get_subnets(self, context, filters=None, fields=None): ++ """Called from Neutron API -> get_.""" ++ cfgdb = self._get_user_cfgdb(context) ++ subnets_info = cfgdb.subnets_list(filters) ++ ++ subnets_dicts = [] ++ for sn_info in subnets_info: ++ # verify transformation is conforming to api ++ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) ++ ++ subnets_dicts.append(sn_dict) ++ ++ LOG.debug( ++ "get_subnets(): filters: %r data: %r", filters, subnets_dicts) ++ return subnets_dicts ++ ++ def get_subnets_count(self, context, filters=None): ++ cfgdb = self._get_user_cfgdb(context) ++ subnets_count = cfgdb.subnets_count(filters) ++ LOG.debug(_("get_subnets_count(): %r"), str(subnets_count)) ++ return subnets_count ++ ++ def _make_floatingip_dict(self, floatingip, fields=None): ++ res = {'id': floatingip['id'], ++ 'tenant_id': floatingip['tenant_id'], ++ 'floating_ip_address': floatingip['floating_ip_address'], ++ 'floating_network_id': floatingip['floating_network_id'], ++ 'router_id': floatingip['router_id'], ++ 'port_id': floatingip['fixed_port_id'], ++ 'fixed_ip_address': floatingip['fixed_ip_address']} ++ return self._fields(res, fields) ++ ++ def create_floatingip(self, context, floatingip): ++ cfgdb = self._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ LOG.debug(_("create_floatingip(): %r"), fip_dict) ++ return fip_dict ++ ++ def update_floatingip(self, context, fip_id, floatingip): ++ cfgdb = self._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_update(fip_id, ++ floatingip['floatingip']) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ LOG.debug(_("update_floatingip(): %r"), fip_dict) ++ return fip_dict ++ ++ def get_floatingip(self, context, id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ fip_info = cfgdb.floatingip_read(id) ++ ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ LOG.debug(_("get_floatingip(): %r"), fip_dict) ++ return fip_dict ++ ++ def delete_floatingip(self, context, fip_id): ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.floatingip_delete(fip_id) ++ LOG.debug(_("delete_floating(): %r"), fip_id) ++ ++ def get_floatingips(self, context, filters=None, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ fips_info = cfgdb.floatingip_list(filters) ++ ++ fips_dicts = [] ++ for fip_info in fips_info: ++ # verify transformation is conforming to api ++ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) ++ ++ fips_dicts.append(fip_dict) ++ ++ LOG.debug(_("get_floatingips(): %r"), fips_dicts) ++ return fips_dicts ++ ++ def get_floatingips_count(self, context, filters=None): ++ cfgdb = self._get_user_cfgdb(context) ++ floatingips_count = cfgdb.floatingip_count(filters) ++ LOG.debug(_("get_floatingips_count(): %r"), str(floatingips_count)) ++ return floatingips_count ++ ++ def create_port(self, context, port): ++ """Creates a port on the specified Virtual Network.""" ++ cfgdb = self._get_user_cfgdb(context) ++ port_info = cfgdb.port_create(port['port']) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_dict) ++ ++ LOG.debug(_("create_port(): %r"), port_dict) ++ return port_dict ++ ++ def get_port(self, context, port_id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ port_info = cfgdb.port_read(port_id) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ port_info, ++ port_dict) ++ ++ LOG.debug(_("get_port(): %r"), port_dict) ++ return self._fields(port_dict, fields) ++ ++ def update_port(self, context, port_id, port): ++ """Port update on a virtual network. ++ ++ Updates the attributes of a port on the specified Virtual Network. ++ """ ++ cfgdb = self._get_user_cfgdb(context) ++ port_info = cfgdb.port_update(port_id, port['port']) ++ self._process_portbindings_create_and_update(context, ++ port['port'], ++ port_info) ++ ++ # verify transformation is conforming to api ++ port_dict = self._make_port_dict(port_info['q_api_data']) ++ ++ LOG.debug(_("update_port(): %r"), port_dict) ++ return port_dict ++ ++ def delete_port(self, context, port_id): ++ """port delete on a virtual network. ++ ++ Deletes a port on a specified Virtual Network, ++ if the port contains a remote interface attachment, ++ the remote interface is first un-plugged and then the port ++ is deleted. ++ """ ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.port_delete(port_id) ++ LOG.debug(_("delete_port(): %r"), port_id) ++ ++ def get_ports(self, context, filters=None, fields=None): ++ """Get all port identifiers in the specified Virtual Network.""" ++ cfgdb = self._get_user_cfgdb(context) ++ ports_info = cfgdb.port_list(filters) ++ ++ ports_dicts = [] ++ for p_info in ports_info: ++ # verify transformation is conforming to api ++ p_dict = self._make_port_dict(p_info['q_api_data'], fields) ++ self._process_portbindings_create_and_update(context, ++ p_info, ++ p_dict) ++ ++ ports_dicts.append(p_dict) ++ ++ LOG.debug( ++ "get_ports(): filter: %r data: %r", filters, ports_dicts) ++ return ports_dicts ++ ++ def get_ports_count(self, context, filters=None): ++ cfgdb = self._get_user_cfgdb(context) ++ ports_count = cfgdb.port_count(filters) ++ LOG.debug(_("get_ports_count(): %r"), str(ports_count)) ++ return ports_count ++ ++ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): ++ """Plug in a remote interface. ++ ++ Attaches a remote interface to the specified port on the ++ specified Virtual Network. ++ """ ++ port = self._get_port(tenant_id, net_id, port_id) ++ # Validate attachment ++ self._validate_attachment(tenant_id, net_id, port_id, ++ remote_interface_id) ++ if port['interface_id']: ++ raise exc.PortInUse(net_id=net_id, port_id=port_id, ++ att_id=port['interface_id']) ++ ++ def unplug_interface(self, tenant_id, net_id, port_id): ++ """Unplug a remote interface. ++ ++ Detaches a remote interface from the specified port on the ++ specified Virtual Network. ++ """ ++ self._get_port(tenant_id, net_id, port_id) ++ ++ # Security Group handlers ++ def _make_security_group_rule_dict(self, security_group_rule, fields=None): ++ res = {'id': security_group_rule['id'], ++ 'tenant_id': security_group_rule['tenant_id'], ++ 'security_group_id': security_group_rule['security_group_id'], ++ 'ethertype': security_group_rule['ethertype'], ++ 'direction': security_group_rule['direction'], ++ 'protocol': security_group_rule['protocol'], ++ 'port_range_min': security_group_rule['port_range_min'], ++ 'port_range_max': security_group_rule['port_range_max'], ++ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], ++ 'remote_group_id': security_group_rule['remote_group_id']} ++ ++ return self._fields(res, fields) ++ ++ def _make_security_group_dict(self, security_group, fields=None): ++ res = {'id': security_group['id'], ++ 'name': security_group['name'], ++ 'tenant_id': security_group['tenant_id'], ++ 'description': security_group['description']} ++ res['security_group_rules'] = [self._make_security_group_rule_dict(r) ++ for r in security_group['rules']] ++ return self._fields(res, fields) ++ ++ def create_security_group(self, context, security_group): ++ cfgdb = self._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_create( ++ security_group['security_group']) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) ++ ++ LOG.debug(_("create_security_group(): %r"), sg_dict) ++ return sg_dict ++ ++ def delete_security_group(self, context, id): ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.security_group_delete(id) ++ LOG.debug(_("delete_security_group(): %r"), id) ++ ++ def get_security_groups(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ cfgdb = self._get_user_cfgdb(context) ++ security_groups_info = cfgdb.security_group_list(context, filters) ++ ++ security_groups_dicts = [] ++ for sg_info in security_groups_info: ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ security_groups_dicts.append(sg_dict) ++ ++ LOG.debug( ++ "get_security_groups(): filter: %r data: %r", ++ filters, security_groups_dicts) ++ return security_groups_dicts ++ ++ def get_security_group(self, context, id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ sg_info = cfgdb.security_group_read(id) ++ ++ # verify transformation is conforming to api ++ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], ++ fields) ++ ++ LOG.debug(_("get_security_group(): %r"), sg_dict) ++ return self._fields(sg_dict, fields) ++ ++ def create_security_group_rule(self, context, security_group_rule): ++ cfgdb = self._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_create( ++ security_group_rule['security_group_rule']) ++ ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict(sgr_info['q_api_data']) ++ ++ LOG.debug(_("create_security_group_rule(): %r"), sgr_dict) ++ return sgr_dict ++ ++ def delete_security_group_rule(self, context, id): ++ cfgdb = self._get_user_cfgdb(context) ++ cfgdb.security_group_rule_delete(id) ++ LOG.debug(_("delete_security_group_rule(): %r"), id) ++ ++ def get_security_group_rules(self, context, filters=None, fields=None, ++ sorts=None, limit=None, marker=None, ++ page_reverse=False): ++ cfgdb = self._get_user_cfgdb(context) ++ security_group_rules_info = cfgdb.security_group_rule_list(filters) ++ ++ security_group_rules_dicts = [] ++ for sgr_info in security_group_rules_info: ++ for sgr in sgr_info: ++ # verify transformation is conforming to api ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr['q_api_data'], fields) ++ security_group_rules_dicts.append(sgr_dict) ++ ++ LOG.debug( ++ "get_security_group_rules(): filter: %r data: %r ", ++ filters, security_group_rules_dicts) ++ return security_group_rules_dicts ++ ++ def get_security_group_rule(self, context, id, fields=None): ++ cfgdb = self._get_user_cfgdb(context) ++ sgr_info = cfgdb.security_group_rule_read(id) ++ ++ # verify transformation is conforming to api ++ sgr_dict = {} ++ if sgr_info != {}: ++ sgr_dict = self._make_security_group_rule_dict( ++ sgr_info['q_api_data'], fields) ++ ++ LOG.debug(_("get_security_group_rule(): %r"), sgr_dict) ++ return self._fields(sgr_dict, fields) +diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py +new file mode 100644 +index 0000000..7bc8217 +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/__init__.py +@@ -0,0 +1,17 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. +diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py +new file mode 100644 +index 0000000..efe281c +--- /dev/null ++++ neutron/plugins/juniper/contrail/ctdb/config_db.py +@@ -0,0 +1,1708 @@ ++# vim: tabstop=4 shiftwidth=4 softtabstop=4 ++# ++# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. ++ ++import json ++import netaddr ++import re ++import requests ++import socket ++import time ++import uuid ++ ++from cfgm_common import exceptions as vnc_exc ++from vnc_api import vnc_api ++ ++from neutron.api.v2 import attributes as attr ++from neutron.common import constants ++from neutron.common import exceptions ++from neutron.extensions import portbindings ++from neutron.openstack.common import log as logging ++ ++ ++LOG = logging.getLogger(__name__) ++ ++_DEFAULT_HEADERS = { ++ 'Content-type': 'application/json; charset="UTF-8"', } ++ ++CREATE = 1 ++READ = 2 ++UPDATE = 3 ++DELETE = 4 ++ ++ ++class DBInterface(object): ++ """An instance of this class forwards requests to vnc cfg api server""" ++ Q_URL_PREFIX = '/extensions/ct' ++ ++ def __init__(self, admin_name, admin_password, admin_tenant_name, ++ api_server_ip, api_server_port, max_retries, retry_interval, ++ user_info=None): ++ self._api_server_ip = api_server_ip ++ self._api_server_port = api_server_port ++ self._max_retries = max_retries ++ self._retry_interval = retry_interval ++ ++ self._db_cache = { ++ 'q_networks': {}, ++ 'q_subnets': {}, ++ 'q_subnet_maps': {}, ++ 'q_policies': {}, ++ 'q_ipams': {}, ++ 'q_floatingips': {}, ++ 'q_ports': {}, ++ 'q_fixed_ip_to_subnet': {}, ++ # obj-uuid to tenant-uuid mapping ++ 'q_obj_to_tenant': {}, ++ # port count per tenant-id ++ 'q_tenant_port_count': {}, ++ 'vnc_networks': {}, ++ 'vnc_ports': {}, ++ 'vnc_projects': {}, ++ 'vnc_instance_ips': {}, ++ } ++ ++ # Retry till a api-server is up or up to max_retries ++ connected = False ++ remaining = self._max_retries ++ if remaining == -1: ++ remaining = 'infinite' ++ msg = _('api-server connection failed. %s attempts left.') ++ ++ while not connected: ++ try: ++ self._vnc_lib = vnc_api.VncApi( ++ admin_name, admin_password, ++ admin_tenant_name, api_server_ip, ++ api_server_port, '/', user_info=user_info) ++ connected = True ++ except requests.exceptions.RequestException: ++ LOG.warn(msg % remaining) ++ if (remaining != 'infinite' and remaining == 0): ++ raise ++ if (remaining != 'infinite'): ++ remaining -= 1 ++ ++ time.sleep(self._retry_interval) ++ ++ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key ++ # eg. domain1:project1:net1 1.1.1.0/24 becomes 1.1.1.0/24 ++ subnet_map = self._vnc_lib.kv_retrieve(key=None) ++ for kv_dict in subnet_map: ++ key = kv_dict['key'] ++ if len(key.split()) == 1: ++ subnet_id = key ++ # uuid key, fixup value portion to 'net_id pfx/len' format ++ # if not already so ++ if len(kv_dict['value'].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ net_fq_name = kv_dict['value'].split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ LOG.warning(_("No network: %r"), net_fq_name) ++ self._vnc_lib.kv_delete(subnet_id) ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, ++ kv_dict['value'].split()[1]) ++ self._vnc_lib.kv_store(subnet_id, new_subnet_key) ++ else: # subnet key ++ if len(key.split()[0].split(':')) == 1: ++ # new format already, skip ++ continue ++ ++ # delete old key, convert to new key format and save ++ old_subnet_key = key ++ self._vnc_lib.kv_delete(old_subnet_key) ++ ++ subnet_id = kv_dict['value'] ++ net_fq_name = key.split()[0].split(':') ++ try: ++ net_obj = self._virtual_network_read(fq_name=net_fq_name) ++ except vnc_exc.NoIdError: ++ LOG.warning(_("No network: %r"), net_fq_name) ++ continue ++ ++ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) ++ self._vnc_lib.kv_store(new_subnet_key, subnet_id) ++ ++ def _request_api_server(self, url, method, data=None, headers=None): ++ return requests.request(method, url=url, data=data, headers=headers) ++ ++ def _relay_request(self, request): ++ """Send received request to api server""" ++ # chop neutron parts of url and add api server address ++ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) ++ url = "http://%s:%s%s" % (self._api_server_ip, self._api_server_port, ++ url_path) ++ ++ return self._request_api_server( ++ url, request.environ['REQUEST_METHOD'], ++ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) ++ ++ def _obj_to_dict(self, obj): ++ return self._vnc_lib.obj_to_dict(obj) ++ #end _obj_to_dict ++ ++ def _ensure_instance_exists(self, instance_id): ++ instance_name = instance_id ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ try: ++ id = self._vnc_lib.obj_to_id(instance_obj) ++ instance_obj = self._vnc_lib.virtual_machine_read(id=id) ++ except vnc_exc.NoIdError: # instance doesn't exist, create it ++ instance_obj.uuid = instance_id ++ self._vnc_lib.virtual_machine_create(instance_obj) ++ ++ return instance_obj ++ ++ def _ensure_default_security_group_exists(self, proj_id): ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ sg_groups = proj_obj.get_security_groups() ++ for sg_group in sg_groups or []: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) ++ if sg_obj.name == 'default': ++ return ++ ++ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) ++ self._vnc_lib.security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = { ++ 'port_range_min': 0, ++ 'port_range_max': 65535, ++ 'direction': 'egress', ++ 'remote_ip_prefix': None, ++ 'remote_group_id': None, ++ 'protocol': 'any', ++ } ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ #allow ingress traffic from within default security group ++ def_rule = { ++ 'port_range_min': 0, ++ 'port_range_max': 65535, ++ 'direction': 'ingress', ++ 'remote_ip_prefix': None, ++ 'remote_group_id': None, ++ 'protocol': 'any', ++ } ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_obj.uuid, rule) ++ ++ def _get_obj_tenant_id(self, q_type, obj_uuid): ++ # Get the mapping from cache, else seed cache and return ++ try: ++ return self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except KeyError: ++ # Seed the cache and return ++ if q_type == 'port': ++ port_obj = self._virtual_machine_interface_read(obj_uuid) ++ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] ++ # recurse up type-hierarchy ++ tenant_id = self._get_obj_tenant_id('network', net_id) ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ if q_type == 'network': ++ net_obj = self._virtual_network_read(net_id=obj_uuid) ++ tenant_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(obj_uuid, tenant_id) ++ return tenant_id ++ ++ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): ++ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid ++ ++ def _del_obj_tenant_id(self, obj_uuid): ++ try: ++ del self._db_cache['q_obj_to_tenant'][obj_uuid] ++ except Exception: ++ pass ++ ++ def _project_read(self, proj_id=None, fq_name=None): ++ if proj_id: ++ proj_obj = self._vnc_lib.project_read(id=proj_id) ++ fq_name_str = json.dumps(proj_obj.get_fq_name()) ++ self._db_cache['vnc_projects'][proj_id] = proj_obj ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ return proj_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) ++ self._db_cache['vnc_projects'][fq_name_str] = proj_obj ++ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj ++ return proj_obj ++ ++ def _security_group_rule_create(self, sg_id, sg_rule): ++ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) ++ rules = sg_vnc.get_security_group_entries() ++ if rules is None: ++ rules = vnc_api.PolicyEntriesType([sg_rule]) ++ else: ++ rules.add_policy_rule(sg_rule) ++ ++ sg_vnc.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_vnc) ++ ++ def _security_group_rule_find(self, sgr_id): ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ project_sgs = self._security_group_list_project(proj_id) ++ ++ for sg in project_sgs: ++ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) ++ sgr_entries = sg_obj.get_security_group_entries() ++ if sgr_entries is None: ++ continue ++ ++ for sg_rule in sgr_entries.get_policy_rule(): ++ if sg_rule.get_rule_uuid() == sgr_id: ++ return sg_obj, sg_rule ++ ++ return None, None ++ ++ def _security_group_rule_delete(self, sg_obj, sg_rule): ++ rules = sg_obj.get_security_group_entries() ++ rules.get_policy_rule().remove(sg_rule) ++ sg_obj.set_security_group_entries(rules) ++ self._vnc_lib.security_group_update(sg_obj) ++ ++ def _security_group_create(self, sg_obj): ++ sg_uuid = self._vnc_lib.security_group_create(sg_obj) ++ return sg_uuid ++ ++ def _security_group_delete(self, sg_id): ++ self._vnc_lib.security_group_delete(id=sg_id) ++ ++ def _virtual_network_create(self, net_obj): ++ net_uuid = self._vnc_lib.virtual_network_create(net_obj) ++ ++ return net_uuid ++ ++ def _virtual_network_read(self, net_id=None, fq_name=None): ++ if net_id: ++ net_obj = self._vnc_lib.virtual_network_read(id=net_id) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ self._db_cache['vnc_networks'][net_id] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ return net_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ return net_obj ++ ++ def _virtual_network_update(self, net_obj): ++ self._vnc_lib.virtual_network_update(net_obj) ++ # read back to get subnet gw allocated by api-server ++ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ ++ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj ++ self._db_cache['vnc_networks'][fq_name_str] = net_obj ++ ++ def _virtual_network_delete(self, net_id): ++ fq_name_str = None ++ try: ++ net_obj = self._db_cache['vnc_networks'][net_id] ++ fq_name_str = json.dumps(net_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_network_delete(id=net_id) ++ ++ try: ++ del self._db_cache['vnc_networks'][net_id] ++ if fq_name_str: ++ del self._db_cache['vnc_networks'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _virtual_machine_interface_create(self, port_obj): ++ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) ++ ++ return port_uuid ++ ++ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): ++ if port_id: ++ port_obj = self._vnc_lib.virtual_machine_interface_read(id=port_id) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ self._db_cache['vnc_ports'][port_id] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ return port_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ port_obj = self._vnc_lib.virtual_machine_interface_read( ++ fq_name=fq_name) ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ return port_obj ++ ++ def _virtual_machine_interface_update(self, port_obj): ++ self._vnc_lib.virtual_machine_interface_update(port_obj) ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ ++ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj ++ self._db_cache['vnc_ports'][fq_name_str] = port_obj ++ ++ def _virtual_machine_interface_delete(self, port_id): ++ fq_name_str = None ++ try: ++ port_obj = self._db_cache['vnc_ports'][port_id] ++ fq_name_str = json.dumps(port_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.virtual_machine_interface_delete(id=port_id) ++ ++ try: ++ del self._db_cache['vnc_ports'][port_id] ++ if fq_name_str: ++ del self._db_cache['vnc_ports'][fq_name_str] ++ except KeyError: ++ pass ++ ++ def _instance_ip_create(self, iip_obj): ++ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) ++ ++ return iip_uuid ++ ++ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): ++ if instance_ip_id: ++ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ return iip_obj ++ ++ if fq_name: ++ fq_name_str = json.dumps(fq_name) ++ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ return iip_obj ++ ++ def _instance_ip_update(self, iip_obj): ++ self._vnc_lib.instance_ip_update(iip_obj) ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ ++ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj ++ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj ++ ++ def _instance_ip_delete(self, instance_ip_id): ++ fq_name_str = None ++ try: ++ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] ++ fq_name_str = json.dumps(iip_obj.get_fq_name()) ++ except KeyError: ++ pass ++ ++ self._vnc_lib.instance_ip_delete(id=instance_ip_id) ++ ++ try: ++ del self._db_cache['vnc_instance_ips'][instance_ip_id] ++ if fq_name_str: ++ del self._db_cache['vnc_instance_ips'][fq_name_str] ++ except KeyError: ++ pass ++ ++ # find projects on a given domain ++ def _project_list_domain(self, domain_id): ++ fq_name = ['default-domain'] ++ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) ++ ++ return resp_dict['projects'] ++ ++ # find network ids on a given project ++ def _network_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ LOG.warning(_("Error in converting uuid: %r"), project_id) ++ ++ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) ++ ++ return resp_dict['virtual-networks'] ++ ++ def _security_group_list_project(self, project_id): ++ try: ++ project_uuid = str(uuid.UUID(project_id)) ++ except Exception: ++ LOG.warning(_("Error in converting uuid: %r"), project_id) ++ ++ self._ensure_default_security_group_exists(project_uuid) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ def _security_group_entries_list_sg(self, sg_id): ++ try: ++ sg_uuid = str(uuid.UUID(sg_id)) ++ except Exception: ++ LOG.warning(_("Error in converting SG uuid: %r"), sg_id) ++ ++ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) ++ ++ return resp_dict['security-groups'] ++ ++ # find floating ip pools a project has access to ++ def _fip_pool_refs_project(self, project_id): ++ project_uuid = str(uuid.UUID(project_id)) ++ project_obj = self._project_read(proj_id=project_uuid) ++ ++ return project_obj.get_floating_ip_pool_refs() ++ ++ # find networks of floating ip pools project has access to ++ def _fip_pool_ref_networks(self, project_id): ++ ret_nets = [] ++ ++ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) ++ if not proj_fip_pool_refs: ++ return ret_nets ++ ++ for fip_pool_ref in proj_fip_pool_refs: ++ fip_uuid = fip_pool_ref['uuid'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) ++ net_uuid = fip_pool_obj.parent_uuid ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ ret_nets.append({'uuid': net_obj.uuid, ++ 'fq_name': net_obj.get_fq_name()}) ++ ++ return ret_nets ++ ++ # find floating ip pools defined by network ++ def _fip_pool_list_network(self, net_id): ++ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) ++ ++ return resp_dict['floating-ip-pools'] ++ ++ # find port ids on a given network ++ def _port_list_network(self, network_id): ++ ret_list = [] ++ ++ try: ++ net_obj = self._virtual_network_read(net_id=network_id) ++ except vnc_exc.NoIdError: ++ return ret_list ++ ++ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() ++ if port_back_refs: ++ ret_list = [{'id': port_back_ref['uuid']} ++ for port_back_ref in port_back_refs] ++ ++ return ret_list ++ ++ # find port ids on a given project ++ def _port_list_project(self, project_id): ++ ret_list = [] ++ project_nets = self._network_list_project(project_id) ++ for net in project_nets: ++ net_ports = self._port_list_network(net['uuid']) ++ ret_list.extend(net_ports) ++ ++ return ret_list ++ ++ def _filters_is_present(self, filters, key_name, match_value): ++ """Check if filters present or not. ++ ++ Returns True if no filter is specified ++ OR search-param is not present in filters ++ OR (search-param is present in filters AND ++ resource matches param-list AND ++ shared parameter in filters is False) ++ """ ++ if filters: ++ if key_name in filters: ++ try: ++ filters[key_name].index(match_value) ++ if ('shared' in filters and filters['shared'][0]): ++ # yuck, q-api has shared as list always of 1 elem ++ return False # no shared-resource support ++ except ValueError: # not in requested list ++ return False ++ elif len(filters.keys()) == 1: ++ shared_val = filters.get('shared') ++ if shared_val and shared_val[0]: ++ return False ++ ++ return True ++ ++ def _network_read(self, net_uuid): ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ return net_obj ++ ++ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): ++ self._vnc_lib.kv_store(subnet_id, subnet_key) ++ self._vnc_lib.kv_store(subnet_key, subnet_id) ++ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key ++ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id ++ ++ def _subnet_vnc_read_mapping(self, id=None, key=None): ++ if id: ++ try: ++ return self._db_cache['q_subnet_maps'][id] ++ except KeyError: ++ subnet_key = self._vnc_lib.kv_retrieve(id) ++ self._db_cache['q_subnet_maps'][id] = subnet_key ++ return subnet_key ++ if key: ++ try: ++ return self._db_cache['q_subnet_maps'][key] ++ except KeyError: ++ subnet_id = self._vnc_lib.kv_retrieve(key) ++ self._db_cache['q_subnet_maps'][key] = subnet_id ++ return subnet_id ++ ++ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): ++ if id: ++ return self._subnet_vnc_read_mapping(id=id) ++ ++ # if subnet was created outside of neutron handle it and create ++ # neutron representation now (lazily) ++ try: ++ return self._subnet_vnc_read_mapping(key=key) ++ except vnc_exc.NoIdError: ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, key) ++ return self._subnet_vnc_read_mapping(key=key) ++ ++ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): ++ self._vnc_lib.kv_delete(subnet_id) ++ self._vnc_lib.kv_delete(subnet_key) ++ try: ++ del self._db_cache['q_subnet_maps'][subnet_id] ++ except KeyError: ++ pass ++ try: ++ del self._db_cache['q_subnet_maps'][subnet_key] ++ except KeyError: ++ pass ++ ++ def _subnet_vnc_get_key(self, subnet_vnc, net_id): ++ pfx = subnet_vnc.subnet.get_ip_prefix() ++ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() ++ ++ return '%s %s/%s' % (net_id, pfx, pfx_len) ++ ++ def _subnet_read(self, net_uuid, subnet_key): ++ try: ++ net_obj = self._virtual_network_read(net_id=net_uuid) ++ except vnc_exc.NoIdError: ++ return ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if not ipam_refs: ++ return ++ ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_uuid) == subnet_key: ++ return subnet_vnc ++ ++ return ++ ++ def _ip_address_to_subnet_id(self, ip_addr, net_obj): ++ # find subnet-id for ip-addr, called when instance-ip created ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ if netaddr.IPAddress(ip_addr) in netaddr.IPSet([cidr]): ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, ++ net_obj.uuid) ++ subnet_id = self._subnet_vnc_read_mapping( ++ key=subnet_key) ++ return subnet_id ++ ++ def _security_group_vnc_to_neutron(self, sg_obj): ++ sg_q_dict = self._obj_to_dict(sg_obj) ++ ++ # replace field names ++ sg_q_dict['id'] = sg_obj.uuid ++ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sg_q_dict['name'] = sg_obj.name ++ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() ++ ++ # get security group rules ++ sg_q_dict['rules'] = [] ++ rule_list = self.security_group_rules_read(sg_obj.uuid) ++ if rule_list: ++ sg_q_dict['rules'] = [rule['q_api_data'] ++ for rule in rule_list] ++ ++ return {'q_api_data': sg_q_dict} ++ ++ def _security_group_neutron_to_vnc(self, sg_q, operator): ++ if operator == CREATE: ++ project_id = str(uuid.UUID(sg_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType( ++ enable=True, description=sg_q['description']) ++ sg_vnc = vnc_api.SecurityGroup( ++ name=sg_q['name'], parent_obj=project_obj, ++ id_perms=id_perms) ++ ++ return sg_vnc ++ ++ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): ++ sgr_q_dict = {} ++ if sg_id is None: ++ return {'q_api_data': sgr_q_dict} ++ ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ direction = 'egress' ++ if sg_rule.get_direction() == '<': ++ direction = 'ingress' ++ ++ remote_cidr = '' ++ remote_sg_uuid = '' ++ if direction == 'ingress': ++ addr = sg_rule.get_src_addresses()[0] ++ else: ++ addr = sg_rule.get_dst_addresses()[0] ++ ++ if addr.get_subnet(): ++ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), ++ addr.get_subnet().get_ip_prefix_len()) ++ elif addr.get_security_group(): ++ if (addr.get_security_group() != 'any') and \ ++ (addr.get_security_group() != 'local'): ++ remote_sg = addr.get_security_group() ++ try: ++ remote_sg_obj = self._vnc_lib.security_group_read( ++ fq_name_str=remote_sg) ++ remote_sg_uuid = remote_sg_obj.uuid ++ except vnc_exc.NoIdError: ++ pass ++ ++ sgr_q_dict['id'] = sg_rule.get_rule_uuid() ++ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') ++ sgr_q_dict['security_group_id'] = sg_obj.uuid ++ sgr_q_dict['ethertype'] = 'IPv4' ++ sgr_q_dict['direction'] = direction ++ sgr_q_dict['protocol'] = sg_rule.get_protocol() ++ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ ++ get_start_port() ++ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ ++ get_end_port() ++ sgr_q_dict['remote_ip_prefix'] = remote_cidr ++ sgr_q_dict['remote_group_id'] = remote_sg_uuid ++ ++ return {'q_api_data': sgr_q_dict} ++ ++ def _security_group_rule_neutron_to_vnc(self, sgr_q, operator): ++ if operator == CREATE: ++ port_min = 0 ++ port_max = 65535 ++ if sgr_q['port_range_min']: ++ port_min = sgr_q['port_range_min'] ++ if sgr_q['port_range_max']: ++ port_max = sgr_q['port_range_max'] ++ ++ endpt = [vnc_api.AddressType(security_group='any')] ++ if sgr_q['remote_ip_prefix']: ++ cidr = sgr_q['remote_ip_prefix'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ endpt = [vnc_api.AddressType( ++ subnet=vnc_api.SubnetType(pfx, pfx_len))] ++ elif sgr_q['remote_group_id']: ++ sg_obj = self._vnc_lib.security_group_read( ++ id=sgr_q['remote_group_id']) ++ endpt = [vnc_api.AddressType( ++ security_group=sg_obj.get_fq_name_str())] ++ ++ if sgr_q['direction'] == 'ingress': ++ dir = '<' ++ local = endpt ++ remote = [vnc_api.AddressType(security_group='local')] ++ else: ++ dir = '>' ++ remote = endpt ++ local = [vnc_api.AddressType(security_group='local')] ++ ++ if not sgr_q['protocol']: ++ sgr_q['protocol'] = 'any' ++ ++ sgr_uuid = str(uuid.uuid4()) ++ ++ rule = vnc_api.PolicyRuleType( ++ rule_uuid=sgr_uuid, ++ direction=dir, ++ protocol=sgr_q['protocol'], ++ src_addresses=local, ++ src_ports=[vnc_api.PortType(0, 65535)], ++ dst_addresses=remote, ++ dst_ports=[vnc_api.PortType(port_min, port_max)]) ++ return rule ++ ++ def _network_neutron_to_vnc(self, network_q, operator): ++ net_name = network_q.get('name', None) ++ if operator == CREATE: ++ project_id = str(uuid.UUID(network_q['tenant_id'])) ++ project_obj = self._project_read(proj_id=project_id) ++ id_perms = vnc_api.IdPermsType(enable=True) ++ net_obj = vnc_api.VirtualNetwork( ++ net_name, project_obj, id_perms=id_perms) ++ else: # READ/UPDATE/DELETE ++ net_obj = self._virtual_network_read(net_id=network_q['id']) ++ ++ id_perms = net_obj.get_id_perms() ++ if 'admin_state_up' in network_q: ++ id_perms.enable = network_q['admin_state_up'] ++ net_obj.set_id_perms(id_perms) ++ ++ if 'contrail:policys' in network_q: ++ policy_fq_names = network_q['contrail:policys'] ++ # reset and add with newly specified list ++ net_obj.set_network_policy_list([], []) ++ seq = 0 ++ for p_fq_name in policy_fq_names: ++ domain_name, project_name, policy_name = p_fq_name ++ ++ domain_obj = vnc_api.Domain(domain_name) ++ project_obj = vnc_api.Project(project_name, domain_obj) ++ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) ++ ++ net_obj.add_network_policy( ++ policy_obj, ++ vnc_api.VirtualNetworkPolicyType( ++ sequence=vnc_api.SequenceType(seq, 0))) ++ seq = seq + 1 ++ ++ if 'vpc:route_table' in network_q: ++ rt_fq_name = network_q['vpc:route_table'] ++ if rt_fq_name: ++ try: ++ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) ++ net_obj.set_route_table(rt_obj) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) ++ ++ return net_obj ++ ++ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): ++ net_q_dict = {} ++ ++ net_q_dict['id'] = net_obj.uuid ++ net_q_dict['name'] = net_obj.name ++ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') ++ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable ++ net_q_dict['shared'] = False ++ net_q_dict['status'] = constants.NET_STATUS_ACTIVE ++ ++ ipam_refs = net_obj.get_network_ipam_refs() ++ net_q_dict['subnets'] = [] ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnets = ipam_ref['attr'].get_ipam_subnets() ++ for subnet in subnets: ++ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, ++ ipam_ref['to']) ++ sn_dict = sn_info['q_api_data'] ++ net_q_dict['subnets'].append(sn_dict) ++ sn_ipam = {} ++ sn_ipam['subnet_cidr'] = sn_dict['cidr'] ++ sn_ipam['ipam_fq_name'] = ipam_ref['to'] ++ ++ return {'q_api_data': net_q_dict} ++ ++ def _subnet_neutron_to_vnc(self, subnet_q): ++ cidr = subnet_q['cidr'].split('/') ++ pfx = cidr[0] ++ pfx_len = int(cidr[1]) ++ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: ++ default_gw = subnet_q['gateway_ip'] ++ else: ++ # Assigned by address manager ++ default_gw = None ++ sub_net = vnc_api.SubnetType(ip_prefix=pfx, ++ ip_prefix_len=pfx_len) ++ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, ++ default_gateway=default_gw) ++ return subnet_vnc ++ ++ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): ++ sn_q_dict = { ++ 'name': '', ++ 'tenant_id': net_obj.parent_uuid.replace('-', ''), ++ 'network_id': net_obj.uuid, ++ 'ip_version': 4, ++ } ++ ++ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), ++ subnet_vnc.subnet.get_ip_prefix_len()) ++ sn_q_dict['cidr'] = cidr ++ ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) ++ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) ++ ++ sn_q_dict['id'] = sn_id ++ ++ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway ++ ++ first_ip = str(netaddr.IPNetwork(cidr).network + 1) ++ last_ip = str(netaddr.IPNetwork(cidr).broadcast - 2) ++ sn_q_dict['allocation_pools'] = [{'id': 'TODO-allocation_pools-id', ++ 'subnet_id': sn_id, ++ 'first_ip': first_ip, ++ 'last_ip': last_ip, ++ 'available_ranges': {}}] ++ ++ sn_q_dict['enable_dhcp'] = False ++ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['routes'] = [{'destination': 'TODO-destination', ++ 'nexthop': 'TODO-nexthop', ++ 'subnet_id': sn_id}] ++ ++ sn_q_dict['shared'] = False ++ ++ return {'q_api_data': sn_q_dict} ++ ++ def _floatingip_neutron_to_vnc(self, fip_q, operator): ++ if operator == CREATE: ++ # use first available pool on net ++ net_id = fip_q['floating_network_id'] ++ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) ++ fip_name = str(uuid.uuid4()) ++ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) ++ fip_obj.uuid = fip_name ++ ++ proj_id = str(uuid.UUID(fip_q['tenant_id'])) ++ proj_obj = self._project_read(proj_id=proj_id) ++ fip_obj.set_project(proj_obj) ++ else: # READ/UPDATE/DELETE ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) ++ ++ if fip_q['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=fip_q['port_id']) ++ fip_obj.set_virtual_machine_interface(port_obj) ++ else: ++ fip_obj.set_virtual_machine_interface_list([]) ++ ++ return fip_obj ++ ++ def _floatingip_vnc_to_neutron(self, fip_obj): ++ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( ++ id=fip_obj.parent_uuid) ++ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) ++ ++ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') ++ ++ port_id = None ++ port_refs = fip_obj.get_virtual_machine_interface_refs() ++ if port_refs: ++ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] ++ ++ fip_q_dict = { ++ 'id': fip_obj.uuid, ++ 'tenant_id': tenant_id, ++ 'floating_ip_address': fip_obj.get_floating_ip_address(), ++ 'floating_network_id': net_obj.uuid, ++ 'router_id': None, ++ 'fixed_port_id': port_id, ++ 'fixed_ip_address': None, ++ } ++ ++ return {'q_api_data': fip_q_dict} ++ ++ def _port_neutron_to_vnc(self, port_q, net_obj, operator): ++ # if name not passed in use name = uuid = ++ if 'name' in port_q and port_q['name'] != '': ++ port_name = port_q['name'] ++ port_uuid = None ++ else: ++ port_name = str(uuid.uuid4()) ++ port_uuid = port_name ++ ++ if operator == CREATE: ++ instance_name = port_q['device_id'] ++ instance_obj = vnc_api.VirtualMachine(instance_name) ++ ++ id_perms = vnc_api.IdPermsType(enable=True) ++ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, ++ id_perms=id_perms) ++ port_obj.uuid = port_uuid ++ port_obj.set_virtual_network(net_obj) ++ ++ else: # READ/UPDATE/DELETE ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_q['id']) ++ ++ port_obj.set_security_group_list([]) ++ if ('security_groups' in port_q and ++ port_q['security_groups'].__class__ is not object): ++ for sg_id in port_q['security_groups']: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ port_obj.add_security_group(sg_obj) ++ ++ id_perms = port_obj.get_id_perms() ++ if 'admin_state_up' in port_q: ++ id_perms.enable = port_q['admin_state_up'] ++ port_obj.set_id_perms(id_perms) ++ ++ return port_obj ++ ++ def _port_vnc_to_neutron(self, port_obj, net_obj=None): ++ port_q_dict = {} ++ port_q_dict['name'] = port_obj.name ++ port_q_dict['id'] = port_obj.uuid ++ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_VROUTER ++ ++ if not net_obj: ++ net_refs = port_obj.get_virtual_network_refs() ++ if net_refs: ++ net_id = net_refs[0]['uuid'] ++ else: ++ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) ++ ++ proj_id = None ++ # not in cache, get by reading VN obj, and populate cache ++ net_obj = self._virtual_network_read(net_id=net_id) ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ self._set_obj_tenant_id(port_obj.uuid, proj_id) ++ else: ++ net_id = net_obj.uuid ++ proj_id = net_obj.parent_uuid.replace('-', '') ++ ++ port_q_dict['tenant_id'] = proj_id ++ port_q_dict['network_id'] = net_id ++ ++ port_q_dict['mac_address'] = '' ++ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() ++ if mac_refs: ++ port_q_dict['mac_address'] = mac_refs.mac_address[0] ++ ++ port_q_dict['fixed_ips'] = [] ++ ip_back_refs = port_obj.get_instance_ip_back_refs() ++ if ip_back_refs: ++ for ip_back_ref in ip_back_refs: ++ try: ++ ip_obj = self._instance_ip_read( ++ instance_ip_id=ip_back_ref['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ++ ip_addr = ip_obj.get_instance_ip_address() ++ ++ ip_q_dict = {} ++ ip_q_dict['port_id'] = port_obj.uuid ++ ip_q_dict['ip_address'] = ip_addr ++ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, ++ net_obj) ++ ip_q_dict['net_id'] = net_id ++ ++ port_q_dict['fixed_ips'].append(ip_q_dict) ++ ++ sg_dict = {'port_security_enabled': True} ++ sg_dict['security_groups'] = [] ++ sg_refs = port_obj.get_security_group_refs() ++ for sg_ref in sg_refs or []: ++ sg_dict['security_groups'].append(sg_ref['uuid']) ++ ++ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable ++ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE ++ port_q_dict['device_id'] = port_obj.parent_name ++ port_q_dict['device_owner'] = 'TODO-device-owner' ++ ++ return {'q_api_data': port_q_dict} ++ ++ def network_create(self, network_q): ++ net_obj = self._network_neutron_to_vnc(network_q, CREATE) ++ net_uuid = self._virtual_network_create(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_uuid] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_read(self, net_uuid, fields=None): ++ # see if we can return fast... ++ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': ++ tenant_id = self._get_obj_tenant_id('network', net_uuid) ++ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} ++ ++ try: ++ net_obj = self._network_read(net_uuid) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=net_uuid) ++ ++ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ ++ def network_update(self, net_id, network_q): ++ network_q['id'] = net_id ++ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) ++ self._virtual_network_update(net_obj) ++ ++ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') ++ self._db_cache['q_networks'][net_id] = ret_network_q ++ ++ return ret_network_q ++ ++ def network_delete(self, net_id): ++ self._virtual_network_delete(net_id=net_id) ++ try: ++ del self._db_cache['q_networks'][net_id] ++ except KeyError: ++ pass ++ ++ def network_list(self, filters=None): ++ ret_list = [] ++ ++ if filters and 'shared' in filters: ++ if filters['shared'][0]: ++ # no support for shared networks ++ return ret_list ++ ++ # collect phase ++ all_nets = [] # all networks in all projects ++ if filters and 'tenant_id' in filters: ++ # project-id is present ++ if 'id' in filters: ++ # required networks are also specified, ++ # just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in project, and prune below ++ project_ids = filters['tenant_id'] ++ for p_id in project_ids: ++ if 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(p_id)) ++ else: ++ project_nets = self._network_list_project(p_id) ++ all_nets.append(project_nets) ++ elif filters and 'id' in filters: ++ # required networks are specified, just read and populate ret_list ++ # prune is skipped because all_nets is empty ++ for net_id in filters['id']: ++ net_obj = self._network_read(net_id) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ ret_list.append(net_info) ++ else: ++ # read all networks in all projects ++ dom_projects = self._project_list_domain(None) ++ for project in dom_projects: ++ proj_id = project['uuid'] ++ if filters and 'router:external' in filters: ++ all_nets.append(self._fip_pool_ref_networks(proj_id)) ++ else: ++ project_nets = self._network_list_project(proj_id) ++ all_nets.append(project_nets) ++ ++ # prune phase ++ for project_nets in all_nets: ++ for proj_net in project_nets: ++ proj_net_id = proj_net['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_net_id): ++ continue ++ ++ proj_net_fq_name = unicode(proj_net['fq_name']) ++ if not self._filters_is_present(filters, 'contrail:fq_name', ++ proj_net_fq_name): ++ continue ++ ++ try: ++ net_obj = self._network_read(proj_net['uuid']) ++ net_info = self._network_vnc_to_neutron(net_obj, ++ net_repr='LIST') ++ except vnc_exc.NoIdError: ++ continue ++ ret_list.append(net_info) ++ ++ return ret_list ++ ++ def network_count(self, filters=None): ++ nets_info = self.network_list(filters) ++ return len(nets_info) ++ ++ def subnet_create(self, subnet_q): ++ net_id = subnet_q['network_id'] ++ net_obj = self._virtual_network_read(net_id=net_id) ++ ++ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] ++ if ipam_fq_name != '': ++ domain_name, project_name, ipam_name = ipam_fq_name ++ ++ project_obj = vnc_api.Project(project_name) ++ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) ++ else: # link subnet with default ipam ++ project_obj = vnc_api.Project(net_obj.parent_name) ++ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) ++ ipam_fq_name = netipam_obj.get_fq_name() ++ ++ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) ++ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) ++ ++ # Locate list of subnets to which this subnet has to be appended ++ net_ipam_ref = None ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ if ipam_ref['to'] == ipam_fq_name: ++ net_ipam_ref = ipam_ref ++ break ++ ++ if not net_ipam_ref: ++ # First link from net to this ipam ++ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) ++ net_obj.add_network_ipam(netipam_obj, vnsn_data) ++ else: # virtual-network already linked to this ipam ++ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): ++ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): ++ # duplicate !! ++ subnet_info = self._subnet_vnc_to_neutron(subnet, ++ net_obj, ++ ipam_fq_name) ++ return subnet_info ++ vnsn_data = net_ipam_ref['attr'] ++ vnsn_data.ipam_subnets.append(subnet_vnc) ++ ++ self._virtual_network_update(net_obj) ++ ++ # allocate an id to the subnet and store mapping with ++ # api-server ++ subnet_id = str(uuid.uuid4()) ++ self._subnet_vnc_create_mapping(subnet_id, subnet_key) ++ ++ # Read in subnet from server to get updated values for gw etc. ++ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) ++ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, ++ ipam_fq_name) ++ ++ #self._db_cache['q_subnets'][subnet_id] = subnet_info ++ ++ return subnet_info ++ ++ def subnet_read(self, subnet_id): ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ if self._subnet_vnc_get_key(subnet_vnc, ++ net_id) == subnet_key: ++ ret_subnet_q = self._subnet_vnc_to_neutron( ++ subnet_vnc, net_obj, ipam_ref['to']) ++ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q ++ return ret_subnet_q ++ ++ return {} ++ ++ def subnet_update(self, subnet_id, subnet_q): ++ ret_subnet_q = self.subnet_read(subnet_id) ++ if 'name' in subnet_q: ++ ret_subnet_q['q_api_data']['name'] = subnet_q['name'] ++ return ret_subnet_q ++ ++ def subnet_delete(self, subnet_id): ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ orig_subnets = ipam_ref['attr'].get_ipam_subnets() ++ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets ++ if self._subnet_vnc_get_key(subnet_vnc, net_id) ++ != subnet_key] ++ if len(orig_subnets) != len(new_subnets): ++ # matched subnet to be deleted ++ ipam_ref['attr'].set_ipam_subnets(new_subnets) ++ self._virtual_network_update(net_obj) ++ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) ++ try: ++ del self._db_cache['q_subnets'][subnet_id] ++ except KeyError: ++ pass ++ ++ def subnets_list(self, filters=None): ++ ret_subnets = [] ++ ++ if filters and 'id' in filters: ++ # required subnets are specified, ++ # just read in corresponding net_ids ++ net_ids = set([]) ++ for subnet_id in filters['id']: ++ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) ++ net_id = subnet_key.split()[0] ++ net_ids.add(net_id) ++ else: ++ nets_info = self.network_list() ++ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] ++ ++ for net_id in net_ids: ++ net_obj = self._network_read(net_id) ++ ipam_refs = net_obj.get_network_ipam_refs() ++ if ipam_refs: ++ for ipam_ref in ipam_refs: ++ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() ++ for subnet_vnc in subnet_vncs: ++ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, ++ net_obj, ++ ipam_ref['to']) ++ sn_id = sn_info['q_api_data']['id'] ++ sn_proj_id = sn_info['q_api_data']['tenant_id'] ++ sn_net_id = sn_info['q_api_data']['network_id'] ++ ++ if filters: ++ if not self._filters_is_present(filters, 'id', ++ sn_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'tenant_id', ++ sn_proj_id): ++ continue ++ if not self._filters_is_present(filters, ++ 'network_id', ++ sn_net_id): ++ continue ++ ++ ret_subnets.append(sn_info) ++ ++ return ret_subnets ++ ++ def subnets_count(self, filters=None): ++ subnets_info = self.subnets_list(filters) ++ return len(subnets_info) ++ ++ # floatingip api handlers ++ def floatingip_create(self, fip_q): ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) ++ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_read(self, fip_uuid): ++ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_update(self, fip_id, fip_q): ++ fip_q['id'] = fip_id ++ fip_obj = self._floatingip_neutron_to_vnc(fip_q, UPDATE) ++ self._vnc_lib.floating_ip_update(fip_obj) ++ ++ return self._floatingip_vnc_to_neutron(fip_obj) ++ ++ def floatingip_delete(self, fip_id): ++ self._vnc_lib.floating_ip_delete(id=fip_id) ++ ++ def floatingip_list(self, filters=None): ++ # Find networks, get floatingip backrefs and return ++ ret_list = [] ++ ++ if filters: ++ if 'tenant_id' in filters: ++ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] ++ elif 'port_id' in filters: ++ # required ports are specified, just read and populate ret_list ++ # prune is skipped because proj_objs is empty ++ proj_ids = [] ++ for port_id in filters['port_id']: ++ port_obj = self._virtual_machine_interface_read( ++ port_id=port_id) ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron( ++ fip_obj)) ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ proj_ids = [proj['uuid'] for proj in dom_projects] ++ ++ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] ++ ++ for proj_obj in proj_objs: ++ fip_back_refs = proj_obj.get_floating_ip_back_refs() ++ if not fip_back_refs: ++ continue ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) ++ ++ return ret_list ++ ++ def floatingip_count(self, filters=None): ++ floatingip_info = self.floatingip_list(filters) ++ return len(floatingip_info) ++ ++ # port api handlers ++ def port_create(self, port_q): ++ net_id = port_q['network_id'] ++ net_obj = self._network_read(net_id) ++ proj_id = net_obj.parent_uuid ++ ++ self._ensure_instance_exists(port_q['device_id']) ++ ++ # initialize port object ++ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) ++ ++ # if ip address passed then use it ++ ip_addr = None ++ ip_obj = None ++ if port_q['fixed_ips'].__class__ is not object: ++ ip_addr = port_q['fixed_ips'][0]['ip_address'] ++ ip_name = '%s %s' % (net_id, ip_addr) ++ try: ++ ip_obj = self._instance_ip_read(fq_name=[ip_name]) ++ #ip_id = ip_obj.uuid ++ except Exception as e: ++ ip_obj = None ++ ++ # create the object ++ port_id = self._virtual_machine_interface_create(port_obj) ++ ++ # initialize ip object ++ if ip_obj is None: ++ # Allocate an IP address only if there is a defined subnet ++ if net_obj.get_network_ipam_refs(): ++ ip_name = str(uuid.uuid4()) ++ ip_obj = vnc_api.InstanceIp(name=ip_name) ++ ip_obj.uuid = ip_name ++ ip_obj.set_virtual_machine_interface(port_obj) ++ ip_obj.set_virtual_network(net_obj) ++ if ip_addr: ++ ip_obj.set_instance_ip_address(ip_addr) ++ try: ++ self._instance_ip_create(ip_obj) ++ except Exception as e: ++ # ResourceExhaustionError, resources are not available ++ self._virtual_machine_interface_delete(port_id=port_id) ++ raise e ++ # shared ip address ++ else: ++ if ip_addr == ip_obj.get_instance_ip_address(): ++ ip_obj.add_virtual_machine_interface(port_obj) ++ self._instance_ip_update(ip_obj) ++ ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) ++ #self._db_cache['q_ports'][port_id] = ret_port_q ++ self._set_obj_tenant_id(port_id, proj_id) ++ ++ # update cache on successful creation ++ tenant_id = proj_id.replace('-', '') ++ if tenant_id not in self._db_cache['q_tenant_port_count']: ++ ncurports = self.port_count({'tenant_id': tenant_id}) ++ else: ++ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] ++ ++ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 ++ ++ return ret_port_q ++ ++ def port_read(self, port_id): ++ port_obj = self._virtual_machine_interface_read(port_id=port_id) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_update(self, port_id, port_q): ++ port_q['id'] = port_id ++ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) ++ self._virtual_machine_interface_update(port_obj) ++ ++ ret_port_q = self._port_vnc_to_neutron(port_obj) ++ self._db_cache['q_ports'][port_id] = ret_port_q ++ ++ return ret_port_q ++ ++ def port_delete(self, port_id): ++ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) ++ instance_id = port_obj.parent_uuid ++ ++ # release instance IP address ++ iip_back_refs = port_obj.get_instance_ip_back_refs() ++ if iip_back_refs: ++ for iip_back_ref in iip_back_refs: ++ # if name contains IP address then this is shared ip ++ iip_obj = self._vnc_lib.instance_ip_read( ++ id=iip_back_ref['uuid']) ++ name = iip_obj.name ++ if len(name.split(' ')) > 1: ++ name = name.split(' ')[1] ++ ++ # in case of shared ip only delete the link to the VMI ++ try: ++ socket.inet_aton(name) ++ iip_obj.del_virtual_machine_interface(port_obj) ++ self._instance_ip_update(iip_obj) ++ except socket.error: ++ self._instance_ip_delete( ++ instance_ip_id=iip_back_ref['uuid']) ++ ++ # disassociate any floating IP used by instance ++ fip_back_refs = port_obj.get_floating_ip_back_refs() ++ if fip_back_refs: ++ for fip_back_ref in fip_back_refs: ++ fip_obj = self._vnc_lib.floating_ip_read( ++ id=fip_back_ref['uuid']) ++ self.floatingip_update(fip_obj.uuid, {'port_id': None}) ++ ++ self._virtual_machine_interface_delete(port_id=port_id) ++ ++ # delete instance if this was the last port ++ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) ++ inst_intfs = inst_obj.get_virtual_machine_interfaces() ++ if not inst_intfs: ++ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) ++ ++ try: ++ del self._db_cache['q_ports'][port_id] ++ except KeyError: ++ pass ++ ++ # update cache on successful deletion ++ try: ++ tenant_id = self._get_obj_tenant_id('port', port_id) ++ self._db_cache['q_tenant_port_count'][tenant_id] = \ ++ self._db_cache['q_tenant_port_count'][tenant_id] - 1 ++ except KeyError: ++ pass ++ ++ self._del_obj_tenant_id(port_id) ++ ++ def port_list(self, filters=None): ++ ret_q_ports = [] ++ all_project_ids = [] ++ ++ if 'device_owner' in filters: ++ return ret_q_ports ++ ++ if 'device_id' not in filters: ++ # Listing from back references ++ if not filters: ++ # no filters => return all ports! ++ all_projects = self._project_list_domain(None) ++ all_project_ids = [project['uuid'] for project in all_projects] ++ elif 'tenant_id' in filters: ++ all_project_ids = filters.get('tenant_id') ++ ++ for proj_id in all_project_ids: ++ proj_ports = self._port_list_project(proj_id) ++ for port in proj_ports: ++ try: ++ port_info = self.port_read(port['id']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ for net_id in filters.get('network_id', []): ++ net_ports = self._port_list_network(net_id) ++ for port in net_ports: ++ port_info = self.port_read(port['id']) ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ # Listing from parent to children ++ virtual_machine_ids = filters['device_id'] ++ for vm_id in virtual_machine_ids: ++ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( ++ parent_id=vm_id) ++ vm_intf_ids = resp_dict['virtual-machine-interfaces'] ++ for vm_intf in vm_intf_ids: ++ try: ++ port_info = self.port_read(vm_intf['uuid']) ++ except vnc_exc.NoIdError: ++ continue ++ ret_q_ports.append(port_info) ++ ++ return ret_q_ports ++ ++ def port_count(self, filters=None): ++ if 'device_owner' in filters: ++ return 0 ++ ++ if 'tenant_id' in filters: ++ project_id = filters['tenant_id'][0] ++ try: ++ return self._db_cache['q_tenant_port_count'][project_id] ++ except KeyError: ++ # do it the hard way but remember for next time ++ nports = len(self._port_list_project(project_id)) ++ self._db_cache['q_tenant_port_count'][project_id] = nports ++ else: ++ # across all projects ++ # get only a count from api-server! ++ nports = len(self.port_list(filters)) ++ ++ return nports ++ ++ # security group api handlers ++ def security_group_create(self, sg_q): ++ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) ++ sg_uuid = self._security_group_create(sg_obj) ++ ++ #allow all egress traffic ++ def_rule = { ++ 'port_range_min': 0, ++ 'port_range_max': 65535, ++ 'direction': 'egress', ++ 'remote_ip_prefix': None, ++ 'remote_group_id': None, ++ 'protocol': 'any', ++ } ++ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) ++ self._security_group_rule_create(sg_uuid, rule) ++ ++ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) ++ return ret_sg_q ++ ++ def security_group_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return self._security_group_vnc_to_neutron(sg_obj) ++ ++ def security_group_delete(self, sg_id): ++ self._security_group_delete(sg_id) ++ ++ def security_group_list(self, context, filters=None): ++ ret_list = [] ++ ++ # all_sgs[] all sgs in all projects ++ # collect phase ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ all_sgs = [self._security_group_list_project(p_id) for ++ p_id in project_ids] ++ elif filters and 'name' in filters: ++ all_sgs = [self._security_group_list_project( ++ str(uuid.UUID(context.tenant)))] ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ all_sgs = [self._security_group_list_project(project['uuid']) for ++ project in dom_projects] ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ for proj_sg in project_sgs: ++ proj_sg_id = proj_sg['uuid'] ++ if not self._filters_is_present(filters, 'id', proj_sg_id): ++ continue ++ sg_info = self.security_group_read(proj_sg_id) ++ if not self._filters_is_present(filters, 'name', ++ sg_info['q_api_data']['name']): ++ continue ++ ret_list.append(sg_info) ++ ++ return ret_list ++ ++ def security_group_rule_create(self, sgr_q): ++ sg_id = sgr_q['security_group_id'] ++ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) ++ self._security_group_rule_create(sg_id, sg_rule) ++ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, ++ sg_rule) ++ ++ return ret_sg_rule_q ++ ++ def security_group_rule_read(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, ++ sg_rule) ++ ++ return {} ++ ++ def security_group_rule_delete(self, sgr_id): ++ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) ++ if sg_obj and sg_rule: ++ return self._security_group_rule_delete(sg_obj, sg_rule) ++ ++ def security_group_rules_read(self, sg_id): ++ try: ++ sg_obj = self._vnc_lib.security_group_read(id=sg_id) ++ sgr_entries = sg_obj.get_security_group_entries() ++ if sgr_entries is None: ++ return ++ ++ sg_rules = [self._security_group_rule_vnc_to_neutron( ++ sg_obj.uuid, sg_rule) for ++ sg_rule in sgr_entries.get_policy_rule()] ++ except vnc_exc.NoIdError: ++ raise exceptions.NetworkNotFound(net_id=sg_id) ++ ++ return sg_rules ++ ++ def security_group_rule_list(self, filters=None): ++ ret_list = [] ++ ++ # collect phase ++ if filters and 'tenant_id' in filters: ++ project_ids = filters['tenant_id'] ++ all_sgs = [self._security_group_list_project(p_id) for ++ p_id in project_ids] ++ else: # no filters ++ dom_projects = self._project_list_domain(None) ++ all_sgs = [self._security_group_list_project(project['uuid']) ++ for project in dom_projects] ++ ++ # prune phase ++ for project_sgs in all_sgs: ++ ret_list.extend( ++ self.security_group_rules_read(proj_sg['uuid']) ++ for proj_sg in project_sgs ++ if self._filters_is_present(filters, 'id', proj_sg['uuid']) ++ ) ++ ++ return ret_list +diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py +new file mode 100644 +index 0000000..72bebec +--- /dev/null ++++ neutron/tests/unit/juniper/__init__.py +@@ -0,0 +1,14 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. +diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py +new file mode 100644 +index 0000000..3984971 +--- /dev/null ++++ neutron/tests/unit/juniper/test_contrail_plugin.py +@@ -0,0 +1,1021 @@ ++# Copyright (c) 2012 OpenStack Foundation. ++# ++# 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. ++ ++import datetime ++import mock ++import sys ++import uuid ++ ++import neutron.db.api ++from neutron.manager import NeutronManager ++from neutron.tests.unit import test_db_plugin as test_plugin ++ ++ ++subnet_obj = {u'subnet': ++ {'name': '', 'enable_dhcp': True, ++ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', ++ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', ++ 'dns_nameservers': '', ++ u'contrail:ipam_fq_name': ++ [u'default-domain', u'admin', u'default-network-ipam'], ++ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, ++ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} ++ ++vn_list = [] ++GlobalProjects = [] ++ ++ ++class MockVncApi(mock.MagicMock): ++ def __init__(self, *args, **kwargs): ++ pass ++ ++ def kv_retrieve(self, *args, **kwargs): ++ return [] ++ ++ def kv_store(self, *args, **kwargs): ++ return ++ ++ def kv_delete(self, *args, **kwargs): ++ return ++ ++ def project_read(self, *args, **kwargs): ++ return GlobalProjects[0] ++ ++ def virtual_network_create(self, net_obj): ++ net_id = unicode(str(uuid.uuid4())) ++ net_obj.set_uuid(net_id) ++ vn_list.append(net_obj) ++ return net_id ++ ++ def virtual_network_read(self, id, *args, **kwargs): ++ if len(vn_list): ++ for index in range(len(vn_list)): ++ if ((vn_list[index].get_uuid()) == id): ++ return vn_list[index] ++ ++ #return a mock object if it is not created so far ++ return MockVirtualNetwork('dummy-net', MockProject()) ++ ++ def virtual_network_delete(self, *args, **kwargs): ++ return ++ ++ def virtual_network_update(self, *args, **kwargs): ++ return ++ ++ def virtual_networks_list(self, *args, **kwargs): ++ return vn_list ++ ++ ++class MockVncObject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ if not parent_obj: ++ self._fq_name = [name] ++ else: ++ self._fq_name = parent_obj.get_fq_name() + [name] ++ ++ self._ipam_refs = [{'to': [u'default-domain', u'admin', ++ u'default-network-ipam']}] ++ self.uuid = None ++ self.name = name ++ self.network_ipam_refs = [] ++ ++ def set_uuid(self, uuid): ++ self.uuid = uuid ++ ++ def get_uuid(self): ++ return self.uuid ++ ++ def get_fq_name(self): ++ return self._fq_name ++ ++ def get_network_ipam_refs(self): ++ return getattr(self, 'network_ipam_refs', None) ++ ++ def add_network_ipam(self, ref_obj, ref_data): ++ refs = getattr(self, 'network_ipam_refs', []) ++ if not refs: ++ self.network_ipam_refs = [] ++ ++ # if ref already exists, update any attr with it ++ for ref in refs: ++ if ref['to'] == ref_obj.get_fq_name(): ++ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref['uuid'] = ref_obj.uuid ++ return ++ ++ # ref didn't exist before ++ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} ++ if ref_obj.uuid: ++ ref_info['uuid'] = ref_obj.uuid ++ ++ self.network_ipam_refs.append(ref_info) ++ ++ ++class MockVirtualNetwork(MockVncObject): ++ pass ++ ++ ++class MockSubnetType(mock.MagicMock): ++ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ip_prefix = ip_prefix ++ self.ip_prefix_len = ip_prefix_len ++ ++ def get_ip_prefix(self): ++ return self.ip_prefix ++ ++ def set_ip_prefix(self, ip_prefix): ++ self.ip_prefix = ip_prefix ++ ++ def get_ip_prefix_len(self): ++ return self.ip_prefix_len ++ ++ def set_ip_prefix_len(self, ip_prefix_len): ++ self.ip_prefix_len = ip_prefix_len ++ ++ ++class MockIpamSubnetType(mock.MagicMock): ++ def __init__(self, name=None, subnet=None, default_gateway=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.subnet = subnet ++ self.default_gateway = default_gateway ++ ++ def get_subnet(self): ++ return self.subnet ++ ++ def set_subnet(self, subnet): ++ self.subnet = subnet ++ ++ def get_default_gateway(self): ++ return self.default_gateway ++ ++ def set_default_gateway(self, default_gateway): ++ self.default_gateway = default_gateway ++ ++ def validate_IpAddressType(self, value): ++ pass ++ ++ ++class MockVnSubnetsType(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self.ipam_subnets = [] ++ if ipam_subnets: ++ #self.ipam_subnets = copy.deepcopy(ipam_subnets) ++ self.ipam_subnets = ipam_subnets ++ ++ def get_ipam_subnets(self): ++ return self.ipam_subnets ++ ++ def set_ipam_subnets(self, ipam_subnets): ++ self.ipam_subnets = ipam_subnets ++ ++ def add_ipam_subnets(self, value): ++ self.ipam_subnets.append(value) ++ ++ def insert_ipam_subnets(self, index, value): ++ self.ipam_subnets[index] = value ++ ++ def delete_ipam_subnets(self, value): ++ self.ipam_subnets.remove(value) ++ ++ ++class MockNetworkIpam(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, ++ network_ipam_mgmt=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'default-network-ipam' ++ self.name = name ++ self.uuid = None ++ if parent_obj: ++ self.parent_type = parent_obj._type ++ # copy parent's fq_name ++ self.fq_name = list(parent_obj.fq_name) ++ self.fq_name.append(name) ++ if not parent_obj.get_network_ipams(): ++ parent_obj.network_ipams = [] ++ parent_obj.network_ipams.append(self) ++ else: # No parent obj specified ++ self.parent_type = 'project' ++ self.fq_name = [u'default-domain', u'default-project'] ++ self.fq_name.append(name) ++ ++ # property fields ++ if network_ipam_mgmt: ++ self.network_ipam_mgmt = network_ipam_mgmt ++ if id_perms: ++ self.id_perms = id_perms ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++class MockProject(mock.MagicMock): ++ def __init__(self, name=None, parent_obj=None, id_perms=None, ++ *args, **kwargs): ++ super(mock.MagicMock, self).__init__() ++ self._type = 'project' ++ self.uuid = None ++ self.parent_type = 'domain' ++ self.fq_name = [u'default-domain'] ++ self.fq_name.append(name) ++ ++ def get_fq_name(self): ++ return self.fq_name ++ ++ ++def GlobalProjectApi(project_name): ++ if not GlobalProjects: ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ return GlobalProjects[0] ++ ++ ++# Mock definations for different pkgs, modules and VncApi ++mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) ++mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') ++mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork ++mock_vnc_api_mod.SubnetType = MockSubnetType ++mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType ++mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType ++mock_vnc_api_mod.NetworkIpam = MockNetworkIpam ++mock_vnc_api_mod.Project = GlobalProjectApi ++ ++mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') ++mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') ++mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ ++ mock_vnc_api_pkg ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ ++ mock_vnc_api_mod ++sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ ++ mock_vnc_common_mod ++sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' ++ 'exceptions')] = \ ++ mock_vnc_exception_mod ++ ++CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" ++ ++ ++class RouterInstance(object): ++ def __init__(self): ++ self._name = 'rounter_instance' ++ ++ ++class Context(object): ++ def __init__(self, tenant_id=''): ++ self.read_only = False ++ self.show_deleted = False ++ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] ++ self._read_deleted = 'no' ++ self.timestamp = datetime.datetime.now() ++ self.auth_token = None ++ self._session = None ++ self._is_admin = True ++ self.admin = uuid.uuid4().hex.decode() ++ self.request_id = 'req-' + str(uuid.uuid4()) ++ self.tenant = tenant_id ++ ++ ++class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): ++ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) ++ ++ def setUp(self): ++ ++ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod ++ ++ mock_vnc_api_mod.common = mock_vnc_common_mod ++ mock_vnc_api_mod.VncApi = mock_vnc_api_cls ++ ++ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod ++ ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ neutron.db.api._ENGINE = mock.MagicMock() ++ ++ def teardown(self): ++ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) ++ ++ ++class TestContrailNetworks(test_plugin.TestNetworksV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ router_inst = RouterInstance() ++ network = { ++ 'router:external': router_inst, ++ u'name': u'network1', ++ 'admin_state_up': 'True', ++ 'tenant_id': uuid.uuid4().hex.decode(), ++ 'vpc:route_table': '', ++ 'shared': False, ++ 'port_security_enabled': True, ++ u'contrail:policys': [], ++ } ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ if 'contrail:fq_name' not in net.keys(): ++ assert False ++ else: ++ assert True ++ ++ def test_delete_network(self): ++ # First create the network and request to delete the same ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ router_inst = RouterInstance() ++ network = { ++ 'router:external': router_inst, ++ u'name': u'network1', ++ 'admin_state_up': 'True', ++ 'tenant_id': uuid.uuid4().hex.decode(), ++ 'vpc:route_table': '', ++ 'shared': False, ++ 'port_security_enabled': True, ++ u'contrail:policys': [], ++ } ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ ++ plugin_obj.delete_network(context_obj, net_id) ++ mock_vnc_api_cls.virtual_network_delete.assert_called_once() ++ ++ def test_update_network(self): ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ router_inst = RouterInstance() ++ network = { ++ 'router:external': router_inst, ++ u'name': u'network1', ++ 'admin_state_up': 'True', ++ 'tenant_id': uuid.uuid4().hex.decode(), ++ 'vpc:route_table': '', ++ 'shared': False, ++ 'port_security_enabled': True, ++ u'contrail:policys': [], ++ } ++ ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ networks_req[u'network'] = network ++ net_dict = plugin_obj.create_network(context_obj, networks_req) ++ net_id = net_dict.get('id') ++ # change one of the attribute and update the network ++ network['admin_state_up'] = 'False' ++ new_dict = plugin_obj.update_network(context_obj, net_id, ++ networks_req) ++ self.assertNotEqual(net_dict.get('admin_state_up'), ++ new_dict.get('admin_state_up')) ++ ++ # Not supported test cases in the this TestClass ++ def test_create_networks_bulk_emulated(self): ++ pass ++ ++ def test_create_networks_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_public_network(self): ++ pass ++ ++ def test_create_networks_bulk_wrong_input(self): ++ pass ++ ++ def test_update_shared_network_noadmin_returns_403(self): ++ pass ++ ++ def test_update_network_set_shared(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): ++ pass ++ ++ def test_update_network_set_not_shared_single_tenant(self): ++ pass ++ ++ def test_update_network_set_not_shared_other_tenant_returns_409(self): ++ pass ++ ++ def test_update_network_with_subnet_set_shared(self): ++ pass ++ ++ def test_show_network(self): ++ pass ++ ++ def test_show_network_with_subnet(self): ++ pass ++ ++ def test_list_networks(self): ++ pass ++ ++ def test_list_shared_networks_with_non_admin_user(self): ++ pass ++ ++ def test_list_networks_with_parameters(self): ++ pass ++ ++ def test_list_networks_with_fields(self): ++ pass ++ ++ def test_list_networks_with_parameters_invalid_values(self): ++ pass ++ ++ def test_list_networks_with_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_without_pk_in_fields_pagination_emulated(self): ++ pass ++ ++ def test_list_networks_with_sort_emulated(self): ++ pass ++ ++ def test_list_networks_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_invalid_admin_status(self): ++ pass ++ ++ ++class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ router_inst = RouterInstance() ++ network = { ++ 'router:external': router_inst, ++ u'name': u'network1', ++ 'admin_state_up': 'True', ++ 'tenant_id': uuid.uuid4().hex.decode(), ++ 'vpc:route_table': '', ++ 'shared': False, ++ 'port_security_enabled': True, ++ u'contrail:policys': [], ++ } ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ self.assertEqual(subnet_dict['cidr'], ++ subnet_obj['subnet']['cidr']) ++ ++ def test_delete_subnet(self): ++ #First create virtual network without subnet and then ++ #create subnet to update given network. ++ plugin_obj = NeutronManager.get_plugin() ++ networks_req = {} ++ router_inst = RouterInstance() ++ network = { ++ 'router:external': router_inst, ++ u'name': u'network1', ++ 'admin_state_up': 'True', ++ 'tenant_id': uuid.uuid4().hex.decode(), ++ 'vpc:route_table': '', ++ 'shared': False, ++ 'port_security_enabled': True, ++ u'contrail:policys': [], ++ } ++ ++ networks_req[u'network'] = network ++ context_obj = Context(network['tenant_id']) ++ #create project ++ if not GlobalProjects: ++ project_name = 'admin' ++ GlobalProjects.append(MockProject(name=project_name)) ++ ++ net = plugin_obj.create_network(context_obj, networks_req) ++ ++ subnet_obj[u'subnet']['network_id'] = net['id'] ++ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) ++ subnet_id = subnet_dict['id'] ++ plugin_obj.delete_subnet(context_obj, subnet_id) ++ ++ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_delete_network(self): ++ pass ++ ++ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet_adding_additional_host_routes_and_dns(self): ++ pass ++ ++ def test_update_subnet_no_gateway(self): ++ pass ++ ++ def test_create_subnet_bad_cidr(self): ++ pass ++ ++ def test_create_subnet_gw_of_network_force_on_returns_400(self): ++ pass ++ ++ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): ++ pass ++ ++ def test_create_two_subnets(self): ++ pass ++ ++ def test_create_two_subnets_same_cidr_returns_400(self): ++ pass ++ ++ def test_create_subnet_bad_V4_cidr(self): ++ pass ++ ++ def test_create_subnet_bad_V6_cidr(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): ++ pass ++ ++ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): ++ pass ++ ++ def test_create_subnets_bulk_native(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated(self): ++ pass ++ ++ def test_create_subnets_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_subnets_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_network(self): ++ pass ++ ++ def test_delete_subnet_port_exists_owned_by_other(self): ++ pass ++ ++ def test_create_subnet_bad_tenant(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version(self): ++ pass ++ ++ def test_create_subnet_bad_ip_version_null(self): ++ pass ++ ++ def test_create_subnet_bad_uuid(self): ++ pass ++ ++ def test_create_subnet_bad_boolean(self): ++ pass ++ ++ def test_create_subnet_bad_pools(self): ++ pass ++ ++ def test_create_subnet_bad_nameserver(self): ++ pass ++ ++ def test_create_subnet_bad_hostroutes(self): ++ pass ++ ++ def test_create_subnet_defaults(self): ++ pass ++ ++ def test_create_subnet_gw_values(self): ++ pass ++ ++ def test_create_force_subnet_gw_values(self): ++ pass ++ ++ def test_create_subnet_with_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_fully_allocated(self): ++ pass ++ ++ def test_subnet_with_allocation_range(self): ++ pass ++ ++ def test_create_subnet_with_none_gateway_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_v6_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_with_large_allocation_pool(self): ++ pass ++ ++ def test_create_subnet_multiple_allocation_pools(self): ++ pass ++ ++ def test_create_subnet_with_dhcp_disabled(self): ++ pass ++ ++ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( ++ self): ++ pass ++ ++ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): ++ pass ++ ++ def test_create_subnet_overlapping_allocation_pools_returns_409(self): ++ pass ++ ++ def test_create_subnet_invalid_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): ++ pass ++ ++ def test_create_subnet_shared_returns_400(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_cidrv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_cidrv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv6_dns_v4(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): ++ pass ++ ++ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): ++ pass ++ ++ def test_create_subnet_gw_bcast_force_on_returns_400(self): ++ pass ++ ++ def test_update_subnet(self): ++ pass ++ ++ def test_update_subnet_shared_returns_400(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv4_dns_v6(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): ++ pass ++ ++ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): ++ pass ++ ++ def test_show_subnet(self): ++ pass ++ ++ def test_list_subnets(self): ++ pass ++ ++ def test_list_subnets_shared(self): ++ pass ++ ++ def test_list_subnets_with_parameter(self): ++ pass ++ ++ def test_invalid_ip_version(self): ++ pass ++ ++ def test_invalid_subnet(self): ++ pass ++ ++ def test_invalid_ip_address(self): ++ pass ++ ++ def test_invalid_uuid(self): ++ pass ++ ++ def test_create_subnet_with_one_dns(self): ++ pass ++ ++ def test_create_subnet_with_two_dns(self): ++ pass ++ ++ def test_create_subnet_with_too_many_dns(self): ++ pass ++ ++ def test_create_subnet_with_one_host_route(self): ++ pass ++ ++ def test_create_subnet_with_two_host_routes(self): ++ pass ++ ++ def test_create_subnet_with_too_many_routes(self): ++ pass ++ ++ def test_create_subnet_as_admin(self): ++ pass ++ ++ def test_update_subnet_dns(self): ++ pass ++ ++ def test_update_subnet_dns_to_None(self): ++ pass ++ ++ def test_update_subnet_dns_with_too_many_entries(self): ++ pass ++ ++ def test_update_subnet_route(self): ++ pass ++ ++ def test_update_subnet_route_to_None(self): ++ pass ++ ++ def test_update_subnet_route_with_too_many_entries(self): ++ pass ++ ++ def test_delete_subnet_with_dns(self): ++ pass ++ ++ def test_delete_subnet_with_route(self): ++ pass ++ ++ def test_delete_subnet_with_dns_and_route(self): ++ pass ++ ++ def test_list_subnets_with_pagination_emulated(self): ++ pass ++ ++ def test_list_subnets_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_subnets_with_sort_emulated(self): ++ pass ++ ++ def test_validate_subnet_host_routes_exhausted(self): ++ pass ++ ++ def test_validate_subnet_dns_nameservers_exhausted(self): ++ pass ++ ++ def test_update_subnet_gw_ip_in_use_returns_409(self): ++ pass ++ ++ ++class TestContrailPortsV2(test_plugin.TestPortsV2, ++ JVContrailPluginTestCase): ++ ++ def test_create_port(self): ++ pass ++ ++ def test_create_port_json(self): ++ pass ++ ++ def test_create_port_bad_tenant(self): ++ pass ++ ++ def test_create_port_public_network(self): ++ pass ++ ++ def test_create_port_public_network_with_ip(self): ++ pass ++ ++ def test_create_ports_bulk_native(self): ++ pass ++ ++ def test_create_ports_bulk_emulated(self): ++ pass ++ ++ def test_create_ports_bulk_wrong_input(self): ++ pass ++ ++ def test_create_ports_bulk_emulated_plugin_failure(self): ++ pass ++ ++ def test_create_ports_bulk_native_plugin_failure(self): ++ pass ++ ++ def test_create_port_as_admin(self): ++ pass ++ ++ def test_list_ports(self): ++ pass ++ ++ def test_list_ports_filtered_by_fixed_ip(self): ++ pass ++ ++ def test_list_ports_public_network(self): ++ pass ++ ++ def test_show_port(self): ++ pass ++ ++ def test_delete_port(self): ++ pass ++ ++ def test_delete_port_public_network(self): ++ pass ++ ++ def test_update_port(self): ++ pass ++ ++ def test_update_device_id_null(self): ++ pass ++ ++ def test_delete_network_if_port_exists(self): ++ pass ++ ++ def test_delete_network_port_exists_owned_by_network(self): ++ pass ++ ++ def test_update_port_delete_ip(self): ++ pass ++ ++ def test_no_more_port_exception(self): ++ pass ++ ++ def test_update_port_update_ip(self): ++ pass ++ ++ def test_update_port_update_ip_address_only(self): ++ pass ++ ++ def test_update_port_update_ips(self): ++ pass ++ ++ def test_update_port_add_additional_ip(self): ++ pass ++ ++ def test_requested_duplicate_mac(self): ++ pass ++ ++ def test_mac_generation(self): ++ pass ++ ++ def test_mac_generation_4octet(self): ++ pass ++ ++ def test_bad_mac_format(self): ++ pass ++ ++ def test_mac_exhaustion(self): ++ pass ++ ++ def test_requested_duplicate_ip(self): ++ pass ++ ++ def test_requested_subnet_delete(self): ++ pass ++ ++ def test_requested_subnet_id(self): ++ pass ++ ++ def test_requested_subnet_id_not_on_network(self): ++ pass ++ ++ def test_overlapping_subnets(self): ++ pass ++ ++ def test_requested_subnet_id_v4_and_v6(self): ++ pass ++ ++ def test_range_allocation(self): ++ pass ++ ++ def test_requested_invalid_fixed_ips(self): ++ pass ++ ++ def test_invalid_ip(self): ++ pass ++ ++ def test_requested_split(self): ++ pass ++ ++ def test_duplicate_ips(self): ++ pass ++ ++ def test_fixed_ip_invalid_subnet_id(self): ++ pass ++ ++ def test_fixed_ip_invalid_ip(self): ++ pass ++ ++ def test_requested_ips_only(self): ++ pass ++ ++ def test_recycling(self): ++ pass ++ ++ def test_invalid_admin_state(self): ++ pass ++ ++ def test_invalid_mac_address(self): ++ pass ++ ++ def test_default_allocation_expiration(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration(self): ++ pass ++ ++ def test_port_delete_holds_ip(self): ++ pass ++ ++ def test_update_fixed_ip_lease_expiration_invalid_address(self): ++ pass ++ ++ def test_hold_ip_address(self): ++ pass ++ ++ def test_recycle_held_ip_address(self): ++ pass ++ ++ def test_recycle_expired_previously_run_within_context(self): ++ pass ++ ++ def test_update_port_not_admin(self): ++ pass ++ ++ def test_list_ports_with_pagination_emulated(self): ++ pass ++ ++ def test_list_ports_with_pagination_reverse_emulated(self): ++ pass ++ ++ def test_list_ports_with_sort_emulated(self): ++ pass ++ ++ def test_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_update_max_fixed_ips_exceeded(self): ++ pass ++ ++ def test_recycle_ip_address_without_allocation_pool(self): ++ pass ++ ++ def test_recycle_ip_address_on_exhausted_allocation_pool(self): ++ pass ++ ++ def test_recycle_ip_address_outside_allocation_pool(self): ++ pass ++ ++ def test_recycle_ip_address_in_allocation_pool(self): ++ pass +diff --git setup.cfg setup.cfg +index bae3ffd..6c2ea4f 100644 +--- setup.cfg ++++ setup.cfg +@@ -63,6 +63,7 @@ data_files = + etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini + etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini + etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini ++ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini + scripts = + bin/quantum-rootwrap + bin/neutron-rootwrap diff --git a/contrail/nova_v4.patch b/contrail/nova_v4.patch new file mode 100644 index 0000000000..10894878b7 --- /dev/null +++ b/contrail/nova_v4.patch @@ -0,0 +1,3252 @@ +diff --git nova/network/model.py nova/network/model.py +index 9a543a3..cf5f56d 100644 +--- nova/network/model.py ++++ nova/network/model.py +@@ -39,6 +39,7 @@ VIF_TYPE_802_QBG = '802.1qbg' + VIF_TYPE_802_QBH = '802.1qbh' + VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' + VIF_TYPE_MIDONET = 'midonet' ++VIF_TYPE_VROUTER = 'vrouter' + VIF_TYPE_OTHER = 'other' + + # Constant for max length of network interface names +diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py +index cfff8dd..0a51783 100644 +--- nova/virt/libvirt/vif.py ++++ nova/virt/libvirt/vif.py +@@ -309,6 +309,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + + return conf + ++ def get_config_contrail(self, instance, vif, image_meta, ++ inst_type): ++ conf = super(LibvirtGenericVIFDriver, ++ self).get_config(instance, vif, ++ image_meta, inst_type) ++ ++ dev = self.get_vif_devname(vif) ++ designer.set_vif_host_backend_ethernet_config(conf, dev) ++ ++ return conf ++ + def get_config_mlnx_direct(self, instance, vif, image_meta, + inst_type): + conf = super(LibvirtGenericVIFDriver, +@@ -372,6 +383,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + vif, + image_meta, + inst_type) ++ elif vif_type == network_model.VIF_TYPE_VROUTER: ++ return self.get_config_contrail(instance, ++ vif, ++ image_meta, ++ inst_type) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -564,6 +580,31 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except processutils.ProcessExecutionError: + LOG.exception(_("Failed while plugging vif"), instance=instance) + ++ def plug_contrail(self, instance, vif): ++ """Plug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).plug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ iface_id = vif['id'] ++ from nova.virt import netutils ++ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) ++ try: ++ linux_net.create_tap_dev(dev) ++ utils.execute('config_parser', 'create', ++ '--port_id', vif['id'], ++ '--tap_name', dev, ++ '--ip_address', vif['network']['subnets'][0]['ips'][0]['address'], ++ '--instance_id', instance['uuid'], ++ '--vn_id', vif['network']['id'], ++ '--mac_address', vif['address'], ++ '--display_name', instance['display_name'], ++ '--hostname', instance['hostname'], ++ '--host', instance['host'], ++ '--prefix_len', prefix_len) ++ except processutils.ProcessExecutionError: ++ LOG.exception(_("Failed while plugging vif"), instance=instance) ++ + def plug(self, instance, vif): + vif_type = vif['type'] + +@@ -571,7 +612,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + 'vif=%(vif)s'), + {'vif_type': vif_type, 'instance': instance, + 'vif': vif}) +- + if vif_type is None: + raise exception.NovaException( + _("vif_type parameter must be present " +@@ -592,6 +632,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.plug_mlnx_direct(instance, vif) + elif vif_type == network_model.VIF_TYPE_MIDONET: + self.plug_midonet(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_VROUTER: ++ self.plug_contrail(instance, vif) + else: + raise exception.NovaException( + _("Unexpected vif_type=%s") % vif_type) +@@ -746,6 +788,19 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + except processutils.ProcessExecutionError: + LOG.exception(_("Failed while unplugging vif"), instance=instance) + ++ def unplug_contrail(self, instance, vif): ++ """Unplug using Contrail Driver ++ """ ++ super(LibvirtGenericVIFDriver, ++ self).unplug(instance, vif) ++ dev = self.get_vif_devname(vif) ++ try: ++ utils.execute('config_parser', 'delete', ++ '--port_id', vif['id']) ++ linux_net.delete_net_dev(dev) ++ except processutils.ProcessExecutionError: ++ LOG.exception(_("Failed while unplugging vif"), instance=instance) ++ + def unplug(self, instance, vif): + vif_type = vif['type'] + +@@ -770,6 +825,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): + self.unplug_ivs(instance, vif) + elif vif_type == network_model.VIF_TYPE_IOVISOR: + self.unplug_iovisor(instance, vif) ++ elif vif_type == network_model.VIF_TYPE_VROUTER: ++ self.unplug_contrail(instance, vif) + elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: + self.unplug_mlnx_direct(instance, vif) + elif vif_type == network_model.VIF_TYPE_MIDONET: +diff --git plugins/contrail/contrail_parser.py plugins/contrail/contrail_parser.py +new file mode 100755 +index 0000000..acac9fb +--- /dev/null ++++ plugins/contrail/contrail_parser.py +@@ -0,0 +1,126 @@ ++#! /usr/bin/env python ++import os ++import sys ++import cgitb ++import argparse ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' ++ ++class ContrailVifDelete(object): ++ def __init__(self, port_id): ++ if os.path.exists(VIF_DIR+port_id): ++ os.remove(VIF_DIR+port_id) ++ #end __init__ ++# end ContrailVifDelete ++ ++class ContrailVifUpdate(object): ++ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, ++ hostname, host, prefix_len): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ self.__update_vif(port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, display_name, ++ hostname, host, prefix_len) ++ ++ # end __init__ ++ ++ def __update_vif(self, port_id, tap_name, ++ ip_address, instance_id, ++ vn_id, mac_address, ++ display_name, ++ hostname, ++ host, prefix_len): ++ if (port_id and tap_name and ++ ip_address and instance_id and ++ vn_id and mac_address and ++ host and prefix_len): ++ import ConfigParser ++ config = ConfigParser.RawConfigParser() ++ config.add_section('Vif') ++ config.set('Vif', 'port_id', port_id) ++ config.set('Vif', 'tap_name', tap_name) ++ config.set('Vif', 'ip_address', ip_address) ++ config.set('Vif', 'instance_id', instance_id) ++ config.set('Vif', 'vn_id', vn_id) ++ config.set('Vif', 'mac_address', mac_address) ++ config.set('Vif', 'display_name', display_name) ++ config.set('Vif', 'hostname', hostname) ++ config.set('Vif', 'host', host) ++ config.set('Vif', 'prefix_len', prefix_len) ++ with open(VIF_DIR + port_id, 'wb') as configfile: ++ config.write(configfile) ++ ++ # end __update_vif ++# end ContrailVifUpdate ++ ++def update_vif_file(args): ++ if args.which is 'create': ++ if (args.port_id and args.tap_name and ++ args.ip_address and args.instance_id and ++ args.vn_id and args.mac_address and ++ args.host and args.prefix_len): ++ ContrailVifUpdate(args.port_id, args.tap_name, ++ args.ip_address, args.instance_id, ++ args.vn_id, args.mac_address, args.display_name, ++ args.hostname, args.host, args.prefix_len) ++ elif args.which is 'delete': ++ if args.port_id is not None: ++ ContrailVifDelete(args.port_id) ++ ++# end update_vif_file ++ ++def parse_args(args_str): ++ ''' ++ ''' ++ # Source any specified config/ini file ++ # Turn off help, so we all options in response to -h ++ conf_parser = argparse.ArgumentParser(add_help=False) ++ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) ++ parser = argparse.ArgumentParser( ++ # Inherit options from config_parser ++ parents=[conf_parser], ++ # print script description with -h/--help ++ description=__doc__, ++ # Don't mess with format of description ++ formatter_class=argparse.RawDescriptionHelpFormatter, ++ ) ++ #defaults.update(secopts) ++ #defaults.update(ksopts) ++ #parser.set_defaults(**defaults) ++ ++ subparsers = parser.add_subparsers(help='commands') ++ create_parser = subparsers.add_parser('create', help='Create/Modify vif') ++ create_parser.set_defaults(which='create') ++ create_parser.add_argument("--port_id", help = "port id") ++ create_parser.add_argument("--tap_name", help = "tap_name") ++ create_parser.add_argument("--ip_address", help = "ip_address") ++ create_parser.add_argument("--instance_id", help = "instance_id") ++ create_parser.add_argument("--vn_id", help = "vn_id") ++ create_parser.add_argument("--mac_address", help = "mac_address") ++ create_parser.add_argument("--display_name", help = "display_name") ++ create_parser.add_argument("--hostname", help = "hostname") ++ create_parser.add_argument("--host", help = "host") ++ create_parser.add_argument("--prefix_len", help = "prefix_len") ++ delete_parser = subparsers.add_parser('delete', help='Delete vif') ++ delete_parser.set_defaults(which='delete') ++ delete_parser.add_argument("--port_id", help = "port id") ++ print parser.parse_args() ++ args = parser.parse_args(remaining_argv) ++ update_vif_file(args) ++# end parse_args ++ ++def main(args_str=None): ++ if not args_str: ++ args_str = ' '.join(sys.argv[1:]) ++ args = parse_args(args_str) ++# end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py +new file mode 100644 +index 0000000..7d004a0 +--- /dev/null ++++ plugins/contrail/contrail_vif.py +@@ -0,0 +1,298 @@ ++# ++# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. ++# ++ ++""" ++contril vif plug, communicate with contrail agent ++""" ++import os ++import pyinotify ++import sys ++import socket ++import cgitb ++from nova import utils ++from nova import exception ++from nova.openstack.common import log as logging ++from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent ++import gevent ++from gevent import monkey; monkey.patch_time() ++ ++LOG = logging.getLogger(__name__) ++ ++''' ++struct Port { ++ 1:required tuuid port_id, ++ 2:required tuuid instance_id, ++ 3:required string tap_name, ++ 4:required string ip_address, ++ 5:required tuuid vn_id, ++ 6:required string mac_address, ++ 7:optional string display_name, ++ 8:optional string hostname, ++ 9:optional string host; ++ 10: optional byte prefix_len; ++} ++''' ++ ++class ContrailVifPlug(object): ++ "" ++ "" ++ def __init__(self): ++ self._agent_alive = False ++ self._agent_connected = False ++ self._port_dict = {} ++ self._protocol = None ++ self._notifier = None ++ #end __init__ ++ ++ def _agent_connect(self, protocol): ++ # Agent connect for first time ++ if protocol != None: ++ from instance_service import InstanceService ++ service = InstanceService.Client(protocol) ++ return service.Connect() ++ else: ++ return False ++ #end __agent_connect ++ ++ def _keep_alive(self): ++ try: ++ if self._agent_alive == False: ++ self._protocol = self._agent_conn_open() ++ if self._protocol == None: ++ return ++ from instance_service import InstanceService ++ service = InstanceService.Client(self._protocol) ++ aa_latest = service.KeepAliveCheck() ++ if self._agent_alive == False and aa_latest == True: ++ port_l = [v for k, v in self._port_dict.iteritems()] ++ service.AddPort(port_l) ++ self._agent_alive = True ++ return ++ if self._agent_alive == True and aa_latest == False: ++ self._agent_alive = False ++ return ++ except: ++ self._agent_alive = False ++ #end _keep_alive ++ ++ def _agent_conn_open(self): ++ import socket ++ import sys ++ import uuid ++ from thrift.transport import TTransport, TSocket ++ from thrift.transport.TTransport import TTransportException ++ from thrift.protocol import TBinaryProtocol, TProtocol ++ from instance_service import InstanceService ++ from instance_service import ttypes ++ try: ++ socket = TSocket.TSocket("127.0.0.1", 9090) ++ transport = TTransport.TFramedTransport(socket) ++ transport.open() ++ protocol = TBinaryProtocol.TBinaryProtocol(transport) ++ self._agent_connected = self._agent_connect(protocol) ++ return protocol ++ except TTransportException: ++ return None ++ #end _agent_conn_open ++ ++ def get_dev_name(self, iface_id): ++ return "tap" + iface_id[0:11] ++ #end get_dev_name ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _agent_inform_port_add(self, port, port_id): ++ # First add to the port list ++ self._port_dict[port_id] = port ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.AddPort([port]) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_add ++ ++ def _agent_inform_port_delete(self, port_id): ++ # First add to the port list ++ if port_id in self._port_dict: ++ del_port_id = self._port_dict[port_id].port_id ++ del self._port_dict[port_id] ++ if not self._agent_alive: ++ return ++ from instance_service import InstanceService ++ import socket ++ try: ++ service = InstanceService.Client(self._protocol) ++ service.DeletePort(del_port_id) ++ except: ++ self._agent_alive = False ++ #end _agent_inform_port_delete ++ ++ ++#end class ContrailVifPlug ++ ++def launch_interval_looping(contrail_vif_plug): ++ while True: ++ contrail_vif_plug._keep_alive() ++ gevent.sleep(2) ++#end launch_internal_looping ++ ++ ++class ContrailVifDir(ProcessEvent): ++ def __init__(self, contrail_vif, vif_dir): ++ self._create_port_list(contrail_vif, vif_dir) ++ self._contrail_vif_plug = contrail_vif ++ #end __init__ ++ ++ def _convert_to_bl(self, id): ++ import uuid ++ hexstr = uuid.UUID(id).hex ++ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] ++ #end _convert_to_bl ++ ++ def _create_port_list(self, contrail_vif, vif_dir): ++ import os ++ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] ++ for f in files: ++ print f ++ file_name = os.path.join(vif_dir, f) ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ contrail_vif._agent_inform_port_add(port, port_id) ++ #end create_port_list ++ ++ def _get_port_info(self, config): ++ import ConfigParser ++ #import pdb; pdb.set_trace() ++ from instance_service import ttypes ++ try: ++ vif = 'Vif' ++ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), ++ self._convert_to_bl(config.get(vif, 'instance_id')), ++ config.get(vif, 'tap_name'), ++ config.get(vif, 'ip_address'), ++ self._convert_to_bl(config.get(vif, 'vn_id')), ++ config.get(vif, 'mac_address'), ++ config.get(vif, 'display_name'), ++ config.get(vif, 'hostname'), ++ config.get(vif, 'host')) ++ #print config.get(vif, 'prefix_len') ++ return port ++ except: ++ return None ++ ++ def _print_port_info(self, config): ++ import ConfigParser ++ try: ++ vif = 'Vif' ++ print config.get(vif, 'port_id') ++ print config.get(vif, 'instance_id') ++ print config.get(vif, 'tap_name') ++ print config.get(vif, 'ip_address') ++ print config.get(vif, 'vn_id') ++ print config.get(vif, 'mac_address') ++ print config.get(vif, 'display_name') ++ print config.get(vif, 'hostname') ++ print config.get(vif, 'host') ++ print config.get(vif, 'prefix_len') ++ except: ++ return ++ #end __print_port_into ++ ++ def _read_port_info_from_file(self, file_name): ++ import ConfigParser ++ config = ConfigParser.ConfigParser() ++ config.read(file_name) ++ self._print_port_info(config) ++ port = self._get_port_info(config) ++ if port is not None: ++ return port, config.get('Vif', 'port_id') ++ else: ++ return None, None ++ #end _read_port_info_from_file ++ ++ def _is_allowed(self, file_name): ++ ret = True ++ if (file_name[0] == '.' or file_name[-1] == '~'): ++ ret = False ++ return ret ++ #end _is_allowed ++ ++ def process_IN_CREATE(self, event): ++ file_name = os.path.join(event.path, event.name) ++ if not self._is_allowed(event.name): ++ return ++ print "Create: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In create: %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ ++ #end process_IN_CREATE ++ ++ def process_IN_DELETE(self, event): ++ if not self._is_allowed(event.name): ++ return ++ print "Remove: %s" % os.path.join(event.path, event.name) ++ file_name = os.path.join(event.path, event.name) ++ #import pdb; pdb.set_trace() ++ if self._is_allowed(event.name): ++ self._contrail_vif_plug._agent_inform_port_delete(event.name) ++ return ++ ++ #end process_IN_DELETE ++ ++ def process_IN_MODIFY(self, event): ++ if not self._is_allowed(event.name): ++ return ++ file_name = os.path.join(event.path, event.name) ++ print "Modify: %s" % file_name ++ port, port_id = self._read_port_info_from_file(file_name) ++ if port is not None: ++ print "In modify %s" % port.tap_name ++ self._contrail_vif_plug._agent_inform_port_add(port, port_id) ++ #end process_IN_MODIFY ++#end ContrilVifDir ++ ++ ++VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' ++def contrail_vif_dir_monitor(contrail_vif_plug): ++ #import pdb; pdb.set_trace() ++ wm = WatchManager() ++ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) ++ contrail_vif_plug._notifier = notifier ++ # watched events ++ mask = pyinotify.IN_DELETE | \ ++ pyinotify.IN_CREATE | \ ++ pyinotify.IN_MODIFY | \ ++ pyinotify.IN_ISDIR ++ wm.add_watch(VIF_DIR, mask, quiet=False) ++ notifier.start() ++#end contrail_vif_dir_monitor ++ ++def main(args_str = None): ++ try: ++ os.makedirs(VIF_DIR) ++ except OSError: ++ if os.path.exists(VIF_DIR): ++ pass ++ else: ++ raise ++ contrail_vif_plug = ContrailVifPlug() ++ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) ++ #import pdb; pdb.set_trace() ++ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) ++ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) ++#end main ++ ++if __name__ == '__main__': ++ cgitb.enable(format='text') ++ main() +diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote +new file mode 100644 +index 0000000..76626d4 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService-remote +@@ -0,0 +1,165 @@ ++#!/usr/bin/env python ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++import sys ++import pprint ++from urlparse import urlparse ++from thrift.transport import TTransport ++from thrift.transport import TSocket ++from thrift.transport import THttpClient ++from thrift.protocol import TBinaryProtocol ++ ++import InstanceService ++from ttypes import * ++ ++if len(sys.argv) <= 1 or sys.argv[1] == '--help': ++ print '' ++ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' ++ print '' ++ print 'Functions:' ++ print ' bool AddPort(PortList port_list)' ++ print ' bool KeepAliveCheck()' ++ print ' bool Connect()' ++ print ' bool DeletePort(tuuid port_id)' ++ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' ++ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' ++ print ' bool AddHostRoute(string ip_address, string vrf_name)' ++ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' ++ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' ++ print ' bool CreateVrf(string vrf_name)' ++ print '' ++ sys.exit(0) ++ ++pp = pprint.PrettyPrinter(indent = 2) ++host = 'localhost' ++port = 9090 ++uri = '' ++framed = False ++http = False ++argi = 1 ++ ++if sys.argv[argi] == '-h': ++ parts = sys.argv[argi+1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ argi += 2 ++ ++if sys.argv[argi] == '-u': ++ url = urlparse(sys.argv[argi+1]) ++ parts = url[1].split(':') ++ host = parts[0] ++ if len(parts) > 1: ++ port = int(parts[1]) ++ else: ++ port = 80 ++ uri = url[2] ++ if url[4]: ++ uri += '?%s' % url[4] ++ http = True ++ argi += 2 ++ ++if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': ++ framed = True ++ argi += 1 ++ ++cmd = sys.argv[argi] ++args = sys.argv[argi+1:] ++ ++if http: ++ transport = THttpClient.THttpClient(host, port, uri) ++else: ++ socket = TSocket.TSocket(host, port) ++ if framed: ++ transport = TTransport.TFramedTransport(socket) ++ else: ++ transport = TTransport.TBufferedTransport(socket) ++protocol = TBinaryProtocol.TBinaryProtocol(transport) ++client = InstanceService.Client(protocol) ++transport.open() ++ ++if cmd == 'AddPort': ++ if len(args) != 1: ++ print 'AddPort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.AddPort(eval(args[0]),)) ++ ++elif cmd == 'KeepAliveCheck': ++ if len(args) != 0: ++ print 'KeepAliveCheck requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.KeepAliveCheck()) ++ ++elif cmd == 'Connect': ++ if len(args) != 0: ++ print 'Connect requires 0 args' ++ sys.exit(1) ++ pp.pprint(client.Connect()) ++ ++elif cmd == 'DeletePort': ++ if len(args) != 1: ++ print 'DeletePort requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.DeletePort(eval(args[0]),)) ++ ++elif cmd == 'TunnelNHEntryAdd': ++ if len(args) != 3: ++ print 'TunnelNHEntryAdd requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) ++ ++elif cmd == 'TunnelNHEntryDelete': ++ if len(args) != 3: ++ print 'TunnelNHEntryDelete requires 3 args' ++ sys.exit(1) ++ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) ++ ++elif cmd == 'RouteEntryAdd': ++ if len(args) != 4: ++ print 'RouteEntryAdd requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'RouteEntryDelete': ++ if len(args) != 2: ++ print 'RouteEntryDelete requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) ++ ++elif cmd == 'AddHostRoute': ++ if len(args) != 2: ++ print 'AddHostRoute requires 2 args' ++ sys.exit(1) ++ pp.pprint(client.AddHostRoute(args[0],args[1],)) ++ ++elif cmd == 'AddLocalVmRoute': ++ if len(args) != 4: ++ print 'AddLocalVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'AddRemoteVmRoute': ++ if len(args) != 4: ++ print 'AddRemoteVmRoute requires 4 args' ++ sys.exit(1) ++ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) ++ ++elif cmd == 'CreateVrf': ++ if len(args) != 1: ++ print 'CreateVrf requires 1 args' ++ sys.exit(1) ++ pp.pprint(client.CreateVrf(args[0],)) ++ ++else: ++ print 'Unrecognized method %s' % cmd ++ sys.exit(1) ++ ++transport.close() +diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py +new file mode 100644 +index 0000000..2219045 +--- /dev/null ++++ plugins/contrail/instance_service/InstanceService.py +@@ -0,0 +1,2275 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++from thrift.Thrift import TProcessor ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++class Iface: ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ pass ++ ++ def KeepAliveCheck(self, ): ++ pass ++ ++ def Connect(self, ): ++ pass ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ pass ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ pass ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ pass ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ pass ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ pass ++ ++ ++class Client(Iface): ++ def __init__(self, iprot, oprot=None): ++ self._iprot = self._oprot = iprot ++ if oprot is not None: ++ self._oprot = oprot ++ self._seqid = 0 ++ ++ def AddPort(self, port_list): ++ """ ++ Parameters: ++ - port_list ++ """ ++ self.send_AddPort(port_list) ++ return self.recv_AddPort() ++ ++ def send_AddPort(self, port_list): ++ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) ++ args = AddPort_args() ++ args.port_list = port_list ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddPort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddPort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); ++ ++ def KeepAliveCheck(self, ): ++ self.send_KeepAliveCheck() ++ return self.recv_KeepAliveCheck() ++ ++ def send_KeepAliveCheck(self, ): ++ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) ++ args = KeepAliveCheck_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_KeepAliveCheck(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = KeepAliveCheck_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); ++ ++ def Connect(self, ): ++ self.send_Connect() ++ return self.recv_Connect() ++ ++ def send_Connect(self, ): ++ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) ++ args = Connect_args() ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_Connect(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = Connect_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); ++ ++ def DeletePort(self, port_id): ++ """ ++ Parameters: ++ - port_id ++ """ ++ self.send_DeletePort(port_id) ++ return self.recv_DeletePort() ++ ++ def send_DeletePort(self, port_id): ++ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) ++ args = DeletePort_args() ++ args.port_id = port_id ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_DeletePort(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = DeletePort_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); ++ ++ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryAdd() ++ ++ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryAdd_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); ++ ++ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ """ ++ Parameters: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) ++ return self.recv_TunnelNHEntryDelete() ++ ++ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): ++ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) ++ args = TunnelNHEntryDelete_args() ++ args.src_ip = src_ip ++ args.dst_ip = dst_ip ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_TunnelNHEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = TunnelNHEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); ++ ++ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) ++ return self.recv_RouteEntryAdd() ++ ++ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) ++ args = RouteEntryAdd_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryAdd(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryAdd_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); ++ ++ def RouteEntryDelete(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_RouteEntryDelete(ip_address, vrf_name) ++ return self.recv_RouteEntryDelete() ++ ++ def send_RouteEntryDelete(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) ++ args = RouteEntryDelete_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_RouteEntryDelete(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = RouteEntryDelete_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); ++ ++ def AddHostRoute(self, ip_address, vrf_name): ++ """ ++ Parameters: ++ - ip_address ++ - vrf_name ++ """ ++ self.send_AddHostRoute(ip_address, vrf_name) ++ return self.recv_AddHostRoute() ++ ++ def send_AddHostRoute(self, ip_address, vrf_name): ++ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) ++ args = AddHostRoute_args() ++ args.ip_address = ip_address ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddHostRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddHostRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); ++ ++ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) ++ return self.recv_AddLocalVmRoute() ++ ++ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): ++ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) ++ args = AddLocalVmRoute_args() ++ args.ip_address = ip_address ++ args.intf_uuid = intf_uuid ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddLocalVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddLocalVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); ++ ++ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ """ ++ Parameters: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) ++ return self.recv_AddRemoteVmRoute() ++ ++ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): ++ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) ++ args = AddRemoteVmRoute_args() ++ args.ip_address = ip_address ++ args.gw_ip = gw_ip ++ args.vrf_name = vrf_name ++ args.label = label ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_AddRemoteVmRoute(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = AddRemoteVmRoute_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); ++ ++ def CreateVrf(self, vrf_name): ++ """ ++ Parameters: ++ - vrf_name ++ """ ++ self.send_CreateVrf(vrf_name) ++ return self.recv_CreateVrf() ++ ++ def send_CreateVrf(self, vrf_name): ++ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) ++ args = CreateVrf_args() ++ args.vrf_name = vrf_name ++ args.write(self._oprot) ++ self._oprot.writeMessageEnd() ++ self._oprot.trans.flush() ++ ++ def recv_CreateVrf(self, ): ++ (fname, mtype, rseqid) = self._iprot.readMessageBegin() ++ if mtype == TMessageType.EXCEPTION: ++ x = TApplicationException() ++ x.read(self._iprot) ++ self._iprot.readMessageEnd() ++ raise x ++ result = CreateVrf_result() ++ result.read(self._iprot) ++ self._iprot.readMessageEnd() ++ if result.success is not None: ++ return result.success ++ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); ++ ++ ++class Processor(Iface, TProcessor): ++ def __init__(self, handler): ++ self._handler = handler ++ self._processMap = {} ++ self._processMap["AddPort"] = Processor.process_AddPort ++ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck ++ self._processMap["Connect"] = Processor.process_Connect ++ self._processMap["DeletePort"] = Processor.process_DeletePort ++ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd ++ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete ++ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd ++ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete ++ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute ++ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute ++ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute ++ self._processMap["CreateVrf"] = Processor.process_CreateVrf ++ ++ def process(self, iprot, oprot): ++ (name, type, seqid) = iprot.readMessageBegin() ++ if name not in self._processMap: ++ iprot.skip(TType.STRUCT) ++ iprot.readMessageEnd() ++ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) ++ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) ++ x.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ return ++ else: ++ self._processMap[name](self, seqid, iprot, oprot) ++ return True ++ ++ def process_AddPort(self, seqid, iprot, oprot): ++ args = AddPort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddPort_result() ++ result.success = self._handler.AddPort(args.port_list) ++ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_KeepAliveCheck(self, seqid, iprot, oprot): ++ args = KeepAliveCheck_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = KeepAliveCheck_result() ++ result.success = self._handler.KeepAliveCheck() ++ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_Connect(self, seqid, iprot, oprot): ++ args = Connect_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = Connect_result() ++ result.success = self._handler.Connect() ++ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_DeletePort(self, seqid, iprot, oprot): ++ args = DeletePort_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = DeletePort_result() ++ result.success = self._handler.DeletePort(args.port_id) ++ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): ++ args = TunnelNHEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryAdd_result() ++ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): ++ args = TunnelNHEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = TunnelNHEntryDelete_result() ++ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) ++ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryAdd(self, seqid, iprot, oprot): ++ args = RouteEntryAdd_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryAdd_result() ++ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_RouteEntryDelete(self, seqid, iprot, oprot): ++ args = RouteEntryDelete_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = RouteEntryDelete_result() ++ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddHostRoute(self, seqid, iprot, oprot): ++ args = AddHostRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddHostRoute_result() ++ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) ++ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddLocalVmRoute(self, seqid, iprot, oprot): ++ args = AddLocalVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddLocalVmRoute_result() ++ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): ++ args = AddRemoteVmRoute_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = AddRemoteVmRoute_result() ++ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) ++ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ def process_CreateVrf(self, seqid, iprot, oprot): ++ args = CreateVrf_args() ++ args.read(iprot) ++ iprot.readMessageEnd() ++ result = CreateVrf_result() ++ result.success = self._handler.CreateVrf(args.vrf_name) ++ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) ++ result.write(oprot) ++ oprot.writeMessageEnd() ++ oprot.trans.flush() ++ ++ ++# HELPER FUNCTIONS AND STRUCTURES ++ ++class AddPort_args: ++ """ ++ Attributes: ++ - port_list ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_list=None,): ++ self.port_list = port_list ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_list = [] ++ (_etype24, _size21) = iprot.readListBegin() ++ for _i25 in xrange(_size21): ++ _elem26 = Port() ++ _elem26.read(iprot) ++ self.port_list.append(_elem26) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_args') ++ if self.port_list is not None: ++ oprot.writeFieldBegin('port_list', TType.LIST, -1) ++ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) ++ for iter27 in self.port_list: ++ iter27.write(oprot) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddPort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddPort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class KeepAliveCheck_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('KeepAliveCheck_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_args: ++ ++ thrift_spec = ( ++ ) ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_args') ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class Connect_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Connect_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_args: ++ """ ++ Attributes: ++ - port_id ++ """ ++ ++ thrift_spec = None ++ def __init__(self, port_id=None,): ++ self.port_id = port_id ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == -1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype31, _size28) = iprot.readListBegin() ++ for _i32 in xrange(_size28): ++ _elem33 = iprot.readI16(); ++ self.port_id.append(_elem33) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_args') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, -1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter34 in self.port_id: ++ oprot.writeI16(iter34) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class DeletePort_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('DeletePort_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_args: ++ """ ++ Attributes: ++ - src_ip ++ - dst_ip ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'src_ip', None, None, ), # 1 ++ (2, TType.STRING, 'dst_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ ) ++ ++ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): ++ self.src_ip = src_ip ++ self.dst_ip = dst_ip ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.src_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.dst_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_args') ++ if self.src_ip is not None: ++ oprot.writeFieldBegin('src_ip', TType.STRING, 1) ++ oprot.writeString(self.src_ip) ++ oprot.writeFieldEnd() ++ if self.dst_ip is not None: ++ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) ++ oprot.writeString(self.dst_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.src_ip is None: ++ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') ++ if self.dst_ip is None: ++ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class TunnelNHEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('TunnelNHEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryAdd_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryAdd_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class RouteEntryDelete_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('RouteEntryDelete_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'vrf_name', None, None, ), # 2 ++ ) ++ ++ def __init__(self, ip_address=None, vrf_name=None,): ++ self.ip_address = ip_address ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddHostRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddHostRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - intf_uuid ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.intf_uuid = intf_uuid ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.intf_uuid = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.intf_uuid is not None: ++ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) ++ oprot.writeString(self.intf_uuid) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.intf_uuid is None: ++ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddLocalVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddLocalVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_args: ++ """ ++ Attributes: ++ - ip_address ++ - gw_ip ++ - vrf_name ++ - label ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'ip_address', None, None, ), # 1 ++ (2, TType.STRING, 'gw_ip', None, None, ), # 2 ++ (3, TType.STRING, 'vrf_name', None, None, ), # 3 ++ (4, TType.STRING, 'label', None, None, ), # 4 ++ ) ++ ++ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): ++ self.ip_address = ip_address ++ self.gw_ip = gw_ip ++ self.vrf_name = vrf_name ++ self.label = label ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.STRING: ++ self.gw_ip = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.label = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_args') ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 1) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.gw_ip is not None: ++ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) ++ oprot.writeString(self.gw_ip) ++ oprot.writeFieldEnd() ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ if self.label is not None: ++ oprot.writeFieldBegin('label', TType.STRING, 4) ++ oprot.writeString(self.label) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.gw_ip is None: ++ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class AddRemoteVmRoute_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('AddRemoteVmRoute_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_args: ++ """ ++ Attributes: ++ - vrf_name ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.STRING, 'vrf_name', None, None, ), # 1 ++ ) ++ ++ def __init__(self, vrf_name=None,): ++ self.vrf_name = vrf_name ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.STRING: ++ self.vrf_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_args') ++ if self.vrf_name is not None: ++ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) ++ oprot.writeString(self.vrf_name) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.vrf_name is None: ++ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) ++ ++class CreateVrf_result: ++ """ ++ Attributes: ++ - success ++ """ ++ ++ thrift_spec = ( ++ (0, TType.BOOL, 'success', None, None, ), # 0 ++ ) ++ ++ def __init__(self, success=None,): ++ self.success = success ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 0: ++ if ftype == TType.BOOL: ++ self.success = iprot.readBool(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('CreateVrf_result') ++ if self.success is not None: ++ oprot.writeFieldBegin('success', TType.BOOL, 0) ++ oprot.writeBool(self.success) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) +diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py +new file mode 100644 +index 0000000..f34ead4 +--- /dev/null ++++ plugins/contrail/instance_service/__init__.py +@@ -0,0 +1 @@ ++__all__ = ['ttypes', 'constants', 'InstanceService'] +diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py +new file mode 100644 +index 0000000..73f07fe +--- /dev/null ++++ plugins/contrail/instance_service/constants.py +@@ -0,0 +1,11 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++from ttypes import * ++ +diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py +new file mode 100644 +index 0000000..564f82e +--- /dev/null ++++ plugins/contrail/instance_service/ttypes.py +@@ -0,0 +1,210 @@ ++# ++# Autogenerated by Thrift Compiler (0.8.0) ++# ++# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING ++# ++# options string: py ++# ++ ++from thrift.Thrift import TType, TMessageType, TException ++ ++from thrift.transport import TTransport ++from thrift.protocol import TBinaryProtocol, TProtocol ++try: ++ from thrift.protocol import fastbinary ++except: ++ fastbinary = None ++ ++ ++ ++class Port: ++ """ ++ Attributes: ++ - port_id ++ - instance_id ++ - tap_name ++ - ip_address ++ - vn_id ++ - mac_address ++ - display_name ++ - hostname ++ - host ++ """ ++ ++ thrift_spec = ( ++ None, # 0 ++ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 ++ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 ++ (3, TType.STRING, 'tap_name', None, None, ), # 3 ++ (4, TType.STRING, 'ip_address', None, None, ), # 4 ++ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 ++ (6, TType.STRING, 'mac_address', None, None, ), # 6 ++ (7, TType.STRING, 'display_name', None, None, ), # 7 ++ (8, TType.STRING, 'hostname', None, None, ), # 8 ++ (9, TType.STRING, 'host', None, None, ), # 9 ++ ) ++ ++ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): ++ self.port_id = port_id ++ self.instance_id = instance_id ++ self.tap_name = tap_name ++ self.ip_address = ip_address ++ self.vn_id = vn_id ++ self.mac_address = mac_address ++ self.display_name = display_name ++ self.hostname = hostname ++ self.host = host ++ ++ def read(self, iprot): ++ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: ++ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) ++ return ++ iprot.readStructBegin() ++ while True: ++ (fname, ftype, fid) = iprot.readFieldBegin() ++ if ftype == TType.STOP: ++ break ++ if fid == 1: ++ if ftype == TType.LIST: ++ self.port_id = [] ++ (_etype3, _size0) = iprot.readListBegin() ++ for _i4 in xrange(_size0): ++ _elem5 = iprot.readI16(); ++ self.port_id.append(_elem5) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 2: ++ if ftype == TType.LIST: ++ self.instance_id = [] ++ (_etype9, _size6) = iprot.readListBegin() ++ for _i10 in xrange(_size6): ++ _elem11 = iprot.readI16(); ++ self.instance_id.append(_elem11) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 3: ++ if ftype == TType.STRING: ++ self.tap_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 4: ++ if ftype == TType.STRING: ++ self.ip_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 5: ++ if ftype == TType.LIST: ++ self.vn_id = [] ++ (_etype15, _size12) = iprot.readListBegin() ++ for _i16 in xrange(_size12): ++ _elem17 = iprot.readI16(); ++ self.vn_id.append(_elem17) ++ iprot.readListEnd() ++ else: ++ iprot.skip(ftype) ++ elif fid == 6: ++ if ftype == TType.STRING: ++ self.mac_address = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 7: ++ if ftype == TType.STRING: ++ self.display_name = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 8: ++ if ftype == TType.STRING: ++ self.hostname = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ elif fid == 9: ++ if ftype == TType.STRING: ++ self.host = iprot.readString(); ++ else: ++ iprot.skip(ftype) ++ else: ++ iprot.skip(ftype) ++ iprot.readFieldEnd() ++ iprot.readStructEnd() ++ ++ def write(self, oprot): ++ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: ++ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) ++ return ++ oprot.writeStructBegin('Port') ++ if self.port_id is not None: ++ oprot.writeFieldBegin('port_id', TType.LIST, 1) ++ oprot.writeListBegin(TType.I16, len(self.port_id)) ++ for iter18 in self.port_id: ++ oprot.writeI16(iter18) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.instance_id is not None: ++ oprot.writeFieldBegin('instance_id', TType.LIST, 2) ++ oprot.writeListBegin(TType.I16, len(self.instance_id)) ++ for iter19 in self.instance_id: ++ oprot.writeI16(iter19) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.tap_name is not None: ++ oprot.writeFieldBegin('tap_name', TType.STRING, 3) ++ oprot.writeString(self.tap_name) ++ oprot.writeFieldEnd() ++ if self.ip_address is not None: ++ oprot.writeFieldBegin('ip_address', TType.STRING, 4) ++ oprot.writeString(self.ip_address) ++ oprot.writeFieldEnd() ++ if self.vn_id is not None: ++ oprot.writeFieldBegin('vn_id', TType.LIST, 5) ++ oprot.writeListBegin(TType.I16, len(self.vn_id)) ++ for iter20 in self.vn_id: ++ oprot.writeI16(iter20) ++ oprot.writeListEnd() ++ oprot.writeFieldEnd() ++ if self.mac_address is not None: ++ oprot.writeFieldBegin('mac_address', TType.STRING, 6) ++ oprot.writeString(self.mac_address) ++ oprot.writeFieldEnd() ++ if self.display_name is not None: ++ oprot.writeFieldBegin('display_name', TType.STRING, 7) ++ oprot.writeString(self.display_name) ++ oprot.writeFieldEnd() ++ if self.hostname is not None: ++ oprot.writeFieldBegin('hostname', TType.STRING, 8) ++ oprot.writeString(self.hostname) ++ oprot.writeFieldEnd() ++ if self.host is not None: ++ oprot.writeFieldBegin('host', TType.STRING, 9) ++ oprot.writeString(self.host) ++ oprot.writeFieldEnd() ++ oprot.writeFieldStop() ++ oprot.writeStructEnd() ++ ++ def validate(self): ++ if self.port_id is None: ++ raise TProtocol.TProtocolException(message='Required field port_id is unset!') ++ if self.instance_id is None: ++ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') ++ if self.tap_name is None: ++ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') ++ if self.ip_address is None: ++ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') ++ if self.vn_id is None: ++ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') ++ if self.mac_address is None: ++ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') ++ return ++ ++ ++ def __repr__(self): ++ L = ['%s=%r' % (key, value) ++ for key, value in self.__dict__.iteritems()] ++ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) ++ ++ def __eq__(self, other): ++ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ ++ ++ def __ne__(self, other): ++ return not (self == other) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 1ad3959397..732b012822 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -101,7 +101,7 @@ function install_contrail() { elif [ ! -d $CONTRAIL_SRC/third_party/apache-cassandra-2.0.2-bin ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://www.bizdirusa.com/mirrors/apache/cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz + wget http://repo1.maven.org/maven2/org/apache/cassandra/apache-cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz tar xvzf apache-cassandra-2.0.2-bin.tar.gz cd ${contrail_cwd} fi @@ -177,11 +177,11 @@ function test_install_cassandra_patch() { } function test_install_neutron_patch() { - apply_patch $TOP_DIR/contrail/neutron_v3.patch $DEST/neutron + apply_patch $TOP_DIR/contrail/neutron_v4.patch $DEST/neutron } function test_install_nova_patch() { - apply_patch $TOP_DIR/contrail/nova_v3.patch $DEST/nova + apply_patch $TOP_DIR/contrail/nova_v4.patch $DEST/nova if [ -e $DEST/nova/plugins/contrail/config_parser.py ]; then sudo cp $DEST/nova/plugins/contrail/config_parser.py /usr/bin/config_parser sudo chmod +x /usr/bin/config_parser From 22d96b5bbaf4dc3aa92ab3d2d951c0421830f42e Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 5 Dec 2013 22:04:07 -0800 Subject: [PATCH 088/179] Provision Vrouter --- lib/neutron_thirdparty/contrail | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 732b012822..c605102ffe 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -314,6 +314,13 @@ function start_contrail() { source /etc/contrail/control_param screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + # Provision Vrouter - must be run after API server and schema transformer are up + sleep 2 + admin_user=${CONTRAIL_ADMIN_USERNAME:-"admin"} + admin_passwd=${ADMIN_PASSWORD:-"contrail123"} + admin_tenant=${CONTRAIL_ADMIN_TENANT:-"admin"} + python $TOP_DIR/contrail/provision_vrouter.py --host_name $HOSTNAME --host_ip $HOST_IP --api_server_ip $SERVICE_HOST --oper add --admin_user $admin_user --admin_password $admin_passwd --admin_tenant_name $admin_tenant + # vrouter test_insert_vrouter From 050ebc490dc980cdc38148936a23b53495989122 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 6 Dec 2013 08:58:13 +0000 Subject: [PATCH 089/179] use cirros test image if available --- contrail/test_network.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/contrail/test_network.sh b/contrail/test_network.sh index 2ec4178618..d7f9ce2604 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -59,17 +59,17 @@ python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --pr # vms image=cirros-0.3.1-x86_64-uec # default stock image -## try to use a test image instead of stock -#IMAGE_NAME=${IMAGE_NAME:-cirros-test} -#IMAGE_FILE=${IMAGE_FILE:-~/projects/piston/projects/cirros/cirros-0.3.1-x86_64-nbk.qcow2} -#if glance image-show $IMAGE_NAME > /dev/null 2>&1; then -# image=$IMAGE_NAME -#else -# if [ -e $IMAGE_FILE ] && -# glance image-create --name=$IMAGE_NAME --disk-format qcow2 --container-format=bare < $IMAGE_FILE; then -# image=$IMAGE_NAME -# fi -#fi +# try to use a test image instead of stock +IMAGE_NAME=${IMAGE_NAME:-cirros-test} +IMAGE_FILE=${IMAGE_FILE:-~/projects/piston/projects/cirros/cirros-0.3.1-x86_64-nbk.qcow2} +if glance image-show $IMAGE_NAME > /dev/null 2>&1; then + image=$IMAGE_NAME +else + if [ -e $IMAGE_FILE ] && + glance image-create --name=$IMAGE_NAME --disk-format qcow2 --container-format=bare < $IMAGE_FILE; then + image=$IMAGE_NAME + fi +fi flavor=m1.tiny base="--image $image --flavor $flavor" From aea55de00174d2d98d3c09f9f3dd8fd7e1f98ad7 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 6 Dec 2013 18:33:54 +0000 Subject: [PATCH 090/179] cloudinit.sh script injection works --- contrail/test_network.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/contrail/test_network.sh b/contrail/test_network.sh index d7f9ce2604..4500177391 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -29,6 +29,10 @@ set -ex . ./openrc admin demo +ssh-keygen -f id_rsa +nova keypair-add --pub-key id_rsa.pub sshkey + + # allow ping and ssh nova secgroup-list nova secgroup-list-rules default @@ -71,8 +75,19 @@ else fi fi +tee cloudinit.sh < Date: Mon, 9 Dec 2013 05:17:07 -0800 Subject: [PATCH 091/179] Add steps for Ubuntu --- contrail/README | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/contrail/README b/contrail/README index 93144dc007..8d70451164 100644 --- a/contrail/README +++ b/contrail/README @@ -1,6 +1,11 @@ This fork of devstack brings up all in one openstack + opencontrail system. Run stack.sh as usual to setup OpenStack + contrail modules. +Contrail directory also includes some sample localrc files. +1) localrc-single: for all-in-one system +2) localrc-multinode-server: master host on a multi node system. +3) localrc-multinode-compute: all compute nodes. + Notes: 1) You will need to install kernel-devel package to compile OpenContrail Vrouter module @@ -12,12 +17,35 @@ Notes: otherwise checking out contrail code will fail. The repo tool assumes ssh and will not work with HTTPS git url. You can have ssh-agent forward keys to target system running devstack. +6) Copy sample localrc-single as localrc for a single node system. Copy + localrc-multinode-server and localrc-multinode-compute as localrc on + master and compute nodes respectively for a multi-node system. -Contrail directory also includes some sample localrc files. -1) localrc-single: for all-in-one system -2) localrc-multinode-server: master host on a multi node system. -3) localrc-multinode-compute: all compute nodes. - -Change the following to suit your deployment: +Change the following in localrc to suit your deployment: PHYSICAL_INTERFACE -- external interface Vrouter should bind to SERVICE_HOST -- IP address of master + +Steps for basic Ubuntu VM image +------------------------------- +1) ssh as ubuntu to target. Password should be ubuntu +2) Add following line to /etc/hosts to avoid + "sudo: unable to resolve host ubuntu" error + 127.0.1.1 ubuntu +3) Get following packages. You may need to change linux header version + package based on "uname -a" output + sudo apt-get update + sudo apt-get install git-core + sudo aptitude install build-essential + sudo apt-get install pkg-config + sudo apt-get install linux-headers-3.2.0-35-virtual (for vrouter.ko) +4) verify ssh to github is working + ssh -T git@github.com +5) download devstack (should have already done this) + git clone git@github.com:dsetia/devstack.git +6) copy sample localrc as mentioned above. Edit localrc + PHYSICAL_INTERFACE/SERVICE_HOST/... to match your setup + + cd devstack + cp contrail/localrc-single localrc + vi localrc # edit PHYSICAL_INTERFACE +7) ./stack.sh From f412b51282b74bebb1b127a0cf9ec98e4a70a5a6 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 9 Dec 2013 18:55:28 +0000 Subject: [PATCH 092/179] fixed localrc-multinode-compute for my local setup --- contrail/localrc-multinode-compute | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index f6b3279da2..d649e2addb 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -1,7 +1,7 @@ -HOST_IP=192.168.56.103 # publicly routable ip to me +#HOST_IP=192.168.56.104 # publicly routable ip to me # change this to your master node's ip -SERVICE_HOST=172.18.4.119 # control1 +SERVICE_HOST=192.168.56.119 # control1 # the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 From 1b2f488fe90b6a41fcb08da9e63ff128123dd949 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 9 Dec 2013 10:59:33 -0800 Subject: [PATCH 093/179] Update READEM --- contrail/README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrail/README b/contrail/README index 22bd743c2e..93144dc007 100644 --- a/contrail/README +++ b/contrail/README @@ -8,6 +8,10 @@ Notes: 3) This fork includes Neutron and Nova patches. These patches have been seperately submitted for review. 4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 +5) You need a github account. Register host's SSH keys to the github account + otherwise checking out contrail code will fail. The repo tool assumes + ssh and will not work with HTTPS git url. You can have ssh-agent forward + keys to target system running devstack. Contrail directory also includes some sample localrc files. 1) localrc-single: for all-in-one system From e4867dfea0004d646d9f50b435dd2f1c68da5685 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 9 Dec 2013 19:33:31 +0000 Subject: [PATCH 094/179] bumped cassandra from 08x to 11x --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index beac71de8a..503e8ca273 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -88,7 +88,7 @@ function install_contrail() { yes | apt_get install oracle-java7-installer # See http://wiki.apache.org/cassandra/DebianPackaging - echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | \ + echo "deb http://www.apache.org/dist/cassandra/debian 11x main" | \ sudo tee /etc/apt/sources.list.d/cassandra.list gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D gpg --export --armor F758CE318D77295D | sudo apt-key add - From d0ce3f44c43cc7a3627c22e980b42e9f3c7a1b6b Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 9 Dec 2013 20:30:51 +0000 Subject: [PATCH 095/179] refactored functions for creating/associating floating ips --- contrail/test_network.sh | 75 ++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/contrail/test_network.sh b/contrail/test_network.sh index 4500177391..dd722c9bd3 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -29,8 +29,9 @@ set -ex . ./openrc admin demo -ssh-keygen -f id_rsa -nova keypair-add --pub-key id_rsa.pub sshkey +\rm -f sshkey +ssh-keygen -f sshkey +nova keypair-add --pub-key sshkey.pub sshkey # allow ping and ssh @@ -98,31 +99,61 @@ nova boot $base --nic net-id=$net2_id vm2 # vm3: net1, net2 nova boot $base --nic net-id=$net1_id --nic net-id=$net2_id vm3 -# floatingip for vm1 -eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) -floatingip1_id=$id -vm1_net1_ip=$(nova show vm1 | sed -ne 's/^| net1 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') -port1_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm1_net1_ip"'.*/\1/p') -neutron floatingip-associate $floatingip1_id $port1_id -neutron floatingip-show $floatingip1_id - -# floatingip for vm2 -eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p) -floatingip2_id=$id -vm2_net2_ip=$(nova show vm2 | sed -ne 's/^| net2 network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p') -port2_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm2_net2_ip"'.*/\1/p') -neutron floatingip-associate $floatingip2_id $port2_id -neutron floatingip-show $floatingip2_id - -# show where the vms ended up -nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host # if the net_policy_join script exists, then use it to join net1 and net2 -THIS_DIR=$(dirname $0) +# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced +THIS_DIR=$(dirname ${BASH_SOURCE[0]}) PATH=$THIS_DIR:$PATH if which net_policy_join.py; then net_policy_join.py $net1_id $net2_id fi -set +ex \ No newline at end of file +die() { + echo "ERROR: " "$@" >&2 + exit 1 +} + +# create a floating ip, usually on the $public network +floatingip_create() { + local public_id=$1 + + eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p || \ + die "couldn't create floatnig ip") + floatingip_id=$id + echo $floatingip_id +} + +# assign $floatingip_id to $vm_name's interface on $net_name +floatingip_associate() { + local vm_name=$1 + local net_name=$2 + local floatingip_id=$3 + + # find the port that the vm is attached to + vm_net_ip=$(nova show $vm_name | sed -ne 's/^| '"$net_name"' network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p' || \ + die "couldn't find $vm_name's ip on network $net_name") + port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm_net_ip"'.*/\1/p' || \ + die "couldn't find prt_id for ip $vm_net_ip") + neutron floatingip-associate $floatingip_id $port_id +} + +# floatingip1 for vm1,net1 +floatingip1_id=$(floatingip_create $public_id) +floatingip_associate vm1 net1 $floatingip1_id +neutron floatingip-show $floatingip1_id + +# floatingip2 for vm2,net2 +floatingip2_id=$(floatingip_create $public_id) +floatingip_associate vm2 net2 $floatingip2_id +neutron floatingip-show $floatingip2_id + +# floatingip3 for vm3,net1 +floatingip3_id=$(floatingip_create $public_id) +floatingip_associate vm3 net1 $floatingip3_id +neutron floatingip-show $floatingip3_id + +# show where the vms ended up +nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host + +set +ex From 6ecd1fa5dda2b4a98bd840aa3251e2e6648e2786 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 9 Dec 2013 20:38:31 +0000 Subject: [PATCH 096/179] regenerate sshkey without prompts --- contrail/test_network.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrail/test_network.sh b/contrail/test_network.sh index dd722c9bd3..8b3f28ac73 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -29,8 +29,7 @@ set -ex . ./openrc admin demo -\rm -f sshkey -ssh-keygen -f sshkey +yes | ssh-keygen -N "" -f sshkey nova keypair-add --pub-key sshkey.pub sshkey From 74ad6759d8e5bb2b67eae48c278dc482d25844ac Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Mon, 9 Dec 2013 21:40:42 +0000 Subject: [PATCH 097/179] added test for complex network --- contrail/test_network_complex.sh | 218 +++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100755 contrail/test_network_complex.sh diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh new file mode 100755 index 0000000000..ea9c5b4fae --- /dev/null +++ b/contrail/test_network_complex.sh @@ -0,0 +1,218 @@ +#! /bin/bash +# +# test_network_complex.sh +# +# test a complex network: +# +# +# net1 net2 net3 net4 +# | | | | +# | +- vrouter -+ | +# | 1 2 | | | +# +--- vm1 ---+ +- vrouter -+ +# | f | 1 2 | | +# | +--- vm3 ---+ | +# | 2 1 | | vm8 ---+ +# +--- vm2 ---+ | | +# | | 2 1 | | +# | +--- vm6 ---+ | +# | | | | +# +-----------------+ | | +# | | | | | +# | | 1| | | +# | +--- vm7 ---+ | +# | | 2 3 | | +# +--- vm4 | | | +# | | vm9 ---+ | +# | | | | +# | vm5----+ | | +# | | | | +# +# +# vm1: net1, net2, float on net2 +# vm2: net2, net1 +# vm4: net1 +# vm5: net2 +# vm3: net2, net3 +# vm6: net3, net2 +# vm7: net1, net2, net3 +# vm9: net3 +# vm8: net4 + +# die on errors +set -ex + +# source openrc after stack.sh completes to join the demo project as admin user +. ./openrc admin demo + +# add this script's directory to the path +THIS_DIR=$(pwd)$(dirname ${BASH_SOURCE[0]}) +PATH=$THIS_DIR:$PATH + +# functions + +die() { + echo "ERROR: " "$@" >&2 + exit 1 +} + +# create a network with $net_name and return its id +net_create() { + net_name="$1" + neutron net-create -f shell -c id $net_name | sed -ne '/^id=/p' || \ + die "Couldn't create network $net_name" +} + +# floatingip_create net_id +# +# create a floating ip on a network. The network must have a +# floatingip pool created for it. See create_floating_pool.py +# +floatingip_create() { + local net_id=$1 + + eval $(neutron floatingip-create -f shell -c id $net_id | sed -ne /id=/p || \ + die "couldn't create floating ip") + floatingip_id=$id + echo $floatingip_id=floatingip_id +} + +# floatingip_associate vm_name net_name floatingip_id +# +# assign floatingip_id to vm_name's interface on net_name +# +floatingip_associate() { + local vm_name=$1 + local net_name=$2 + local floatingip_id=$3 + + # find the port that the vm is attached to + vm_net_ip=$(nova show $vm_name | sed -ne 's/^| '"$net_name"' network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p' || \ + die "couldn't find $vm_name's ip on network $net_name") + port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm_net_ip"'.*/\1/p' || \ + die "couldn't find prt_id for ip $vm_net_ip") + neutron floatingip-associate $floatingip_id $port_id +} + + +# test script + +# secgroup allow ping and ssh +nova secgroup-list +nova secgroup-list-rules default +nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 +nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +nova secgroup-list-rules default + +# net1 +eval $(net_create net1) +net1_id=$id +neutron subnet-create --name net1-subnet1 $net1_id 10.1.0.0/24 + +# net2 (cloud) +eval $(net_create net2) +net2_id=$id +echo "net2_id=$net2_id" +neutron subnet-create --name net2-subnet1 $net2_id 10.2.0.0/24 + +# net3 (public) +eval $(net_create net3) +net3_id=$id +echo "net3_id=$net3_id" +# CONTRAIL_VGW_PUBLIC_SUBNET is set in localrc to be publicly addressable ips +neutron subnet-create --name net3-subnet1 $net3_id $CONTRAIL_VGW_PUBLIC_SUBNET --disable-dhcp + +# call contrail to create floating ip pool +python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py --public_vn_name default-domain:$OS_TENANT_NAME:net3 --floating_ip_pool_name floatingip_pool +python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:$OS_TENANT_NAME --floating_ip_pool_name default-domain:$OS_TENANT_NAME:net3:floatingip_pool + +# net4 (new) +eval $(net_create net4) +net4_id=$id +echo "net4_id=$net4_id" +neutron subnet-create --name net4-subnet1 $net4_id 10.4.0.0/24 + + +# call contrail to join networks, like a vrouter would +# if the net_policy_join script exists, then use it to join net1 and net2 +# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced +net_policy_join.py $net2_id $net3_id +net_policy_join.py $net3_id $net4_id + +# try to use a fixed cirros image that boots all network interfaces. +# default image name: cirros-test +IMAGE_NAME=${IMAGE_NAME:-cirros-test} +IMAGE_FILE=${IMAGE_FILE:-~/projects/piston/projects/cirros/cirros-0.3.1-x86_64-nbk.qcow2} +image="" +if glance image-show $IMAGE_NAME > /dev/null 2>&1; then + image=$IMAGE_NAME +fi +if [ ! "$image" ] && [ -e $IMAGE_FILE ] && \ + glance image-create --name=$IMAGE_NAME --disk-format qcow2 --container-format=bare < $IMAGE_FILE; then + image=$IMAGE_NAME +fi +if [ ! "$image" ]; then + # fall back to stock cirros + image=cirros-0.3.1-x86_64-uec +fi + +# make an ssh key +yes | ssh-keygen -N "" -f sshkey +nova keypair-add --pub-key sshkey.pub sshkey + +# cloudinit script to verify that the metadata server is working +tee cloudinit.sh < Date: Mon, 9 Dec 2013 14:50:25 -0800 Subject: [PATCH 098/179] Fix config_parser.py name --- contrail/nova_v4.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrail/nova_v4.patch b/contrail/nova_v4.patch index 10894878b7..93716cb3a7 100644 --- a/contrail/nova_v4.patch +++ b/contrail/nova_v4.patch @@ -122,11 +122,11 @@ index cfff8dd..0a51783 100644 elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: self.unplug_mlnx_direct(instance, vif) elif vif_type == network_model.VIF_TYPE_MIDONET: -diff --git plugins/contrail/contrail_parser.py plugins/contrail/contrail_parser.py +diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py new file mode 100755 index 0000000..acac9fb --- /dev/null -+++ plugins/contrail/contrail_parser.py ++++ plugins/contrail/config_parser.py @@ -0,0 +1,126 @@ +#! /usr/bin/env python +import os From 0565f80e7c4afdda4be6cad050f22987e4b842f2 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 10 Dec 2013 16:31:41 -0800 Subject: [PATCH 099/179] Fix permission error - install nova and neutron patch without sudo --- lib/neutron_thirdparty/contrail | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index c605102ffe..097f2fc513 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -153,6 +153,7 @@ function install_contrail() { function apply_patch() { local patch="$1" local dir="$2" + local sudo="$3" local patch_applied="${dir}/$(basename ${patch}).appled" # run patch, ignore previously applied patches, and return an @@ -163,7 +164,7 @@ function apply_patch() { echo "Patch $(basename $patch) was previously applied in $dir" else echo "Installing patch $(basename $patch) in $dir..." - if sudo patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then + if $sudo patch -p0 -N -r - -d "$dir" < "$patch" 2>&1 | grep -i fail; then die "Failed to apply $patch in $dir" else sudo touch "$patch_applied" @@ -173,7 +174,7 @@ function apply_patch() { } function test_install_cassandra_patch() { - apply_patch $TOP_DIR/contrail/cassandra-env.sh.patch /etc/cassandra + apply_patch $TOP_DIR/contrail/cassandra-env.sh.patch /etc/cassandra sudo } function test_install_neutron_patch() { From 0ab42ba7a88eb3cb0db544623f6f882a8cf08633 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Wed, 11 Dec 2013 13:18:08 -0800 Subject: [PATCH 100/179] test_network_complex works on multi-host --- contrail/test_network.sh | 105 +++++++++++-------------- contrail/test_network_complex.sh | 131 +++++++++++++++---------------- 2 files changed, 108 insertions(+), 128 deletions(-) diff --git a/contrail/test_network.sh b/contrail/test_network.sh index 8b3f28ac73..bbb9081cb0 100755 --- a/contrail/test_network.sh +++ b/contrail/test_network.sh @@ -27,11 +27,36 @@ set -ex -. ./openrc admin demo +die() { + echo "ERROR: " "$@" >&2 + exit 1 +} -yes | ssh-keygen -N "" -f sshkey -nova keypair-add --pub-key sshkey.pub sshkey +# create a floating ip, usually on the $public network +floatingip_create() { + local public_id=$1 + + eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p || \ + die "couldn't create floatnig ip") + floatingip_id=$id + echo $floatingip_id +} +# assign $floatingip_id to $vm_name's interface on $net_name +floatingip_associate() { + local vm_name=$1 + local net_name=$2 + local floatingip_id=$3 + + # find the port that the vm is attached to + vm_net_ip=$(nova show $vm_name | sed -ne 's/^| '"$net_name"' network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p' || \ + die "couldn't find $vm_name's ip on network $net_name") + port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm_net_ip"'.*/\1/p' || \ + die "couldn't find prt_id for ip $vm_net_ip") + neutron floatingip-associate $floatingip_id $port_id +} + +. ./openrc admin demo # allow ping and ssh nova secgroup-list @@ -60,6 +85,15 @@ neutron subnet-create --name public-subnet1 $public_id $CONTRAIL_VGW_PUBLIC_SUBN python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py --public_vn_name default-domain:demo:public --floating_ip_pool_name floatingip_pool python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:demo --floating_ip_pool_name default-domain:demo:public:floatingip_pool +# if the net_policy_join script exists, then use it to join net1 and net2 +# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced +THIS_DIR=$(dirname ${BASH_SOURCE[0]}) +PATH=$THIS_DIR:$PATH +if which net_policy_join.py; then + net_policy_join.py $net1_id $net2_id +fi + + # vms image=cirros-0.3.1-x86_64-uec # default stock image @@ -85,73 +119,24 @@ ip -f inet -o addr list EOF chmod a+x cloudinit.sh +yes | ssh-keygen -N "" -f sshkey +nova keypair-add --pub-key sshkey.pub sshkey flavor=m1.tiny -base="--image $image --flavor $flavor --key-name sshkey --user-data cloudinit.sh" - -# vm1: net1 -nova boot $base --nic net-id=$net1_id vm1 +vmargs="--image $image --flavor $flavor --key-name sshkey --user-data cloudinit.sh" -# vm2: net2 -nova boot $base --nic net-id=$net2_id vm2 - -# vm3: net1, net2 -nova boot $base --nic net-id=$net1_id --nic net-id=$net2_id vm3 - - -# if the net_policy_join script exists, then use it to join net1 and net2 -# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced -THIS_DIR=$(dirname ${BASH_SOURCE[0]}) -PATH=$THIS_DIR:$PATH -if which net_policy_join.py; then - net_policy_join.py $net1_id $net2_id -fi - - -die() { - echo "ERROR: " "$@" >&2 - exit 1 -} - -# create a floating ip, usually on the $public network -floatingip_create() { - local public_id=$1 - - eval $(neutron floatingip-create -f shell -c id $public_id | sed -ne /id=/p || \ - die "couldn't create floatnig ip") - floatingip_id=$id - echo $floatingip_id -} - -# assign $floatingip_id to $vm_name's interface on $net_name -floatingip_associate() { - local vm_name=$1 - local net_name=$2 - local floatingip_id=$3 - - # find the port that the vm is attached to - vm_net_ip=$(nova show $vm_name | sed -ne 's/^| '"$net_name"' network[ \t]*|[ \t]*\([.0-9]*\)[ \t]*|/\1/p' || \ - die "couldn't find $vm_name's ip on network $net_name") - port_id=$(neutron port-list | sed -ne 's/| \([-0-9a-f]*\)[ \t]*|[ \t]*.*'"$vm_net_ip"'.*/\1/p' || \ - die "couldn't find prt_id for ip $vm_net_ip") - neutron floatingip-associate $floatingip_id $port_id -} - -# floatingip1 for vm1,net1 +# vm1: net1, net2, floatingip1 on net1 (nic1): OK +nova boot $vmargs --nic net-id=$net1_id --nic net-id=$net2_id vm1 floatingip1_id=$(floatingip_create $public_id) floatingip_associate vm1 net1 $floatingip1_id neutron floatingip-show $floatingip1_id -# floatingip2 for vm2,net2 +# vm2: net2, net1, floatingip2 on net1 (nic2): FAIL +nova boot $vmargs --nic net-id=$net2_id --nic net-id=$net1_id vm2 floatingip2_id=$(floatingip_create $public_id) -floatingip_associate vm2 net2 $floatingip2_id +floatingip_associate vm2 net1 $floatingip2_id neutron floatingip-show $floatingip2_id -# floatingip3 for vm3,net1 -floatingip3_id=$(floatingip_create $public_id) -floatingip_associate vm3 net1 $floatingip3_id -neutron floatingip-show $floatingip3_id - # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh index ea9c5b4fae..04ab924f10 100755 --- a/contrail/test_network_complex.sh +++ b/contrail/test_network_complex.sh @@ -4,24 +4,24 @@ # # test a complex network: # -# -# net1 net2 net3 net4 +# net1 net2 public net4 # | | | | -# | +- vrouter -+ | +# +- vrouter -+ | | +# | +------------- vrouter -+ # | 1 2 | | | -# +--- vm1 ---+ +- vrouter -+ -# | f | 1 2 | | +# +--- vm1 ---+ | | +# | | 2 1 | vm8 ---+ # | +--- vm3 ---+ | -# | 2 1 | | vm8 ---+ +# | 2 1 | | | # +--- vm2 ---+ | | -# | | 2 1 | | +# | f | 2 1 | | # | +--- vm6 ---+ | # | | | | # +-----------------+ | | # | | | | | -# | | 1| | | +# | | 2| | | # | +--- vm7 ---+ | -# | | 2 3 | | +# | | 3 1 | | # +--- vm4 | | | # | | vm9 ---+ | # | | | | @@ -29,14 +29,14 @@ # | | | | # # -# vm1: net1, net2, float on net2 -# vm2: net2, net1 +# vm1: net1, net2 +# vm2: net2, net1, float on net2 # vm4: net1 # vm5: net2 -# vm3: net2, net3 -# vm6: net3, net2 -# vm7: net1, net2, net3 -# vm9: net3 +# vm3: public, net2 +# vm6: public, net2 +# vm7: public, net1, net2 +# vm9: public # vm8: net4 # die on errors @@ -45,10 +45,11 @@ set -ex # source openrc after stack.sh completes to join the demo project as admin user . ./openrc admin demo -# add this script's directory to the path -THIS_DIR=$(pwd)$(dirname ${BASH_SOURCE[0]}) +# add this script's parent directory to the path +THIS_DIR=$(dirname ${BASH_SOURCE[0]}) PATH=$THIS_DIR:$PATH +#---------------------------------------------------------------------- # functions die() { @@ -59,26 +60,26 @@ die() { # create a network with $net_name and return its id net_create() { net_name="$1" - neutron net-create -f shell -c id $net_name | sed -ne '/^id=/p' || \ - die "Couldn't create network $net_name" + eval $(neutron net-create -f shell -c id $net_name | sed -ne '/^id=/p' || \ + die "couldn't create network $net_name") + echo $id } # floatingip_create net_id # -# create a floating ip on a network. The network must have a -# floatingip pool created for it. See create_floating_pool.py +# create a floating ip on a network. the network must have a +# floatingip pool created for it. see create_floating_pool.py # floatingip_create() { local net_id=$1 eval $(neutron floatingip-create -f shell -c id $net_id | sed -ne /id=/p || \ die "couldn't create floating ip") - floatingip_id=$id - echo $floatingip_id=floatingip_id + echo $id } # floatingip_associate vm_name net_name floatingip_id -# +# # assign floatingip_id to vm_name's interface on net_name # floatingip_associate() { @@ -95,7 +96,8 @@ floatingip_associate() { } -# test script +#---------------------------------------------------------------------- +# create vms and network # secgroup allow ping and ssh nova secgroup-list @@ -105,39 +107,26 @@ nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 nova secgroup-list-rules default # net1 -eval $(net_create net1) -net1_id=$id +net1_id=$(net_create net1) neutron subnet-create --name net1-subnet1 $net1_id 10.1.0.0/24 # net2 (cloud) -eval $(net_create net2) -net2_id=$id +net2_id=$(net_create net2) echo "net2_id=$net2_id" neutron subnet-create --name net2-subnet1 $net2_id 10.2.0.0/24 -# net3 (public) -eval $(net_create net3) -net3_id=$id -echo "net3_id=$net3_id" +# public (public) +public_id=$(net_create public) +echo "public_id=$public_id" # CONTRAIL_VGW_PUBLIC_SUBNET is set in localrc to be publicly addressable ips -neutron subnet-create --name net3-subnet1 $net3_id $CONTRAIL_VGW_PUBLIC_SUBNET --disable-dhcp +neutron subnet-create --name public-subnet1 $public_id $CONTRAIL_VGW_PUBLIC_SUBNET --disable-dhcp # call contrail to create floating ip pool -python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py --public_vn_name default-domain:$OS_TENANT_NAME:net3 --floating_ip_pool_name floatingip_pool -python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:$OS_TENANT_NAME --floating_ip_pool_name default-domain:$OS_TENANT_NAME:net3:floatingip_pool - -# net4 (new) -eval $(net_create net4) -net4_id=$id -echo "net4_id=$net4_id" -neutron subnet-create --name net4-subnet1 $net4_id 10.4.0.0/24 +python /opt/stack/contrail/controller/src/config/utils/create_floating_pool.py --public_vn_name default-domain:demo:public --floating_ip_pool_name floatingip_pool +python /opt/stack/contrail/controller/src/config/utils/use_floating_pool.py --project_name default-domain:demo --floating_ip_pool_name default-domain:demo:public:floatingip_pool - -# call contrail to join networks, like a vrouter would -# if the net_policy_join script exists, then use it to join net1 and net2 -# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced -net_policy_join.py $net2_id $net3_id -net_policy_join.py $net3_id $net4_id +# route between net1 and net2 +net_policy_join.py $net1_id $net2_id # try to use a fixed cirros image that boots all network interfaces. # default image name: cirros-test @@ -151,13 +140,14 @@ if [ ! "$image" ] && [ -e $IMAGE_FILE ] && \ glance image-create --name=$IMAGE_NAME --disk-format qcow2 --container-format=bare < $IMAGE_FILE; then image=$IMAGE_NAME fi -if [ ! "$image" ]; then +if [ ! "$image" ]; then # fall back to stock cirros image=cirros-0.3.1-x86_64-uec fi # make an ssh key yes | ssh-keygen -N "" -f sshkey +ssh-add sshkey nova keypair-add --pub-key sshkey.pub sshkey # cloudinit script to verify that the metadata server is working @@ -167,7 +157,7 @@ echo "Cloudinit worked!" echo echo "Inet interfaces:" -ip -f inet -o addr list +ip -o -f inet addr list EOF chmod a+x cloudinit.sh @@ -175,37 +165,43 @@ chmod a+x cloudinit.sh flavor=m1.tiny vm_params="--image $image --flavor $flavor --key-name sshkey --user-data cloudinit.sh" - # vms -# vm1: net1, net2, float on net2 +# vm1: net1, net2 nova boot $vm_params --nic net-id=$net1_id --nic net-id=$net2_id vm1 -# floatingip1 for vm1,net2 -eval $(floatingip_create $net3_id) -floatingip1_id=$floatingip_id -floatingip_associate vm1 net2 $floatingip1_id -neutron floatingip-show $floatingip1_id -# vm2: net2, net1 +# vm2: net2, net1, float on net2 nova boot $vm_params --nic net-id=$net2_id --nic net-id=$net1_id vm2 +# floatingip1 for vm2,net2 +floatingip1_id=$(floatingip_create $public_id) +floatingip_associate vm2 net2 $floatingip1_id + # vm4: net1 nova boot $vm_params --nic net-id=$net1_id vm4 # vm5: net2 nova boot $vm_params --nic net-id=$net2_id vm5 -# vm3: net2, net3 -nova boot $vm_params --nic net-id=$net2_id --nic net-id=$net3_id vm3 +# vm3: public, net2 +nova boot $vm_params --nic net-id=$public_id --nic net-id=$net2_id vm3 + +# vm6: public, net2 +nova boot $vm_params --nic net-id=$public_id --nic net-id=$net2_id vm6 -# vm6: net3, net2 -nova boot $vm_params --nic net-id=$net3_id --nic net-id=$net2_id vm6 +# vm7: public, net1, net2 +nova boot $vm_params --nic net-id=$public_id --nic net-id=$net1_id --nic net-id=$net2_id vm7 -# vm7: net1, net2, net3 -nova boot $vm_params --nic net-id=$net1_id --nic net-id=$net2_id --nic net-id=$net3_id vm7 +# vm9: public +nova boot $vm_params --nic net-id=$public_id vm9 + +# net4 (new) +net4_id=$(net_create net4) +echo "net4_id=$net4_id" +neutron subnet-create --name net4-subnet1 $net4_id 10.4.0.0/24 -# vm9: net3 -nova boot $vm_params --nic net-id=$net3_id vm9 +# allow traffic between net2 and net4 +net_policy_join.py $net2_id $net4_id # vm8: net4 nova boot $vm_params --nic net-id=$net4_id vm8 @@ -213,6 +209,5 @@ nova boot $vm_params --nic net-id=$net4_id vm8 # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host - - +# restore the shell flags, since this script is usually sourced set +ex From c0ed17aa79ca0aab58fb60e3abdeeca0a4010d05 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 13 Dec 2013 09:51:20 -0800 Subject: [PATCH 101/179] call provision_linklocal.py to enable metadata server --- lib/neutron_thirdparty/contrail | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 0d3edac1ec..18fba23646 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -365,6 +365,19 @@ END screen_it vif "python /opt/stack/nova/plugins/contrail/contrail_vif.py" + if is_service_enabled q-meta; then + # set up a proxy route in contrail from 169.254.169.254:80 to + # my metadata server at port 8775 + python /opt/stack/contrail/controller/src/config/utils/provision_linklocal.py \ + --linklocal_service_name metadata \ + --linklocal_service_ip 169.254.169.254 \ + --linklocal_service_port 80 \ + --ipfabric_service_ip $Q_META_DATA_IP \ + --ipfabric_service_port 8775 \ + --oper add + fi + + # restore saved screen settings SCREEN_NAME=$SAVED_SCREEN_NAME } From a67a1b8eebdb6fd8767cbddb1df9a79506031446 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 13 Dec 2013 13:34:20 -0800 Subject: [PATCH 102/179] Use forked neutron repo --- contrail/localrc-multinode-compute | 4 ++++ contrail/localrc-multinode-server | 4 +++- contrail/localrc-single | 4 ++++ lib/neutron_thirdparty/contrail | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index f6b3279da2..96c3a886cf 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -34,3 +34,7 @@ SERVICE_TOKEN=contrail123 SERVICE_PASSWORD=contrail123 ADMIN_PASSWORD=contrail123 DATABASE_TYPE=mysql +# +# use contrail forked neutron repo +NEUTRON_REPO=https://github.com/dsetia/neutron.git +NEUTRON_BRANCH=master diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 750d95648b..2aaa01a7b4 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -39,4 +39,6 @@ SERVICE_TOKEN=contrail123 SERVICE_PASSWORD=contrail123 ADMIN_PASSWORD=contrail123 - +# use contrail forked neutron repo +NEUTRON_REPO=https://github.com/dsetia/neutron.git +NEUTRON_BRANCH=master diff --git a/contrail/localrc-single b/contrail/localrc-single index b44601aa05..58f43b55b9 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -1,5 +1,6 @@ STACK_DIR=$(cd $(dirname $0) && pwd) +SCREEN_LOGDIR=$STACK_DIR/log/screens LOG=True DEBUG=True LOGFILE=$STACK_DIR/log/stack.log @@ -24,3 +25,6 @@ ENABLE_CONTRAIL=yes Q_PLUGIN=contrail PHYSICAL_INTERFACE=eth1 +# use contrail forked neutron repo +NEUTRON_REPO=https://github.com/dsetia/neutron.git +NEUTRON_BRANCH=master diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 0d3edac1ec..33dfc1e6e0 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -68,7 +68,7 @@ function install_contrail() { sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) # install neutron patch after VNC api is built and installed - test_install_neutron_patch + # test_install_neutron_patch # get cassandra if ! which cassandra > /dev/null 2>&1 ; then From e311b8492099e633ba812f564807378cec7c7a23 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 13 Dec 2013 15:57:00 -0800 Subject: [PATCH 103/179] test script waits for vms to finish booting and completes ssh connectitivy tests --- contrail/test_network_complex.sh | 103 +++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh index 04ab924f10..453bb350cf 100755 --- a/contrail/test_network_complex.sh +++ b/contrail/test_network_complex.sh @@ -8,6 +8,7 @@ # | | | | # +- vrouter -+ | | # | +------------- vrouter -+ +# | | | | # | 1 2 | | | # +--- vm1 ---+ | | # | | 2 1 | vm8 ---+ @@ -153,11 +154,10 @@ nova keypair-add --pub-key sshkey.pub sshkey # cloudinit script to verify that the metadata server is working tee cloudinit.sh <&1) + if [ $? = 0 ]; then + echo "ok" + else + echo "fail" + die "$ssh_cmdline" $out + fi +} + +echo +echo "Testing SSH connecivity..." + +test_vm_ssh "vm2_float" $vm2_float_ip +test_vm_ssh "vm3_public" $vm3_public_ip +test_vm_ssh "vm6_public" $vm6_public_ip +test_vm_ssh "vm7_public" $vm7_public_ip +test_vm_ssh "vm9_public" $vm9_public_ip + +test_vm_ssh "vm2_float -> vm1_net1" $vm2_float_ip $vm1_net1_ip +test_vm_ssh "vm2_float -> vm4_net1" $vm2_float_ip $vm4_net1_ip +test_vm_ssh "vm2_float -> vm5_net2" $vm2_float_ip $vm5_net2_ip +test_vm_ssh "vm2_float -> vm1_net2 -> vm4_net1" $vm2_float_ip $vm1_net2_ip $vm4_net1_ip +test_vm_ssh "vm2_float -> vm8_net4" $vm2_float_ip $vm8_net4_ip +test_vm_ssh "vm2_float -> vm5_net2 -> vm8_net4" $vm2_float_ip $vm5_net2_ip $vm8_net4_ip +test_vm_ssh "vm7_public -> vm4_net1" $vm7_public_ip $vm4_net1_ip +test_vm_ssh "vm7_public -> vm5_net2" $vm7_public_ip $vm5_net2_ip +test_vm_ssh "vm7_public -> vm9_public" $vm7_public_ip $vm9_public_ip +test_vm_ssh "vm6_public -> vm2_net2" $vm6_public_ip $vm2_net2_ip + + From 11a5e33b32bf39dbb580bb91d17a68676e3c7066 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 13 Dec 2013 16:06:51 -0800 Subject: [PATCH 104/179] removed tabs to fix up ascii diagram --- contrail/test_network_complex.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh index 453bb350cf..83ab3071d8 100755 --- a/contrail/test_network_complex.sh +++ b/contrail/test_network_complex.sh @@ -7,8 +7,8 @@ # net1 net2 public net4 # | | | | # +- vrouter -+ | | -# | +------------- vrouter -+ -# | | | | +# | +------------- vrouter -+ +# | | | | # | 1 2 | | | # +--- vm1 ---+ | | # | | 2 1 | vm8 ---+ From 8f7e88a1b88e191b675c59fc0af75546afedefb1 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 16 Dec 2013 14:04:58 -0800 Subject: [PATCH 105/179] Start service monitor --- contrail/localrc-single | 8 +++++--- contrail/setup_contrail.py | 1 + lib/neutron_thirdparty/contrail | 1 + stackrc | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index 58f43b55b9..5a0924e165 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -8,13 +8,15 @@ LOGDAYS=1 disable_service n-net enable_service q-svc -disable_service q-agt -disable_service q-dhcp -disable_service q-l3 enable_service q-meta enable_service neutron enable_service contrail +# not used by contrail +disable_service q-agt +disable_service q-dhcp +disable_service q-l3 + DATABASE_PASSWORD=contrail123 RABBIT_PASSWORD=contrail123 SERVICE_TOKEN=contrail123 diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 6297751982..83268fa3f0 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -643,6 +643,7 @@ def fixup_config_files(self): self.run_shell("echo '# Contrail users' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'api-server:api-server' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'schema-transformer:schema-transformer' >> %s/basicauthusers.properties" % dir) + self.run_shell("echo 'svc-monitor:svc-monitor' >> %s/basicauthusers.properties" % dir) self.run_shell("sudo sed -e '/%s:/d' -e '/%s.dns:/d' %s/%s > %s/%s.new" \ %(control_ip, control_ip, dir, 'basicauthusers.properties', dir, 'basicauthusers.properties')) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 265abe88c8..3d3c4f4529 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -315,6 +315,7 @@ function start_contrail() { fi sleep 2 screen_it schema "python $(pywhere schema_transformer)/to_bgp.py --reset_config --conf_file /etc/contrail/schema_transformer.conf" + screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" diff --git a/stackrc b/stackrc index 3857212101..1cc62c84fb 100644 --- a/stackrc +++ b/stackrc @@ -33,7 +33,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,zk,control,agent,disco,vif,redis +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,vif,redis # Set the default Nova APIs to enable NOVA_ENABLED_APIS=ec2,osapi_compute,metadata From 5ec7ea929c9d7b7b2480abe028c358e075fccc22 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 13 Dec 2013 15:57:00 -0800 Subject: [PATCH 106/179] test script waits for vms to finish booting and completes ssh connectitivy tests --- contrail/test_network_complex.sh | 103 +++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh index 04ab924f10..453bb350cf 100755 --- a/contrail/test_network_complex.sh +++ b/contrail/test_network_complex.sh @@ -8,6 +8,7 @@ # | | | | # +- vrouter -+ | | # | +------------- vrouter -+ +# | | | | # | 1 2 | | | # +--- vm1 ---+ | | # | | 2 1 | vm8 ---+ @@ -153,11 +154,10 @@ nova keypair-add --pub-key sshkey.pub sshkey # cloudinit script to verify that the metadata server is working tee cloudinit.sh <&1) + if [ $? = 0 ]; then + echo "ok" + else + echo "fail" + die "$ssh_cmdline" $out + fi +} + +echo +echo "Testing SSH connecivity..." + +test_vm_ssh "vm2_float" $vm2_float_ip +test_vm_ssh "vm3_public" $vm3_public_ip +test_vm_ssh "vm6_public" $vm6_public_ip +test_vm_ssh "vm7_public" $vm7_public_ip +test_vm_ssh "vm9_public" $vm9_public_ip + +test_vm_ssh "vm2_float -> vm1_net1" $vm2_float_ip $vm1_net1_ip +test_vm_ssh "vm2_float -> vm4_net1" $vm2_float_ip $vm4_net1_ip +test_vm_ssh "vm2_float -> vm5_net2" $vm2_float_ip $vm5_net2_ip +test_vm_ssh "vm2_float -> vm1_net2 -> vm4_net1" $vm2_float_ip $vm1_net2_ip $vm4_net1_ip +test_vm_ssh "vm2_float -> vm8_net4" $vm2_float_ip $vm8_net4_ip +test_vm_ssh "vm2_float -> vm5_net2 -> vm8_net4" $vm2_float_ip $vm5_net2_ip $vm8_net4_ip +test_vm_ssh "vm7_public -> vm4_net1" $vm7_public_ip $vm4_net1_ip +test_vm_ssh "vm7_public -> vm5_net2" $vm7_public_ip $vm5_net2_ip +test_vm_ssh "vm7_public -> vm9_public" $vm7_public_ip $vm9_public_ip +test_vm_ssh "vm6_public -> vm2_net2" $vm6_public_ip $vm2_net2_ip + + From 5da69f2eef350ed32a5ef658139b69793ac7f8d2 Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 13 Dec 2013 16:06:51 -0800 Subject: [PATCH 107/179] removed tabs to fix up ascii diagram --- contrail/test_network_complex.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrail/test_network_complex.sh b/contrail/test_network_complex.sh index 453bb350cf..83ab3071d8 100755 --- a/contrail/test_network_complex.sh +++ b/contrail/test_network_complex.sh @@ -7,8 +7,8 @@ # net1 net2 public net4 # | | | | # +- vrouter -+ | | -# | +------------- vrouter -+ -# | | | | +# | +------------- vrouter -+ +# | | | | # | 1 2 | | | # +--- vm1 ---+ | | # | | 2 1 | vm8 ---+ From cd316e65a6bc8ef0ebbb9bb6c74d2435322f82bd Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Fri, 20 Dec 2013 05:12:19 +0000 Subject: [PATCH 108/179] added keyserver imports for cassandra on ubuntu --- lib/neutron_thirdparty/contrail | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 3d3c4f4529..beac71de8a 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -87,8 +87,14 @@ function install_contrail() { sudo debconf-set-selections yes | apt_get install oracle-java7-installer + # See http://wiki.apache.org/cassandra/DebianPackaging echo "deb http://www.apache.org/dist/cassandra/debian 08x main" | \ sudo tee /etc/apt/sources.list.d/cassandra.list + gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D + gpg --export --armor F758CE318D77295D | sudo apt-key add - + gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 + gpg --export --armor 2B5C1B00 | sudo apt-key add - + apt_get update apt_get install --force-yes cassandra From bde8640397c8b7b859d3b9dec76fdf153fbf0658 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Sun, 22 Dec 2013 01:01:46 -0800 Subject: [PATCH 109/179] Do not reset API server configuration permanently --- contrail/contrail_config_templates.py | 1 - 1 file changed, 1 deletion(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 5634f36321..fe58b25171 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -2,7 +2,6 @@ api_server_conf_template = string.Template(""" [DEFAULTS] -reset_config=True ifmap_server_ip=$__contrail_ifmap_server_ip__ ifmap_server_port=$__contrail_ifmap_server_port__ ifmap_username=$__contrail_ifmap_username__ From 1616493d80c1c835e24e43e4c68ac721724dd69c Mon Sep 17 00:00:00 2001 From: Noel Burton-Krahn Date: Thu, 2 Jan 2014 09:53:40 -0800 Subject: [PATCH 110/179] use cassandra 1.2 --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 503e8ca273..6d06b6d43b 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -88,7 +88,7 @@ function install_contrail() { yes | apt_get install oracle-java7-installer # See http://wiki.apache.org/cassandra/DebianPackaging - echo "deb http://www.apache.org/dist/cassandra/debian 11x main" | \ + echo "deb http://www.apache.org/dist/cassandra/debian 12x main" | \ sudo tee /etc/apt/sources.list.d/cassandra.list gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D gpg --export --armor F758CE318D77295D | sudo apt-key add - From 3311614b69c352d5bf88cc0cafbff4b7c7c43613 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 2 Jan 2014 15:56:05 -0800 Subject: [PATCH 111/179] Part of cassandra patch not needed after upgrade to latest version since stack size has been bumped up --- contrail/cassandra-env.sh.patch | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/contrail/cassandra-env.sh.patch b/contrail/cassandra-env.sh.patch index e16e64c1c4..1348e2e8bd 100644 --- a/contrail/cassandra-env.sh.patch +++ b/contrail/cassandra-env.sh.patch @@ -11,24 +11,3 @@ if [ "x$MAX_HEAP_SIZE" = "x" ] && [ "x$HEAP_NEWSIZE" = "x" ]; then calculate_heap_sizes -@@ -124,13 +124,13 @@ - JVM_OPTS="$JVM_OPTS -XX:HeapDumpPath=$CASSANDRA_HEAPDUMP_DIR/cassandra-`date +%s`-pid$$.hprof" - fi - --if [ "`uname`" = "Linux" ] ; then -- # reduce the per-thread stack size to minimize the impact of Thrift -- # thread-per-client. (Best practice is for client connections to -- # be pooled anyway.) Only do so on Linux where it is known to be -- # supported. -- JVM_OPTS="$JVM_OPTS -Xss128k" --fi -+#if [ "`uname`" = "Linux" ] ; then -+# # reduce the per-thread stack size to minimize the impact of Thrift -+# # thread-per-client. (Best practice is for client connections to -+# # be pooled anyway.) Only do so on Linux where it is known to be -+# # supported. -+# JVM_OPTS="$JVM_OPTS -Xss128k" -+#fi - - # GC tuning options - JVM_OPTS="$JVM_OPTS -XX:+UseParNewGC" From b55d9db855b65fcd737420763083385f65db22db Mon Sep 17 00:00:00 2001 From: Raj Reddy Date: Wed, 15 Jan 2014 11:23:01 -0800 Subject: [PATCH 112/179] start contrail analytics daemons w/ devstack --- contrail/contrail_config_templates.py | 8 ++- contrail/setup_contrail.py | 70 ++++++++++++++++++++++++++- lib/neutron_thirdparty/contrail | 54 ++++++++++++++++----- stackrc | 1 + 4 files changed, 117 insertions(+), 16 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index fe58b25171..7c73d662fd 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -15,6 +15,7 @@ log_file=$__contrail_log_file__ disc_server_ip=$__contrail_disc_server_ip__ disc_server_port=$__contrail_disc_server_port__ +collectors=$__contrail_collectors__ [SECURITY] use_certs=$__contrail_use_certs__ @@ -59,6 +60,7 @@ cassandra_server_list=$__contrail_cassandra_server_list__ disc_server_ip=$__contrail_disc_server_ip__ disc_server_port=$__contrail_disc_server_port__ +collectors=$__contrail_collectors__ [SECURITY] use_certs=$__contrail_use_certs__ @@ -86,6 +88,7 @@ cassandra_server_list=$__contrail_cassandra_server_list__ disc_server_ip=$__contrail_disc_server_ip__ disc_server_port=$__contrail_disc_server_port__ +collectors=$__contrail_collectors__ [SECURITY] use_certs=$__contrail_use_certs__ @@ -182,6 +185,7 @@ REDIS_SERVER=$__contrail_redis_server__ REDIS_SERVER_PORT=$__contrail_redis_server_port__ DISCOVERY=$__contrail_discovery_ip__ +COLLECTORS=$__contrail_collectors__ HOST_IP=$__contrail_host_ip__ LISTEN_PORT=$__contrail_listen_port__ HTTP_SERVER_PORT=$__contrail_http_server_port__ @@ -194,8 +198,8 @@ REDIS_SERVER=$__contrail_redis_server__ REDIS_SERVER_PORT=$__contrail_redis_server_port__ REDIS_QUERY_PORT=$__contrail_redis_query_port__ -COLLECTOR=$__contrail_collector__ -COLLECTOR_PORT=$__contrail_collector_port__ +HOST_IP=$__contrail_host_ip__ +COLLECTORS=$__contrail_collectors__ HTTP_SERVER_PORT=$__contrail_http_server_port__ REST_API_PORT=$__contrail_rest_api_port__ LOG_FILE=$__contrail_log_file__ diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 83268fa3f0..24eb958479 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -169,6 +169,7 @@ def _parse_args(self, args_str): # dsetia self._args.openstack_ip = self._args.cfgm_ip self._args.collector_ip = self._args.cfgm_ip + self._args.collector_ip_list = [self._args.cfgm_ip] self._args.discovery_ip = self._args.cfgm_ip self._args.control_ip = self._args.cfgm_ip self._args.compute_ip = self.get_management_ip(self._args.physical_interface) @@ -448,6 +449,9 @@ def fixup_config_files(self): self.run_shell("sudo chkconfig iptables off") self.run_shell("sudo iptables --flush") + cassandra_server_list = [(cassandra_server_ip, '9160') for cassandra_server_ip in self._args.cassandra_ip_list] + collector_server_list = [(collector_ip, '8086') for collector_ip in self._args.collector_ip_list] + if 'config' in self._args.role or 'compute' in self._args.role or 'openstack' in self._args.role: openstack_ip = self._args.openstack_ip compute_ip = self._args.compute_ip @@ -468,10 +472,71 @@ def fixup_config_files(self): # database (cassandra setup in contrail.sh) # collector in Phase 2 + if 'collector' in self._args.role: + self.run_shell("wget http://download.redis.io/releases/redis-2.6.14.tar.gz") + self.run_shell("tar xvzf redis-2.6.14.tar.gz redis-2.6.14/sentinel.conf") + self.run_shell("cp redis-2.6.14/sentinel.conf /opt/stack/sentinel.conf") + self.run_shell("rm -rf redis-2.6.14 redis-2.6.14.tar.gz") + REDIS_SENTINEL_BASE="/opt/stack/sentinel.conf" + REDIS_UVE="/etc/contrail/redis-uve.conf" + REDIS_QUERY="/etc/contrail/redis-query.conf" + REDIS_SENTINEL="/etc/contrail/sentinel.conf" + if os.path.isfile('/etc/redis/redis.conf'): + REDIS_CONF="/etc/redis/redis.conf" + else: + REDIS_CONF="/etc/redis.conf" + self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_UVE)) + self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_QUERY)) + self.run_shell("cp %s %s" %(REDIS_SENTINEL_BASE, REDIS_SENTINEL)) + + self.replace_in_file(REDIS_UVE, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-uve.pid') + self.replace_in_file(REDIS_UVE, 'port 6379', 'port 6381') + self.replace_in_file(REDIS_UVE, 'bind 127.0.0.1', '#bind 127.0.0.1') + self.replace_in_file(REDIS_UVE, 'logfile /var/log/redis/redis.log', 'logfile /var/log/redis/redis-uve.log') + self.replace_in_file(REDIS_UVE, 'dbfilename dump.rdb', 'dbfilename dump-uve.rdb') + + self.replace_in_file(REDIS_QUERY, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-query.pid') + self.replace_in_file(REDIS_QUERY, 'port 6379', 'port 6380') + self.replace_in_file(REDIS_QUERY, 'bind 127.0.0.1', '#bind 127.0.0.1') + self.replace_in_file(REDIS_QUERY, 'logfile /var/log/redis/redis.log', 'logfile /var/log/redis/redis-query.log') + self.replace_in_file(REDIS_QUERY, 'dbfilename dump.rdb', 'dbfilename dump-query.rdb') + + self.replace_in_file(REDIS_SENTINEL, 'sentinel monitor mymaster 127.0.0.1 6379 2', 'sentinel monitor mymaster '+collector_ip+' 6381 1') + + template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, + '__contrail_host_ip__': self._args.collector_ip, + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_log_local__': '--log-local', + '__contrail_log_file__': '--log-file=/var/log/contrail/collector.log', + } + self._template_substitute_write(vizd_param_template, + template_vals, temp_dir_name + '/vizd_param') + self.run_shell("sudo mv %s/vizd_param /etc/contrail/vizd_param" %(temp_dir_name)) + + template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_log_local__': '--log-local', + '__contrail_log_file__': '--log-file=/var/log/contrail/qe.log', + '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), + '__contrail_redis_server__' : collector_ip, + '__contrail_redis_server_port__' : 6380, + } + self._template_substitute_write(qe_param_template, + template_vals, temp_dir_name + '/qed_param') + self.run_shell("sudo mv %s/qed_param /etc/contrail/qed_param" %(temp_dir_name)) + + template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, + '__contrail_host_ip__': self._args.collector_ip, + '__contrail_log_local__': '--log_local', + '__contrail_log_file__': '--log_file=/var/log/contrail/opserver.log', + '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), + } + self._template_substitute_write(opserver_param_template, + template_vals, temp_dir_name + '/opserver_param') + self.run_shell("sudo mv %s/opserver_param /etc/contrail/opserver_param" %(temp_dir_name)) if 'config' in self._args.role: openstack_ip = self._args.openstack_ip - cassandra_server_list = [(cassandra_server_ip, '9160') for cassandra_server_ip in self._args.cassandra_ip_list] template_vals = {'__contrail_ifmap_server_ip__': cfgm_ip, '__contrail_ifmap_server_port__': '8444' if use_certs else '8443', '__contrail_ifmap_username__': 'api-server', @@ -492,6 +557,7 @@ def fixup_config_files(self): '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), '__contrail_disc_server_ip__': self._args.discovery_ip or '', '__contrail_disc_server_port__': '5998', + '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), } self._template_substitute_write(api_server_conf_template, template_vals, temp_dir_name + '/api_server.conf') @@ -529,6 +595,7 @@ def fixup_config_files(self): '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), '__contrail_disc_server_ip__': self._args.discovery_ip or '', '__contrail_disc_server_port__': '5998', + '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), } self._template_substitute_write(schema_transformer_conf_template, template_vals, temp_dir_name + '/schema_transformer.conf') @@ -554,6 +621,7 @@ def fixup_config_files(self): '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), '__contrail_disc_server_ip__': self._args.discovery_ip or '', '__contrail_disc_server_port__': '5998', + '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), } self._template_substitute_write(svc_monitor_conf_template, template_vals, temp_dir_name + '/svc_monitor.conf') diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 6d06b6d43b..058bb1ace1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -35,8 +35,13 @@ function install_contrail() { sudo yum -y install gcc-c++ python-devel autoconf automake libtool sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel sudo yum -y install tunctl - sudo yum -y install redis sudo yum -y install java-1.7.0-openjdk + + if ! which redis-server > /dev/null 2>&1 ; then + wget http://mir01.syntis.net/atomic/fedora/17/x86_64/RPMS/redis-2.6.13-3.fc17.art.x86_64.rpm + sudo yum -y install redis-2.6.13-3.fc17.art.x86_64.rpm + rm -rf redis-2.6.13-3.fc17.art.x86_64.rpm + fi fi # api server requirements @@ -104,13 +109,13 @@ function install_contrail() { # don't start cassandra at boot. I'll screen_it later sudo service cassandra stop sudo update-rc.d -f cassandra remove - elif [ ! -d $CONTRAIL_SRC/third_party/apache-cassandra-2.0.2-bin ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - wget http://repo1.maven.org/maven2/org/apache/cassandra/apache-cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz - tar xvzf apache-cassandra-2.0.2-bin.tar.gz - cd ${contrail_cwd} - fi + else + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + wget http://rpm.datastax.com/community/noarch/cassandra12-1.2.11-1.noarch.rpm + sudo yum -y install ./cassandra12-1.2.11-1.noarch.rpm + cd ${contrail_cwd} + fi fi # get ifmap @@ -291,17 +296,15 @@ function start_contrail() { if is_ubuntu; then REDIS_CONF="/etc/redis/redis.conf" - CASS_PATH="/usr/sbin/cassandra" else REDIS_CONF="/etc/redis.conf" - CASS_PATH="$CONTRAIL_SRC/third_party/apache-cassandra-2.0.2/bin/cassandra" fi # launch ... redis-cli flushall screen_it redis "sudo redis-server $REDIS_CONF" - screen_it cass "sudo $CASS_PATH -f" + screen_it cass "sudo cassandra -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" @@ -324,7 +327,31 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --collector ${COLLECTOR}" + + # collector services + # redis-uve + screen_it redis-u "sudo redis-server /etc/contrail/redis-uve.conf" + sleep 2 + # redis-query + screen_it redis-q "sudo redis-server /etc/contrail/redis-query.conf" + sleep 2 + # redis-sentinel + screen_it redis-s "sudo redis-server /etc/contrail/sentinel.conf --sentinel" + sleep 2 + + # collector/vizd + source /etc/contrail/vizd_param + screen_it vizd "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/analytics/vizd --cassandra-server-list ${CASSANDRA_SERVER_LIST} --host-ip ${HOST_IP} ${LOG_FILE} ${LOG_LOCAL}" + sleep 2 + + source /etc/contrail/opserver_param + screen_it opserver "python $(pywhere opserver)/opserver.py --collectors ${COLLECTORS} --host_ip ${HOST_IP} ${LOG_FILE} ${LOG_LOCAL}" + sleep 2 + + source /etc/contrail/qed_param + screen_it qed "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/query_engine/qed --collectors ${COLLECTORS} --cassandra-server-list ${CASSANDRA_SERVER_LIST} --redis-ip ${REDIS_SERVER} --redis-port ${REDIS_SERVER_PORT} ${LOG_FILE} ${LOG_LOCAL}" + sleep 2 # Provision Vrouter - must be run after API server and schema transformer are up sleep 2 @@ -365,7 +392,7 @@ EOF2 cat > $TOP_DIR/bin/vnsw.hlpr < Date: Thu, 16 Jan 2014 01:49:33 +0000 Subject: [PATCH 113/179] contrail analytics need 2.6.13 redis-server - installing that specific version --- lib/neutron_thirdparty/contrail | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 058bb1ace1..00ae87aa0a 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -28,7 +28,15 @@ function install_contrail() { apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities - apt_get install redis-server + + if ! which redis-server > /dev/null 2>&1 ; then + sudo apt-get install libjemalloc1 + wget http://us.archive.ubuntu.com/ubuntu/pool/universe/r/redis/redis-server_2.6.13-1_amd64.deb + sudo dpkg -i redis-server_2.6.13-1_amd64.deb + rm -rf redis-server_2.6.13-1_amd64.deb + # service will be started later + sudo service redis-server stop + fi else sudo yum -y install patch scons flex bison make vim sudo yum -y install expat-devel gettext-devel curl-devel From 84d0fe0da44da4d498a9e43a45e963132bfb2a54 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 16 Jan 2014 14:41:02 -0800 Subject: [PATCH 114/179] Add note regarding interface cleanup --- contrail/README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrail/README b/contrail/README index 8d70451164..bdeda69345 100644 --- a/contrail/README +++ b/contrail/README @@ -20,6 +20,12 @@ Notes: 6) Copy sample localrc-single as localrc for a single node system. Copy localrc-multinode-server and localrc-multinode-compute as localrc on master and compute nodes respectively for a multi-node system. +7) After running unstack.sh, run ifconfig and verify IP address has been + restored on PHYSICAL_INTERFACE and vhost0 interface is gone. Sometimes + you might see "ERROR: Module vrouter is in use" after running unstack.sh + which means interface cleanup couldn't be done since vrouter is busy and + could not be uninstalled. Repeat unstack.sh untill the interfaces are + restored to original state. Change the following in localrc to suit your deployment: PHYSICAL_INTERFACE -- external interface Vrouter should bind to From 55979d1beed4b6f8d2a89c6e7d3e80f9014b1cc6 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 17 Jan 2014 11:36:35 -0800 Subject: [PATCH 115/179] Added small section on software gateway --- contrail/README | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/contrail/README b/contrail/README index bdeda69345..d853d96722 100644 --- a/contrail/README +++ b/contrail/README @@ -55,3 +55,35 @@ Steps for basic Ubuntu VM image cp contrail/localrc-single localrc vi localrc # edit PHYSICAL_INTERFACE 7) ./stack.sh + +Software Gateway support +------------------------ + +Software gateway provides internet connectivity to virtual machines. It +supports routing between virtual-network and external public-networks. The +Simple Gateway is a restricted implementation of gateway. The features +supported are, + - A compute node provides Simple Gateway functionality for a single + virtual-network + - A virtual-network can ideally have multiple subnets. But, gateway + supports only one subnet per virtual-network + - Relies on the networking stack of host operating-system to route packets + between public-network and virtual-network + +Configuration: + Following parameters must be configured in localrc for Simple Gateway: + + CONTRAIL_VGW_PUBLIC_NETWORK + Specifies FQDN of the routing-instance that needs public access. + Example: If domain=default-domain, user=admin and vm=public, FQDN is + default-domain:admin:public:public + CONTRAIL_VGW_PUBLIC_SUBNET + Specifies the subnet configured for the virtual-network. + Example: 192.168.1.0/24 + CONTRAIL_VGW_INTERFACE + A tap interface is created with this name. The interface is added to + routing-instance of virtual-network. Packets to/from virtual-network + use this interface (Example: vgw) + +Please see detailed instructions at: +https://github.com/Juniper/contrail-controller/wiki/Simple-Gateway From 2bd798153b6cb63634260a1313e636eda80d8cd6 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 24 Jan 2014 16:58:37 -0800 Subject: [PATCH 116/179] Added my steps for Fedora --- contrail/README | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/contrail/README b/contrail/README index d853d96722..c971d272cb 100644 --- a/contrail/README +++ b/contrail/README @@ -56,6 +56,30 @@ Steps for basic Ubuntu VM image vi localrc # edit PHYSICAL_INTERFACE 7) ./stack.sh +Steps for basic Fedora host +--------------------------- +I perform these steps on a minimal Fedora host. You may not +need these steps and will depend upon your starting image. + +1) sudo yum -y install git-core patch vim +2) sudo yum -y install kernel-devel-3.6.6-1 + My "uname -a" shows "Linux a6s34 3.6.6-1.fc17.x86_64" +3) sudo yum -y upgrade libtasn1 +4) sudo yum -y install python-pip +5) sudo easy_install -U distribute +6) verify ssh to github is working + ssh -T git@github.com +7) download devstack (should have already done this) + git clone git@github.com:dsetia/devstack.git +8) copy sample localrc as mentioned above. Edit localrc + PHYSICAL_INTERFACE/SERVICE_HOST/... to match your setup + + cd devstack + cp contrail/localrc-single localrc + vi localrc # edit PHYSICAL_INTERFACE +9) ./stack.sh + + Software Gateway support ------------------------ From f8c2ed099b7e3702a10a40c5dad51d84d4e3a504 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 31 Jan 2014 17:39:26 -0800 Subject: [PATCH 117/179] Enable agent (accidentally got removed in last merge) --- stackrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackrc b/stackrc index d347212c0d..845f133c23 100644 --- a/stackrc +++ b/stackrc @@ -36,7 +36,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,disco,vif,redis +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,vif,redis # Tell Tempest which services are available. The default is set here as # Tempest falls late in the configuration sequence. This differs from From 31341d1972fd298b2df8a0df0c5277f89ca5dd98 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 3 Feb 2014 14:25:13 -0800 Subject: [PATCH 118/179] Resync stack. from openstack-dev --- stack.sh | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/stack.sh b/stack.sh index 14dcea34ee..45d47c819c 100755 --- a/stack.sh +++ b/stack.sh @@ -456,6 +456,7 @@ if is_service_enabled s-proxy; then read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH." fi + # Configure logging # ----------------- @@ -973,6 +974,7 @@ if is_service_enabled ir-api ir-cond; then init_ironic fi + # Neutron # ------- @@ -1324,31 +1326,6 @@ fi # Check the status of running services service_check -if is_service_enabled q-svc; then - echo_summary "Starting Neutron" - - start_neutron_service_and_check - # create_neutron_initial_network - setup_neutron_debug -elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then - NM_CONF=${NOVA_CONF} - if is_service_enabled n-cell; then - NM_CONF=${NOVA_CELLS_CONF} - fi - - # Create a small network - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS - - # Create some floating ips - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME - - # Create a second pool - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL -fi - -if is_service_enabled neutron; then - start_neutron_agents -fi # Fin # === From 64253ff16d24ad3f9a5c0f676272d5538189e6a7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 7 Feb 2014 13:41:04 -0800 Subject: [PATCH 119/179] support https option for contrail repo (default still ssh) --- contrail/README | 10 ++++++---- contrail/localrc-multinode-compute | 6 ++++++ contrail/localrc-multinode-server | 6 ++++++ contrail/localrc-single | 6 ++++++ lib/neutron_thirdparty/contrail | 9 ++++++++- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/contrail/README b/contrail/README index c971d272cb..193653935e 100644 --- a/contrail/README +++ b/contrail/README @@ -13,10 +13,10 @@ Notes: 3) This fork includes Neutron and Nova patches. These patches have been seperately submitted for review. 4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 -5) You need a github account. Register host's SSH keys to the github account - otherwise checking out contrail code will fail. The repo tool assumes - ssh and will not work with HTTPS git url. You can have ssh-agent forward - keys to target system running devstack. +5) Repo tool uses SSH by default. Use ssh-agent to forward keys to target + running devstack or upload host's SSH keys to the github account. + Set CONTRAIL_REPO_PROTO to https to use HTTPS instead. This line is + commented out in sample localrc file 6) Copy sample localrc-single as localrc for a single node system. Copy localrc-multinode-server and localrc-multinode-compute as localrc on master and compute nodes respectively for a multi-node system. @@ -26,6 +26,8 @@ Notes: which means interface cleanup couldn't be done since vrouter is busy and could not be uninstalled. Repeat unstack.sh untill the interfaces are restored to original state. +8) Protocol for openstack bits is also SSH by default. Uncomment out + GIT_BASE line to use https instead Change the following in localrc to suit your deployment: PHYSICAL_INTERFACE -- external interface Vrouter should bind to diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 29e8c9049a..16174ab9e7 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -38,3 +38,9 @@ DATABASE_TYPE=mysql # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 2aaa01a7b4..be5bfada30 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -42,3 +42,9 @@ ADMIN_PASSWORD=contrail123 # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org diff --git a/contrail/localrc-single b/contrail/localrc-single index 5a0924e165..f86e363d0f 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -30,3 +30,9 @@ PHYSICAL_INTERFACE=eth1 # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 4024795959..054936fd1e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -1,3 +1,4 @@ +# proto is https or ssh #! /bin/bash # Contrail NFV @@ -48,6 +49,7 @@ function install_contrail() { sudo pip install stevedore xmltodict python-keystoneclient sudo pip install kazoo pyinotify + CONTRAIL_REPO_PROTO=${CONTRAIL_REPO_PROTO:-ssh} CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} mkdir -p $CONTRAIL_SRC contrail_cwd=$(pwd) @@ -55,7 +57,12 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/.repo ]; then git config --global --get user.name || git config --global user.name "Anonymous" git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" - repo init -u git@github.com:Juniper/contrail-vnc + if [ "$CONTRAIL_REPO_PROTO" == "ssh" ]; then + repo init -u git@github.com:Juniper/contrail-vnc + else + repo init -u https://github.com/Juniper/contrail-vnc + sed -i 's/fetch=".."/fetch=\"https:\/\/github.com\/Juniper\/\"/' .repo/manifest.xml + fi fi repo sync python third_party/fetch_packages.py From 7d7a651dbd1d36fa6d0f1c743b02edccdf987768 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 10 Feb 2014 16:06:49 -0800 Subject: [PATCH 120/179] Drop nova patch; use contrail VIF driver --- contrail/localrc-multinode-compute | 5 ++++- contrail/localrc-multinode-server | 3 +++ contrail/localrc-single | 3 +++ lib/neutron_thirdparty/contrail | 7 ++++--- stackrc | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 16174ab9e7..3731d9f960 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -18,7 +18,7 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif,contrail +ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,contrail Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default @@ -44,3 +44,6 @@ NEUTRON_BRANCH=master # proto for openstack bits. Use HTTPS if git is firewalled # GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index be5bfada30..41c9f14ba5 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -48,3 +48,6 @@ NEUTRON_BRANCH=master # proto for openstack bits. Use HTTPS if git is firewalled # GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/contrail/localrc-single b/contrail/localrc-single index f86e363d0f..5c62f43f3a 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -36,3 +36,6 @@ NEUTRON_BRANCH=master # proto for openstack bits. Use HTTPS if git is firewalled # GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 054936fd1e..04e411e347 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -74,6 +74,9 @@ function install_contrail() { echo "Installing contrail modules" sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + # install VIF driver + sudo pip install $CONTRAIL_SRC/build/noarch/nova_contrail_vif/dist/nova_contrail_vif*.tar.gz + # install neutron patch after VNC api is built and installed # test_install_neutron_patch @@ -377,8 +380,6 @@ END chmod a+x $TOP_DIR/bin/vnsw.hlpr screen_it agent "sudo $TOP_DIR/bin/vnsw.hlpr" - screen_it vif "python /opt/stack/nova/plugins/contrail/contrail_vif.py" - if is_service_enabled q-meta; then # set up a proxy route in contrail from 169.254.169.254:80 to # my metadata server at port 8775 @@ -397,7 +398,7 @@ END } function configure_contrail() { - test_install_nova_patch + : } function init_contrail() { diff --git a/stackrc b/stackrc index 845f133c23..180e71b4f8 100644 --- a/stackrc +++ b/stackrc @@ -36,7 +36,7 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,vif,redis +ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,redis # Tell Tempest which services are available. The default is set here as # Tempest falls late in the configuration sequence. This differs from From 9c0993ab29bae22a0e01f0ae70cde0a293b3907c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 11 Feb 2014 16:41:13 -0800 Subject: [PATCH 121/179] Revert back to stock stackrc; move contrail modules to localrc --- contrail/localrc-multinode-server | 14 +++++++++++++- contrail/localrc-single | 14 +++++++++++++- stackrc | 1 - 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 41c9f14ba5..79f191c183 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -21,12 +21,24 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 +# contrail services +enable_service cass +enable_service ifmap +enable_service apiSrv +enable_service schema +enable_service svc-mon +enable_service zk +enable_service control +enable_service agent +enable_service disco +enable_service redis +enable_service contrail + disable_service n-net enable_service q-svc enable_service q-meta enable_service neutron enable_service rabbit -enable_service contrail # not used by contrail disable_service q-dhcp diff --git a/contrail/localrc-single b/contrail/localrc-single index 5c62f43f3a..f326e0b2b5 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -6,11 +6,23 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 +# contrail services +enable_service cass +enable_service ifmap +enable_service apiSrv +enable_service schema +enable_service svc-mon +enable_service zk +enable_service control +enable_service agent +enable_service disco +enable_service redis +enable_service contrail + disable_service n-net enable_service q-svc enable_service q-meta enable_service neutron -enable_service contrail # not used by contrail disable_service q-agt diff --git a/stackrc b/stackrc index 180e71b4f8..197b4cfc46 100644 --- a/stackrc +++ b/stackrc @@ -36,7 +36,6 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,redis # Tell Tempest which services are available. The default is set here as # Tempest falls late in the configuration sequence. This differs from From ae5b5db45b2cb6f0e76ef96b3b03d42b0979c937 Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Thu, 13 Feb 2014 13:09:40 +0100 Subject: [PATCH 122/179] Add some missing dependencies --- lib/neutron_thirdparty/contrail | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 04e411e347..6bfd42dc8e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -24,11 +24,16 @@ function install_contrail() { # dependencies if is_ubuntu; then - apt_get install patch scons flex bison make vim + apt_get install patch scons flex bison make vim chkconfig apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities + + # last version of redis + sudo add-apt-repository -y ppa:rwky/redis + apt_get update + apt_get install redis-server else sudo yum -y install patch scons flex bison make vim @@ -48,10 +53,11 @@ function install_contrail() { sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient sudo pip install kazoo pyinotify + sudo pip install bottle CONTRAIL_REPO_PROTO=${CONTRAIL_REPO_PROTO:-ssh} CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} - mkdir -p $CONTRAIL_SRC + mkdir -p $CONTRAIL_SRC/third_party contrail_cwd=$(pwd) cd $CONTRAIL_SRC if [ ! -d $CONTRAIL_SRC/.repo ]; then From 0fed983077ea13997893ad8fac6ba6efac54218d Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Thu, 13 Feb 2014 19:09:48 +0100 Subject: [PATCH 123/179] Use wget option to check if the file changed before downloading --- lib/neutron_thirdparty/contrail | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 04e411e347..b06b649c1f 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -17,7 +17,7 @@ function install_contrail() { # basic dependencies if ! which repo > /dev/null 2>&1 ; then - wget http://commondatastorage.googleapis.com/git-repo-downloads/repo + wget -N http://commondatastorage.googleapis.com/git-repo-downloads/repo chmod 0755 repo sudo mv repo /usr/bin fi @@ -117,7 +117,7 @@ function install_contrail() { elif [ ! -d $CONTRAIL_SRC/third_party/apache-cassandra-2.0.2-bin ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://repo1.maven.org/maven2/org/apache/cassandra/apache-cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz + wget -N http://repo1.maven.org/maven2/org/apache/cassandra/apache-cassandra/2.0.2/apache-cassandra-2.0.2-bin.tar.gz tar xvzf apache-cassandra-2.0.2-bin.tar.gz cd ${contrail_cwd} fi @@ -127,7 +127,7 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + wget -N http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip unzip irond-0.3.0-bin.zip chmod -w irond-0.3.0-bin/ifmap.properties cd ${contrail_cwd} @@ -136,7 +136,7 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz + wget -N http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz tar xvzf zookeeper-3.4.5.tar.gz cd zookeeper-3.4.5 cp conf/zoo_sample.cfg conf/zoo.cfg @@ -147,7 +147,7 @@ function install_contrail() { if ! python -c 'import ncclient' >/dev/null 2>&1; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + wget -N https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz sudo pip install ncclient-v0.3.2.tar.gz cd ${contrail_cwd} fi From 9a84dd367261e8c794a0a77524a482598e7d706a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89douard=20Thuleau?= Date: Fri, 21 Feb 2014 10:05:48 +0100 Subject: [PATCH 124/179] Ubuntu does not support anymore package chkconfig From release 12.10, Ubuntu removed the support of chkconfig package. I set a specific install chkconfig command in case it fails, it fails alone. --- lib/neutron_thirdparty/contrail | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 11e085cea2..4d6583988d 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -24,7 +24,8 @@ function install_contrail() { # dependencies if is_ubuntu; then - apt_get install patch scons flex bison make vim chkconfig + apt_get install patch scons flex bison make vim + apt_get install chkconfig apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev From 2735a95253d6497b85599d4e6806e73314142eef Mon Sep 17 00:00:00 2001 From: Praneet Bachheti Date: Tue, 4 Mar 2014 01:59:08 -0800 Subject: [PATCH 125/179] devstack changes to have it work with github changes --- contrail/contrail_config_templates.py | 1 + lib/neutron_thirdparty/contrail | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index fe58b25171..08f0a59fa9 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -25,6 +25,7 @@ [KEYSTONE] auth_host=$__contrail_openstack_ip__ auth_protocol=http +auth_port=35357 admin_user=$__contrail_admin_user__ admin_password=$__contrail_admin_password__ admin_tenant_name=$__contrail_admin_tenant_name__ diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 4d6583988d..aae5c376f1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -330,7 +330,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --reset_config --conf_file /etc/contrail/api_server.conf" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" @@ -341,7 +341,7 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" # Provision Vrouter - must be run after API server and schema transformer are up sleep 2 From 9c4738482fb153cf61cc2db8e457cca5a74f0d6f Mon Sep 17 00:00:00 2001 From: Praneet Bachheti Date: Thu, 6 Mar 2014 11:43:55 -0800 Subject: [PATCH 126/179] Add --rabbit_password argument to api-server --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index aae5c376f1..62a1a9db35 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -330,7 +330,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" From cfa5b8474526c46005f80f98ae210dc8fc3b0cd9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 19 Mar 2014 13:19:41 +0200 Subject: [PATCH 127/179] zookeeper version 3.4.5 -> 3.4.6 --- lib/neutron_thirdparty/contrail | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 62a1a9db35..2507191887 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -140,12 +140,12 @@ function install_contrail() { cd ${contrail_cwd} fi - if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.6 ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget -N http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz - tar xvzf zookeeper-3.4.5.tar.gz - cd zookeeper-3.4.5 + wget -N http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.6.tar.gz + tar xvzf zookeeper-3.4.6.tar.gz + cd zookeeper-3.4.6 cp conf/zoo_sample.cfg conf/zoo.cfg cd ${contrail_cwd} fi From 95b0d5770484a63752184967d36f16fd727634c7 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 20 Mar 2014 10:35:06 -0700 Subject: [PATCH 128/179] Fix zookeeper invocation after version update --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 2507191887..a788a2ed12 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -320,7 +320,7 @@ function start_contrail() { screen_it cass "sudo $CASS_PATH -f" - screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" + screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.6; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 From d567356c32bb03b32a5552fbd771b8e0fe9a84ea Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 25 Mar 2014 16:48:50 -0700 Subject: [PATCH 129/179] API server needs new options - redis server IP and admin token --- contrail/contrail_config_templates.py | 2 ++ contrail/setup_contrail.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 08f0a59fa9..9861384428 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -7,6 +7,7 @@ ifmap_username=$__contrail_ifmap_username__ ifmap_password=$__contrail_ifmap_password__ redis_server_port=6379 +redis_server_ip=$__contrail_redis_server_ip__ cassandra_server_list=$__contrail_cassandra_server_list__ listen_ip_addr=$__contrail_listen_ip_addr__ listen_port=$__contrail_listen_port__ @@ -29,6 +30,7 @@ admin_user=$__contrail_admin_user__ admin_password=$__contrail_admin_password__ admin_tenant_name=$__contrail_admin_tenant_name__ +admin_token = $__contrail_admin_token__ $__contrail_memcached_opt__ """) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 83268fa3f0..40ee681915 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -487,11 +487,13 @@ def fixup_config_files(self): '__contrail_admin_user__': ks_admin_user, '__contrail_admin_password__': ks_admin_password, '__contrail_admin_tenant_name__': ks_admin_tenant_name, + '__contrail_admin_token__': ks_admin_password, '__contrail_memcached_opt__': 'memcache_servers=127.0.0.1:11211' if self._args.multi_tenancy else '', '__contrail_log_file__': '/var/log/contrail/api.log', '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), '__contrail_disc_server_ip__': self._args.discovery_ip or '', '__contrail_disc_server_port__': '5998', + '__contrail_redis_server_ip__': cfgm_ip, } self._template_substitute_write(api_server_conf_template, template_vals, temp_dir_name + '/api_server.conf') From 4610b780e4e8116f5790a8747d2a831e4f1ad0ce Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 26 Mar 2014 13:36:23 -0700 Subject: [PATCH 130/179] g-api does not seem to be needed on compute node --- contrail/localrc-multinode-compute | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 3731d9f960..a4a8431602 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -18,7 +18,7 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,contrail +ENABLED_SERVICES=n-cpu,rabbit,neutron,agent,contrail Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default From 7d098142c9bfeaf7b30b4d8789a2c90b19f679e8 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Wed, 16 Apr 2014 16:59:20 -0700 Subject: [PATCH 131/179] Merge dsetia/devstack to rajreddy/devstack --- .gitignore | 10 +- HACKING.rst | 78 ++- README.md | 180 ++++-- clean.sh | 51 +- contrail/README | 72 ++- contrail/contrail_config_templates.py | 3 + contrail/localrc-multinode-compute | 11 +- contrail/localrc-multinode-server | 23 +- contrail/localrc-single | 23 +- contrail/setup_contrail.py | 2 + driver_certs/cinder_driver_cert.sh | 103 ++++ eucarc | 2 +- exercises/aggregates.sh | 24 +- exercises/boot_from_volume.sh | 13 +- exercises/bundle.sh | 4 + exercises/client-args.sh | 16 +- exercises/docker.sh | 105 ---- exercises/euca.sh | 56 +- exercises/floating_ips.sh | 11 +- exercises/marconi.sh | 43 ++ exercises/neutron-adv-test.sh | 49 +- exercises/savanna.sh | 43 ++ exercises/sec_groups.sh | 5 + exercises/swift.sh | 2 +- exercises/volumes.sh | 7 +- extras.d/70-marconi.sh | 29 + extras.d/70-savanna.sh | 32 + extras.d/70-trove.sh | 33 + extras.d/80-tempest.sh | 35 +- extras.d/README | 14 - extras.d/README.md | 30 + files/apts/cinder | 2 +- files/apts/general | 2 + files/apts/glance | 1 - files/apts/horizon | 2 - files/apts/ldap | 2 +- files/apts/marconi-server | 3 + files/apts/n-cpu | 2 +- files/apts/neutron | 4 +- files/apts/tempest | 1 + files/apts/tls-proxy | 2 +- files/apts/trema | 1 + files/default_catalog.templates | 16 +- files/keystone_data.sh | 119 ++-- .../ldap/{openstack.ldif => keystone.ldif.in} | 16 +- files/ldap/manager.ldif.in | 9 +- ...e-config.ldif => suse-base-config.ldif.in} | 4 +- files/rpms-suse/general | 3 +- files/rpms-suse/horizon | 1 - files/rpms/ceilometer-collector | 1 + files/rpms/cinder | 1 + files/rpms/general | 2 + files/rpms/glance | 5 +- files/rpms/horizon | 5 +- files/rpms/keystone | 10 +- files/rpms/marconi-server | 3 + files/rpms/neutron | 4 +- files/rpms/nova | 6 +- files/rpms/swift | 2 +- files/rpms/tempest | 1 + files/rpms/trove | 2 +- functions | 407 ++++++++++--- lib/apache | 32 +- lib/baremetal | 190 +++--- lib/ceilometer | 108 +++- lib/cinder | 124 ++-- lib/config | 130 ++++ lib/database | 22 +- lib/databases/mysql | 3 +- lib/databases/postgresql | 13 +- lib/glance | 49 +- lib/heat | 52 +- lib/horizon | 56 +- lib/infra | 14 +- lib/ironic | 66 +- lib/keystone | 115 ++-- lib/ldap | 156 +++-- lib/marconi | 176 ++++++ lib/neutron | 186 ++++-- lib/neutron_plugins/bigswitch_floodlight | 2 +- lib/neutron_plugins/brocade | 2 +- lib/neutron_plugins/linuxbridge_agent | 2 +- lib/neutron_plugins/midonet | 16 +- lib/neutron_plugins/ml2 | 29 +- lib/neutron_plugins/nec | 29 +- lib/neutron_plugins/ovs_base | 8 +- lib/neutron_plugins/plumgrid | 11 +- lib/neutron_plugins/services/firewall | 10 +- lib/neutron_plugins/services/loadbalancer | 11 +- lib/neutron_plugins/services/metering | 30 + lib/neutron_plugins/services/vpn | 15 +- lib/neutron_plugins/{nicira => vmware_nsx} | 85 +-- lib/neutron_thirdparty/README.md | 3 + lib/neutron_thirdparty/bigswitch_floodlight | 4 + lib/neutron_thirdparty/contrail | 49 +- lib/neutron_thirdparty/midonet | 4 + lib/neutron_thirdparty/nicira | 52 -- lib/neutron_thirdparty/ryu | 4 + lib/neutron_thirdparty/trema | 12 +- lib/neutron_thirdparty/vmware_nsx | 86 +++ lib/nova | 387 ++++++------ lib/nova_plugins/hypervisor-baremetal | 93 +++ lib/nova_plugins/hypervisor-docker | 17 +- lib/nova_plugins/hypervisor-libvirt | 166 ++++++ lib/nova_plugins/hypervisor-openvz | 67 +++ lib/nova_plugins/hypervisor-xenserver | 85 +++ lib/oslo | 16 +- lib/rpc_backend | 40 +- lib/savanna | 138 +++++ lib/savanna-dashboard | 71 +++ lib/stackforge | 67 +++ lib/swift | 215 ++++--- lib/tempest | 127 ++-- lib/template | 26 +- lib/tls | 86 ++- lib/trove | 89 ++- openrc | 12 +- run_tests.sh | 29 + samples/{localrc => local.conf} | 18 +- samples/local.sh | 60 +- stack.sh | 562 ++++++++++-------- stackrc | 55 +- tests/functions.sh | 189 ------ tests/test_config.sh | 195 ++++++ tests/test_ini.sh | 240 ++++++++ tools/bash8.py | 115 ++++ tools/build_bm_multi.sh | 4 +- tools/build_docs.sh | 145 +++++ tools/build_ramdisk.sh | 11 +- tools/build_tempest.sh | 2 +- tools/build_uec.sh | 302 ---------- tools/create-stack-user.sh | 51 ++ tools/create_userrc.sh | 40 +- tools/docker/install_docker.sh | 4 +- tools/fixup_stuff.sh | 67 ++- tools/get_uec_image.sh | 6 +- tools/info.sh | 14 +- tools/install_pip.sh | 18 +- tools/install_prereqs.sh | 2 +- tools/jenkins/adapters/euca.sh | 1 + tools/jenkins/adapters/floating_ips.sh | 1 + tools/jenkins/adapters/volumes.sh | 1 + tools/jenkins/jenkins_home/build_jenkins.sh | 16 +- tools/sar_filter.py | 82 +++ tools/upload_image.sh | 1 + tools/xen/README.md | 3 + tools/xen/build_xva.sh | 54 +- tools/xen/devstackubuntupreseed.cfg | 2 +- tools/xen/functions | 61 +- tools/xen/install_os_domU.sh | 63 +- tools/xen/mocks | 8 +- tools/xen/prepare_guest_template.sh | 4 + tools/xen/scripts/install-os-vpx.sh | 114 ++-- tools/xen/scripts/uninstall-os-vpx.sh | 58 +- tools/xen/test_functions.sh | 28 +- tools/xen/xenrc | 17 +- unstack.sh | 81 ++- 157 files changed, 5615 insertions(+), 2515 deletions(-) create mode 100755 driver_certs/cinder_driver_cert.sh delete mode 100755 exercises/docker.sh create mode 100755 exercises/marconi.sh create mode 100755 exercises/savanna.sh create mode 100644 extras.d/70-marconi.sh create mode 100644 extras.d/70-savanna.sh create mode 100644 extras.d/70-trove.sh delete mode 100644 extras.d/README create mode 100644 extras.d/README.md create mode 100644 files/apts/marconi-server create mode 100644 files/apts/tempest rename files/ldap/{openstack.ldif => keystone.ldif.in} (54%) rename files/ldap/{base-config.ldif => suse-base-config.ldif.in} (77%) create mode 100644 files/rpms/marconi-server create mode 100644 files/rpms/tempest create mode 100644 lib/config mode change 100755 => 100644 lib/keystone create mode 100644 lib/marconi create mode 100644 lib/neutron_plugins/services/metering rename lib/neutron_plugins/{nicira => vmware_nsx} (52%) delete mode 100644 lib/neutron_thirdparty/nicira create mode 100644 lib/neutron_thirdparty/vmware_nsx create mode 100644 lib/nova_plugins/hypervisor-baremetal create mode 100644 lib/nova_plugins/hypervisor-libvirt create mode 100644 lib/nova_plugins/hypervisor-openvz create mode 100644 lib/nova_plugins/hypervisor-xenserver create mode 100644 lib/savanna create mode 100644 lib/savanna-dashboard create mode 100644 lib/stackforge create mode 100755 run_tests.sh rename samples/{localrc => local.conf} (81%) create mode 100755 tests/test_config.sh create mode 100755 tests/test_ini.sh create mode 100755 tools/bash8.py create mode 100755 tools/build_docs.sh delete mode 100755 tools/build_uec.sh create mode 100755 tools/create-stack-user.sh create mode 100755 tools/sar_filter.py diff --git a/.gitignore b/.gitignore index 798b0814c9..1840352636 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,23 @@ proto *~ -.*.sw[nop] +.*.sw? *.log *.log.[1-9] src localrc local.sh files/*.gz +files/*.qcow2 files/images +files/pip-* +files/get-pip.py stack-screenrc *.pem accrc .stackenv .prereqs +devstack-docs-* +docs/ +docs-files +.localrc.auto +local.conf diff --git a/HACKING.rst b/HACKING.rst index dd665a2304..103b579621 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -5,10 +5,10 @@ Contributing to DevStack General ------- -DevStack is written in POSIX shell script. This choice was made because -it best illustrates the configuration steps that this implementation takes -on setting up and interacting with OpenStack components. DevStack specifically -uses Bash and is compatible with Bash 3. +DevStack is written in UNIX shell script. It uses a number of bash-isms +and so is limited to Bash (version 3 and up) and compatible shells. +Shell script was chosen because it best illustrates the steps used to +set up and interact with OpenStack components. DevStack's official repository is located on GitHub at https://github.com/openstack-dev/devstack.git. Besides the master branch that @@ -38,7 +38,7 @@ such as Grenade, to manage a DevStack installation. A number of additional scripts can be found in the ``tools`` directory that may be useful in supporting DevStack installations. Of particular note are ``info.sh`` -to collect and report information about the installed system, and ``instal_prereqs.sh`` +to collect and report information about the installed system, and ``install_prereqs.sh`` that handles installation of the prerequisite packages for DevStack. It is suitable, for example, to pre-load a system for making a snapshot. @@ -54,14 +54,14 @@ Sometimes the script needs to know the location of the DevStack install director ``TOP_DIR`` should always point there, even if the script itself is located in a subdirectory:: - # Keep track of the current devstack directory. + # Keep track of the current DevStack directory. TOP_DIR=$(cd $(dirname "$0") && pwd) Many scripts will utilize shared functions from the ``functions`` file. There are also rc files (``stackrc`` and ``openrc``) that are often included to set the primary configuration of the user environment:: - # Keep track of the current devstack directory. + # Keep track of the current DevStack directory. TOP_DIR=$(cd $(dirname "$0") && pwd) # Import common functions @@ -100,13 +100,14 @@ stackrc ------- ``stackrc`` is the global configuration file for DevStack. It is responsible for -calling ``localrc`` if it exists so configuration can be overridden by the user. +calling ``local.conf`` (or ``localrc`` if it exists) so local user configuration +is recognized. The criteria for what belongs in ``stackrc`` can be vaguely summarized as follows: -* All project respositories and branches (for historical reasons) -* Global configuration that may be referenced in ``localrc``, i.e. ``DEST``, ``DATA_DIR`` +* All project repositories and branches handled directly in ``stack.sh`` +* Global configuration that may be referenced in ``local.conf``, i.e. ``DEST``, ``DATA_DIR`` * Global service configuration like ``ENABLED_SERVICES`` * Variables used by multiple services that do not have a clear owner, i.e. ``VOLUME_BACKING_FILE_SIZE`` (nova-volumes and cinder) or ``PUBLIC_NETWORK_NAME`` @@ -116,8 +117,9 @@ follows: not be changed for other reasons but the earlier file needs to dereference a variable set in the later file. This should be rare. -Also, variable declarations in ``stackrc`` do NOT allow overriding (the form -``FOO=${FOO:-baz}``); if they did then they can already be changed in ``localrc`` +Also, variable declarations in ``stackrc`` before ``local.conf`` is sourced +do NOT allow overriding (the form +``FOO=${FOO:-baz}``); if they did then they can already be changed in ``local.conf`` and can stay in the project file. @@ -139,7 +141,9 @@ verbose in the comments _ABOVE_ the code they pertain to. Shocco also supports Markdown formatting in the comments; use it sparingly. Specifically, ``stack.sh`` uses Markdown headers to divide the script into logical sections. -.. _shocco: http://rtomayko.github.com/shocco/ +.. _shocco: https://github.com/dtroyer/shocco/tree/rst_support + +The script used to drive shocco is tools/build_docs.sh. Exercises @@ -223,3 +227,51 @@ These scripts are executed serially by ``exercise.sh`` in testing situations. or graciously handle possible artifacts left over from previous runs if executed again. It is acceptable to require a reboot or even a re-install of DevStack to restore a clean test environment. + + +Bash Style Guidelines +~~~~~~~~~~~~~~~~~~~~~ +Devstack defines a bash set of best practices for maintaining large +collections of bash scripts. These should be considered as part of the +review process. + +We have a preliminary enforcing script for this called bash8 (only a +small number of these rules are enforced). + +Whitespace Rules +---------------- + +- lines should not include trailing whitespace +- there should be no hard tabs in the file +- indents are 4 spaces, and all indentation should be some multiple of + them + +Control Structure Rules +----------------------- +- then should be on the same line as the if +- do should be on the same line as the for + +Example:: + + if [[ -r $TOP_DIR/local.conf ]]; then + LRC=$(get_meta_section_files $TOP_DIR/local.conf local) + for lfile in $LRC; do + if [[ "$lfile" == "localrc" ]]; then + if [[ -r $TOP_DIR/localrc ]]; then + warn $LINENO "localrc and local.conf:[[local]] both exist, using localrc" + else + echo "# Generated file, do not edit" >$TOP_DIR/.localrc.auto + get_meta_section $TOP_DIR/local.conf local $lfile >>$TOP_DIR/.localrc.auto + fi + fi + done + fi + +Variables and Functions +----------------------- +- functions should be used whenever possible for clarity +- functions should use ``local`` variables as much as possible to + ensure they are isolated from the rest of the environment +- local variables should be lower case, global variables should be + upper case +- function names should_have_underscores, NotCamelCase. diff --git a/README.md b/README.md index 99e983887e..9914b1ed69 100644 --- a/README.md +++ b/README.md @@ -6,35 +6,39 @@ DevStack is a set of scripts and utilities to quickly deploy an OpenStack cloud. * To describe working configurations of OpenStack (which code branches work together? what do config files look like for those branches?) * To make it easier for developers to dive into OpenStack so that they can productively contribute without having to understand every part of the system at once * To make it easy to prototype cross-project features -* To sanity-check OpenStack builds (used in gating commits to the primary repos) +* To provide an environment for the OpenStack CI testing on every commit to the projects -Read more at http://devstack.org (built from the gh-pages branch) +Read more at http://devstack.org. -IMPORTANT: Be sure to carefully read `stack.sh` and any other scripts you execute before you run them, as they install software and may alter your networking configuration. We strongly recommend that you run `stack.sh` in a clean and disposable vm when you are first getting started. - -# DevStack on Xenserver - -If you would like to use Xenserver as the hypervisor, please refer to the instructions in `./tools/xen/README.md`. - -# DevStack on Docker - -If you would like to use Docker as the hypervisor, please refer to the instructions in `./tools/docker/README.md`. +IMPORTANT: Be sure to carefully read `stack.sh` and any other scripts you +execute before you run them, as they install software and will alter your +networking configuration. We strongly recommend that you run `stack.sh` +in a clean and disposable vm when you are first getting started. # Versions -The devstack master branch generally points to trunk versions of OpenStack components. For older, stable versions, look for branches named stable/[release] in the DevStack repo. For example, you can do the following to create a diablo OpenStack cloud: +The DevStack master branch generally points to trunk versions of OpenStack +components. For older, stable versions, look for branches named +stable/[release] in the DevStack repo. For example, you can do the +following to create a grizzly OpenStack cloud: - git checkout stable/diablo + git checkout stable/grizzly ./stack.sh -You can also pick specific OpenStack project releases by setting the appropriate `*_BRANCH` variables in `localrc` (look in `stackrc` for the default set). Usually just before a release there will be milestone-proposed branches that need to be tested:: +You can also pick specific OpenStack project releases by setting the appropriate +`*_BRANCH` variables in the ``localrc`` section of `local.conf` (look in +`stackrc` for the default set). Usually just before a release there will be +milestone-proposed branches that need to be tested:: - GLANCE_REPO=https://github.com/openstack/glance.git + GLANCE_REPO=git://git.openstack.org/openstack/glance.git GLANCE_BRANCH=milestone-proposed # Start A Dev Cloud -Installing in a dedicated disposable vm is safer than installing on your dev machine! To start a dev cloud: +Installing in a dedicated disposable VM is safer than installing on your +dev machine! Plus you can pick one of the supported Linux distros for +your VM. To start a dev cloud run the following NOT AS ROOT (see +**DevStack Execution Environment** below for more on user accounts): ./stack.sh @@ -45,7 +49,7 @@ When the script finishes executing, you should be able to access OpenStack endpo We also provide an environment file that you can use to interact with your cloud via CLI: - # source openrc file to load your environment with osapi and ec2 creds + # source openrc file to load your environment with OpenStack CLI creds . openrc # list instances nova list @@ -57,14 +61,41 @@ If the EC2 API is your cup-o-tea, you can create credentials and use euca2ools: # list instances using ec2 api euca-describe-instances +# DevStack Execution Environment + +DevStack runs rampant over the system it runs on, installing things and uninstalling other things. Running this on a system you care about is a recipe for disappointment, or worse. Alas, we're all in the virtualization business here, so run it in a VM. And take advantage of the snapshot capabilities of your hypervisor of choice to reduce testing cycle times. You might even save enough time to write one more feature before the next feature freeze... + +``stack.sh`` needs to have root access for a lot of tasks, but uses ``sudo`` +for all of those tasks. However, it needs to be not-root for most of its +work and for all of the OpenStack services. ``stack.sh`` specifically +does not run if started as root. + +This is a recent change (Oct 2013) from the previous behaviour of +automatically creating a ``stack`` user. Automatically creating +user accounts is not the right response to running as root, so +that bit is now an explicit step using ``tools/create-stack-user.sh``. +Run that (as root!) or just check it out to see what DevStack's +expectations are for the account it runs under. Many people simply +use their usual login (the default 'ubuntu' login on a UEC image +for example). + # Customizing -You can override environment variables used in `stack.sh` by creating file name `localrc`. It is likely that you will need to do this to tweak your networking configuration should you need to access your cloud from a different host. +You can override environment variables used in `stack.sh` by creating file +name `local.conf` with a ``localrc`` section as shown below. It is likely +that you will need to do this to tweak your networking configuration should +you need to access your cloud from a different host. + + [[local|localrc]] + VARIABLE=value + +See the **Local Configuration** section below for more details. # Database Backend Multiple database backends are available. The available databases are defined in the lib/databases directory. -`mysql` is the default database, choose a different one by putting the following in `localrc`: +`mysql` is the default database, choose a different one by putting the +following in the `localrc` section: disable_service mysql enable_service postgresql @@ -75,7 +106,7 @@ Multiple database backends are available. The available databases are defined in Multiple RPC backends are available. Currently, this includes RabbitMQ (default), Qpid, and ZeroMQ. Your backend of -choice may be selected via the `localrc`. +choice may be selected via the `localrc` section. Note that selecting more than one RPC backend will result in a failure. @@ -89,9 +120,10 @@ Example (Qpid): # Apache Frontend -Apache web server is enabled for wsgi services by setting `APACHE_ENABLED_SERVICES` in your localrc. But remember to enable these services at first as above. +Apache web server is enabled for wsgi services by setting +`APACHE_ENABLED_SERVICES` in your ``localrc`` section. Remember to +enable these services at first as above. -Example: APACHE_ENABLED_SERVICES+=keystone,swift # Swift @@ -102,23 +134,23 @@ vm. When running with only one replica the account, container and object services will run directly in screen. The others services like replicator, updaters or auditor runs in background. -If you would like to enable Swift you can add this to your `localrc` : +If you would like to enable Swift you can add this to your `localrc` section: enable_service s-proxy s-object s-container s-account If you want a minimal Swift install with only Swift and Keystone you -can have this instead in your `localrc`: +can have this instead in your `localrc` section: disable_all_services enable_service key mysql s-proxy s-object s-container s-account If you only want to do some testing of a real normal swift cluster with multiple replicas you can do so by customizing the variable -`SWIFT_REPLICAS` in your `localrc` (usually to 3). +`SWIFT_REPLICAS` in your `localrc` section (usually to 3). # Swift S3 -If you are enabling `swift3` in `ENABLED_SERVICES` devstack will +If you are enabling `swift3` in `ENABLED_SERVICES` DevStack will install the swift3 middleware emulation. Swift will be configured to act as a S3 endpoint for Keystone so effectively replacing the `nova-objectstore`. @@ -131,7 +163,7 @@ services are started in background and managed by `swift-init` tool. Basic Setup In order to enable Neutron a single node setup, you'll need the -following settings in your `localrc` : +following settings in your `localrc` section: disable_service n-net enable_service q-svc @@ -139,13 +171,17 @@ following settings in your `localrc` : enable_service q-dhcp enable_service q-l3 enable_service q-meta + enable_service q-metering enable_service neutron - # Optional, to enable tempest configuration as part of devstack + # Optional, to enable tempest configuration as part of DevStack enable_service tempest Then run `stack.sh` as normal. -devstack supports adding specific Neutron configuration flags to the service, Open vSwitch plugin and LinuxBridge plugin configuration files. To make use of this feature, the following variables are defined and can be configured in your `localrc` file: +DevStack supports setting specific Neutron configuration flags to the +service, Open vSwitch plugin and LinuxBridge plugin configuration files. +To make use of this feature, the following variables are defined and can +be configured in your `localrc` section: Variable Name Config File Section Modified ------------------------------------------------------------------------------------- @@ -154,12 +190,14 @@ devstack supports adding specific Neutron configuration flags to the service, Op Q_AGENT_EXTRA_SRV_OPTS Plugin `OVS` (for Open Vswitch) or `LINUX_BRIDGE` (for LinuxBridge) Q_SRV_EXTRA_DEFAULT_OPTS Service DEFAULT -An example of using the variables in your `localrc` is below: +An example of using the variables in your `localrc` section is below: Q_AGENT_EXTRA_AGENT_OPTS=(tunnel_type=vxlan vxlan_udp_port=8472) Q_SRV_EXTRA_OPTS=(tenant_network_type=vxlan) -devstack also supports configuring the Neutron ML2 plugin. The ML2 plugin can run with the OVS, LinuxBridge, or Hyper-V agents on compute hosts. A simple way to configure the ml2 plugin is shown below: +DevStack also supports configuring the Neutron ML2 plugin. The ML2 plugin +can run with the OVS, LinuxBridge, or Hyper-V agents on compute hosts. A +simple way to configure the ml2 plugin is shown below: # VLAN configuration Q_PLUGIN=ml2 @@ -173,7 +211,9 @@ devstack also supports configuring the Neutron ML2 plugin. The ML2 plugin can ru Q_PLUGIN=ml2 Q_ML2_TENANT_NETWORK_TYPE=vxlan -The above will default in devstack to using the OVS on each compute host. To change this, set the `Q_AGENT` variable to the agent you want to run (e.g. linuxbridge). +The above will default in DevStack to using the OVS on each compute host. +To change this, set the `Q_AGENT` variable to the agent you want to run +(e.g. linuxbridge). Variable Name Notes ------------------------------------------------------------------------------------- @@ -188,13 +228,13 @@ The above will default in devstack to using the OVS on each compute host. To cha # Heat Heat is disabled by default. To enable it you'll need the following settings -in your `localrc` : +in your `localrc` section: enable_service heat h-api h-api-cfn h-api-cw h-eng Heat can also run in standalone mode, and be configured to orchestrate on an external OpenStack cloud. To launch only Heat in standalone mode -you'll need the following settings in your `localrc` : +you'll need the following settings in your `localrc` section: disable_all_services enable_service rabbit mysql heat h-api h-api-cfn h-api-cw h-eng @@ -209,6 +249,24 @@ If tempest has been successfully configured, a basic set of smoke tests can be r $ cd /opt/stack/tempest $ nosetests tempest/scenario/test_network_basic_ops.py +# DevStack on Xenserver + +If you would like to use Xenserver as the hypervisor, please refer to the instructions in `./tools/xen/README.md`. + +# DevStack on Docker + +If you would like to use Docker as the hypervisor, please refer to the instructions in `./tools/docker/README.md`. + +# Additional Projects + +DevStack has a hook mechanism to call out to a dispatch script at specific +points in the execution of `stack.sh`, `unstack.sh` and `clean.sh`. This +allows upper-layer projects, especially those that the lower layer projects +have no dependency on, to be added to DevStack without modifying the core +scripts. Tempest is built this way as an example of how to structure the +dispatch script, see `extras.d/80-tempest.sh`. See `extras.d/README.md` +for more information. + # Multi-Node Setup A more interesting setup involves running multiple compute nodes, with Neutron networks connecting VMs on different compute nodes. @@ -222,7 +280,8 @@ You should run at least one "controller node", which should have a `stackrc` tha enable_service q-meta enable_service neutron -You likely want to change your `localrc` to run a scheduler that will balance VMs across hosts: +You likely want to change your `localrc` section to run a scheduler that +will balance VMs across hosts: SCHEDULER=nova.scheduler.simple.SimpleScheduler @@ -239,8 +298,57 @@ You can then run many compute nodes, each of which should have a `stackrc` which Cells is a new scaling option with a full spec at http://wiki.openstack.org/blueprint-nova-compute-cells. -To setup a cells environment add the following to your `localrc`: +To setup a cells environment add the following to your `localrc` section: enable_service n-cell Be aware that there are some features currently missing in cells, one notable one being security groups. The exercises have been patched to disable functionality not supported by cells. + + +# Local Configuration + +Historically DevStack has used ``localrc`` to contain all local configuration and customizations. More and more of the configuration variables available for DevStack are passed-through to the individual project configuration files. The old mechanism for this required specific code for each file and did not scale well. This is handled now by a master local configuration file. + +# local.conf + +The new config file ``local.conf`` is an extended-INI format that introduces a new meta-section header that provides some additional information such as a phase name and destination config filename: + + [[ | ]] + +where ```` is one of a set of phase names defined by ``stack.sh`` +and ```` is the configuration filename. The filename is +eval'ed in the ``stack.sh`` context so all environment variables are +available and may be used. Using the project config file variables in +the header is strongly suggested (see the ``NOVA_CONF`` example below). +If the path of the config file does not exist it is skipped. + +The defined phases are: + +* **local** - extracts ``localrc`` from ``local.conf`` before ``stackrc`` is sourced +* **post-config** - runs after the layer 2 services are configured and before they are started +* **extra** - runs after services are started and before any files in ``extra.d`` are executed +* **post-extra** - runs after files in ``extra.d`` are executed + +The file is processed strictly in sequence; meta-sections may be specified more than once but if any settings are duplicated the last to appear in the file will be used. + + [[post-config|$NOVA_CONF]] + [DEFAULT] + use_syslog = True + + [osapi_v3] + enabled = False + +A specific meta-section ``local|localrc`` is used to provide a default +``localrc`` file (actually ``.localrc.auto``). This allows all custom +settings for DevStack to be contained in a single file. If ``localrc`` +exists it will be used instead to preserve backward-compatibility. + + [[local|localrc]] + FIXED_RANGE=10.254.1.0/24 + ADMIN_PASSWORD=speciale + LOGFILE=$DEST/logs/stack.sh.log + +Note that ``Q_PLUGIN_CONF_FILE`` is unique in that it is assumed to *NOT* +start with a ``/`` (slash) character. A slash will need to be added: + + [[post-config|/$Q_PLUGIN_CONF_FILE]] diff --git a/clean.sh b/clean.sh index 6ceb5a4933..e16bdb7f36 100755 --- a/clean.sh +++ b/clean.sh @@ -15,6 +15,8 @@ TOP_DIR=$(cd $(dirname "$0") && pwd) # Import common functions source $TOP_DIR/functions +FILES=$TOP_DIR/files + # Load local configuration source $TOP_DIR/stackrc @@ -28,13 +30,17 @@ fi # and ``DISTRO`` GetDistro +# Import apache functions +source $TOP_DIR/lib/apache +source $TOP_DIR/lib/ldap # Import database library source $TOP_DIR/lib/database source $TOP_DIR/lib/rpc_backend -source $TOP_DIR/lib/oslo source $TOP_DIR/lib/tls + +source $TOP_DIR/lib/oslo source $TOP_DIR/lib/horizon source $TOP_DIR/lib/keystone source $TOP_DIR/lib/glance @@ -45,8 +51,19 @@ source $TOP_DIR/lib/ceilometer source $TOP_DIR/lib/heat source $TOP_DIR/lib/neutron source $TOP_DIR/lib/baremetal -source $TOP_DIR/lib/ldap +source $TOP_DIR/lib/ironic +source $TOP_DIR/lib/trove + +# Extras Source +# -------------- + +# Phase: source +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i source + done +fi # See if there is anything running... # need to adapt when run_service is merged @@ -56,6 +73,16 @@ if [[ -n "$SESSION" ]]; then $TOP_DIR/unstack.sh --all fi +# Run extras +# ========== + +# Phase: clean +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i clean + done +fi + # Clean projects cleanup_oslo cleanup_cinder @@ -65,18 +92,15 @@ cleanup_nova cleanup_neutron cleanup_swift +if is_service_enabled ldap; then + cleanup_ldap +fi + # Do the hypervisor cleanup until this can be moved back into lib/nova if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then cleanup_nova_hypervisor fi -# cinder doesn't always clean up the volume group as it might be used elsewhere... -# clean it up if it is a loop device -VG_DEV=$(sudo losetup -j $DATA_DIR/${VOLUME_GROUP}-backing-file | awk -F':' '/backing-file/ { print $1}') -if [[ -n "$VG_DEV" ]]; then - sudo losetup -d $VG_DEV -fi - #if mount | grep $DATA_DIR/swift/drives; then # sudo umount $DATA_DIR/swift/drives/sdb1 #fi @@ -86,12 +110,19 @@ fi sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift # Clean out tgt -sudo rm /etc/tgt/conf.d/* +sudo rm -f /etc/tgt/conf.d/* # Clean up the message queue cleanup_rpc_backend cleanup_database +# Clean out data, logs and status +LOGDIR=$(dirname "$LOGFILE") +sudo rm -rf $DATA_DIR $LOGDIR $DEST/status +if [[ -n "$SCREEN_LOGDIR" ]] && [[ -d "$SCREEN_LOGDIR" ]]; then + sudo rm -rf $SCREEN_LOGDIR +fi + # Clean up networking... # should this be in nova? # FIXED_IP_ADDR in br100 diff --git a/contrail/README b/contrail/README index 8d70451164..193653935e 100644 --- a/contrail/README +++ b/contrail/README @@ -13,13 +13,21 @@ Notes: 3) This fork includes Neutron and Nova patches. These patches have been seperately submitted for review. 4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 -5) You need a github account. Register host's SSH keys to the github account - otherwise checking out contrail code will fail. The repo tool assumes - ssh and will not work with HTTPS git url. You can have ssh-agent forward - keys to target system running devstack. +5) Repo tool uses SSH by default. Use ssh-agent to forward keys to target + running devstack or upload host's SSH keys to the github account. + Set CONTRAIL_REPO_PROTO to https to use HTTPS instead. This line is + commented out in sample localrc file 6) Copy sample localrc-single as localrc for a single node system. Copy localrc-multinode-server and localrc-multinode-compute as localrc on master and compute nodes respectively for a multi-node system. +7) After running unstack.sh, run ifconfig and verify IP address has been + restored on PHYSICAL_INTERFACE and vhost0 interface is gone. Sometimes + you might see "ERROR: Module vrouter is in use" after running unstack.sh + which means interface cleanup couldn't be done since vrouter is busy and + could not be uninstalled. Repeat unstack.sh untill the interfaces are + restored to original state. +8) Protocol for openstack bits is also SSH by default. Uncomment out + GIT_BASE line to use https instead Change the following in localrc to suit your deployment: PHYSICAL_INTERFACE -- external interface Vrouter should bind to @@ -49,3 +57,59 @@ Steps for basic Ubuntu VM image cp contrail/localrc-single localrc vi localrc # edit PHYSICAL_INTERFACE 7) ./stack.sh + +Steps for basic Fedora host +--------------------------- +I perform these steps on a minimal Fedora host. You may not +need these steps and will depend upon your starting image. + +1) sudo yum -y install git-core patch vim +2) sudo yum -y install kernel-devel-3.6.6-1 + My "uname -a" shows "Linux a6s34 3.6.6-1.fc17.x86_64" +3) sudo yum -y upgrade libtasn1 +4) sudo yum -y install python-pip +5) sudo easy_install -U distribute +6) verify ssh to github is working + ssh -T git@github.com +7) download devstack (should have already done this) + git clone git@github.com:dsetia/devstack.git +8) copy sample localrc as mentioned above. Edit localrc + PHYSICAL_INTERFACE/SERVICE_HOST/... to match your setup + + cd devstack + cp contrail/localrc-single localrc + vi localrc # edit PHYSICAL_INTERFACE +9) ./stack.sh + + +Software Gateway support +------------------------ + +Software gateway provides internet connectivity to virtual machines. It +supports routing between virtual-network and external public-networks. The +Simple Gateway is a restricted implementation of gateway. The features +supported are, + - A compute node provides Simple Gateway functionality for a single + virtual-network + - A virtual-network can ideally have multiple subnets. But, gateway + supports only one subnet per virtual-network + - Relies on the networking stack of host operating-system to route packets + between public-network and virtual-network + +Configuration: + Following parameters must be configured in localrc for Simple Gateway: + + CONTRAIL_VGW_PUBLIC_NETWORK + Specifies FQDN of the routing-instance that needs public access. + Example: If domain=default-domain, user=admin and vm=public, FQDN is + default-domain:admin:public:public + CONTRAIL_VGW_PUBLIC_SUBNET + Specifies the subnet configured for the virtual-network. + Example: 192.168.1.0/24 + CONTRAIL_VGW_INTERFACE + A tap interface is created with this name. The interface is added to + routing-instance of virtual-network. Packets to/from virtual-network + use this interface (Example: vgw) + +Please see detailed instructions at: +https://github.com/Juniper/contrail-controller/wiki/Simple-Gateway diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 7c73d662fd..963136dcb1 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -7,6 +7,7 @@ ifmap_username=$__contrail_ifmap_username__ ifmap_password=$__contrail_ifmap_password__ redis_server_port=6379 +redis_server_ip=$__contrail_redis_server_ip__ cassandra_server_list=$__contrail_cassandra_server_list__ listen_ip_addr=$__contrail_listen_ip_addr__ listen_port=$__contrail_listen_port__ @@ -26,9 +27,11 @@ [KEYSTONE] auth_host=$__contrail_openstack_ip__ auth_protocol=http +auth_port=35357 admin_user=$__contrail_admin_user__ admin_password=$__contrail_admin_password__ admin_tenant_name=$__contrail_admin_tenant_name__ +admin_token = $__contrail_admin_token__ $__contrail_memcached_opt__ """) diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index 29e8c9049a..a4a8431602 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -18,7 +18,7 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 -ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,agent,vif,contrail +ENABLED_SERVICES=n-cpu,rabbit,neutron,agent,contrail Q_USE_DEBUG_COMMAND=True PHYSICAL_NETWORK=default @@ -38,3 +38,12 @@ DATABASE_TYPE=mysql # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 2aaa01a7b4..79f191c183 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -21,12 +21,24 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 +# contrail services +enable_service cass +enable_service ifmap +enable_service apiSrv +enable_service schema +enable_service svc-mon +enable_service zk +enable_service control +enable_service agent +enable_service disco +enable_service redis +enable_service contrail + disable_service n-net enable_service q-svc enable_service q-meta enable_service neutron enable_service rabbit -enable_service contrail # not used by contrail disable_service q-dhcp @@ -42,3 +54,12 @@ ADMIN_PASSWORD=contrail123 # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/contrail/localrc-single b/contrail/localrc-single index 5a0924e165..f326e0b2b5 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -6,11 +6,23 @@ DEBUG=True LOGFILE=$STACK_DIR/log/stack.log LOGDAYS=1 +# contrail services +enable_service cass +enable_service ifmap +enable_service apiSrv +enable_service schema +enable_service svc-mon +enable_service zk +enable_service control +enable_service agent +enable_service disco +enable_service redis +enable_service contrail + disable_service n-net enable_service q-svc enable_service q-meta enable_service neutron -enable_service contrail # not used by contrail disable_service q-agt @@ -30,3 +42,12 @@ PHYSICAL_INTERFACE=eth1 # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git NEUTRON_BRANCH=master + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +# GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 24eb958479..4465ea6e4e 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -552,12 +552,14 @@ def fixup_config_files(self): '__contrail_admin_user__': ks_admin_user, '__contrail_admin_password__': ks_admin_password, '__contrail_admin_tenant_name__': ks_admin_tenant_name, + '__contrail_admin_token__': ks_admin_password, '__contrail_memcached_opt__': 'memcache_servers=127.0.0.1:11211' if self._args.multi_tenancy else '', '__contrail_log_file__': '/var/log/contrail/api.log', '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), '__contrail_disc_server_ip__': self._args.discovery_ip or '', '__contrail_disc_server_port__': '5998', '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), + '__contrail_redis_server_ip__': cfgm_ip, } self._template_substitute_write(api_server_conf_template, template_vals, temp_dir_name + '/api_server.conf') diff --git a/driver_certs/cinder_driver_cert.sh b/driver_certs/cinder_driver_cert.sh new file mode 100755 index 0000000000..edcc6d4800 --- /dev/null +++ b/driver_certs/cinder_driver_cert.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# **cinder_cert.sh** + +# This script is a simple wrapper around the tempest volume api tests +# It requires that you have a working and functional devstack install +# and that you've enabled your device driver by making the necessary +# modifications to /etc/cinder/cinder.conf + +# This script will refresh your openstack repo's and restart the cinder +# services to pick up your driver changes. +# please NOTE; this script assumes your devstack install is functional +# and includes tempest. A good first step is to make sure you can +# create volumes on your device before you even try and run this script. + +# It also assumes default install location (/opt/stack/xxx) +# to aid in debug, you should also verify that you've added +# an output directory for screen logs: +# SCREEN_LOGDIR=/opt/stack/screen-logs + +CERT_DIR=$(cd $(dirname "$0") && pwd) +TOP_DIR=$(cd $CERT_DIR/..; pwd) + +source $TOP_DIR/functions +source $TOP_DIR/stackrc +source $TOP_DIR/openrc +source $TOP_DIR/lib/tempest +source $TOP_DIR/lib/cinder + +TEMPFILE=`mktemp` +RECLONE=True + +function log_message() { + MESSAGE=$1 + STEP_HEADER=$2 + if [[ "$STEP_HEADER" = "True" ]]; then + echo -e "\n========================================================" | tee -a $TEMPFILE + fi + echo -e `date +%m/%d/%y/%T:`"${MESSAGE}" | tee -a $TEMPFILE + if [[ "$STEP_HEADER" = "True" ]]; then + echo -e "========================================================" | tee -a $TEMPFILE + fi +} + +if [[ "$OFFLINE" = "True" ]]; then + echo "ERROR: Driver cert requires fresh clone/pull from ${CINDER_BRANCH}" + echo " Please set OFFLINE=False and retry." + exit 1 +fi + +log_message "RUNNING CINDER DRIVER CERTIFICATION CHECK", True +log_message "Output is being logged to: $TEMPFILE" + +cd $CINDER_DIR +log_message "Cloning to ${CINDER_REPO}...", True +install_cinder + +log_message "Pull a fresh Clone of cinder repo...", True +git status | tee -a $TEMPFILE +git log --pretty=oneline -n 1 | tee -a $TEMPFILE + +log_message "Gathering copy of cinder.conf file (passwords will be scrubbed)...", True +cat /etc/cinder/cinder.conf | egrep -v "(^#.*|^$)" | tee -a $TEMPFILE +sed -i "s/\(.*password.*=\).*$/\1 xxx/i" $TEMPFILE +log_message "End of cinder.conf.", True + +cd $TOP_DIR +# Verify tempest is installed/enabled +if ! is_service_enabled tempest; then + log_message "ERROR!!! Cert requires tempest in enabled_services!", True + log_message" Please add tempest to enabled_services and retry." + exit 1 +fi + +cd $TEMPEST_DIR +install_tempest + +log_message "Verify tempest is current....", True +git status | tee -a $TEMPFILE +log_message "Check status and get latest commit..." +git log --pretty=oneline -n 1 | tee -a $TEMPFILE + + +#stop and restart cinder services +log_message "Restart Cinder services...", True +stop_cinder +sleep 1 +start_cinder +sleep 5 + +# run tempest api/volume/test_* +log_message "Run the actual tempest volume tests (./tools/pretty_tox.sh api.volume_*)...", True +exec 2> >(tee -a $TEMPFILE) +`./tools/pretty_tox.sh api.volume` +if [[ $? = 0 ]]; then + log_message "CONGRATULATIONS!!! Device driver PASSED!", True + log_message "Submit output: ($TEMPFILE)" + exit 0 +else + log_message "SORRY!!! Device driver FAILED!", True + log_message "Check output in $TEMPFILE" + exit 1 +fi diff --git a/eucarc b/eucarc index 2b0f7dd143..350235106c 100644 --- a/eucarc +++ b/eucarc @@ -13,7 +13,7 @@ if [[ -n "$2" ]]; then fi # Find the other rc files -RC_DIR=$(cd $(dirname "$BASH_SOURCE") && pwd) +RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd) # Get user configuration source $RC_DIR/openrc diff --git a/exercises/aggregates.sh b/exercises/aggregates.sh index e2baecdb11..d223301f35 100755 --- a/exercises/aggregates.sh +++ b/exercises/aggregates.sh @@ -3,12 +3,13 @@ # **aggregates.sh** # This script demonstrates how to use host aggregates: -# * Create an Aggregate -# * Updating Aggregate details -# * Testing Aggregate metadata -# * Testing Aggregate delete -# * Testing General Aggregates (https://blueprints.launchpad.net/nova/+spec/general-host-aggregates) -# * Testing add/remove hosts (with one host) +# +# * Create an Aggregate +# * Updating Aggregate details +# * Testing Aggregate metadata +# * Testing Aggregate delete +# * Testing General Aggregates (https://blueprints.launchpad.net/nova/+spec/general-host-aggregates) +# * Testing add/remove hosts (with one host) echo "**************************************************" echo "Begin DevStack Exercise: $0" @@ -42,6 +43,10 @@ source $TOP_DIR/exerciserc # Test as the admin user . $TOP_DIR/openrc admin admin +# If nova api is not enabled we exit with exitcode 55 so that +# the exercise is skipped +is_service_enabled n-api || exit 55 + # Cells does not support aggregates. is_service_enabled n-cell && exit 55 @@ -66,7 +71,10 @@ exit_if_aggregate_present() { exit_if_aggregate_present $AGGREGATE_NAME AGGREGATE_ID=$(nova aggregate-create $AGGREGATE_NAME $AGGREGATE_A_ZONE | grep " $AGGREGATE_NAME " | get_field 1) +die_if_not_set $LINENO AGGREGATE_ID "Failure creating AGGREGATE_ID for $AGGREGATE_NAME $AGGREGATE_A_ZONE" + AGGREGATE2_ID=$(nova aggregate-create $AGGREGATE2_NAME $AGGREGATE_A_ZONE | grep " $AGGREGATE2_NAME " | get_field 1) +die_if_not_set $LINENO AGGREGATE2_ID "Fail creating AGGREGATE2_ID for $AGGREGATE2_NAME $AGGREGATE_A_ZONE" # check aggregate created nova aggregate-list | grep -q " $AGGREGATE_NAME " || die $LINENO "Aggregate $AGGREGATE_NAME not created" @@ -100,7 +108,7 @@ META_DATA_2_KEY=foo META_DATA_3_KEY=bar #ensure no additional metadata is set -nova aggregate-details $AGGREGATE_ID | egrep "{u'availability_zone': u'$AGGREGATE_A_ZONE'}|{}" +nova aggregate-details $AGGREGATE_ID | egrep "\|[{u ]*'availability_zone.+$AGGREGATE_A_ZONE'[ }]*\|" nova aggregate-set-metadata $AGGREGATE_ID ${META_DATA_1_KEY}=123 nova aggregate-details $AGGREGATE_ID | grep $META_DATA_1_KEY @@ -117,7 +125,7 @@ nova aggregate-details $AGGREGATE_ID | grep $META_DATA_3_KEY nova aggregate-details $AGGREGATE_ID | grep $META_DATA_2_KEY && die $LINENO "ERROR metadata was not cleared" nova aggregate-set-metadata $AGGREGATE_ID $META_DATA_3_KEY $META_DATA_1_KEY -nova aggregate-details $AGGREGATE_ID | egrep "{u'availability_zone': u'$AGGREGATE_A_ZONE'}|{}" +nova aggregate-details $AGGREGATE_ID | egrep "\|[{u ]*'availability_zone.+$AGGREGATE_A_ZONE'[ }]*\|" # Test aggregate-add/remove-host diff --git a/exercises/boot_from_volume.sh b/exercises/boot_from_volume.sh index fe27bd0956..ed8ba6310e 100755 --- a/exercises/boot_from_volume.sh +++ b/exercises/boot_from_volume.sh @@ -3,8 +3,9 @@ # **boot_from_volume.sh** # This script demonstrates how to boot from a volume. It does the following: -# * Create a bootable volume -# * Boot a volume-backed instance +# +# * Create a bootable volume +# * Boot a volume-backed instance echo "*********************************************************************" echo "Begin DevStack Exercise: $0" @@ -119,7 +120,7 @@ nova flavor-list INSTANCE_TYPE=$(nova flavor-list | grep $DEFAULT_INSTANCE_TYPE | get_field 1) if [[ -z "$INSTANCE_TYPE" ]]; then # grab the first flavor in the list to launch if default doesn't exist - INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) + INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) fi # Clean-up from previous runs @@ -148,7 +149,7 @@ fi # Create the bootable volume start_time=$(date +%s) -cinder create --image-id $IMAGE --display_name=$VOL_NAME --display_description "test bootable volume: $VOL_NAME" $DEFAULT_VOLUME_SIZE || \ +cinder create --image-id $IMAGE --display-name=$VOL_NAME --display-description "test bootable volume: $VOL_NAME" $DEFAULT_VOLUME_SIZE || \ die $LINENO "Failure creating volume $VOL_NAME" if ! timeout $ACTIVE_TIMEOUT sh -c "while ! cinder list | grep $VOL_NAME | grep available; do sleep 1; done"; then echo "Volume $VOL_NAME not created" @@ -164,10 +165,10 @@ die_if_not_set $LINENO VOL_ID "Failure retrieving volume ID for $VOL_NAME" # Boot instance # ------------- -# Boot using the --block_device_mapping param. The format of mapping is: +# Boot using the --block-device-mapping param. The format of mapping is: # =::: # Leaving the middle two fields blank appears to do-the-right-thing -VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --block-device-mapping vda=$VOL_ID --security_groups=$SECGROUP --key_name $KEY_NAME $VM_NAME | grep ' id ' | get_field 2) +VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --block-device-mapping vda=$VOL_ID --security-groups=$SECGROUP --key-name $KEY_NAME $VM_NAME | grep ' id ' | get_field 2) die_if_not_set $LINENO VM_UUID "Failure launching $VM_NAME" # Check that the status is active within ACTIVE_TIMEOUT seconds diff --git a/exercises/bundle.sh b/exercises/bundle.sh index b83678ab1f..5470960b91 100755 --- a/exercises/bundle.sh +++ b/exercises/bundle.sh @@ -39,6 +39,10 @@ rm -f $TOP_DIR/cacert.pem rm -f $TOP_DIR/cert.pem rm -f $TOP_DIR/pk.pem +# If nova api is not enabled we exit with exitcode 55 so that +# the exercise is skipped +is_service_enabled n-api || exit 55 + # Get Certificates nova x509-get-root-cert $TOP_DIR/cacert.pem nova x509-create-cert $TOP_DIR/pk.pem $TOP_DIR/cert.pem diff --git a/exercises/client-args.sh b/exercises/client-args.sh index 1e68042cec..e79774f98c 100755 --- a/exercises/client-args.sh +++ b/exercises/client-args.sh @@ -56,10 +56,8 @@ unset OS_PASSWORD unset OS_AUTH_URL # Common authentication args -TENANT_ARG="--os_tenant_name=$x_TENANT_NAME" -TENANT_ARG_DASH="--os-tenant-name=$x_TENANT_NAME" -ARGS="--os_username=$x_USERNAME --os_password=$x_PASSWORD --os_auth_url=$x_AUTH_URL" -ARGS_DASH="--os-username=$x_USERNAME --os-password=$x_PASSWORD --os-auth-url=$x_AUTH_URL" +TENANT_ARG="--os-tenant-name=$x_TENANT_NAME" +ARGS="--os-username=$x_USERNAME --os-password=$x_PASSWORD --os-auth-url=$x_AUTH_URL" # Set global return RETURN=0 @@ -71,7 +69,7 @@ if [[ "$ENABLED_SERVICES" =~ "key" ]]; then STATUS_KEYSTONE="Skipped" else echo -e "\nTest Keystone" - if keystone $TENANT_ARG_DASH $ARGS_DASH catalog --service identity; then + if keystone $TENANT_ARG $ARGS catalog --service identity; then STATUS_KEYSTONE="Succeeded" else STATUS_KEYSTONE="Failed" @@ -90,7 +88,7 @@ if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then else # Test OSAPI echo -e "\nTest Nova" - if nova $TENANT_ARG_DASH $ARGS_DASH flavor-list; then + if nova $TENANT_ARG $ARGS flavor-list; then STATUS_NOVA="Succeeded" else STATUS_NOVA="Failed" @@ -107,7 +105,7 @@ if [[ "$ENABLED_SERVICES" =~ "c-api" ]]; then STATUS_CINDER="Skipped" else echo -e "\nTest Cinder" - if cinder $TENANT_ARG_DASH $ARGS_DASH list; then + if cinder $TENANT_ARG $ARGS list; then STATUS_CINDER="Succeeded" else STATUS_CINDER="Failed" @@ -124,7 +122,7 @@ if [[ "$ENABLED_SERVICES" =~ "g-api" ]]; then STATUS_GLANCE="Skipped" else echo -e "\nTest Glance" - if glance $TENANT_ARG_DASH $ARGS_DASH image-list; then + if glance $TENANT_ARG $ARGS image-list; then STATUS_GLANCE="Succeeded" else STATUS_GLANCE="Failed" @@ -141,7 +139,7 @@ if [[ "$ENABLED_SERVICES" =~ "swift" || "$ENABLED_SERVICES" =~ "s-proxy" ]]; the STATUS_SWIFT="Skipped" else echo -e "\nTest Swift" - if swift $TENANT_ARG_DASH $ARGS_DASH stat; then + if swift $TENANT_ARG $ARGS stat; then STATUS_SWIFT="Succeeded" else STATUS_SWIFT="Failed" diff --git a/exercises/docker.sh b/exercises/docker.sh deleted file mode 100755 index 0672bc0087..0000000000 --- a/exercises/docker.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# **docker** - -# Test Docker hypervisor - -echo "*********************************************************************" -echo "Begin DevStack Exercise: $0" -echo "*********************************************************************" - -# This script exits on an error so that errors don't compound and you see -# only the first error that occurred. -set -o errexit - -# Print the commands being run so that we can see the command that triggers -# an error. It is also useful for following allowing as the install occurs. -set -o xtrace - - -# Settings -# ======== - -# Keep track of the current directory -EXERCISE_DIR=$(cd $(dirname "$0") && pwd) -TOP_DIR=$(cd $EXERCISE_DIR/..; pwd) - -# Import common functions -source $TOP_DIR/functions - -# Import configuration -source $TOP_DIR/openrc - -# Import exercise configuration -source $TOP_DIR/exerciserc - -# Skip if the hypervisor is not Docker -[[ "$VIRT_DRIVER" == "docker" ]] || exit 55 - -# Import docker functions and declarations -source $TOP_DIR/lib/nova_plugins/hypervisor-docker - -# Image and flavor are ignored but the CLI requires them... - -# Instance type to create -DEFAULT_INSTANCE_TYPE=${DEFAULT_INSTANCE_TYPE:-m1.tiny} - -# Boot this image, use first AMI image if unset -DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ami} - -# Instance name -VM_NAME=ex-docker - - -# Launching a server -# ================== - -# Grab the id of the image to launch -IMAGE=$(glance image-list | egrep " $DOCKER_IMAGE_NAME:latest " | get_field 1) -die_if_not_set $LINENO IMAGE "Failure getting image $DOCKER_IMAGE_NAME" - -# Select a flavor -INSTANCE_TYPE=$(nova flavor-list | grep $DEFAULT_INSTANCE_TYPE | get_field 1) -if [[ -z "$INSTANCE_TYPE" ]]; then - # grab the first flavor in the list to launch if default doesn't exist - INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) -fi - -# Clean-up from previous runs -nova delete $VM_NAME || true -if ! timeout $ACTIVE_TIMEOUT sh -c "while nova show $VM_NAME; do sleep 1; done"; then - die $LINENO "server didn't terminate!" -fi - -# Boot instance -# ------------- - -VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE $VM_NAME | grep ' id ' | get_field 2) -die_if_not_set $LINENO VM_UUID "Failure launching $VM_NAME" - -# Check that the status is active within ACTIVE_TIMEOUT seconds -if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova show $VM_UUID | grep status | grep -q ACTIVE; do sleep 1; done"; then - die $LINENO "server didn't become active!" -fi - -# Get the instance IP -IP=$(nova show $VM_UUID | grep "$PRIVATE_NETWORK_NAME" | get_field 2) -die_if_not_set $LINENO IP "Failure retrieving IP address" - -# Private IPs can be pinged in single node deployments -ping_check "$PRIVATE_NETWORK_NAME" $IP $BOOT_TIMEOUT - -# Clean up -# -------- - -# Delete instance -nova delete $VM_UUID || die $LINENO "Failure deleting instance $VM_NAME" -if ! timeout $TERMINATE_TIMEOUT sh -c "while nova list | grep -q $VM_UUID; do sleep 1; done"; then - die $LINENO "Server $VM_NAME not deleted" -fi - -set +o xtrace -echo "*********************************************************************" -echo "SUCCESS: End DevStack Exercise: $0" -echo "*********************************************************************" - diff --git a/exercises/euca.sh b/exercises/euca.sh index 64c0014236..51b2644458 100755 --- a/exercises/euca.sh +++ b/exercises/euca.sh @@ -41,6 +41,10 @@ fi # Import exercise configuration source $TOP_DIR/exerciserc +# If nova api is not enabled we exit with exitcode 55 so that +# the exercise is skipped +is_service_enabled n-api || exit 55 + # Skip if the hypervisor is Docker [[ "$VIRT_DRIVER" == "docker" ]] && exit 55 @@ -87,31 +91,31 @@ fi # Volumes # ------- if is_service_enabled c-vol && ! is_service_enabled n-cell; then - VOLUME_ZONE=`euca-describe-availability-zones | head -n1 | cut -f2` - die_if_not_set $LINENO VOLUME_ZONE "Failure to find zone for volume" - - VOLUME=`euca-create-volume -s 1 -z $VOLUME_ZONE | cut -f2` - die_if_not_set $LINENO VOLUME "Failure to create volume" - - # Test that volume has been created - VOLUME=`euca-describe-volumes $VOLUME | cut -f2` - die_if_not_set $LINENO VOLUME "Failure to get volume" - - # Test volume has become available - if ! timeout $RUNNING_TIMEOUT sh -c "while ! euca-describe-volumes $VOLUME | grep -q available; do sleep 1; done"; then - die $LINENO "volume didn't become available within $RUNNING_TIMEOUT seconds" - fi - - # Attach volume to an instance - euca-attach-volume -i $INSTANCE -d $ATTACH_DEVICE $VOLUME || \ - die $LINENO "Failure attaching volume $VOLUME to $INSTANCE" - if ! timeout $ACTIVE_TIMEOUT sh -c "while ! euca-describe-volumes $VOLUME | grep -A 1 in-use | grep -q attach; do sleep 1; done"; then - die $LINENO "Could not attach $VOLUME to $INSTANCE" - fi - - # Detach volume from an instance - euca-detach-volume $VOLUME || \ - die $LINENO "Failure detaching volume $VOLUME to $INSTANCE" + VOLUME_ZONE=`euca-describe-availability-zones | head -n1 | cut -f2` + die_if_not_set $LINENO VOLUME_ZONE "Failure to find zone for volume" + + VOLUME=`euca-create-volume -s 1 -z $VOLUME_ZONE | cut -f2` + die_if_not_set $LINENO VOLUME "Failure to create volume" + + # Test that volume has been created + VOLUME=`euca-describe-volumes $VOLUME | cut -f2` + die_if_not_set $LINENO VOLUME "Failure to get volume" + + # Test volume has become available + if ! timeout $RUNNING_TIMEOUT sh -c "while ! euca-describe-volumes $VOLUME | grep -q available; do sleep 1; done"; then + die $LINENO "volume didn't become available within $RUNNING_TIMEOUT seconds" + fi + + # Attach volume to an instance + euca-attach-volume -i $INSTANCE -d $ATTACH_DEVICE $VOLUME || \ + die $LINENO "Failure attaching volume $VOLUME to $INSTANCE" + if ! timeout $ACTIVE_TIMEOUT sh -c "while ! euca-describe-volumes $VOLUME | grep -A 1 in-use | grep -q attach; do sleep 1; done"; then + die $LINENO "Could not attach $VOLUME to $INSTANCE" + fi + + # Detach volume from an instance + euca-detach-volume $VOLUME || \ + die $LINENO "Failure detaching volume $VOLUME to $INSTANCE" if ! timeout $ACTIVE_TIMEOUT sh -c "while ! euca-describe-volumes $VOLUME | grep -q available; do sleep 1; done"; then die $LINENO "Could not detach $VOLUME to $INSTANCE" fi @@ -120,7 +124,7 @@ if is_service_enabled c-vol && ! is_service_enabled n-cell; then euca-delete-volume $VOLUME || \ die $LINENO "Failure to delete volume" if ! timeout $ACTIVE_TIMEOUT sh -c "while euca-describe-volumes | grep $VOLUME; do sleep 1; done"; then - die $LINENO "Could not delete $VOLUME" + die $LINENO "Could not delete $VOLUME" fi else echo "Volume Tests Skipped" diff --git a/exercises/floating_ips.sh b/exercises/floating_ips.sh index 2833b650ba..4ca90a5c35 100755 --- a/exercises/floating_ips.sh +++ b/exercises/floating_ips.sh @@ -38,6 +38,10 @@ fi # Import exercise configuration source $TOP_DIR/exerciserc +# If nova api is not enabled we exit with exitcode 55 so that +# the exercise is skipped +is_service_enabled n-api || exit 55 + # Skip if the hypervisor is Docker [[ "$VIRT_DRIVER" == "docker" ]] && exit 55 @@ -113,7 +117,8 @@ nova flavor-list INSTANCE_TYPE=$(nova flavor-list | grep $DEFAULT_INSTANCE_TYPE | get_field 1) if [[ -z "$INSTANCE_TYPE" ]]; then # grab the first flavor in the list to launch if default doesn't exist - INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) + INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) + die_if_not_set $LINENO INSTANCE_TYPE "Failure retrieving INSTANCE_TYPE" fi # Clean-up from previous runs @@ -126,7 +131,7 @@ fi # Boot instance # ------------- -VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --security_groups=$SECGROUP $VM_NAME | grep ' id ' | get_field 2) +VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --security-groups=$SECGROUP $VM_NAME | grep ' id ' | get_field 2) die_if_not_set $LINENO VM_UUID "Failure launching $VM_NAME" # Check that the status is active within ACTIVE_TIMEOUT seconds @@ -168,7 +173,7 @@ if ! is_service_enabled neutron; then # list floating addresses if ! timeout $ASSOCIATE_TIMEOUT sh -c "while ! nova floating-ip-list | grep $TEST_FLOATING_POOL | grep -q $TEST_FLOATING_IP; do sleep 1; done"; then die $LINENO "Floating IP not allocated" - fi + fi fi # Dis-allow icmp traffic (ping) diff --git a/exercises/marconi.sh b/exercises/marconi.sh new file mode 100755 index 0000000000..9d83a99f02 --- /dev/null +++ b/exercises/marconi.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# **marconi.sh** + +# Sanity check that Marconi started if enabled + +echo "*********************************************************************" +echo "Begin DevStack Exercise: $0" +echo "*********************************************************************" + +# This script exits on an error so that errors don't compound and you see +# only the first error that occurred. +set -o errexit + +# Print the commands being run so that we can see the command that triggers +# an error. It is also useful for following allowing as the install occurs. +set -o xtrace + + +# Settings +# ======== + +# Keep track of the current directory +EXERCISE_DIR=$(cd $(dirname "$0") && pwd) +TOP_DIR=$(cd $EXERCISE_DIR/..; pwd) + +# Import common functions +source $TOP_DIR/functions + +# Import configuration +source $TOP_DIR/openrc + +# Import exercise configuration +source $TOP_DIR/exerciserc + +is_service_enabled marconi-server || exit 55 + +curl http://$SERVICE_HOST:8888/v1/ 2>/dev/null | grep -q 'queue_name' || die $LINENO "Marconi API not functioning!" + +set +o xtrace +echo "*********************************************************************" +echo "SUCCESS: End DevStack Exercise: $0" +echo "*********************************************************************" diff --git a/exercises/neutron-adv-test.sh b/exercises/neutron-adv-test.sh index abb29cf333..1343f11553 100755 --- a/exercises/neutron-adv-test.sh +++ b/exercises/neutron-adv-test.sh @@ -102,6 +102,7 @@ KEYSTONE="keystone" # and save it. TOKEN=`keystone token-get | grep ' id ' | awk '{print $4}'` +die_if_not_set $LINENO TOKEN "Keystone fail to get token" # Various functions # ----------------- @@ -138,24 +139,28 @@ function foreach_tenant_net { function get_image_id { local IMAGE_ID=$(glance image-list | egrep " $DEFAULT_IMAGE_NAME " | get_field 1) + die_if_not_set $LINENO IMAGE_ID "Failure retrieving IMAGE_ID" echo "$IMAGE_ID" } function get_tenant_id { local TENANT_NAME=$1 local TENANT_ID=`keystone tenant-list | grep " $TENANT_NAME " | head -n 1 | get_field 1` + die_if_not_set $LINENO TENANT_ID "Failure retrieving TENANT_ID for $TENANT_NAME" echo "$TENANT_ID" } function get_user_id { local USER_NAME=$1 local USER_ID=`keystone user-list | grep $USER_NAME | awk '{print $2}'` + die_if_not_set $LINENO USER_ID "Failure retrieving USER_ID for $USER_NAME" echo "$USER_ID" } function get_role_id { local ROLE_NAME=$1 local ROLE_ID=`keystone role-list | grep $ROLE_NAME | awk '{print $2}'` + die_if_not_set $LINENO ROLE_ID "Failure retrieving ROLE_ID for $ROLE_NAME" echo "$ROLE_ID" } @@ -168,6 +173,7 @@ function get_network_id { function get_flavor_id { local INSTANCE_TYPE=$1 local FLAVOR_ID=`nova flavor-list | grep $INSTANCE_TYPE | awk '{print $2}'` + die_if_not_set $LINENO FLAVOR_ID "Failure retrieving FLAVOR_ID for $INSTANCE_TYPE" echo "$FLAVOR_ID" } @@ -179,6 +185,14 @@ function confirm_server_active { fi } +function neutron_debug_admin { + local os_username=$OS_USERNAME + local os_tenant_id=$OS_TENANT_ID + source $TOP_DIR/openrc admin admin + neutron-debug $@ + source $TOP_DIR/openrc $os_username $os_tenant_id +} + function add_tenant { local TENANT=$1 local USER=$2 @@ -232,9 +246,10 @@ function create_network { source $TOP_DIR/openrc admin admin local TENANT_ID=$(get_tenant_id $TENANT) source $TOP_DIR/openrc $TENANT $TENANT - local NET_ID=$(neutron net-create --tenant_id $TENANT_ID $NET_NAME $EXTRA| grep ' id ' | awk '{print $4}' ) - neutron subnet-create --ip_version 4 --tenant_id $TENANT_ID --gateway $GATEWAY $NET_ID $CIDR - neutron-debug probe-create --device-owner compute $NET_ID + local NET_ID=$(neutron net-create --tenant-id $TENANT_ID $NET_NAME $EXTRA| grep ' id ' | awk '{print $4}' ) + die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $TENANT_ID $NET_NAME $EXTRA" + neutron subnet-create --ip-version 4 --tenant-id $TENANT_ID --gateway $GATEWAY $NET_ID $CIDR + neutron_debug_admin probe-create --device-owner compute $NET_ID source $TOP_DIR/openrc demo demo } @@ -272,12 +287,12 @@ function create_vms { } function ping_ip { - # Test agent connection. Assumes namespaces are disabled, and - # that DHCP is in use, but not L3 - local VM_NAME=$1 - local NET_NAME=$2 - IP=$(get_instance_ip $VM_NAME $NET_NAME) - ping_check $NET_NAME $IP $BOOT_TIMEOUT + # Test agent connection. Assumes namespaces are disabled, and + # that DHCP is in use, but not L3 + local VM_NAME=$1 + local NET_NAME=$2 + IP=$(get_instance_ip $VM_NAME $NET_NAME) + ping_check $NET_NAME $IP $BOOT_TIMEOUT } function check_vm { @@ -329,12 +344,12 @@ function delete_network { } function delete_networks { - foreach_tenant_net 'delete_network ${%TENANT%_NAME} %NUM%' - #TODO(nati) add secuirty group check after it is implemented - # source $TOP_DIR/openrc demo1 demo1 - # nova secgroup-delete-rule default icmp -1 -1 0.0.0.0/0 - # source $TOP_DIR/openrc demo2 demo2 - # nova secgroup-delete-rule default icmp -1 -1 0.0.0.0/0 + foreach_tenant_net 'delete_network ${%TENANT%_NAME} %NUM%' + # TODO(nati) add secuirty group check after it is implemented + # source $TOP_DIR/openrc demo1 demo1 + # nova secgroup-delete-rule default icmp -1 -1 0.0.0.0/0 + # source $TOP_DIR/openrc demo2 demo2 + # nova secgroup-delete-rule default icmp -1 -1 0.0.0.0/0 } function create_all { @@ -393,10 +408,10 @@ main() { echo Description echo echo Copyright 2012, Cisco Systems - echo Copyright 2012, Nicira Networks, Inc. + echo Copyright 2012, VMware, Inc. echo Copyright 2012, NTT MCL, Inc. echo - echo Please direct any questions to dedutta@cisco.com, dan@nicira.com, nachi@nttmcl.com + echo Please direct any questions to dedutta@cisco.com, dwendlandt@vmware.com, nachi@nttmcl.com echo diff --git a/exercises/savanna.sh b/exercises/savanna.sh new file mode 100755 index 0000000000..fc3f9760e5 --- /dev/null +++ b/exercises/savanna.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# **savanna.sh** + +# Sanity check that Savanna started if enabled + +echo "*********************************************************************" +echo "Begin DevStack Exercise: $0" +echo "*********************************************************************" + +# This script exits on an error so that errors don't compound and you see +# only the first error that occurred. +set -o errexit + +# Print the commands being run so that we can see the command that triggers +# an error. It is also useful for following allowing as the install occurs. +set -o xtrace + + +# Settings +# ======== + +# Keep track of the current directory +EXERCISE_DIR=$(cd $(dirname "$0") && pwd) +TOP_DIR=$(cd $EXERCISE_DIR/..; pwd) + +# Import common functions +source $TOP_DIR/functions + +# Import configuration +source $TOP_DIR/openrc + +# Import exercise configuration +source $TOP_DIR/exerciserc + +is_service_enabled savanna || exit 55 + +curl http://$SERVICE_HOST:8386/ 2>/dev/null | grep -q 'Auth' || die $LINENO "Savanna API not functioning!" + +set +o xtrace +echo "*********************************************************************" +echo "SUCCESS: End DevStack Exercise: $0" +echo "*********************************************************************" diff --git a/exercises/sec_groups.sh b/exercises/sec_groups.sh index 7d80570326..d71a1e0755 100755 --- a/exercises/sec_groups.sh +++ b/exercises/sec_groups.sh @@ -33,6 +33,10 @@ source $TOP_DIR/openrc # Import exercise configuration source $TOP_DIR/exerciserc +# If nova api is not enabled we exit with exitcode 55 so that +# the exercise is skipped +is_service_enabled n-api || exit 55 + # Skip if the hypervisor is Docker [[ "$VIRT_DRIVER" == "docker" ]] && exit 55 @@ -56,6 +60,7 @@ done # Check to make sure rules were added SEC_GROUP_RULES=( $(nova secgroup-list-rules $SEC_GROUP_NAME | grep -v \- | grep -v 'Source Group' | cut -d '|' -f3 | tr -d ' ') ) +die_if_not_set $LINENO SEC_GROUP_RULES "Failure retrieving SEC_GROUP_RULES for $SEC_GROUP_NAME" for i in "${RULES_TO_ADD[@]}"; do skip= for j in "${SEC_GROUP_RULES[@]}"; do diff --git a/exercises/swift.sh b/exercises/swift.sh index b9f1b566bb..25ea6719c1 100755 --- a/exercises/swift.sh +++ b/exercises/swift.sh @@ -2,7 +2,7 @@ # **swift.sh** -# Test swift via the ``swift`` command line from ``python-swiftclient` +# Test swift via the ``swift`` command line from ``python-swiftclient`` echo "*********************************************************************" echo "Begin DevStack Exercise: $0" diff --git a/exercises/volumes.sh b/exercises/volumes.sh index e536d16249..21b5d21c04 100755 --- a/exercises/volumes.sh +++ b/exercises/volumes.sh @@ -117,7 +117,8 @@ nova flavor-list INSTANCE_TYPE=$(nova flavor-list | grep $DEFAULT_INSTANCE_TYPE | get_field 1) if [[ -z "$INSTANCE_TYPE" ]]; then # grab the first flavor in the list to launch if default doesn't exist - INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) + INSTANCE_TYPE=$(nova flavor-list | head -n 4 | tail -n 1 | get_field 1) + die_if_not_set $LINENO INSTANCE_TYPE "Failure retrieving INSTANCE_TYPE" fi # Clean-up from previous runs @@ -129,7 +130,7 @@ fi # Boot instance # ------------- -VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --security_groups=$SECGROUP $VM_NAME | grep ' id ' | get_field 2) +VM_UUID=$(nova boot --flavor $INSTANCE_TYPE --image $IMAGE --security-groups=$SECGROUP $VM_NAME | grep ' id ' | get_field 2) die_if_not_set $LINENO VM_UUID "Failure launching $VM_NAME" # Check that the status is active within ACTIVE_TIMEOUT seconds @@ -155,7 +156,7 @@ fi # Create a new volume start_time=$(date +%s) -cinder create --display_name $VOL_NAME --display_description "test volume: $VOL_NAME" $DEFAULT_VOLUME_SIZE || \ +cinder create --display-name $VOL_NAME --display-description "test volume: $VOL_NAME" $DEFAULT_VOLUME_SIZE || \ die $LINENO "Failure creating volume $VOL_NAME" if ! timeout $ACTIVE_TIMEOUT sh -c "while ! cinder list | grep $VOL_NAME | grep available; do sleep 1; done"; then die $LINENO "Volume $VOL_NAME not created" diff --git a/extras.d/70-marconi.sh b/extras.d/70-marconi.sh new file mode 100644 index 0000000000..a96a4c546c --- /dev/null +++ b/extras.d/70-marconi.sh @@ -0,0 +1,29 @@ +# marconi.sh - Devstack extras script to install Marconi + +if is_service_enabled marconi-server; then + if [[ "$1" == "source" ]]; then + # Initial source + source $TOP_DIR/lib/marconi + elif [[ "$1" == "stack" && "$2" == "install" ]]; then + echo_summary "Installing Marconi" + install_marconiclient + install_marconi + elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + echo_summary "Configuring Marconi" + configure_marconi + configure_marconiclient + + if is_service_enabled key; then + create_marconi_accounts + fi + + elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + echo_summary "Initializing Marconi" + init_marconi + start_marconi + fi + + if [[ "$1" == "unstack" ]]; then + stop_marconi + fi +fi diff --git a/extras.d/70-savanna.sh b/extras.d/70-savanna.sh new file mode 100644 index 0000000000..6bbe113fa7 --- /dev/null +++ b/extras.d/70-savanna.sh @@ -0,0 +1,32 @@ +# savanna.sh - DevStack extras script to install Savanna + +if is_service_enabled savanna; then + if [[ "$1" == "source" ]]; then + # Initial source + source $TOP_DIR/lib/savanna + source $TOP_DIR/lib/savanna-dashboard + elif [[ "$1" == "stack" && "$2" == "install" ]]; then + echo_summary "Installing Savanna" + install_savanna + if is_service_enabled horizon; then + install_savanna_dashboard + fi + elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + echo_summary "Configuring Savanna" + configure_savanna + create_savanna_accounts + if is_service_enabled horizon; then + configure_savanna_dashboard + fi + elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + echo_summary "Initializing Savanna" + start_savanna + fi + + if [[ "$1" == "unstack" ]]; then + stop_savanna + if is_service_enabled horizon; then + cleanup_savanna_dashboard + fi + fi +fi diff --git a/extras.d/70-trove.sh b/extras.d/70-trove.sh new file mode 100644 index 0000000000..a4dc7fbc5b --- /dev/null +++ b/extras.d/70-trove.sh @@ -0,0 +1,33 @@ +# trove.sh - Devstack extras script to install Trove + +if is_service_enabled trove; then + if [[ "$1" == "source" ]]; then + # Initial source + source $TOP_DIR/lib/trove + elif [[ "$1" == "stack" && "$2" == "install" ]]; then + echo_summary "Installing Trove" + install_trove + install_troveclient + cleanup_trove + elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + echo_summary "Configuring Trove" + configure_troveclient + configure_trove + + if is_service_enabled key; then + create_trove_accounts + fi + + elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + # Initialize trove + init_trove + + # Start the trove API and trove taskmgr components + echo_summary "Starting Trove" + start_trove + fi + + if [[ "$1" == "unstack" ]]; then + stop_trove + fi +fi diff --git a/extras.d/80-tempest.sh b/extras.d/80-tempest.sh index f159955726..0186e36aee 100644 --- a/extras.d/80-tempest.sh +++ b/extras.d/80-tempest.sh @@ -1,21 +1,32 @@ # tempest.sh - DevStack extras script -source $TOP_DIR/lib/tempest - -if [[ "$1" == "stack" ]]; then - # Configure Tempest last to ensure that the runtime configuration of - # the various OpenStack services can be queried. - if is_service_enabled tempest; then - echo_summary "Configuring Tempest" +if is_service_enabled tempest; then + if [[ "$1" == "source" ]]; then + # Initial source + source $TOP_DIR/lib/tempest + elif [[ "$1" == "stack" && "$2" == "install" ]]; then + echo_summary "Installing Tempest" install_tempest + elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + # Tempest config must come after layer 2 services are running + : + elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + echo_summary "Initializing Tempest" configure_tempest init_tempest + elif [[ "$1" == "stack" && "$2" == "post-extra" ]]; then + # local.conf Tempest option overrides + : fi -fi -if [[ "$1" == "unstack" ]]; then - # no-op - : -fi + if [[ "$1" == "unstack" ]]; then + # no-op + : + fi + if [[ "$1" == "clean" ]]; then + # no-op + : + fi +fi diff --git a/extras.d/README b/extras.d/README deleted file mode 100644 index ffc6793abd..0000000000 --- a/extras.d/README +++ /dev/null @@ -1,14 +0,0 @@ -The extras.d directory contains project initialization scripts to be -sourced by stack.sh at the end of its run. This is expected to be -used by external projects that want to be configured, started and -stopped with DevStack. - -Order is controlled by prefixing the script names with the a two digit -sequence number. Script names must end with '.sh'. This provides a -convenient way to disable scripts by simoy renaming them. - -DevStack reserves the sequence numbers 00 through 09 and 90 through 99 -for its own use. - -The scripts are called with an argument of 'stack' by stack.sh and -with an argument of 'unstack' by unstack.sh. diff --git a/extras.d/README.md b/extras.d/README.md new file mode 100644 index 0000000000..1dd17da2d6 --- /dev/null +++ b/extras.d/README.md @@ -0,0 +1,30 @@ +# Extras Hooks + +The `extras.d` directory contains project dispatch scripts that are called +at specific times by `stack.sh`, `unstack.sh` and `clean.sh`. These hooks are +used to install, configure and start additional projects during a DevStack run +without any modifications to the base DevStack scripts. + +When `stack.sh` reaches one of the hook points it sources the scripts in `extras.d` +that end with `.sh`. To control the order that the scripts are sourced their +names start with a two digit sequence number. DevStack reserves the sequence +numbers 00 through 09 and 90 through 99 for its own use. + +The scripts are sourced at the beginning of each script that calls them. The +entire `stack.sh` variable space is available. The scripts are +sourced with one or more arguments, the first of which defines the hook phase: + + source | stack | unstack | clean + + source: always called first in any of the scripts, used to set the + initial defaults in a lib/* script or similar + + stack: called by stack.sh. There are four possible values for + the second arg to distinguish the phase stack.sh is in: + + arg 2: install | post-config | extra | post-extra + + unstack: called by unstack.sh + + clean: called by clean.sh. Remember, clean.sh also calls unstack.sh + so that work need not be repeated. diff --git a/files/apts/cinder b/files/apts/cinder index f8e3b6d06d..712fee99ec 100644 --- a/files/apts/cinder +++ b/files/apts/cinder @@ -4,4 +4,4 @@ qemu-utils libpq-dev python-dev open-iscsi -open-iscsi-utils # Deprecated since quantal dist:lucid,oneiric,precise +open-iscsi-utils # Deprecated since quantal dist:precise diff --git a/files/apts/general b/files/apts/general index fcf0b5b06e..32d31f0642 100644 --- a/files/apts/general +++ b/files/apts/general @@ -20,3 +20,5 @@ tcpdump euca2ools # only for testing client tar python-cmd2 # dist:precise +python2.7 +bc diff --git a/files/apts/glance b/files/apts/glance index 26826a53c7..22787bc5a2 100644 --- a/files/apts/glance +++ b/files/apts/glance @@ -9,7 +9,6 @@ python-dev python-eventlet python-routes python-greenlet -python-argparse # dist:oneiric python-sqlalchemy python-wsgiref python-pastedeploy diff --git a/files/apts/horizon b/files/apts/horizon index 0865931d44..8969046355 100644 --- a/files/apts/horizon +++ b/files/apts/horizon @@ -19,5 +19,3 @@ python-kombu python-coverage python-cherrypy3 # why? python-migrate -nodejs -nodejs-legacy # dist:quantal diff --git a/files/apts/ldap b/files/apts/ldap index 81a00f27bf..26f7aeffe3 100644 --- a/files/apts/ldap +++ b/files/apts/ldap @@ -1,3 +1,3 @@ ldap-utils -slapd # NOPRIME +slapd python-ldap diff --git a/files/apts/marconi-server b/files/apts/marconi-server new file mode 100644 index 0000000000..bc7ef22445 --- /dev/null +++ b/files/apts/marconi-server @@ -0,0 +1,3 @@ +python-pymongo +mongodb-server +pkg-config diff --git a/files/apts/n-cpu b/files/apts/n-cpu index 88e0144079..29e37603b7 100644 --- a/files/apts/n-cpu +++ b/files/apts/n-cpu @@ -2,7 +2,7 @@ nbd-client lvm2 open-iscsi -open-iscsi-utils # Deprecated since quantal dist:lucid,oneiric,precise +open-iscsi-utils # Deprecated since quantal dist:precise genisoimage sysfsutils sg3-utils diff --git a/files/apts/neutron b/files/apts/neutron index 0f4b69f8ef..648716a75e 100644 --- a/files/apts/neutron +++ b/files/apts/neutron @@ -18,8 +18,8 @@ python-mysqldb python-pyudev python-qpid # dist:precise dnsmasq-base -dnsmasq-utils # for dhcp_release only available in dist:oneiric,precise,quantal +dnsmasq-utils # for dhcp_release only available in dist:precise rabbitmq-server # NOPRIME -qpid # NOPRIME +qpidd # NOPRIME sqlite3 vlan diff --git a/files/apts/tempest b/files/apts/tempest new file mode 100644 index 0000000000..f244e4e783 --- /dev/null +++ b/files/apts/tempest @@ -0,0 +1 @@ +libxslt1-dev \ No newline at end of file diff --git a/files/apts/tls-proxy b/files/apts/tls-proxy index 0a44015925..8fca42d124 100644 --- a/files/apts/tls-proxy +++ b/files/apts/tls-proxy @@ -1 +1 @@ -stud # only available in dist:precise,quantal +stud # only available in dist:precise diff --git a/files/apts/trema b/files/apts/trema index e33ccd3004..09cb7c6794 100644 --- a/files/apts/trema +++ b/files/apts/trema @@ -6,6 +6,7 @@ rubygems1.8 ruby1.8-dev libpcap-dev libsqlite3-dev +libglib2.0-dev # Sliceable Switch sqlite3 diff --git a/files/default_catalog.templates b/files/default_catalog.templates index 277904a8e3..e64f68f033 100644 --- a/files/default_catalog.templates +++ b/files/default_catalog.templates @@ -47,7 +47,17 @@ catalog.RegionOne.image.adminURL = http://%SERVICE_HOST%:9292 catalog.RegionOne.image.internalURL = http://%SERVICE_HOST%:9292 catalog.RegionOne.image.name = Image Service -catalog.RegionOne.orchestration.publicURL = http://%SERVICE_HOST%:8000/v1 -catalog.RegionOne.orchestration.adminURL = http://%SERVICE_HOST%:8000/v1 -catalog.RegionOne.orchestration.internalURL = http://%SERVICE_HOST%:8000/v1 +catalog.RegionOne.cloudformation.publicURL = http://%SERVICE_HOST%:8000/v1 +catalog.RegionOne.cloudformation.adminURL = http://%SERVICE_HOST%:8000/v1 +catalog.RegionOne.cloudformation.internalURL = http://%SERVICE_HOST%:8000/v1 +catalog.RegionOne.cloudformation.name = Heat CloudFormation Service + +catalog.RegionOne.orchestration.publicURL = http://%SERVICE_HOST%:8004/v1/$(tenant_id)s +catalog.RegionOne.orchestration.adminURL = http://%SERVICE_HOST%:8004/v1/$(tenant_id)s +catalog.RegionOne.orchestration.internalURL = http://%SERVICE_HOST%:8004/v1/$(tenant_id)s catalog.RegionOne.orchestration.name = Heat Service + +catalog.RegionOne.metering.publicURL = http://%SERVICE_HOST%:8777/v1 +catalog.RegionOne.metering.adminURL = http://%SERVICE_HOST%:8777/v1 +catalog.RegionOne.metering.internalURL = http://%SERVICE_HOST%:8777/v1 +catalog.RegionOne.metering.name = Telemetry Service diff --git a/files/keystone_data.sh b/files/keystone_data.sh index 3f3137cb14..d477c42906 100755 --- a/files/keystone_data.sh +++ b/files/keystone_data.sh @@ -6,7 +6,6 @@ # ------------------------------------------------------------------ # service glance admin # service heat service # if enabled -# service ceilometer admin # if enabled # Tempest Only: # alt_demo alt_demo Member # @@ -28,16 +27,6 @@ export SERVICE_TOKEN=$SERVICE_TOKEN export SERVICE_ENDPOINT=$SERVICE_ENDPOINT SERVICE_TENANT_NAME=${SERVICE_TENANT_NAME:-service} -function get_id () { - echo `"$@" | awk '/ id / { print $4 }'` -} - -# Lookups -SERVICE_TENANT=$(keystone tenant-list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }") -ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") -MEMBER_ROLE=$(keystone role-list | awk "/ Member / { print \$2 }") - - # Roles # ----- @@ -45,53 +34,52 @@ MEMBER_ROLE=$(keystone role-list | awk "/ Member / { print \$2 }") # The admin role in swift allows a user to act as an admin for their tenant, # but ResellerAdmin is needed for a user to act as any tenant. The name of this # role is also configurable in swift-proxy.conf -RESELLER_ROLE=$(get_id keystone role-create --name=ResellerAdmin) +keystone role-create --name=ResellerAdmin # Service role, so service users do not have to be admins -SERVICE_ROLE=$(get_id keystone role-create --name=service) +keystone role-create --name=service # Services # -------- if [[ "$ENABLED_SERVICES" =~ "n-api" ]] && [[ "$ENABLED_SERVICES" =~ "s-proxy" || "$ENABLED_SERVICES" =~ "swift" ]]; then - NOVA_USER=$(keystone user-list | awk "/ nova / { print \$2 }") # Nova needs ResellerAdmin role to download images when accessing # swift through the s3 api. keystone user-role-add \ - --tenant-id $SERVICE_TENANT \ - --user-id $NOVA_USER \ - --role-id $RESELLER_ROLE + --tenant $SERVICE_TENANT_NAME \ + --user nova \ + --role ResellerAdmin fi # Heat if [[ "$ENABLED_SERVICES" =~ "heat" ]]; then - HEAT_USER=$(get_id keystone user-create --name=heat \ - --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ - --email=heat@example.com) - keystone user-role-add --tenant-id $SERVICE_TENANT \ - --user-id $HEAT_USER \ - --role-id $SERVICE_ROLE + keystone user-create --name=heat \ + --pass="$SERVICE_PASSWORD" \ + --tenant $SERVICE_TENANT_NAME \ + --email=heat@example.com + keystone user-role-add --tenant $SERVICE_TENANT_NAME \ + --user heat \ + --role service # heat_stack_user role is for users created by Heat keystone role-create --name heat_stack_user if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then - HEAT_CFN_SERVICE=$(get_id keystone service-create \ + keystone service-create \ --name=heat-cfn \ --type=cloudformation \ - --description="Heat CloudFormation Service") + --description="Heat CloudFormation Service" keystone endpoint-create \ --region RegionOne \ - --service_id $HEAT_CFN_SERVICE \ + --service heat-cfn \ --publicurl "http://$SERVICE_HOST:$HEAT_API_CFN_PORT/v1" \ --adminurl "http://$SERVICE_HOST:$HEAT_API_CFN_PORT/v1" \ --internalurl "http://$SERVICE_HOST:$HEAT_API_CFN_PORT/v1" - HEAT_SERVICE=$(get_id keystone service-create \ + keystone service-create \ --name=heat \ --type=orchestration \ - --description="Heat Service") + --description="Heat Service" keystone endpoint-create \ --region RegionOne \ - --service_id $HEAT_SERVICE \ + --service heat \ --publicurl "http://$SERVICE_HOST:$HEAT_API_PORT/v1/\$(tenant_id)s" \ --adminurl "http://$SERVICE_HOST:$HEAT_API_PORT/v1/\$(tenant_id)s" \ --internalurl "http://$SERVICE_HOST:$HEAT_API_PORT/v1/\$(tenant_id)s" @@ -100,23 +88,23 @@ fi # Glance if [[ "$ENABLED_SERVICES" =~ "g-api" ]]; then - GLANCE_USER=$(get_id keystone user-create \ + keystone user-create \ --name=glance \ --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ - --email=glance@example.com) + --tenant $SERVICE_TENANT_NAME \ + --email=glance@example.com keystone user-role-add \ - --tenant-id $SERVICE_TENANT \ - --user-id $GLANCE_USER \ - --role-id $ADMIN_ROLE + --tenant $SERVICE_TENANT_NAME \ + --user glance \ + --role admin if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then - GLANCE_SERVICE=$(get_id keystone service-create \ + keystone service-create \ --name=glance \ --type=image \ - --description="Glance Image Service") + --description="Glance Image Service" keystone endpoint-create \ --region RegionOne \ - --service_id $GLANCE_SERVICE \ + --service glance \ --publicurl "http://$SERVICE_HOST:9292" \ --adminurl "http://$SERVICE_HOST:9292" \ --internalurl "http://$SERVICE_HOST:9292" @@ -124,42 +112,23 @@ if [[ "$ENABLED_SERVICES" =~ "g-api" ]]; then fi # Ceilometer -if [[ "$ENABLED_SERVICES" =~ "ceilometer" ]]; then - CEILOMETER_USER=$(get_id keystone user-create --name=ceilometer \ - --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ - --email=ceilometer@example.com) - keystone user-role-add --tenant-id $SERVICE_TENANT \ - --user-id $CEILOMETER_USER \ - --role-id $ADMIN_ROLE +if [[ "$ENABLED_SERVICES" =~ "ceilometer" ]] && [[ "$ENABLED_SERVICES" =~ "s-proxy" || "$ENABLED_SERVICES" =~ "swift" ]]; then # Ceilometer needs ResellerAdmin role to access swift account stats. - keystone user-role-add --tenant-id $SERVICE_TENANT \ - --user-id $CEILOMETER_USER \ - --role-id $RESELLER_ROLE - if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then - CEILOMETER_SERVICE=$(get_id keystone service-create \ - --name=ceilometer \ - --type=metering \ - --description="Ceilometer Service") - keystone endpoint-create \ - --region RegionOne \ - --service_id $CEILOMETER_SERVICE \ - --publicurl "http://$SERVICE_HOST:8777" \ - --adminurl "http://$SERVICE_HOST:8777" \ - --internalurl "http://$SERVICE_HOST:8777" - fi + keystone user-role-add --tenant $SERVICE_TENANT_NAME \ + --user ceilometer \ + --role ResellerAdmin fi # EC2 if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then - EC2_SERVICE=$(get_id keystone service-create \ + keystone service-create \ --name=ec2 \ --type=ec2 \ - --description="EC2 Compatibility Layer") + --description="EC2 Compatibility Layer" keystone endpoint-create \ --region RegionOne \ - --service_id $EC2_SERVICE \ + --service ec2 \ --publicurl "http://$SERVICE_HOST:8773/services/Cloud" \ --adminurl "http://$SERVICE_HOST:8773/services/Admin" \ --internalurl "http://$SERVICE_HOST:8773/services/Cloud" @@ -169,13 +138,13 @@ fi # S3 if [[ "$ENABLED_SERVICES" =~ "n-obj" || "$ENABLED_SERVICES" =~ "swift3" ]]; then if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then - S3_SERVICE=$(get_id keystone service-create \ + keystone service-create \ --name=s3 \ --type=s3 \ - --description="S3") + --description="S3" keystone endpoint-create \ --region RegionOne \ - --service_id $S3_SERVICE \ + --service s3 \ --publicurl "http://$SERVICE_HOST:$S3_SERVICE_PORT" \ --adminurl "http://$SERVICE_HOST:$S3_SERVICE_PORT" \ --internalurl "http://$SERVICE_HOST:$S3_SERVICE_PORT" @@ -185,14 +154,14 @@ fi if [[ "$ENABLED_SERVICES" =~ "tempest" ]]; then # Tempest has some tests that validate various authorization checks # between two regular users in separate tenants - ALT_DEMO_TENANT=$(get_id keystone tenant-create \ - --name=alt_demo) - ALT_DEMO_USER=$(get_id keystone user-create \ + keystone tenant-create \ + --name=alt_demo + keystone user-create \ --name=alt_demo \ --pass="$ADMIN_PASSWORD" \ - --email=alt_demo@example.com) + --email=alt_demo@example.com keystone user-role-add \ - --tenant-id $ALT_DEMO_TENANT \ - --user-id $ALT_DEMO_USER \ - --role-id $MEMBER_ROLE + --tenant alt_demo \ + --user alt_demo \ + --role Member fi diff --git a/files/ldap/openstack.ldif b/files/ldap/keystone.ldif.in similarity index 54% rename from files/ldap/openstack.ldif rename to files/ldap/keystone.ldif.in index 02caf3f368..cf51907cf6 100644 --- a/files/ldap/openstack.ldif +++ b/files/ldap/keystone.ldif.in @@ -1,26 +1,26 @@ -dn: dc=openstack,dc=org -dc: openstack +dn: ${BASE_DN} objectClass: dcObject objectClass: organizationalUnit -ou: openstack +dc: ${BASE_DC} +ou: ${BASE_DC} -dn: ou=UserGroups,dc=openstack,dc=org +dn: ou=UserGroups,${BASE_DN} objectClass: organizationalUnit ou: UserGroups -dn: ou=Users,dc=openstack,dc=org +dn: ou=Users,${BASE_DN} objectClass: organizationalUnit ou: Users -dn: ou=Roles,dc=openstack,dc=org +dn: ou=Roles,${BASE_DN} objectClass: organizationalUnit ou: Roles -dn: ou=Projects,dc=openstack,dc=org +dn: ou=Projects,${BASE_DN} objectClass: organizationalUnit ou: Projects -dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,dc=openstack,dc=org +dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,${BASE_DN} objectClass: organizationalRole ou: _member_ cn: 9fe2ff9ee4384b1894a90878d3e92bab diff --git a/files/ldap/manager.ldif.in b/files/ldap/manager.ldif.in index e522150f2e..de3b69de7c 100644 --- a/files/ldap/manager.ldif.in +++ b/files/ldap/manager.ldif.in @@ -1,10 +1,15 @@ dn: olcDatabase={${LDAP_OLCDB_NUMBER}}hdb,cn=config changetype: modify replace: olcSuffix -olcSuffix: dc=openstack,dc=org +olcSuffix: ${BASE_DN} - replace: olcRootDN -olcRootDN: dc=Manager,dc=openstack,dc=org +olcRootDN: ${MANAGER_DN} - ${LDAP_ROOTPW_COMMAND}: olcRootPW olcRootPW: ${SLAPPASS} +- +replace: olcDbIndex +olcDbIndex: objectClass eq +olcDbIndex: default pres,eq +olcDbIndex: cn,sn,givenName,co diff --git a/files/ldap/base-config.ldif b/files/ldap/suse-base-config.ldif.in similarity index 77% rename from files/ldap/base-config.ldif rename to files/ldap/suse-base-config.ldif.in index 026d8bc0fc..00256ee9d8 100644 --- a/files/ldap/base-config.ldif +++ b/files/ldap/suse-base-config.ldif.in @@ -12,8 +12,10 @@ objectClass: olcSchemaConfig cn: schema include: file:///etc/openldap/schema/core.ldif +include: file:///etc/openldap/schema/cosine.ldif +include: file:///etc/openldap/schema/inetorgperson.ldif dn: olcDatabase={1}hdb,cn=config objectClass: olcHdbConfig olcDbDirectory: /var/lib/ldap -olcSuffix: dc=openstack,dc=org +olcSuffix: ${BASE_DN} diff --git a/files/rpms-suse/general b/files/rpms-suse/general index 355af885d3..704947ea53 100644 --- a/files/rpms-suse/general +++ b/files/rpms-suse/general @@ -1,4 +1,5 @@ bridge-utils +ca-certificates-mozilla curl euca2ools git-core @@ -10,13 +11,13 @@ python-setuptools # instead of python-distribute; dist:sle11sp2 python-cmd2 # dist:opensuse-12.3 python-pylint python-unittest2 -python-virtualenv screen tar tcpdump unzip vim-enhanced wget +bc findutils-locate # useful when debugging lsof # useful when debugging diff --git a/files/rpms-suse/horizon b/files/rpms-suse/horizon index 73932acc1d..d3bde2690c 100644 --- a/files/rpms-suse/horizon +++ b/files/rpms-suse/horizon @@ -1,6 +1,5 @@ apache2 # NOPRIME apache2-mod_wsgi # NOPRIME -nodejs python-CherryPy # why? (coming from apts) python-Paste python-PasteDeploy diff --git a/files/rpms/ceilometer-collector b/files/rpms/ceilometer-collector index d7b7ea89c1..c91bac36a2 100644 --- a/files/rpms/ceilometer-collector +++ b/files/rpms/ceilometer-collector @@ -1,3 +1,4 @@ selinux-policy-targeted mongodb-server pymongo +mongodb # NOPRIME diff --git a/files/rpms/cinder b/files/rpms/cinder index c4edb68f14..623c13e676 100644 --- a/files/rpms/cinder +++ b/files/rpms/cinder @@ -4,3 +4,4 @@ qemu-img python-devel postgresql-devel iscsi-initiator-utils +python-lxml #dist:f18,f19,f20 diff --git a/files/rpms/general b/files/rpms/general index 2db31d1db0..6cfe31eaf1 100644 --- a/files/rpms/general +++ b/files/rpms/general @@ -20,6 +20,8 @@ tar tcpdump unzip wget +which +bc # [1] : some of installed tools have unversioned dependencies on this, # but others have versioned (<=0.7). So if a later version (0.7.1) diff --git a/files/rpms/glance b/files/rpms/glance index dd66171f7a..fffd9c85b4 100644 --- a/files/rpms/glance +++ b/files/rpms/glance @@ -1,6 +1,6 @@ gcc libffi-devel # testonly -libxml2-devel +libxml2-devel # testonly libxslt-devel # testonly mysql-devel # testonly openssl-devel # testonly @@ -9,7 +9,8 @@ python-argparse python-devel python-eventlet python-greenlet -python-paste-deploy #dist:f16,f17,f18,f19 +python-lxml #dist:f18,f19,f20 +python-paste-deploy #dist:f18,f19,f20 python-routes python-sqlalchemy python-wsgiref diff --git a/files/rpms/horizon b/files/rpms/horizon index 0ca18cadb7..59503cc9aa 100644 --- a/files/rpms/horizon +++ b/files/rpms/horizon @@ -3,7 +3,6 @@ django-registration gcc httpd # NOPRIME mod_wsgi # NOPRIME -nodejs # NOPRIME pylint python-anyjson python-BeautifulSoup @@ -17,8 +16,8 @@ python-kombu python-migrate python-mox python-nose -python-paste #dist:f16,f17,f18,f19 -python-paste-deploy #dist:f16,f17,f18,f19 +python-paste #dist:f18,f19,f20 +python-paste-deploy #dist:f18,f19,f20 python-routes python-sphinx python-sqlalchemy diff --git a/files/rpms/keystone b/files/rpms/keystone index 52dbf477d8..99e8524628 100644 --- a/files/rpms/keystone +++ b/files/rpms/keystone @@ -1,11 +1,11 @@ python-greenlet -python-lxml #dist:f16,f17,f18,f19 -python-paste #dist:f16,f17,f18,f19 -python-paste-deploy #dist:f16,f17,f18,f19 -python-paste-script #dist:f16,f17,f18,f19 +libxslt-devel # dist:f20 +python-lxml #dist:f18,f19,f20 +python-paste #dist:f18,f19,f20 +python-paste-deploy #dist:f18,f19,f20 +python-paste-script #dist:f18,f19,f20 python-routes python-sqlalchemy -python-sqlite2 python-webob sqlite diff --git a/files/rpms/marconi-server b/files/rpms/marconi-server new file mode 100644 index 0000000000..d7b7ea89c1 --- /dev/null +++ b/files/rpms/marconi-server @@ -0,0 +1,3 @@ +selinux-policy-targeted +mongodb-server +pymongo diff --git a/files/rpms/neutron b/files/rpms/neutron index a7700f77d4..67bf52350a 100644 --- a/files/rpms/neutron +++ b/files/rpms/neutron @@ -11,8 +11,8 @@ python-greenlet python-iso8601 python-kombu #rhel6 gets via pip -python-paste # dist:f16,f17,f18,f19 -python-paste-deploy # dist:f16,f17,f18,f19 +python-paste # dist:f18,f19,f20 +python-paste-deploy # dist:f18,f19,f20 python-qpid python-routes python-sqlalchemy diff --git a/files/rpms/nova b/files/rpms/nova index c99f3defc8..ac70ac5d6f 100644 --- a/files/rpms/nova +++ b/files/rpms/nova @@ -28,11 +28,11 @@ python-kombu python-lockfile python-migrate python-mox -python-paramiko # dist:f16,f17,f18,f19 +python-paramiko # dist:f18,f19,f20 # ^ on RHEL, brings in python-crypto which conflicts with version from # pip we need -python-paste # dist:f16,f17,f18,f19 -python-paste-deploy # dist:f16,f17,f18,f19 +python-paste # dist:f18,f19,f20 +python-paste-deploy # dist:f18,f19,f20 python-qpid python-routes python-sqlalchemy diff --git a/files/rpms/swift b/files/rpms/swift index b137f30dce..32432bca9b 100644 --- a/files/rpms/swift +++ b/files/rpms/swift @@ -9,7 +9,7 @@ python-eventlet python-greenlet python-netifaces python-nose -python-paste-deploy # dist:f16,f17,f18,f19 +python-paste-deploy # dist:f18,f19,f20 python-simplejson python-webob pyxattr diff --git a/files/rpms/tempest b/files/rpms/tempest new file mode 100644 index 0000000000..e7bbd43cd6 --- /dev/null +++ b/files/rpms/tempest @@ -0,0 +1 @@ +libxslt-devel diff --git a/files/rpms/trove b/files/rpms/trove index 09dcee8104..c5cbdea012 100644 --- a/files/rpms/trove +++ b/files/rpms/trove @@ -1 +1 @@ -libxslt1-dev # testonly +libxslt-devel # testonly diff --git a/functions b/functions index baeeed49b6..825a68c974 100644 --- a/functions +++ b/functions @@ -1,16 +1,17 @@ # functions - Common functions used by DevStack components # # The following variables are assumed to be defined by certain functions: -# ``ENABLED_SERVICES`` -# ``EROR_ON_CLONE`` -# ``FILES`` -# ``GLANCE_HOSTPORT`` -# ``OFFLINE`` -# ``PIP_DOWNLOAD_CACHE`` -# ``PIP_USE_MIRRORS`` -# ``RECLONE`` -# ``TRACK_DEPENDS`` -# ``http_proxy``, ``https_proxy``, ``no_proxy`` +# +# - ``ENABLED_SERVICES`` +# - ``ERROR_ON_CLONE`` +# - ``FILES`` +# - ``GLANCE_HOSTPORT`` +# - ``OFFLINE`` +# - ``PIP_DOWNLOAD_CACHE`` +# - ``PIP_USE_MIRRORS`` +# - ``RECLONE`` +# - ``TRACK_DEPENDS`` +# - ``http_proxy``, ``https_proxy``, ``no_proxy`` # Save trace setting @@ -54,7 +55,7 @@ function address_in_net() { # Wrapper for ``apt-get`` to set cache and proxy environment variables -# Uses globals ``OFFLINE``, ``*_proxy` +# Uses globals ``OFFLINE``, ``*_proxy`` # apt_get operation package [package ...] function apt_get() { [[ "$OFFLINE" = "True" || -z "$@" ]] && return @@ -155,6 +156,22 @@ function err_if_not_set() { } +# Prints line number and "message" in warning format +# warn $LINENO "message" +function warn() { + local exitcode=$? + errXTRACE=$(set +o | grep xtrace) + set +o xtrace + local msg="[WARNING] ${BASH_SOURCE[2]}:$1 $2" + echo $msg 1>&2; + if [[ -n ${SCREEN_LOGDIR} ]]; then + echo $msg >> "${SCREEN_LOGDIR}/error.log" + fi + $errXTRACE + return $exitcode +} + + # HTTP and HTTPS proxy servers are supported via the usual environment variables [1] # ``http_proxy``, ``https_proxy`` and ``no_proxy``. They can be set in # ``localrc`` or on the command line if necessary:: @@ -244,11 +261,12 @@ function _get_package_dir() { # # Only packages required for the services in 1st argument will be # included. Two bits of metadata are recognized in the prerequisite files: -# - ``# NOPRIME`` defers installation to be performed later in stack.sh +# +# - ``# NOPRIME`` defers installation to be performed later in `stack.sh` # - ``# dist:DISTRO`` or ``dist:DISTRO1,DISTRO2`` limits the selection # of the package to the distros listed. The distro names are case insensitive. function get_packages() { - local services=$1 + local services=$@ local package_dir=$(_get_package_dir) local file_to_parse local service @@ -260,7 +278,7 @@ function get_packages() { if [[ -z "$DISTRO" ]]; then GetDistro fi - for service in general ${services//,/ }; do + for service in ${services//,/ }; do # Allow individual services to specify dependencies if [[ -e ${package_dir}/${service} ]]; then file_to_parse="${file_to_parse} $service" @@ -364,7 +382,7 @@ function get_packages() { # GetOSVersion GetOSVersion() { # Figure out which vendor we are - if [[ -n "`which sw_vers 2>/dev/null`" ]]; then + if [[ -x "`which sw_vers 2>/dev/null`" ]]; then # OS/X os_VENDOR=`sw_vers -productName` os_RELEASE=`sw_vers -productVersion` @@ -404,6 +422,7 @@ GetOSVersion() { os_CODENAME=$(lsb_release -c -s) elif [[ -r /etc/redhat-release ]]; then # Red Hat Enterprise Linux Server release 5.5 (Tikanga) + # Red Hat Enterprise Linux Server release 7.0 Beta (Maipo) # CentOS release 5.5 (Final) # CentOS Linux release 6.0 (Final) # Fedora release 16 (Verne) @@ -412,7 +431,7 @@ GetOSVersion() { for r in "Red Hat" CentOS Fedora XenServer; do os_VENDOR=$r if [[ -n "`grep \"$r\" /etc/redhat-release`" ]]; then - ver=`sed -e 's/^.* \(.*\) (\(.*\)).*$/\1\|\2/' /etc/redhat-release` + ver=`sed -e 's/^.* \([0-9].*\) (\(.*\)).*$/\1\|\2/' /etc/redhat-release` os_CODENAME=${ver#*|} os_RELEASE=${ver%|*} os_UPDATE=${os_RELEASE##*.} @@ -536,7 +555,19 @@ function exit_distro_not_supported { function is_arch { ARCH_TYPE=$1 - [ "($uname -m)" = "$ARCH_TYPE" ] + [[ "$(uname -m)" == "$ARCH_TYPE" ]] +} + +# Checks if installed Apache is <= given version +# $1 = x.y.z (version string of Apache) +function check_apache_version { + local cmd="apachectl" + if ! [[ -x $(which apachectl 2>/dev/null) ]]; then + cmd="/usr/sbin/apachectl" + fi + + local version=$($cmd -v | grep version | grep -Po 'Apache/\K[^ ]*') + expr "$version" '>=' $1 > /dev/null } # git clone only if directory doesn't exist already. Since ``DEST`` might not @@ -564,7 +595,8 @@ function git_clone { if echo $GIT_REF | egrep -q "^refs"; then # If our branch name is a gerrit style refs/changes/... if [[ ! -d $GIT_DEST ]]; then - [[ "$ERROR_ON_CLONE" = "True" ]] && exit 1 + [[ "$ERROR_ON_CLONE" = "True" ]] && \ + die $LINENO "Cloning not allowed in this configuration" git clone $GIT_REMOTE $GIT_DEST fi cd $GIT_DEST @@ -572,7 +604,8 @@ function git_clone { else # do a full clone only if the directory doesn't exist if [[ ! -d $GIT_DEST ]]; then - [[ "$ERROR_ON_CLONE" = "True" ]] && exit 1 + [[ "$ERROR_ON_CLONE" = "True" ]] && \ + die $LINENO "Cloning not allowed in this configuration" git clone $GIT_REMOTE $GIT_DEST cd $GIT_DEST # This checkout syntax works for both branches and tags @@ -596,8 +629,7 @@ function git_clone { elif [[ -n "`git show-ref refs/remotes/origin/$GIT_REF`" ]]; then git_update_remote_branch $GIT_REF else - echo $GIT_REF is neither branch nor tag - exit 1 + die $LINENO "$GIT_REF is neither branch nor tag" fi fi @@ -697,7 +729,10 @@ function iniset() { local section=$2 local option=$3 local value=$4 - if ! grep -q "^\[$section\]" "$file"; then + + [[ -z $section || -z $option ]] && return + + if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then # Add section at the end echo -e "\n[$section]" >>"$file" fi @@ -707,8 +742,9 @@ function iniset() { $option = $value " "$file" else + local sep=$(echo -ne "\x01") # Replace it - sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file" + sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file" fi } @@ -809,6 +845,7 @@ function is_service_enabled() { [[ ${service} == "cinder" && ${ENABLED_SERVICES} =~ "c-" ]] && return 0 [[ ${service} == "ceilometer" && ${ENABLED_SERVICES} =~ "ceilometer-" ]] && return 0 [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && return 0 + [[ ${service} == "ironic" && ${ENABLED_SERVICES} =~ "ir-" ]] && return 0 [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && return 0 [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && return 0 [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && return 0 @@ -926,7 +963,7 @@ function uninstall_package() { elif is_fedora; then sudo yum remove -y "$@" elif is_suse; then - sudo rpm -e "$@" + sudo zypper rm "$@" else exit_distro_not_supported "uninstalling packages" fi @@ -964,7 +1001,7 @@ function is_set() { # Wrapper for ``pip install`` to set cache and proxy environment variables # Uses globals ``OFFLINE``, ``PIP_DOWNLOAD_CACHE``, ``PIP_USE_MIRRORS``, -# ``TRACK_DEPENDS``, ``*_proxy` +# ``TRACK_DEPENDS``, ``*_proxy`` # pip_install package [package ...] function pip_install { [[ "$OFFLINE" = "True" || -z "$@" ]] && return @@ -993,8 +1030,7 @@ function pip_install { # /tmp/$USER-pip-build. Even if a later component specifies foo < # 1.1, the existing extracted build will be used and cause # confusing errors. By creating unique build directories we avoid - # this problem. See - # https://github.com/pypa/pip/issues/709 + # this problem. See https://github.com/pypa/pip/issues/709 local pip_build_tmp=$(mktemp --tmpdir -d pip-build.XXXXX) $SUDO_PIP PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \ @@ -1096,10 +1132,42 @@ function screen_it { sleep 1.5 NL=`echo -ne '\015'` - screen -S $SCREEN_NAME -p $1 -X stuff "$2 || echo \"$1 failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL" + # This fun command does the following: + # - the passed server command is backgrounded + # - the pid of the background process is saved in the usual place + # - the server process is brought back to the foreground + # - if the server process exits prematurely the fg command errors + # and a message is written to stdout and the service failure file + # The pid saved can be used in screen_stop() as a process group + # id to kill off all child processes + screen -S $SCREEN_NAME -p $1 -X stuff "$2 & echo \$! >$SERVICE_DIR/$SCREEN_NAME/$1.pid; fg || echo \"$1 failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/$1.failure\"$NL" else # Spawn directly without screen - run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$service.pid + run_process "$1" "$2" >$SERVICE_DIR/$SCREEN_NAME/$1.pid + fi + fi +} + + +# Stop a service in screen +# If a PID is available use it, kill the whole process group via TERM +# If screen is being used kill the screen window; this will catch processes +# that did not leave a PID behind +# screen_stop service +function screen_stop() { + SCREEN_NAME=${SCREEN_NAME:-stack} + SERVICE_DIR=${SERVICE_DIR:-${DEST}/status} + USE_SCREEN=$(trueorfalse True $USE_SCREEN) + + if is_service_enabled $1; then + # Kill via pid if we have one available + if [[ -r $SERVICE_DIR/$SCREEN_NAME/$1.pid ]]; then + pkill -TERM -P -$(cat $SERVICE_DIR/$SCREEN_NAME/$1.pid) + rm $SERVICE_DIR/$SCREEN_NAME/$1.pid + fi + if [[ "$USE_SCREEN" = "True" ]]; then + # Clean up the screen window + screen -S $SCREEN_NAME -p $1 -X kill fi fi } @@ -1124,12 +1192,17 @@ function screen_rc { NL=`echo -ne '\015'` echo "screen -t $1 bash" >> $SCREENRC echo "stuff \"$2$NL\"" >> $SCREENRC + + if [[ -n ${SCREEN_LOGDIR} ]]; then + echo "logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log" >>$SCREENRC + echo "log on" >>$SCREENRC + fi fi } -# Helper to remove the *.failure files under $SERVICE_DIR/$SCREEN_NAME -# This is used for service_check when all the screen_it are called finished +# Helper to remove the ``*.failure`` files under ``$SERVICE_DIR/$SCREEN_NAME``. +# This is used for ``service_check`` when all the ``screen_it`` are called finished # init_service_check function init_service_check() { SCREEN_NAME=${SCREEN_NAME:-stack} @@ -1219,7 +1292,11 @@ function safe_chmod() { # ``pip install -e`` the package, which processes the dependencies # using pip before running `setup.py develop` -# Uses globals ``STACK_USER``, ``TRACK_DEPENDS``, ``REQUIREMENTS_DIR`` +# +# Updates the dependencies in project_dir from the +# openstack/requirements global list before installing anything. +# +# Uses globals ``TRACK_DEPENDS``, ``REQUIREMENTS_DIR`` # setup_develop directory function setup_develop() { local project_dir=$1 @@ -1227,7 +1304,8 @@ function setup_develop() { echo "cd $REQUIREMENTS_DIR; $SUDO_CMD python update.py $project_dir" # Don't update repo if local changes exist - (cd $project_dir && git diff --quiet) + # Don't use buggy "git diff --quiet" + (cd $project_dir && git diff --exit-code >/dev/null) local update_requirements=$? if [ $update_requirements -eq 0 ]; then @@ -1235,14 +1313,33 @@ function setup_develop() { $SUDO_CMD python update.py $project_dir) fi + setup_develop_no_requirements_update $project_dir + + # We've just gone and possibly modified the user's source tree in an + # automated way, which is considered bad form if it's a development + # tree because we've screwed up their next git checkin. So undo it. + # + # However... there are some circumstances, like running in the gate + # where we really really want the overridden version to stick. So provide + # a variable that tells us whether or not we should UNDO the requirements + # changes (this will be set to False in the OpenStack ci gate) + if [ $UNDO_REQUIREMENTS = "True" ]; then + if [ $update_requirements -eq 0 ]; then + (cd $project_dir && git reset --hard) + fi + fi +} + +# ``pip install -e`` the package, which processes the dependencies +# using pip before running `setup.py develop` +# Uses globals ``STACK_USER`` +# setup_develop_no_requirements_update directory +function setup_develop_no_requirements_update() { + local project_dir=$1 + pip_install -e $project_dir # ensure that further actions can do things like setup.py sdist safe_chown -R $STACK_USER $1/*.egg-info - - # Undo requirements changes, if we made them - if [ $update_requirements -eq 0 ]; then - (cd $project_dir && git checkout -- requirements.txt test-requirements.txt setup.py) - fi } @@ -1283,10 +1380,12 @@ function trueorfalse() { } -# Retrieve an image from a URL and upload into Glance +# Retrieve an image from a URL and upload into Glance. # Uses the following variables: -# ``FILES`` must be set to the cache dir -# ``GLANCE_HOSTPORT`` +# +# - ``FILES`` must be set to the cache dir +# - ``GLANCE_HOSTPORT`` +# # upload_image image-url glance-token function upload_image() { local image_url=$1 @@ -1294,12 +1393,24 @@ function upload_image() { # Create a directory for the downloaded image tarballs. mkdir -p $FILES/images - - # Downloads the image (uec ami+aki style), then extracts it. IMAGE_FNAME=`basename "$image_url"` - if [[ ! -f $FILES/$IMAGE_FNAME || "$(stat -c "%s" $FILES/$IMAGE_FNAME)" = "0" ]]; then - wget -c $image_url -O $FILES/$IMAGE_FNAME - if [[ $? -ne 0 ]]; then + if [[ $image_url != file* ]]; then + # Downloads the image (uec ami+aki style), then extracts it. + if [[ ! -f $FILES/$IMAGE_FNAME || "$(stat -c "%s" $FILES/$IMAGE_FNAME)" = "0" ]]; then + wget -c $image_url -O $FILES/$IMAGE_FNAME + if [[ $? -ne 0 ]]; then + echo "Not found: $image_url" + return + fi + fi + IMAGE="$FILES/${IMAGE_FNAME}" + else + # File based URL (RFC 1738): file://host/path + # Remote files are not considered here. + # *nix: file:///home/user/path/file + # windows: file:///C:/Documents%20and%20Settings/user/path/file + IMAGE=$(echo $image_url | sed "s/^file:\/\///g") + if [[ ! -f $IMAGE || "$(stat -c "%s" $IMAGE)" == "0" ]]; then echo "Not found: $image_url" return fi @@ -1307,7 +1418,6 @@ function upload_image() { # OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading if [[ "$image_url" =~ 'openvz' ]]; then - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME="${IMAGE_FNAME%.tar.gz}" glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public=True --container-format ami --disk-format ami < "${IMAGE}" return @@ -1315,34 +1425,137 @@ function upload_image() { # vmdk format images if [[ "$image_url" =~ '.vmdk' ]]; then - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME="${IMAGE_FNAME%.vmdk}" # Before we can upload vmdk type images to glance, we need to know it's # disk type, storage adapter, and networking adapter. These values are - # passed to glance as custom properties. We take these values from the + # passed to glance as custom properties. + # We take these values from the vmdk file if populated. Otherwise, we use # vmdk filename, which is expected in the following format: # - # -:: + # -;; # # If the filename does not follow the above format then the vsphere # driver will supply default values. - property_string=`echo "$IMAGE_NAME" | grep -oP '(?<=-)(?!.*-).+:.+:.+$'` - if [[ ! -z "$property_string" ]]; then - IFS=':' read -a props <<< "$property_string" - vmdk_disktype="${props[0]}" - vmdk_adapter_type="${props[1]}" - vmdk_net_adapter="${props[2]}" + + vmdk_adapter_type="" + vmdk_disktype="" + vmdk_net_adapter="" + + # vmdk adapter type + vmdk_adapter_type="$(head -25 $IMAGE | grep -a -F -m 1 'ddb.adapterType =' $IMAGE)" + vmdk_adapter_type="${vmdk_adapter_type#*\"}" + vmdk_adapter_type="${vmdk_adapter_type%?}" + + # vmdk disk type + vmdk_create_type="$(head -25 $IMAGE | grep -a -F -m 1 'createType=' $IMAGE)" + vmdk_create_type="${vmdk_create_type#*\"}" + vmdk_create_type="${vmdk_create_type%?}" + + descriptor_data_pair_msg="Monolithic flat and VMFS disks "` + `"should use a descriptor-data pair." + if [[ "$vmdk_create_type" = "monolithicSparse" ]]; then + vmdk_disktype="sparse" + elif [[ "$vmdk_create_type" = "monolithicFlat" || \ + "$vmdk_create_type" = "vmfs" ]]; then + # Attempt to retrieve the *-flat.vmdk + flat_fname="$(head -25 $IMAGE | grep -G 'RW\|RDONLY [0-9]+ FLAT\|VMFS' $IMAGE)" + flat_fname="${flat_fname#*\"}" + flat_fname="${flat_fname%?}" + if [[ -z "$flat_name" ]]; then + flat_fname="$IMAGE_NAME-flat.vmdk" + fi + path_len=`expr ${#image_url} - ${#IMAGE_FNAME}` + flat_url="${image_url:0:$path_len}$flat_fname" + warn $LINENO "$descriptor_data_pair_msg"` + `" Attempt to retrieve the *-flat.vmdk: $flat_url" + if [[ $flat_url != file* ]]; then + if [[ ! -f $FILES/$flat_fname || \ + "$(stat -c "%s" $FILES/$flat_fname)" = "0" ]]; then + wget -c $flat_url -O $FILES/$flat_fname + if [[ $? -ne 0 ]]; then + echo "Flat disk not found: $flat_url" + flat_found=false + fi + fi + if $flat_found; then + IMAGE="$FILES/${flat_fname}" + fi + else + IMAGE=$(echo $flat_url | sed "s/^file:\/\///g") + if [[ ! -f $IMAGE || "$(stat -c "%s" $IMAGE)" == "0" ]]; then + echo "Flat disk not found: $flat_url" + flat_found=false + fi + if ! $flat_found; then + IMAGE=$(echo $image_url | sed "s/^file:\/\///g") + fi + fi + if $flat_found; then + IMAGE_NAME="${flat_fname}" + fi + vmdk_disktype="preallocated" + elif [[ -z "$vmdk_create_type" ]]; then + # *-flat.vmdk provided: attempt to retrieve the descriptor (*.vmdk) + # to retrieve appropriate metadata + if [[ ${IMAGE_NAME: -5} != "-flat" ]]; then + warn $LINENO "Expected filename suffix: '-flat'."` + `" Filename provided: ${IMAGE_NAME}" + else + descriptor_fname="${IMAGE_NAME:0:${#IMAGE_NAME} - 5}.vmdk" + path_len=`expr ${#image_url} - ${#IMAGE_FNAME}` + flat_path="${image_url:0:$path_len}" + descriptor_url=$flat_path$descriptor_fname + warn $LINENO "$descriptor_data_pair_msg"` + `" Attempt to retrieve the descriptor *.vmdk: $descriptor_url" + if [[ $flat_path != file* ]]; then + if [[ ! -f $FILES/$descriptor_fname || \ + "$(stat -c "%s" $FILES/$descriptor_fname)" = "0" ]]; then + wget -c $descriptor_url -O $FILES/$descriptor_fname + if [[ $? -ne 0 ]]; then + warn $LINENO "Descriptor not found $descriptor_url" + descriptor_found=false + fi + fi + descriptor_url="$FILES/$descriptor_fname" + else + descriptor_url=$(echo $descriptor_url | sed "s/^file:\/\///g") + if [[ ! -f $descriptor_url || \ + "$(stat -c "%s" $descriptor_url)" == "0" ]]; then + warn $LINENO "Descriptor not found $descriptor_url" + descriptor_found=false + fi + fi + if $descriptor_found; then + vmdk_adapter_type="$(head -25 $descriptor_url |"` + `"grep -a -F -m 1 'ddb.adapterType =' $descriptor_url)" + vmdk_adapter_type="${vmdk_adapter_type#*\"}" + vmdk_adapter_type="${vmdk_adapter_type%?}" + fi + fi + #TODO(alegendre): handle streamOptimized once supported by the VMware driver. + vmdk_disktype="preallocated" + else + #TODO(alegendre): handle streamOptimized once supported by the VMware driver. + vmdk_disktype="preallocated" fi - glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public=True --container-format bare --disk-format vmdk --property vmware-disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${IMAGE}" + # NOTE: For backwards compatibility reasons, colons may be used in place + # of semi-colons for property delimiters but they are not permitted + # characters in NTFS filesystems. + property_string=`echo "$IMAGE_NAME" | grep -oP '(?<=-)(?!.*-).*[:;].*[:;].*$'` + IFS=':;' read -a props <<< "$property_string" + vmdk_disktype="${props[0]:-$vmdk_disktype}" + vmdk_adapter_type="${props[1]:-$vmdk_adapter_type}" + vmdk_net_adapter="${props[2]:-$vmdk_net_adapter}" + + glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public=True --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${IMAGE}" return fi # XenServer-vhd-ovf-format images are provided as .vhd.tgz # and should not be decompressed prior to loading if [[ "$image_url" =~ '.vhd.tgz' ]]; then - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME="${IMAGE_FNAME%.vhd.tgz}" glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public=True --container-format=ovf --disk-format=vhd < "${IMAGE}" return @@ -1352,12 +1565,11 @@ function upload_image() { # and should not be decompressed prior to loading. # Setting metadata, so PV mode is used. if [[ "$image_url" =~ '.xen-raw.tgz' ]]; then - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME="${IMAGE_FNAME%.xen-raw.tgz}" glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ --name "$IMAGE_NAME" --is-public=True \ --container-format=tgz --disk-format=raw \ --property vm_mode=xen < "${IMAGE}" @@ -1380,17 +1592,16 @@ function upload_image() { mkdir "$xdir" tar -zxf $FILES/$IMAGE_FNAME -C "$xdir" KERNEL=$(for f in "$xdir/"*-vmlinuz* "$xdir/"aki-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) RAMDISK=$(for f in "$xdir/"*-initrd* "$xdir/"ari-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) IMAGE=$(for f in "$xdir/"*.img "$xdir/"ami-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) if [[ -z "$IMAGE_NAME" ]]; then IMAGE_NAME=$(basename "$IMAGE" ".img") fi ;; *.img) - IMAGE="$FILES/$IMAGE_FNAME"; IMAGE_NAME=$(basename "$IMAGE" ".img") format=$(qemu-img info ${IMAGE} | awk '/^file format/ { print $3; exit }') if [[ ",qcow2,raw,vdi,vmdk,vpc," =~ ",$format," ]]; then @@ -1401,20 +1612,17 @@ function upload_image() { CONTAINER_FORMAT=bare ;; *.img.gz) - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME=$(basename "$IMAGE" ".img.gz") DISK_FORMAT=raw CONTAINER_FORMAT=bare UNPACK=zcat ;; *.qcow2) - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME=$(basename "$IMAGE" ".qcow2") DISK_FORMAT=qcow2 CONTAINER_FORMAT=bare ;; *.iso) - IMAGE="$FILES/${IMAGE_FNAME}" IMAGE_NAME=$(basename "$IMAGE" ".iso") DISK_FORMAT=iso CONTAINER_FORMAT=bare @@ -1422,11 +1630,15 @@ function upload_image() { *) echo "Do not know what to do with $IMAGE_FNAME"; false;; esac + if is_arch "ppc64"; then + IMG_PROPERTY="--property hw_disk_bus=scsi --property hw_cdrom_bus=scsi" + fi + if [ "$CONTAINER_FORMAT" = "bare" ]; then if [ "$UNPACK" = "zcat" ]; then - glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public True --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < <(zcat --force "${IMAGE}") + glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" $IMG_PROPERTY --is-public True --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < <(zcat --force "${IMAGE}") else - glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" --is-public True --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < "${IMAGE}" + glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME" $IMG_PROPERTY --is-public True --container-format=$CONTAINER_FORMAT --disk-format $DISK_FORMAT < "${IMAGE}" fi else # Use glance client to add the kernel the root filesystem. @@ -1434,12 +1646,12 @@ function upload_image() { # kernel for use when uploading the root filesystem. KERNEL_ID=""; RAMDISK_ID=""; if [ -n "$KERNEL" ]; then - KERNEL_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-kernel" --is-public True --container-format aki --disk-format aki < "$KERNEL" | grep ' id ' | get_field 2) + KERNEL_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-kernel" $IMG_PROPERTY --is-public True --container-format aki --disk-format aki < "$KERNEL" | grep ' id ' | get_field 2) fi if [ -n "$RAMDISK" ]; then - RAMDISK_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-ramdisk" --is-public True --container-format ari --disk-format ari < "$RAMDISK" | grep ' id ' | get_field 2) + RAMDISK_ID=$(glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "$IMAGE_NAME-ramdisk" $IMG_PROPERTY --is-public True --container-format ari --disk-format ari < "$RAMDISK" | grep ' id ' | get_field 2) fi - glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "${IMAGE_NAME%.img}" --is-public True --container-format ami --disk-format ami ${KERNEL_ID:+--property kernel_id=$KERNEL_ID} ${RAMDISK_ID:+--property ramdisk_id=$RAMDISK_ID} < "${IMAGE}" + glance --os-auth-token $token --os-image-url http://$GLANCE_HOSTPORT image-create --name "${IMAGE_NAME%.img}" $IMG_PROPERTY --is-public True --container-format ami --disk-format ami ${KERNEL_ID:+--property kernel_id=$KERNEL_ID} ${RAMDISK_ID:+--property ramdisk_id=$RAMDISK_ID} < "${IMAGE}" fi } @@ -1448,7 +1660,8 @@ function upload_image() { # When called from stackrc/localrc DATABASE_BACKENDS has not been # initialized yet, just save the configuration selection and call back later # to validate it. -# $1 The name of the database backend to use (mysql, postgresql, ...) +# +# ``$1`` - the name of the database backend to use (mysql, postgresql, ...) function use_database { if [[ -z "$DATABASE_BACKENDS" ]]; then # No backends registered means this is likely called from ``localrc`` @@ -1484,12 +1697,12 @@ function use_exclusive_service { function wait_for_service() { local timeout=$1 local url=$2 - timeout $timeout sh -c "while ! http_proxy= https_proxy= curl -s $url >/dev/null; do sleep 1; done" + timeout $timeout sh -c "while ! curl --noproxy '*' -s $url >/dev/null; do sleep 1; done" } # Wrapper for ``yum`` to set proxy environment variables -# Uses globals ``OFFLINE``, ``*_proxy` +# Uses globals ``OFFLINE``, ``*_proxy`` # yum_install package [package ...] function yum_install() { [[ "$OFFLINE" = "True" ]] && return @@ -1546,7 +1759,6 @@ function _ping_check_novanet() { else die $LINENO "[Fail] Could ping server" fi - exit 1 fi } @@ -1559,7 +1771,6 @@ function get_instance_ip(){ if [[ $ip = "" ]];then echo "$nova_result" die $LINENO "[Fail] Coudn't get ipaddress of VM" - exit 1 fi echo $ip } @@ -1675,23 +1886,23 @@ function check_path_perm_sanity() { # # _vercmp_r sep ver1 ver2 function _vercmp_r { - typeset sep - typeset -a ver1=() ver2=() - sep=$1; shift - ver1=("${@:1:sep}") - ver2=("${@:sep+1}") + typeset sep + typeset -a ver1=() ver2=() + sep=$1; shift + ver1=("${@:1:sep}") + ver2=("${@:sep+1}") - if ((ver1 > ver2)); then - echo 1; return 0 - elif ((ver2 > ver1)); then - echo -1; return 0 - fi + if ((ver1 > ver2)); then + echo 1; return 0 + elif ((ver2 > ver1)); then + echo -1; return 0 + fi - if ((sep <= 1)); then - echo 0; return 0 - fi + if ((sep <= 1)); then + echo 0; return 0 + fi - _vercmp_r $((sep-1)) "${ver1[@]:1}" "${ver2[@]:1}" + _vercmp_r $((sep-1)) "${ver1[@]:1}" "${ver2[@]:1}" } @@ -1713,13 +1924,13 @@ function _vercmp_r { # # vercmp_numbers ver1 ver2 vercmp_numbers() { - typeset v1=$1 v2=$2 sep - typeset -a ver1 ver2 + typeset v1=$1 v2=$2 sep + typeset -a ver1 ver2 - IFS=. read -ra ver1 <<< "$v1" - IFS=. read -ra ver2 <<< "$v2" + IFS=. read -ra ver1 <<< "$v1" + IFS=. read -ra ver2 <<< "$v2" - _vercmp_r "${#ver1[@]}" "${ver1[@]}" "${ver2[@]}" + _vercmp_r "${#ver1[@]}" "${ver1[@]}" "${ver2[@]}" } diff --git a/lib/apache b/lib/apache index 3a1f6f1263..8ae78b2181 100644 --- a/lib/apache +++ b/lib/apache @@ -2,15 +2,20 @@ # Functions to control configuration and operation of apache web server # Dependencies: -# ``functions`` file -# is_apache_enabled_service -# install_apache_wsgi -# config_apache_wsgi -# enable_apache_site -# disable_apache_site -# start_apache_server -# stop_apache_server -# restart_apache_server +# +# - ``functions`` file +# -``STACK_USER`` must be defined + +# lib/apache exports the following functions: +# +# - is_apache_enabled_service +# - install_apache_wsgi +# - config_apache_wsgi +# - enable_apache_site +# - disable_apache_site +# - start_apache_server +# - stop_apache_server +# - restart_apache_server # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -18,7 +23,7 @@ set +o xtrace # Allow overriding the default Apache user and group, default to # current user and his default group. -APACHE_USER=${APACHE_USER:-$USER} +APACHE_USER=${APACHE_USER:-$STACK_USER} APACHE_GROUP=${APACHE_GROUP:-$(id -gn $APACHE_USER)} @@ -116,6 +121,7 @@ function restart_apache_server() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/baremetal b/lib/baremetal index 52af420853..a0df85e700 100644 --- a/lib/baremetal +++ b/lib/baremetal @@ -1,19 +1,19 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2012 Hewlett-Packard Development Company, L.P. -# 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. +## vim: tabstop=4 shiftwidth=4 softtabstop=4 + +## Copyright (c) 2012 Hewlett-Packard Development Company, L.P. +## 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. # This file provides devstack with the environment and utilities to @@ -24,7 +24,8 @@ # control physical hardware resources on the same network, if you know # the MAC address(es) and IPMI credentials. # -# At a minimum, to enable the baremetal driver, you must set these in loclarc: +# At a minimum, to enable the baremetal driver, you must set these in localrc: +# # VIRT_DRIVER=baremetal # ENABLED_SERVICES="$ENABLED_SERVICES,baremetal" # @@ -38,11 +39,13 @@ # Below that, various functions are defined, which are called by devstack # in the following order: # -# before nova-cpu starts: +# before nova-cpu starts: +# # - prepare_baremetal_toolchain # - configure_baremetal_nova_dirs # -# after nova and glance have started: +# after nova and glance have started: +# # - build_and_upload_baremetal_deploy_k_and_r $token # - create_baremetal_flavor $BM_DEPLOY_KERNEL_ID $BM_DEPLOY_RAMDISK_ID # - upload_baremetal_image $url $token @@ -58,11 +61,13 @@ set +o xtrace # ------------------- # sub-driver to use for kernel deployment -# - nova.virt.baremetal.pxe.PXE -# - nova.virt.baremetal.tilera.TILERA +# +# - nova.virt.baremetal.pxe.PXE +# - nova.virt.baremetal.tilera.TILERA BM_DRIVER=${BM_DRIVER:-nova.virt.baremetal.pxe.PXE} # sub-driver to use for remote power management +# # - nova.virt.baremetal.fake.FakePowerManager, for manual power control # - nova.virt.baremetal.ipmi.IPMI, for remote IPMI # - nova.virt.baremetal.tilera_pdu.Pdu, for TilePro hardware @@ -83,10 +88,12 @@ BM_POSEUR_EXTRA_OPTS=${BM_POSEUR_EXTRA_OPTS:-} # To provide PXE, configure nova-network's dnsmasq rather than run the one # dedicated to baremetal. When enable this, make sure these conditions are # fulfilled: -# 1) nova-compute and nova-network runs on the same host -# 2) nova-network uses FlatDHCPManager +# +# 1) nova-compute and nova-network runs on the same host +# 2) nova-network uses FlatDHCPManager +# # NOTE: the other BM_DNSMASQ_* have no effect on the behavior if this option -# is enabled. +# is enabled. BM_DNSMASQ_FROM_NOVA_NETWORK=`trueorfalse False $BM_DNSMASQ_FROM_NOVA_NETWORK` # BM_DNSMASQ_IFACE should match FLAT_NETWORK_BRIDGE @@ -103,9 +110,9 @@ fi # BM_DNSMASQ_DNS provide dns server to bootstrap clients BM_DNSMASQ_DNS=${BM_DNSMASQ_DNS:-} -# BM_FIRST_MAC *must* be set to the MAC address of the node you will boot. -# This is passed to dnsmasq along with the kernel/ramdisk to -# deploy via PXE. +# BM_FIRST_MAC *must* be set to the MAC address of the node you will +# boot. This is passed to dnsmasq along with the kernel/ramdisk to +# deploy via PXE. BM_FIRST_MAC=${BM_FIRST_MAC:-} # BM_SECOND_MAC is only important if the host has >1 NIC. @@ -119,9 +126,9 @@ BM_PM_ADDR=${BM_PM_ADDR:-0.0.0.0} BM_PM_USER=${BM_PM_USER:-user} BM_PM_PASS=${BM_PM_PASS:-pass} -# BM_FLAVOR_* options are arbitrary and not necessarily related to physical -# hardware capacity. These can be changed if you are testing -# BaremetalHostManager with multiple nodes and different flavors. +# BM_FLAVOR_* options are arbitrary and not necessarily related to +# physical hardware capacity. These can be changed if you are testing +# BaremetalHostManager with multiple nodes and different flavors. BM_CPU_ARCH=${BM_CPU_ARCH:-x86_64} BM_FLAVOR_CPU=${BM_FLAVOR_CPU:-1} BM_FLAVOR_RAM=${BM_FLAVOR_RAM:-1024} @@ -198,8 +205,8 @@ function create_fake_baremetal_env() { BM_FIRST_MAC=$(sudo $bm_poseur get-macs) # NOTE: there is currently a limitation in baremetal driver - # that requires second MAC even if it is not used. - # Passing a fake value allows this to work. + # that requires second MAC even if it is not used. + # Passing a fake value allows this to work. # TODO(deva): remove this after driver issue is fixed. BM_SECOND_MAC='12:34:56:78:90:12' } @@ -256,19 +263,19 @@ function upload_baremetal_deploy() { # load them into glance BM_DEPLOY_KERNEL_ID=$(glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ - --name $BM_DEPLOY_KERNEL \ - --is-public True --disk-format=aki \ - < $TOP_DIR/files/$BM_DEPLOY_KERNEL | grep ' id ' | get_field 2) + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ + --name $BM_DEPLOY_KERNEL \ + --is-public True --disk-format=aki \ + < $TOP_DIR/files/$BM_DEPLOY_KERNEL | grep ' id ' | get_field 2) BM_DEPLOY_RAMDISK_ID=$(glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ - --name $BM_DEPLOY_RAMDISK \ - --is-public True --disk-format=ari \ - < $TOP_DIR/files/$BM_DEPLOY_RAMDISK | grep ' id ' | get_field 2) + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ + --name $BM_DEPLOY_RAMDISK \ + --is-public True --disk-format=ari \ + < $TOP_DIR/files/$BM_DEPLOY_RAMDISK | grep ' id ' | get_field 2) } # create a basic baremetal flavor, associated with deploy kernel & ramdisk @@ -278,16 +285,16 @@ function create_baremetal_flavor() { aki=$1 ari=$2 nova flavor-create $BM_FLAVOR_NAME $BM_FLAVOR_ID \ - $BM_FLAVOR_RAM $BM_FLAVOR_ROOT_DISK $BM_FLAVOR_CPU + $BM_FLAVOR_RAM $BM_FLAVOR_ROOT_DISK $BM_FLAVOR_CPU nova flavor-key $BM_FLAVOR_NAME set \ - "cpu_arch"="$BM_FLAVOR_ARCH" \ - "baremetal:deploy_kernel_id"="$aki" \ - "baremetal:deploy_ramdisk_id"="$ari" + "cpu_arch"="$BM_FLAVOR_ARCH" \ + "baremetal:deploy_kernel_id"="$aki" \ + "baremetal:deploy_ramdisk_id"="$ari" } -# pull run-time kernel/ramdisk out of disk image and load into glance -# note that $file is currently expected to be in qcow2 format +# Pull run-time kernel/ramdisk out of disk image and load into glance. +# Note that $file is currently expected to be in qcow2 format. # Sets KERNEL_ID and RAMDISK_ID # # Usage: extract_and_upload_k_and_r_from_image $token $file @@ -311,19 +318,19 @@ function extract_and_upload_k_and_r_from_image() { # load them into glance KERNEL_ID=$(glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ - --name $image_name-kernel \ - --is-public True --disk-format=aki \ - < $TOP_DIR/files/$OUT_KERNEL | grep ' id ' | get_field 2) + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ + --name $image_name-kernel \ + --is-public True --disk-format=aki \ + < $TOP_DIR/files/$OUT_KERNEL | grep ' id ' | get_field 2) RAMDISK_ID=$(glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ - --name $image_name-initrd \ - --is-public True --disk-format=ari \ - < $TOP_DIR/files/$OUT_RAMDISK | grep ' id ' | get_field 2) + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ + --name $image_name-initrd \ + --is-public True --disk-format=ari \ + < $TOP_DIR/files/$OUT_RAMDISK | grep ' id ' | get_field 2) } @@ -365,11 +372,11 @@ function upload_baremetal_image() { mkdir "$xdir" tar -zxf $FILES/$IMAGE_FNAME -C "$xdir" KERNEL=$(for f in "$xdir/"*-vmlinuz* "$xdir/"aki-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) RAMDISK=$(for f in "$xdir/"*-initrd* "$xdir/"ari-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) IMAGE=$(for f in "$xdir/"*.img "$xdir/"ami-*/image; do - [ -f "$f" ] && echo "$f" && break; done; true) + [ -f "$f" ] && echo "$f" && break; done; true) if [[ -z "$IMAGE_NAME" ]]; then IMAGE_NAME=$(basename "$IMAGE" ".img") fi @@ -403,19 +410,19 @@ function upload_baremetal_image() { --container-format ari \ --disk-format ari < "$RAMDISK" | grep ' id ' | get_field 2) else - # TODO(deva): add support for other image types - return + # TODO(deva): add support for other image types + return fi glance \ - --os-auth-token $token \ - --os-image-url http://$GLANCE_HOSTPORT \ - image-create \ - --name "${IMAGE_NAME%.img}" --is-public True \ - --container-format $CONTAINER_FORMAT \ - --disk-format $DISK_FORMAT \ - ${KERNEL_ID:+--property kernel_id=$KERNEL_ID} \ - ${RAMDISK_ID:+--property ramdisk_id=$RAMDISK_ID} < "${IMAGE}" + --os-auth-token $token \ + --os-image-url http://$GLANCE_HOSTPORT \ + image-create \ + --name "${IMAGE_NAME%.img}" --is-public True \ + --container-format $CONTAINER_FORMAT \ + --disk-format $DISK_FORMAT \ + ${KERNEL_ID:+--property kernel_id=$KERNEL_ID} \ + ${RAMDISK_ID:+--property ramdisk_id=$RAMDISK_ID} < "${IMAGE}" # override DEFAULT_IMAGE_NAME so that tempest can find the image # that we just uploaded in glance @@ -430,7 +437,7 @@ function clear_baremetal_of_all_nodes() { done } -# inform nova-baremetal about nodes, MACs, etc +# Inform nova-baremetal about nodes, MACs, etc. # Defaults to using BM_FIRST_MAC and BM_SECOND_MAC if parameters not specified # # Usage: add_baremetal_node @@ -439,24 +446,27 @@ function add_baremetal_node() { mac_2=${2:-$BM_SECOND_MAC} id=$(nova baremetal-node-create \ - --pm_address="$BM_PM_ADDR" \ - --pm_user="$BM_PM_USER" \ - --pm_password="$BM_PM_PASS" \ - "$BM_HOSTNAME" \ - "$BM_FLAVOR_CPU" \ - "$BM_FLAVOR_RAM" \ - "$BM_FLAVOR_ROOT_DISK" \ - "$mac_1" \ - | grep ' id ' | get_field 2 ) + --pm_address="$BM_PM_ADDR" \ + --pm_user="$BM_PM_USER" \ + --pm_password="$BM_PM_PASS" \ + "$BM_HOSTNAME" \ + "$BM_FLAVOR_CPU" \ + "$BM_FLAVOR_RAM" \ + "$BM_FLAVOR_ROOT_DISK" \ + "$mac_1" \ + | grep ' id ' | get_field 2 ) [ $? -eq 0 ] || [ "$id" ] || die $LINENO "Error adding baremetal node" - id2=$(nova baremetal-interface-add "$id" "$mac_2" ) - [ $? -eq 0 ] || [ "$id2" ] || die $LINENO "Error adding interface to barmetal node $id" + if [ -n "$mac_2" ]; then + id2=$(nova baremetal-interface-add "$id" "$mac_2" ) + [ $? -eq 0 ] || [ "$id2" ] || die $LINENO "Error adding interface to barmetal node $id" + fi } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/ceilometer b/lib/ceilometer index 1b0431906a..30bf3aed50 100644 --- a/lib/ceilometer +++ b/lib/ceilometer @@ -2,12 +2,15 @@ # Install and start **Ceilometer** service # To enable a minimal set of Ceilometer services, add the following to localrc: -# enable_service ceilometer-acompute ceilometer-acentral ceilometer-collector ceilometer-api +# +# enable_service ceilometer-acompute ceilometer-acentral ceilometer-anotification ceilometer-collector ceilometer-api # # To ensure Ceilometer alarming services are enabled also, further add to the localrc: +# # enable_service ceilometer-alarm-notifier ceilometer-alarm-evaluator # Dependencies: +# # - functions # - OS_AUTH_URL for auth in api # - DEST set to the destination directory @@ -16,12 +19,12 @@ # stack.sh # --------- -# install_ceilometer -# configure_ceilometer -# init_ceilometer -# start_ceilometer -# stop_ceilometer -# cleanup_ceilometer +# - install_ceilometer +# - configure_ceilometer +# - init_ceilometer +# - start_ceilometer +# - stop_ceilometer +# - cleanup_ceilometer # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -45,8 +48,53 @@ CEILOMETER_BIN_DIR=$(get_python_exec_prefix) # Set up database backend CEILOMETER_BACKEND=${CEILOMETER_BACKEND:-mysql} +# Ceilometer connection info. +CEILOMETER_SERVICE_PROTOCOL=http +CEILOMETER_SERVICE_HOST=$SERVICE_HOST +CEILOMETER_SERVICE_PORT=${CEILOMETER_SERVICE_PORT:-8777} + +# Tell Tempest this project is present +TEMPEST_SERVICES+=,ceilometer + + # Functions # --------- +# +# create_ceilometer_accounts() - Set up common required ceilometer accounts + +create_ceilometer_accounts() { + + SERVICE_TENANT=$(keystone tenant-list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }") + ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") + + # Ceilometer + if [[ "$ENABLED_SERVICES" =~ "ceilometer-api" ]]; then + CEILOMETER_USER=$(keystone user-create \ + --name=ceilometer \ + --pass="$SERVICE_PASSWORD" \ + --tenant_id $SERVICE_TENANT \ + --email=ceilometer@example.com \ + | grep " id " | get_field 2) + keystone user-role-add \ + --tenant-id $SERVICE_TENANT \ + --user-id $CEILOMETER_USER \ + --role-id $ADMIN_ROLE + if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then + CEILOMETER_SERVICE=$(keystone service-create \ + --name=ceilometer \ + --type=metering \ + --description="OpenStack Telemetry Service" \ + | grep " id " | get_field 2) + keystone endpoint-create \ + --region RegionOne \ + --service_id $CEILOMETER_SERVICE \ + --publicurl "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT" \ + --adminurl "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT" \ + --internalurl "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT" + fi + fi +} + # cleanup_ceilometer() - Remove residual data files, anything left over from previous # runs that a clean run would need to clean up @@ -64,10 +112,10 @@ function configure_ceilometer() { setup_develop $CEILOMETER_DIR [ ! -d $CEILOMETER_CONF_DIR ] && sudo mkdir -m 755 -p $CEILOMETER_CONF_DIR - sudo chown $USER $CEILOMETER_CONF_DIR + sudo chown $STACK_USER $CEILOMETER_CONF_DIR [ ! -d $CEILOMETER_API_LOG_DIR ] && sudo mkdir -m 755 -p $CEILOMETER_API_LOG_DIR - sudo chown $USER $CEILOMETER_API_LOG_DIR + sudo chown $STACK_USER $CEILOMETER_API_LOG_DIR iniset_rpc_backend ceilometer $CEILOMETER_CONF DEFAULT @@ -79,6 +127,10 @@ function configure_ceilometer() { cp $CEILOMETER_DIR/etc/ceilometer/pipeline.yaml $CEILOMETER_CONF_DIR iniset $CEILOMETER_CONF DEFAULT policy_file $CEILOMETER_CONF_DIR/policy.json + if [ "$CEILOMETER_PIPELINE_INTERVAL" ]; then + sed -i "s/interval:.*/interval: ${CEILOMETER_PIPELINE_INTERVAL}/" $CEILOMETER_CONF_DIR/pipeline.yaml + fi + # the compute and central agents need these credentials in order to # call out to the public nova and glance APIs iniset $CEILOMETER_CONF DEFAULT os_username ceilometer @@ -91,7 +143,7 @@ function configure_ceilometer() { iniset $CEILOMETER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $CEILOMETER_CONF keystone_authtoken signing_dir $CEILOMETER_AUTH_CACHE_DIR - if [[ "$CEILOMETER_BACKEND" = 'mysql' ]]; then + if [ "$CEILOMETER_BACKEND" = 'mysql' ] || [ "$CEILOMETER_BACKEND" = 'postgresql' ] ; then iniset $CEILOMETER_CONF database connection `database_connection_url ceilometer` else iniset $CEILOMETER_CONF database connection mongodb://localhost:27017/ceilometer @@ -102,6 +154,8 @@ function configure_ceilometer() { function configure_mongodb() { if is_fedora; then + # install mongodb client + install_package mongodb # ensure smallfiles selected to minimize freespace requirements sudo sed -i '/--smallfiles/!s/OPTIONS=\"/OPTIONS=\"--smallfiles /' /etc/sysconfig/mongod @@ -116,7 +170,7 @@ function init_ceilometer() { sudo chown $STACK_USER $CEILOMETER_AUTH_CACHE_DIR rm -f $CEILOMETER_AUTH_CACHE_DIR/* - if [[ "$CEILOMETER_BACKEND" = 'mysql' ]]; then + if [ "$CEILOMETER_BACKEND" = 'mysql' ] || [ "$CEILOMETER_BACKEND" = 'postgresql' ] ; then recreate_database ceilometer utf8 $CEILOMETER_BIN_DIR/ceilometer-dbsync fi @@ -134,19 +188,28 @@ function install_ceilometerclient() { # start_ceilometer() - Start running processes, including screen function start_ceilometer() { - screen_it ceilometer-acompute "sg $LIBVIRT_GROUP \"ceilometer-agent-compute --config-file $CEILOMETER_CONF\"" - screen_it ceilometer-acentral "ceilometer-agent-central --config-file $CEILOMETER_CONF" - screen_it ceilometer-collector "ceilometer-collector --config-file $CEILOMETER_CONF" - screen_it ceilometer-api "ceilometer-api -d -v --log-dir=$CEILOMETER_API_LOG_DIR --config-file $CEILOMETER_CONF" - screen_it ceilometer-alarm-notifier "ceilometer-alarm-notifier --config-file $CEILOMETER_CONF" - screen_it ceilometer-alarm-evaluator "ceilometer-alarm-evaluator --config-file $CEILOMETER_CONF" + if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then + screen_it ceilometer-acompute "cd ; sg $LIBVIRT_GROUP \"ceilometer-agent-compute --config-file $CEILOMETER_CONF\"" + fi + screen_it ceilometer-acentral "cd ; ceilometer-agent-central --config-file $CEILOMETER_CONF" + screen_it ceilometer-anotification "cd ; ceilometer-agent-notification --config-file $CEILOMETER_CONF" + screen_it ceilometer-collector "cd ; ceilometer-collector --config-file $CEILOMETER_CONF" + screen_it ceilometer-api "cd ; ceilometer-api -d -v --log-dir=$CEILOMETER_API_LOG_DIR --config-file $CEILOMETER_CONF" + + echo "Waiting for ceilometer-api to start..." + if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -s http://localhost:8777/v2/ >/dev/null; do sleep 1; done"; then + die $LINENO "ceilometer-api did not start" + fi + + screen_it ceilometer-alarm-notifier "cd ; ceilometer-alarm-notifier --config-file $CEILOMETER_CONF" + screen_it ceilometer-alarm-evaluator "cd ; ceilometer-alarm-evaluator --config-file $CEILOMETER_CONF" } # stop_ceilometer() - Stop running processes function stop_ceilometer() { # Kill the ceilometer screen windows - for serv in ceilometer-acompute ceilometer-acentral ceilometer-collector ceilometer-api ceilometer-alarm-notifier ceilometer-alarm-evaluator; do - screen -S $SCREEN_NAME -p $serv -X kill + for serv in ceilometer-acompute ceilometer-acentral ceilometer-anotification ceilometer-collector ceilometer-api ceilometer-alarm-notifier ceilometer-alarm-evaluator; do + screen_stop $serv done } @@ -154,6 +217,7 @@ function stop_ceilometer() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/cinder b/lib/cinder index bec65ed234..9f70b2a0c9 100644 --- a/lib/cinder +++ b/lib/cinder @@ -2,19 +2,20 @@ # Install and start **Cinder** volume service # Dependencies: +# # - functions # - DEST, DATA_DIR, STACK_USER must be defined -# SERVICE_{TENANT_NAME|PASSWORD} must be defined -# ``KEYSTONE_TOKEN_FORMAT`` must be defined +# - SERVICE_{TENANT_NAME|PASSWORD} must be defined +# - ``KEYSTONE_TOKEN_FORMAT`` must be defined # stack.sh # --------- -# install_cinder -# configure_cinder -# init_cinder -# start_cinder -# stop_cinder -# cleanup_cinder +# - install_cinder +# - configure_cinder +# - init_cinder +# - start_cinder +# - stop_cinder +# - cleanup_cinder # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -78,11 +79,15 @@ VOLUME_BACKING_DEVICE2=${VOLUME_BACKING_DEVICE2:-} VOLUME_NAME_PREFIX=${VOLUME_NAME_PREFIX:-volume-} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,cinder + # Functions # --------- # _clean_lvm_lv removes all cinder LVM volumes -# _clean_lvm_lv $VOLUME_GROUP $VOLUME_NAME_PREFIX +# +# Usage: _clean_lvm_lv $VOLUME_GROUP $VOLUME_NAME_PREFIX function _clean_lvm_lv() { local vg=$1 local lv_prefix=$2 @@ -98,7 +103,8 @@ function _clean_lvm_lv() { # _clean_lvm_backing_file() removes the backing file of the # volume group used by cinder -# _clean_lvm_backing_file() $VOLUME_GROUP +# +# Usage: _clean_lvm_backing_file() $VOLUME_GROUP function _clean_lvm_backing_file() { local vg=$1 @@ -106,8 +112,8 @@ function _clean_lvm_backing_file() { # of the backing file if [ -z "`sudo lvs --noheadings -o lv_name $vg`" ]; then # if the backing physical device is a loop device, it was probably setup by devstack - VG_DEV=$(sudo losetup -j $DATA_DIR/${vg}-backing-file | awk -F':' '/backing-file/ { print $1}') - if [[ -n "$VG_DEV" ]]; then + if [[ -n "$VG_DEV" ]] && [[ -e "$VG_DEV" ]]; then + VG_DEV=$(sudo losetup -j $DATA_DIR/${vg}-backing-file | awk -F':' '/backing-file/ { print $1}') sudo losetup -d $VG_DEV rm -f $DATA_DIR/${vg}-backing-file fi @@ -160,17 +166,16 @@ function cleanup_cinder() { fi } -# configure_cinder() - Set config files, create data dirs, etc -function configure_cinder() { - if [[ ! -d $CINDER_CONF_DIR ]]; then - sudo mkdir -p $CINDER_CONF_DIR - fi - sudo chown $STACK_USER $CINDER_CONF_DIR - - cp -p $CINDER_DIR/etc/cinder/policy.json $CINDER_CONF_DIR - +# configure_cinder_rootwrap() - configure Cinder's rootwrap +function configure_cinder_rootwrap() { # Set the paths of certain binaries CINDER_ROOTWRAP=$(get_rootwrap_location cinder) + if [[ ! -x $CINDER_ROOTWRAP ]]; then + CINDER_ROOTWRAP=$(get_rootwrap_location oslo) + if [[ ! -x $CINDER_ROOTWRAP ]]; then + die $LINENO "No suitable rootwrap found." + fi + fi # If Cinder ships the new rootwrap filters files, deploy them # (owned by root) and add a parameter to $CINDER_ROOTWRAP @@ -186,31 +191,60 @@ function configure_cinder() { sudo chown -R root:root $CINDER_CONF_DIR/rootwrap.d sudo chmod 644 $CINDER_CONF_DIR/rootwrap.d/* # Set up rootwrap.conf, pointing to /etc/cinder/rootwrap.d - sudo cp $CINDER_DIR/etc/cinder/rootwrap.conf $CINDER_CONF_DIR/ + if [[ -f $CINDER_DIR/etc/cinder/rootwrap.conf ]]; then + sudo cp $CINDER_DIR/etc/cinder/rootwrap.conf $CINDER_CONF_DIR/ + else + # rootwrap.conf is no longer shipped in Cinder itself + echo "filters_path=" | sudo tee $CINDER_CONF_DIR/rootwrap.conf > /dev/null + fi sudo sed -e "s:^filters_path=.*$:filters_path=$CINDER_CONF_DIR/rootwrap.d:" -i $CINDER_CONF_DIR/rootwrap.conf sudo chown root:root $CINDER_CONF_DIR/rootwrap.conf sudo chmod 0644 $CINDER_CONF_DIR/rootwrap.conf - # Specify rootwrap.conf as first parameter to cinder-rootwrap + # Specify rootwrap.conf as first parameter to rootwrap CINDER_ROOTWRAP="$CINDER_ROOTWRAP $CINDER_CONF_DIR/rootwrap.conf" ROOTWRAP_CINDER_SUDOER_CMD="$CINDER_ROOTWRAP *" fi TEMPFILE=`mktemp` - echo "$USER ALL=(root) NOPASSWD: $ROOTWRAP_CINDER_SUDOER_CMD" >$TEMPFILE + echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_CINDER_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/cinder-rootwrap +} + +# configure_cinder() - Set config files, create data dirs, etc +function configure_cinder() { + if [[ ! -d $CINDER_CONF_DIR ]]; then + sudo mkdir -p $CINDER_CONF_DIR + fi + sudo chown $STACK_USER $CINDER_CONF_DIR + + cp -p $CINDER_DIR/etc/cinder/policy.json $CINDER_CONF_DIR + + configure_cinder_rootwrap cp $CINDER_DIR/etc/cinder/api-paste.ini $CINDER_API_PASTE_INI - iniset $CINDER_API_PASTE_INI filter:authtoken auth_host $KEYSTONE_AUTH_HOST - iniset $CINDER_API_PASTE_INI filter:authtoken auth_port $KEYSTONE_AUTH_PORT - iniset $CINDER_API_PASTE_INI filter:authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL - iniset $CINDER_API_PASTE_INI filter:authtoken admin_tenant_name $SERVICE_TENANT_NAME - iniset $CINDER_API_PASTE_INI filter:authtoken admin_user cinder - iniset $CINDER_API_PASTE_INI filter:authtoken admin_password $SERVICE_PASSWORD - iniset $CINDER_API_PASTE_INI filter:authtoken signing_dir $CINDER_AUTH_CACHE_DIR + + inicomment $CINDER_API_PASTE_INI filter:authtoken auth_host + inicomment $CINDER_API_PASTE_INI filter:authtoken auth_port + inicomment $CINDER_API_PASTE_INI filter:authtoken auth_protocol + inicomment $CINDER_API_PASTE_INI filter:authtoken cafile + inicomment $CINDER_API_PASTE_INI filter:authtoken admin_tenant_name + inicomment $CINDER_API_PASTE_INI filter:authtoken admin_user + inicomment $CINDER_API_PASTE_INI filter:authtoken admin_password + inicomment $CINDER_API_PASTE_INI filter:authtoken signing_dir cp $CINDER_DIR/etc/cinder/cinder.conf.sample $CINDER_CONF + + iniset $CINDER_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST + iniset $CINDER_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT + iniset $CINDER_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $CINDER_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA + iniset $CINDER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME + iniset $CINDER_CONF keystone_authtoken admin_user cinder + iniset $CINDER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD + iniset $CINDER_CONF keystone_authtoken signing_dir $CINDER_AUTH_CACHE_DIR + iniset $CINDER_CONF DEFAULT auth_strategy keystone iniset $CINDER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL iniset $CINDER_CONF DEFAULT verbose True @@ -222,6 +256,11 @@ function configure_cinder() { iniset $CINDER_CONF lvmdriver-2 volume_group $VOLUME_GROUP2 iniset $CINDER_CONF lvmdriver-2 volume_driver cinder.volume.drivers.lvm.LVMISCSIDriver iniset $CINDER_CONF lvmdriver-2 volume_backend_name LVM_iSCSI_2 + # NOTE(mriedem): Work around Cinder "wishlist" bug 1255593 + if [[ "$CINDER_SECURE_DELETE" == "False" ]]; then + iniset $CINDER_CONF lvmdriver-1 volume_clear none + iniset $CINDER_CONF lvmdriver-2 volume_clear none + fi else iniset $CINDER_CONF DEFAULT volume_group $VOLUME_GROUP iniset $CINDER_CONF DEFAULT volume_name_template ${VOLUME_NAME_PREFIX}%s @@ -233,6 +272,7 @@ function configure_cinder() { iniset $CINDER_CONF DEFAULT rootwrap_config "$CINDER_CONF_DIR/rootwrap.conf" iniset $CINDER_CONF DEFAULT osapi_volume_extension cinder.api.contrib.standard_extensions iniset $CINDER_CONF DEFAULT state_path $CINDER_STATE_PATH + iniset $CINDER_CONF DEFAULT lock_path $CINDER_STATE_PATH iniset $CINDER_CONF DEFAULT periodic_interval $CINDER_PERIODIC_INTERVAL if is_service_enabled ceilometer; then @@ -270,6 +310,11 @@ function configure_cinder() { iniset $CINDER_CONF DEFAULT xenapi_nfs_server "$CINDER_XENAPI_NFS_SERVER" iniset $CINDER_CONF DEFAULT xenapi_nfs_serverpath "$CINDER_XENAPI_NFS_SERVERPATH" ) + elif [ "$CINDER_DRIVER" == "nfs" ]; then + iniset $CINDER_CONF DEFAULT volume_driver "cinder.volume.drivers.nfs.NfsDriver" + iniset $CINDER_CONF DEFAULT nfs_shares_config "$CINDER_CONF_DIR/nfs_shares.conf" + echo "$CINDER_NFS_SERVERPATH" | sudo tee "$CINDER_CONF_DIR/nfs_shares.conf" + sudo chmod 666 $CINDER_CONF_DIR/nfs_shares.conf elif [ "$CINDER_DRIVER" == "sheepdog" ]; then iniset $CINDER_CONF DEFAULT volume_driver "cinder.volume.drivers.sheepdog.SheepdogDriver" elif [ "$CINDER_DRIVER" == "glusterfs" ]; then @@ -304,7 +349,7 @@ function configure_cinder() { -e 's/snapshot_autoextend_percent =.*/snapshot_autoextend_percent = 20/' \ /etc/lvm/lvm.conf fi - iniset $CINDER_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT + configure_API_version $CINDER_CONF $IDENTITY_API_VERSION iniset $CINDER_CONF keystone_authtoken admin_user cinder iniset $CINDER_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $CINDER_CONF keystone_authtoken admin_password $SERVICE_PASSWORD @@ -328,7 +373,7 @@ create_cinder_accounts() { CINDER_USER=$(keystone user-create \ --name=cinder \ --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ + --tenant-id $SERVICE_TENANT \ --email=cinder@example.com \ | grep " id " | get_field 2) keystone user-role-add \ @@ -348,7 +393,7 @@ create_cinder_accounts() { --adminurl "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(tenant_id)s" \ --internalurl "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(tenant_id)s" CINDER_V2_SERVICE=$(keystone service-create \ - --name=cinder \ + --name=cinderv2 \ --type=volumev2 \ --description="Cinder Volume Service V2" \ | grep " id " | get_field 2) @@ -496,6 +541,8 @@ function start_cinder() { # name, and would need to be adjusted too exit_distro_not_supported "restarting tgt" fi + # NOTE(gfidente): ensure tgtd is running in debug mode + sudo tgtadm --mode system --op update --name debug --value on fi screen_it c-api "cd $CINDER_DIR && $CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF" @@ -517,7 +564,7 @@ function start_cinder() { function stop_cinder() { # Kill the cinder screen windows for serv in c-api c-bak c-sch c-vol; do - screen -S $SCREEN_NAME -p $serv -X kill + screen_stop $serv done if is_service_enabled c-vol; then @@ -533,6 +580,7 @@ function stop_cinder() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/config b/lib/config new file mode 100644 index 0000000000..1678aec3fc --- /dev/null +++ b/lib/config @@ -0,0 +1,130 @@ +# lib/config - Configuration file manipulation functions + +# These functions have no external dependencies and the following side-effects: +# +# CONFIG_AWK_CMD is defined, default is ``awk`` + +# Meta-config files contain multiple INI-style configuration files +# using a specific new section header to delimit them: +# +# [[group-name|file-name]] +# +# group-name refers to the group of configuration file changes to be processed +# at a particular time. These are called phases in ``stack.sh`` but +# group here as these functions are not DevStack-specific. +# +# file-name is the destination of the config file + +# Save trace setting +C_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Allow the awk command to be overridden on legacy platforms +CONFIG_AWK_CMD=${CONFIG_AWK_CMD:-awk} + +# Get the section for the specific group and config file +# get_meta_section infile group configfile +function get_meta_section() { + local file=$1 + local matchgroup=$2 + local configfile=$3 + + [[ -r $file ]] || return 0 + [[ -z $configfile ]] && return 0 + + $CONFIG_AWK_CMD -v matchgroup=$matchgroup -v configfile=$configfile ' + BEGIN { group = "" } + /^\[\[.+\|.*\]\]/ { + if (group == "") { + gsub("[][]", "", $1); + split($1, a, "|"); + if (a[1] == matchgroup && a[2] == configfile) { + group=a[1] + } + } else { + group="" + } + next + } + { + if (group != "") + print $0 + } + ' $file +} + + +# Get a list of config files for a specific group +# get_meta_section_files infile group +function get_meta_section_files() { + local file=$1 + local matchgroup=$2 + + [[ -r $file ]] || return 0 + + $CONFIG_AWK_CMD -v matchgroup=$matchgroup ' + /^\[\[.+\|.*\]\]/ { + gsub("[][]", "", $1); + split($1, a, "|"); + if (a[1] == matchgroup) + print a[2] + } + ' $file +} + + +# Merge the contents of a meta-config file into its destination config file +# If configfile does not exist it will be created. +# merge_config_file infile group configfile +function merge_config_file() { + local file=$1 + local matchgroup=$2 + local configfile=$3 + + [[ -r $configfile ]] || touch $configfile + + get_meta_section $file $matchgroup $configfile | \ + $CONFIG_AWK_CMD -v configfile=$configfile ' + BEGIN { section = "" } + /^\[.+\]/ { + gsub("[][]", "", $1); + section=$1 + next + } + /^ *\#/ { + next + } + /^[^ \t]+/ { + split($0, d, " *= *") + print "iniset " configfile " " section " " d[1] " \"" d[2] "\"" + } + ' | while read a; do eval "$a"; done + +} + + +# Merge all of the files specified by group +# merge_config_group infile group [group ...] +function merge_config_group() { + local localfile=$1; shift + local matchgroups=$@ + + [[ -r $localfile ]] || return 0 + + for group in $matchgroups; do + for configfile in $(get_meta_section_files $localfile $group); do + if [[ -d $(dirname $configfile) ]]; then + merge_config_file $localfile $group $configfile + fi + done + done +} + + +# Restore xtrace +$C_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/database b/lib/database index 442ed56fbe..0661049e70 100644 --- a/lib/database +++ b/lib/database @@ -9,10 +9,11 @@ # This is a wrapper for the specific database backends available. # Each database must implement four functions: -# recreate_database_$DATABASE_TYPE -# install_database_$DATABASE_TYPE -# configure_database_$DATABASE_TYPE -# database_connection_url_$DATABASE_TYPE +# +# - recreate_database_$DATABASE_TYPE +# - install_database_$DATABASE_TYPE +# - configure_database_$DATABASE_TYPE +# - database_connection_url_$DATABASE_TYPE # # and call register_database $DATABASE_TYPE @@ -22,7 +23,9 @@ set +o xtrace # Register a database backend -# $1 The name of the database backend +# +# $1 The name of the database backend +# # This is required to be defined before the specific database scripts are sourced function register_database { [ -z "$DATABASE_BACKENDS" ] && DATABASE_BACKENDS=$1 || DATABASE_BACKENDS+=" $1" @@ -64,7 +67,7 @@ function initialize_database_backends { # For backward-compatibility, read in the MYSQL_HOST/USER variables and use # them as the default values for the DATABASE_HOST/USER variables. - MYSQL_HOST=${MYSQL_HOST:-localhost} + MYSQL_HOST=${MYSQL_HOST:-127.0.0.1} MYSQL_USER=${MYSQL_USER:-root} DATABASE_HOST=${DATABASE_HOST:-${MYSQL_HOST}} @@ -121,6 +124,7 @@ function database_connection_url { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/databases/mysql b/lib/databases/mysql index 41e3236f69..0eb8fdd7a2 100644 --- a/lib/databases/mysql +++ b/lib/databases/mysql @@ -2,7 +2,8 @@ # Functions to control the configuration and operation of the **MySQL** database backend # Dependencies: -# DATABASE_{HOST,USER,PASSWORD} must be defined +# +# - DATABASE_{HOST,USER,PASSWORD} must be defined # Save trace setting MY_XTRACE=$(set +o | grep xtrace) diff --git a/lib/databases/postgresql b/lib/databases/postgresql index b173772170..60e5a33715 100644 --- a/lib/databases/postgresql +++ b/lib/databases/postgresql @@ -2,7 +2,8 @@ # Functions to control the configuration and operation of the **PostgreSQL** database backend # Dependencies: -# DATABASE_{HOST,USER,PASSWORD} must be defined +# +# - DATABASE_{HOST,USER,PASSWORD} must be defined # Save trace setting PG_XTRACE=$(set +o | grep xtrace) @@ -63,9 +64,13 @@ function configure_database_postgresql { sudo sed -i "/^host/s/all\s\+::1\/128\s\+ident/$DATABASE_USER\t::0\/0\tpassword/" $PG_HBA restart_service postgresql - # If creating the role fails, chances are it already existed. Try to alter it. - sudo -u root sudo -u postgres -i psql -c "CREATE ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'" || \ - sudo -u root sudo -u postgres -i psql -c "ALTER ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'" + # Create the role if it's not here or else alter it. + root_roles=$(sudo -u root sudo -u postgres -i psql -t -c "SELECT 'HERE' from pg_roles where rolname='root'") + if [[ ${root_roles} == *HERE ]];then + sudo -u root sudo -u postgres -i psql -c "ALTER ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'" + else + sudo -u root sudo -u postgres -i psql -c "CREATE ROLE $DATABASE_USER WITH SUPERUSER LOGIN PASSWORD '$DATABASE_PASSWORD'" + fi } function install_database_postgresql { diff --git a/lib/glance b/lib/glance index 7e6968200f..2d41ea4653 100644 --- a/lib/glance +++ b/lib/glance @@ -2,20 +2,21 @@ # Functions to control the configuration and operation of the **Glance** service # Dependencies: -# ``functions`` file -# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined -# ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined -# ``SERVICE_HOST`` -# ``KEYSTONE_TOKEN_FORMAT`` must be defined +# +# - ``functions`` file +# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined +# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined +# - ``SERVICE_HOST`` +# - ``KEYSTONE_TOKEN_FORMAT`` must be defined # ``stack.sh`` calls the entry points in this order: # -# install_glance -# configure_glance -# init_glance -# start_glance -# stop_glance -# cleanup_glance +# - install_glance +# - configure_glance +# - init_glance +# - start_glance +# - stop_glance +# - cleanup_glance # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -51,6 +52,9 @@ fi # Glance connection info. Note the port must be specified. GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$SERVICE_HOST:9292} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,glance + # Functions # --------- @@ -81,7 +85,8 @@ function configure_glance() { iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL - iniset $GLANCE_REGISTRY_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ + iniset $GLANCE_REGISTRY_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA + configure_API_version $GLANCE_REGISTRY_CONF $IDENTITY_API_VERSION iniset $GLANCE_REGISTRY_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $GLANCE_REGISTRY_CONF keystone_authtoken admin_user glance iniset $GLANCE_REGISTRY_CONF keystone_authtoken admin_password $SERVICE_PASSWORD @@ -98,7 +103,8 @@ function configure_glance() { iniset $GLANCE_API_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $GLANCE_API_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $GLANCE_API_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL - iniset $GLANCE_API_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ + iniset $GLANCE_API_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA + configure_API_version $GLANCE_API_CONF $IDENTITY_API_VERSION iniset $GLANCE_API_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $GLANCE_API_CONF keystone_authtoken admin_user glance iniset $GLANCE_API_CONF keystone_authtoken admin_password $SERVICE_PASSWORD @@ -121,6 +127,8 @@ function configure_glance() { iniset $GLANCE_API_CONF DEFAULT swift_store_user $SERVICE_TENANT_NAME:glance iniset $GLANCE_API_CONF DEFAULT swift_store_key $SERVICE_PASSWORD iniset $GLANCE_API_CONF DEFAULT swift_store_create_container_on_put True + + iniset $GLANCE_API_CONF DEFAULT known_stores "glance.store.filesystem.Store, glance.store.http.Store, glance.store.swift.Store" fi cp -p $GLANCE_DIR/etc/glance-registry-paste.ini $GLANCE_REGISTRY_PASTE_INI @@ -193,22 +201,23 @@ function start_glance() { screen_it g-reg "cd $GLANCE_DIR; $GLANCE_BIN_DIR/glance-registry --config-file=$GLANCE_CONF_DIR/glance-registry.conf" screen_it g-api "cd $GLANCE_DIR; $GLANCE_BIN_DIR/glance-api --config-file=$GLANCE_CONF_DIR/glance-api.conf" echo "Waiting for g-api ($GLANCE_HOSTPORT) to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://$GLANCE_HOSTPORT; do sleep 1; done"; then - die $LINENO "g-api did not start" + if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$GLANCE_HOSTPORT; do sleep 1; done"; then + die $LINENO "g-api did not start" fi } # stop_glance() - Stop running processes function stop_glance() { # Kill the Glance screen windows - screen -S $SCREEN_NAME -p g-api -X kill - screen -S $SCREEN_NAME -p g-reg -X kill + screen_stop g-api + screen_stop g-reg } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/heat b/lib/heat index ff9473ecdb..467619f3c6 100644 --- a/lib/heat +++ b/lib/heat @@ -2,21 +2,23 @@ # Install and start **Heat** service # To enable, add the following to localrc -# ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng +# +# ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng # Dependencies: +# # - functions # stack.sh # --------- -# install_heatclient -# install_heat -# configure_heatclient -# configure_heat -# init_heat -# start_heat -# stop_heat -# cleanup_heat +# - install_heatclient +# - install_heat +# - configure_heatclient +# - configure_heat +# - init_heat +# - start_heat +# - stop_heat +# - cleanup_heat # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -36,6 +38,10 @@ HEAT_CONF=$HEAT_CONF_DIR/heat.conf HEAT_ENV_DIR=$HEAT_CONF_DIR/environment.d HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates +# Tell Tempest this project is present +TEMPEST_SERVICES+=,heat + + # Functions # --------- @@ -58,13 +64,13 @@ function configure_heat() { # remove old config files rm -f $HEAT_CONF_DIR/heat-*.conf - HEAT_API_CFN_HOST=${HEAT_API_CFN_HOST:-$SERVICE_HOST} + HEAT_API_CFN_HOST=${HEAT_API_CFN_HOST:-$HOST_IP} HEAT_API_CFN_PORT=${HEAT_API_CFN_PORT:-8000} HEAT_ENGINE_HOST=${HEAT_ENGINE_HOST:-$SERVICE_HOST} HEAT_ENGINE_PORT=${HEAT_ENGINE_PORT:-8001} - HEAT_API_CW_HOST=${HEAT_API_CW_HOST:-$SERVICE_HOST} + HEAT_API_CW_HOST=${HEAT_API_CW_HOST:-$HOST_IP} HEAT_API_CW_PORT=${HEAT_API_CW_PORT:-8003} - HEAT_API_HOST=${HEAT_API_HOST:-$SERVICE_HOST} + HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP} HEAT_API_PORT=${HEAT_API_PORT:-8004} HEAT_API_PASTE_FILE=$HEAT_CONF_DIR/api-paste.ini HEAT_POLICY_FILE=$HEAT_CONF_DIR/policy.json @@ -78,7 +84,7 @@ function configure_heat() { iniset $HEAT_CONF DEFAULT heat_metadata_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT iniset $HEAT_CONF DEFAULT heat_waitcondition_server_url http://$HEAT_API_CFN_HOST:$HEAT_API_CFN_PORT/v1/waitcondition iniset $HEAT_CONF DEFAULT heat_watch_server_url http://$HEAT_API_CW_HOST:$HEAT_API_CW_PORT - iniset $HEAT_CONF DEFAULT sql_connection `database_connection_url heat` + iniset $HEAT_CONF database connection `database_connection_url heat` iniset $HEAT_CONF DEFAULT auth_encryption_key `hexdump -n 16 -v -e '/1 "%02x"' /dev/random` # logging @@ -86,14 +92,15 @@ function configure_heat() { iniset $HEAT_CONF DEFAULT use_syslog $SYSLOG if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then # Add color to logging output - setup_colorized_logging $HEAT_CONF DEFAULT + setup_colorized_logging $HEAT_CONF DEFAULT tenant user fi # keystone authtoken iniset $HEAT_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $HEAT_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $HEAT_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL - iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0 + configure_API_version $HEAT_CONF $IDENTITY_API_VERSION + iniset $HEAT_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $HEAT_CONF keystone_authtoken admin_user heat iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD @@ -107,20 +114,14 @@ function configure_heat() { [[ "$HEAT_STANDALONE" = "True" ]] && iniset $HEAT_CONF paste_deploy flavor standalone # OpenStack API - iniset $HEAT_CONF heat_api bind_host $HEAT_API_HOST iniset $HEAT_CONF heat_api bind_port $HEAT_API_PORT # Cloudformation API - iniset $HEAT_CONF heat_api_cfn bind_host $HEAT_API_CFN_HOST iniset $HEAT_CONF heat_api_cfn bind_port $HEAT_API_CFN_PORT # Cloudwatch API - iniset $HEAT_CONF heat_api_cloudwatch bind_host $HEAT_API_CW_HOST iniset $HEAT_CONF heat_api_cloudwatch bind_port $HEAT_API_CW_PORT - # Set limits to match tempest defaults - iniset $HEAT_CONF DEFAULT max_template_size 10240 - # heat environment sudo mkdir -p $HEAT_ENV_DIR sudo chown $STACK_USER $HEAT_ENV_DIR @@ -175,7 +176,7 @@ function start_heat() { function stop_heat() { # Kill the screen windows for serv in h-eng h-api h-api-cfn h-api-cw; do - screen -S $SCREEN_NAME -p $serv -X kill + screen_stop $serv done } @@ -198,6 +199,7 @@ function disk_image_create { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/horizon b/lib/horizon index 5973eb2a9f..c64d8502ba 100644 --- a/lib/horizon +++ b/lib/horizon @@ -1,21 +1,20 @@ # lib/horizon # Functions to control the configuration and operation of the horizon service -# # Dependencies: -# ``functions`` file -# ``apache`` file -# ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined -# +# +# - ``functions`` file +# - ``apache`` file +# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined # ``stack.sh`` calls the entry points in this order: # -# install_horizon -# configure_horizon -# init_horizon -# start_horizon -# stop_horizon -# cleanup_horizon +# - install_horizon +# - configure_horizon +# - init_horizon +# - start_horizon +# - stop_horizon +# - cleanup_horizon # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -25,8 +24,6 @@ set +o xtrace # Defaults # -------- -# - # Set up default directories HORIZON_DIR=$DEST/horizon @@ -34,6 +31,9 @@ HORIZON_DIR=$DEST/horizon # The example file in Horizon repo is used by default. HORIZON_SETTINGS=${HORIZON_SETTINGS:-$HORIZON_DIR/openstack_dashboard/local/local_settings.py.example} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,horizon + # Functions # --------- @@ -115,7 +115,12 @@ function init_horizon() { # Create an empty directory that apache uses as docroot sudo mkdir -p $HORIZON_DIR/.blackhole + # Apache 2.4 uses mod_authz_host for access control now (instead of "Allow") HORIZON_REQUIRE='' + if check_apache_version "2.4" ; then + HORIZON_REQUIRE='Require all granted' + fi + local horizon_conf=/etc/$APACHE_NAME/$APACHE_CONF_DIR/horizon.conf if is_ubuntu; then # Clean up the old config name @@ -124,14 +129,11 @@ function init_horizon() { sudo touch $horizon_conf sudo a2ensite horizon.conf elif is_fedora; then - if [[ "$os_RELEASE" -ge "18" ]]; then - # fedora 18 has Require all denied in its httpd.conf - # and requires explicit Require all granted - HORIZON_REQUIRE='Require all granted' - fi sudo sed '/^Listen/s/^.*$/Listen 0.0.0.0:80/' -i /etc/httpd/conf/httpd.conf + elif is_suse; then + : # nothing to do else - exit_distro_not_supported "apache configuration" + exit_distro_not_supported "horizon apache configuration" fi # Remove old log files that could mess with how devstack detects whether Horizon @@ -154,15 +156,6 @@ function install_horizon() { # Apache installation, because we mark it NOPRIME install_apache_wsgi - # NOTE(sdague) quantal changed the name of the node binary - if is_ubuntu; then - if [[ ! -e "/usr/bin/node" ]]; then - install_package nodejs-legacy - fi - elif is_fedora && [[ $DISTRO =~ (rhel6) || "$os_RELEASE" -ge "18" ]]; then - install_package nodejs - fi - git_clone $HORIZON_REPO $HORIZON_DIR $HORIZON_BRANCH $HORIZON_TAG } @@ -181,6 +174,7 @@ function stop_horizon() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/infra b/lib/infra index 0b732598ff..0dcf0ad980 100644 --- a/lib/infra +++ b/lib/infra @@ -5,12 +5,13 @@ # requirements as a global list # Dependencies: -# ``functions`` file +# +# - ``functions`` file # ``stack.sh`` calls the entry points in this order: # -# unfubar_setuptools -# install_infra +# - unfubar_setuptools +# - install_infra # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -51,6 +52,7 @@ function install_infra() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/ironic b/lib/ironic index 072d2ded82..b8838f59fb 100644 --- a/lib/ironic +++ b/lib/ironic @@ -2,20 +2,21 @@ # Functions to control the configuration and operation of the **Ironic** service # Dependencies: -# ``functions`` file -# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined -# ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined -# ``SERVICE_HOST`` -# ``KEYSTONE_TOKEN_FORMAT`` must be defined +# +# - ``functions`` file +# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined +# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined +# - ``SERVICE_HOST`` +# - ``KEYSTONE_TOKEN_FORMAT`` must be defined # ``stack.sh`` calls the entry points in this order: # -# install_ironic -# configure_ironic -# init_ironic -# start_ironic -# stop_ironic -# cleanup_ironic +# - install_ironic +# - install_ironicclient +# - init_ironic +# - start_ironic +# - stop_ironic +# - cleanup_ironic # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -27,11 +28,11 @@ set +o xtrace # Set up default directories IRONIC_DIR=$DEST/ironic +IRONICCLIENT_DIR=$DEST/python-ironicclient IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic} IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic} IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf -IRONIC_ROOTWRAP_FILTERS=$IRONIC_CONF_DIR/rootwrap.d IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json # Support entry points installation of console scripts @@ -41,10 +42,25 @@ IRONIC_BIN_DIR=$(get_python_exec_prefix) IRONIC_SERVICE_PROTOCOL=http IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:6385} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,ironic + # Functions # --------- +# install_ironic() - Collect source and prepare +function install_ironic() { + git_clone $IRONIC_REPO $IRONIC_DIR $IRONIC_BRANCH + setup_develop $IRONIC_DIR +} + +# install_ironicclient() - Collect sources and prepare +function install_ironicclient() { + git_clone $IRONICCLIENT_REPO $IRONICCLIENT_DIR $IRONICCLIENT_BRANCH + setup_develop $IRONICCLIENT_DIR +} + # cleanup_ironic() - Remove residual data files, anything left over from previous # runs that would need to clean up. function cleanup_ironic() { @@ -79,9 +95,12 @@ function configure_ironic() { # configure_ironic_api() - Is used by configure_ironic(). Performs # API specific configuration. function configure_ironic_api() { + iniset $IRONIC_CONF_FILE DEFAULT auth_strategy keystone + iniset $IRONIC_CONF_FILE DEFAULT policy_file $IRONIC_POLICY_JSON iniset $IRONIC_CONF_FILE keystone_authtoken auth_host $KEYSTONE_AUTH_HOST iniset $IRONIC_CONF_FILE keystone_authtoken auth_port $KEYSTONE_AUTH_PORT iniset $IRONIC_CONF_FILE keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $IRONIC_CONF_FILE keystone_authtoken cafile $KEYSTONE_SSL_CA iniset $IRONIC_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset $IRONIC_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset $IRONIC_CONF_FILE keystone_authtoken admin_user ironic @@ -101,7 +120,7 @@ function configure_ironic_api() { # Sets conductor specific settings. function configure_ironic_conductor() { cp $IRONIC_DIR/etc/ironic/rootwrap.conf $IRONIC_ROOTWRAP_CONF - cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_ROOTWRAP_FILTERS + cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR iniset $IRONIC_CONF DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF } @@ -132,11 +151,11 @@ create_ironic_accounts() { IRONIC_USER=$(keystone user-create \ --name=ironic \ --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ + --tenant-id $SERVICE_TENANT \ --email=ironic@example.com \ | grep " id " | get_field 2) keystone user-role-add \ - --tenant_id $SERVICE_TENANT \ + --tenant-id $SERVICE_TENANT \ --user_id $IRONIC_USER \ --role_id $ADMIN_ROLE if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then @@ -170,12 +189,6 @@ function init_ironic() { create_ironic_accounts } -# install_ironic() - Collect source and prepare -function install_ironic() { - git_clone $IRONIC_REPO $IRONIC_DIR $IRONIC_BRANCH - setup_develop $IRONIC_DIR -} - # start_ironic() - Start running processes, including screen function start_ironic() { # Start Ironic API server, if enabled. @@ -194,8 +207,8 @@ function start_ironic() { function start_ironic_api() { screen_it ir-api "cd $IRONIC_DIR; $IRONIC_BIN_DIR/ironic-api --config-file=$IRONIC_CONF_FILE" echo "Waiting for ir-api ($IRONIC_HOSTPORT) to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://$IRONIC_HOSTPORT; do sleep 1; done"; then - die $LINENO "ir-api did not start" + if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$IRONIC_HOSTPORT; do sleep 1; done"; then + die $LINENO "ir-api did not start" fi } @@ -217,6 +230,7 @@ function stop_ironic() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/keystone b/lib/keystone old mode 100755 new mode 100644 index 4d09d29fbf..d7366a1530 --- a/lib/keystone +++ b/lib/keystone @@ -2,31 +2,32 @@ # Functions to control the configuration and operation of **Keystone** # Dependencies: -# ``functions`` file -# ``DEST``, ``STACK_USER`` -# ``IDENTITY_API_VERSION`` -# ``BASE_SQL_CONN`` -# ``SERVICE_HOST``, ``SERVICE_PROTOCOL`` -# ``SERVICE_TOKEN`` -# ``S3_SERVICE_PORT`` (template backend only) +# +# - ``functions`` file +# - ``tls`` file +# - ``DEST``, ``STACK_USER`` +# - ``IDENTITY_API_VERSION`` +# - ``BASE_SQL_CONN`` +# - ``SERVICE_HOST``, ``SERVICE_PROTOCOL`` +# - ``SERVICE_TOKEN`` +# - ``S3_SERVICE_PORT`` (template backend only) # ``stack.sh`` calls the entry points in this order: # -# install_keystone -# configure_keystone -# _config_keystone_apache_wsgi -# init_keystone -# start_keystone -# create_keystone_accounts -# stop_keystone -# cleanup_keystone -# _cleanup_keystone_apache_wsgi +# - install_keystone +# - configure_keystone +# - _config_keystone_apache_wsgi +# - init_keystone +# - start_keystone +# - create_keystone_accounts +# - stop_keystone +# - cleanup_keystone +# - _cleanup_keystone_apache_wsgi # Save trace setting XTRACE=$(set +o | grep xtrace) set +o xtrace - # Defaults # -------- @@ -78,6 +79,13 @@ KEYSTONE_VALID_IDENTITY_BACKENDS=kvs,ldap,pam,sql # valid assignment backends as per dir keystone/identity/backends KEYSTONE_VALID_ASSIGNMENT_BACKENDS=kvs,ldap,sql +# if we are running with SSL use https protocols +if is_ssl_enabled_service "key"; then + KEYSTONE_AUTH_PROTOCOL="https" + KEYSTONE_SERVICE_PROTOCOL="https" +fi + + # Functions # --------- # cleanup_keystone() - Remove residual data files, anything left over from previous @@ -125,6 +133,7 @@ function configure_keystone() { if [[ "$KEYSTONE_CONF_DIR" != "$KEYSTONE_DIR/etc" ]]; then cp -p $KEYSTONE_DIR/etc/keystone.conf.sample $KEYSTONE_CONF + chmod 600 $KEYSTONE_CONF cp -p $KEYSTONE_DIR/etc/policy.json $KEYSTONE_CONF_DIR if [[ -f "$KEYSTONE_DIR/etc/keystone-paste.ini" ]]; then cp -p "$KEYSTONE_DIR/etc/keystone-paste.ini" "$KEYSTONE_PASTE_INI" @@ -141,17 +150,17 @@ function configure_keystone() { if is_service_enabled ldap; then #Set all needed ldap values - iniset $KEYSTONE_CONF ldap password $LDAP_PASSWORD - iniset $KEYSTONE_CONF ldap user "dc=Manager,dc=openstack,dc=org" - iniset $KEYSTONE_CONF ldap suffix "dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap password $LDAP_PASSWORD + iniset $KEYSTONE_CONF ldap user $LDAP_MANAGER_DN + iniset $KEYSTONE_CONF ldap suffix $LDAP_BASE_DN iniset $KEYSTONE_CONF ldap use_dumb_member "True" iniset $KEYSTONE_CONF ldap user_attribute_ignore "enabled,email,tenants,default_project_id" iniset $KEYSTONE_CONF ldap tenant_attribute_ignore "enabled" iniset $KEYSTONE_CONF ldap tenant_domain_id_attribute "businessCategory" iniset $KEYSTONE_CONF ldap tenant_desc_attribute "description" - iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,$LDAP_BASE_DN" iniset $KEYSTONE_CONF ldap user_domain_id_attribute "businessCategory" - iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,dc=openstack,dc=org" + iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,$LDAP_BASE_DN" iniset $KEYSTONE_CONF DEFAULT member_role_id "9fe2ff9ee4384b1894a90878d3e92bab" iniset $KEYSTONE_CONF DEFAULT member_role_name "_member_" fi @@ -170,6 +179,15 @@ function configure_keystone() { iniset $KEYSTONE_CONF DEFAULT public_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:%(public_port)s/" iniset $KEYSTONE_CONF DEFAULT admin_endpoint "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:%(admin_port)s/" + # Register SSL certificates if provided + if is_ssl_enabled_service key; then + ensure_certificates KEYSTONE + + iniset $KEYSTONE_CONF ssl enable True + iniset $KEYSTONE_CONF ssl certfile $KEYSTONE_SSL_CERT + iniset $KEYSTONE_CONF ssl keyfile $KEYSTONE_SSL_KEY + fi + if is_service_enabled tls-proxy; then # Set the service ports for a proxy to take the originals iniset $KEYSTONE_CONF DEFAULT public_port $KEYSTONE_SERVICE_PORT_INT @@ -177,7 +195,6 @@ function configure_keystone() { fi iniset $KEYSTONE_CONF DEFAULT admin_token "$SERVICE_TOKEN" - iniset $KEYSTONE_CONF signing token_format "$KEYSTONE_TOKEN_FORMAT" if [[ "$KEYSTONE_TOKEN_FORMAT" = "UUID" ]]; then iniset $KEYSTONE_CONF token provider keystone.token.providers.uuid.Provider @@ -188,6 +205,8 @@ function configure_keystone() { if [[ "$KEYSTONE_TOKEN_BACKEND" = "sql" ]]; then iniset $KEYSTONE_CONF token driver keystone.token.backends.sql.Token + elif [[ "$KEYSTONE_TOKEN_BACKEND" = "memcache" ]]; then + iniset $KEYSTONE_CONF token driver keystone.token.backends.memcache.Token else iniset $KEYSTONE_CONF token driver keystone.token.backends.kvs.Token fi @@ -226,14 +245,14 @@ function configure_keystone() { fi # Set up logging - LOGGING_ROOT="devel" if [ "$SYSLOG" != "False" ]; then - LOGGING_ROOT="$LOGGING_ROOT,production" + iniset $KEYSTONE_CONF DEFAULT use_syslog "True" + fi + + # Format logging + if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then + setup_colorized_logging $KEYSTONE_CONF DEFAULT fi - KEYSTONE_LOG_CONFIG="--log-config $KEYSTONE_CONF_DIR/logging.conf" - cp $KEYSTONE_DIR/etc/logging.conf.sample $KEYSTONE_CONF_DIR/logging.conf - iniset $KEYSTONE_CONF_DIR/logging.conf logger_root level "DEBUG" - iniset $KEYSTONE_CONF_DIR/logging.conf logger_root handlers "devel,production" if is_apache_enabled_service key; then _config_keystone_apache_wsgi @@ -315,8 +334,20 @@ create_keystone_accounts() { fi } +# Configure the API version for the OpenStack projects. +# configure_API_version conf_file version +function configure_API_version() { + local conf_file=$1 + local api_version=$2 + iniset $conf_file keystone_authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$api_version +} + # init_keystone() - Initialize databases, etc. function init_keystone() { + if is_service_enabled ldap; then + init_ldap + fi + # (Re)create keystone database recreate_database keystone utf8 @@ -360,6 +391,17 @@ function install_keystone() { if is_service_enabled ldap; then install_ldap fi + if [[ "$KEYSTONE_TOKEN_BACKEND" = "memcache" ]]; then + # Install memcached and the memcache Python library that keystone uses. + # Unfortunately the Python library goes by different names in the .deb + # and .rpm circles. + install_package memcached + if is_ubuntu; then + install_package python-memcache + else + install_package python-memcached + fi + fi git_clone $KEYSTONE_REPO $KEYSTONE_DIR $KEYSTONE_BRANCH setup_develop $KEYSTONE_DIR if is_apache_enabled_service key; then @@ -380,12 +422,12 @@ function start_keystone() { screen_it key "cd $KEYSTONE_DIR && sudo tail -f /var/log/$APACHE_NAME/keystone" else # Start Keystone in a screen window - screen_it key "cd $KEYSTONE_DIR && $KEYSTONE_DIR/bin/keystone-all --config-file $KEYSTONE_CONF $KEYSTONE_LOG_CONFIG -d --debug" + screen_it key "cd $KEYSTONE_DIR && $KEYSTONE_DIR/bin/keystone-all --config-file $KEYSTONE_CONF --debug" fi echo "Waiting for keystone to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= curl -k -s ${KEYSTONE_SERVICE_PROTOCOL}://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then - die $LINENO "keystone did not start" + if ! timeout $SERVICE_TIMEOUT sh -c "while ! curl --noproxy '*' -s $KEYSTONE_AUTH_PROTOCOL://$SERVICE_HOST:$service_port/v$IDENTITY_API_VERSION/ >/dev/null; do sleep 1; done"; then + die $LINENO "keystone did not start" fi # Start proxies if enabled @@ -398,13 +440,14 @@ function start_keystone() { # stop_keystone() - Stop running processes function stop_keystone() { # Kill the Keystone screen window - screen -S $SCREEN_NAME -p key -X kill + screen_stop key } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/ldap b/lib/ldap index 2a24ccddf7..e4bd41624d 100644 --- a/lib/ldap +++ b/lib/ldap @@ -2,74 +2,144 @@ # Functions to control the installation and configuration of **ldap** # ``lib/keystone`` calls the entry points in this order: -# install_ldap() +# +# - install_ldap() # Save trace setting XTRACE=$(set +o | grep xtrace) set +o xtrace + +LDAP_DOMAIN=${LDAP_DOMAIN:-openstack.org} +# Make an array of domain components +DC=(${LDAP_DOMAIN/./ }) + +# Leftmost domain component used in top-level entry +LDAP_BASE_DC=${DC[0]} + +# Build the base DN +dn="" +for dc in ${DC[*]}; do + dn="$dn,dc=$dc" +done +LDAP_BASE_DN=${dn#,} + +LDAP_MANAGER_DN="${LDAP_MANAGER_DN:-cn=Manager,${LDAP_BASE_DN}}" +LDAP_URL=${LDAP_URL:-ldap://localhost} + LDAP_SERVICE_NAME=slapd +if is_ubuntu; then + LDAP_OLCDB_NUMBER=1 + LDAP_ROOTPW_COMMAND=replace +elif is_fedora; then + LDAP_OLCDB_NUMBER=2 + LDAP_ROOTPW_COMMAND=add +elif is_suse; then + # SUSE has slappasswd in /usr/sbin/ + PATH=$PATH:/usr/sbin/ + LDAP_OLCDB_NUMBER=1 + LDAP_ROOTPW_COMMAND=add + LDAP_SERVICE_NAME=ldap +fi + + # Functions # --------- +# Perform common variable substitutions on the data files +# _ldap_varsubst file +function _ldap_varsubst() { + local infile=$1 + sed -e " + s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER| + s|\${SLAPPASS}|$SLAPPASS| + s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND| + s|\${BASE_DC}|$LDAP_BASE_DC| + s|\${BASE_DN}|$LDAP_BASE_DN| + s|\${MANAGER_DN}|$LDAP_MANAGER_DN| + " $infile +} + +# clean_ldap() - Remove ldap server +function cleanup_ldap() { + uninstall_package $(get_packages ldap) + if is_ubuntu; then + uninstall_package slapd ldap-utils libslp1 + sudo rm -rf /etc/ldap/ldap.conf /var/lib/ldap + elif is_fedora; then + sudo rm -rf /etc/openldap /var/lib/ldap + elif is_suse; then + sudo rm -rf /var/lib/ldap + fi +} + +# init_ldap +# init_ldap() - Initialize databases, etc. +function init_ldap() { + local keystone_ldif + + TMP_LDAP_DIR=$(mktemp -d -t ldap.$$.XXXXXXXXXX) + + # Remove data but not schemas + clear_ldap_state + + # Add our top level ldap nodes + if ldapsearch -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -b "$LDAP_BASE_DN" | grep -q "Success"; then + printf "LDAP already configured for $LDAP_BASE_DC\n" + else + printf "Configuring LDAP for $LDAP_BASE_DC\n" + # If BASE_DN is changed, the user may override the default file + if [[ -r $FILES/ldap/${LDAP_BASE_DC}.ldif.in ]]; then + keystone_ldif=${LDAP_BASE_DC}.ldif + else + keystone_ldif=keystone.ldif + fi + _ldap_varsubst $FILES/ldap/${keystone_ldif}.in >$TMP_LDAP_DIR/${keystone_ldif} + if [[ -r $TMP_LDAP_DIR/${keystone_ldif} ]]; then + ldapadd -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -c -f $TMP_LDAP_DIR/${keystone_ldif} + fi + fi + + rm -rf TMP_LDAP_DIR +} + # install_ldap # install_ldap() - Collect source and prepare function install_ldap() { echo "Installing LDAP inside function" - echo "LDAP_PASSWORD is $LDAP_PASSWORD" echo "os_VENDOR is $os_VENDOR" - printf "installing" + + TMP_LDAP_DIR=$(mktemp -d -t ldap.$$.XXXXXXXXXX) + + printf "installing OpenLDAP" if is_ubuntu; then - LDAP_OLCDB_NUMBER=1 - LDAP_ROOTPW_COMMAND=replace - sudo DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils - #automatically starts LDAP on ubuntu so no need to call start_ldap + # Ubuntu automatically starts LDAP so no need to call start_ldap() + : elif is_fedora; then - LDAP_OLCDB_NUMBER=2 - LDAP_ROOTPW_COMMAND=add start_ldap elif is_suse; then - LDAP_OLCDB_NUMBER=1 - LDAP_ROOTPW_COMMAND=add - LDAP_SERVICE_NAME=ldap - # SUSE has slappasswd in /usr/sbin/ - PATH=$PATH:/usr/sbin/ - sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $FILES/ldap/base-config.ldif + _ldap_varsubst $FILES/ldap/suse-base-config.ldif.in >$TMP_LDAP_DIR/suse-base-config.ldif + sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $TMP_LDAP_DIR/suse-base-config.ldif sudo sed -i '/^OPENLDAP_START_LDAPI=/s/"no"/"yes"/g' /etc/sysconfig/openldap start_ldap fi - printf "generate password file" - SLAPPASS=`slappasswd -s $LDAP_PASSWORD` - - printf "secret is $SLAPPASS\n" - #create manager.ldif - TMP_MGR_DIFF_FILE=`mktemp -t manager_ldiff.$$.XXXXXXXXXX.ldif` - sed -e "s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER|" -e "s|\${SLAPPASS}|$SLAPPASS|" -e "s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND|" $FILES/ldap/manager.ldif.in >> $TMP_MGR_DIFF_FILE + echo "LDAP_PASSWORD is $LDAP_PASSWORD" + SLAPPASS=$(slappasswd -s $LDAP_PASSWORD) + printf "LDAP secret is $SLAPPASS\n" - #update ldap olcdb - sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $TMP_MGR_DIFF_FILE + # Create manager.ldif and add to olcdb + _ldap_varsubst $FILES/ldap/manager.ldif.in >$TMP_LDAP_DIR/manager.ldif + sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $TMP_LDAP_DIR/manager.ldif # On fedora we need to manually add cosine and inetorgperson schemas - if is_fedora || is_suse; then + if is_fedora; then sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif fi - # add our top level ldap nodes - if ldapsearch -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -b dc=openstack,dc=org | grep -q "Success"; then - printf "LDAP already configured for OpenStack\n" - if [[ "$KEYSTONE_CLEAR_LDAP" == "yes" ]]; then - # clear LDAP state - clear_ldap_state - # reconfigure LDAP for OpenStack - ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f $FILES/ldap/openstack.ldif - fi - else - printf "Configuring LDAP for OpenStack\n" - ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f $FILES/ldap/openstack.ldif - fi + rm -rf TMP_LDAP_DIR } # start_ldap() - Start LDAP @@ -77,7 +147,6 @@ function start_ldap() { sudo service $LDAP_SERVICE_NAME restart } - # stop_ldap() - Stop LDAP function stop_ldap() { sudo service $LDAP_SERVICE_NAME stop @@ -85,12 +154,13 @@ function stop_ldap() { # clear_ldap_state() - Clear LDAP State function clear_ldap_state() { - ldapdelete -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -r "dc=openstack,dc=org" + ldapdelete -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -r "$LDAP_BASE_DN" } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/marconi b/lib/marconi new file mode 100644 index 0000000000..1eaebbdf16 --- /dev/null +++ b/lib/marconi @@ -0,0 +1,176 @@ +# lib/marconi +# Install and start **Marconi** service + +# To enable a minimal set of Marconi services, add the following to localrc: +# enable_service marconi-server +# +# Dependencies: +# - functions +# - OS_AUTH_URL for auth in api +# - DEST set to the destination directory +# - SERVICE_PASSWORD, SERVICE_TENANT_NAME for auth in api +# - STACK_USER service user + +# stack.sh +# --------- +# install_marconi +# configure_marconi +# init_marconi +# start_marconi +# stop_marconi +# cleanup_marconi + +# Save trace setting +XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + +# Set up default directories +MARCONI_DIR=$DEST/marconi +MARCONICLIENT_DIR=$DEST/python-marconiclient +MARCONI_CONF_DIR=/etc/marconi +MARCONI_CONF=$MARCONI_CONF_DIR/marconi.conf +MARCONI_API_LOG_DIR=/var/log/marconi-api +MARCONI_AUTH_CACHE_DIR=${MARCONI_AUTH_CACHE_DIR:-/var/cache/marconi} + +# Support potential entry-points console scripts +MARCONI_BIN_DIR=$(get_python_exec_prefix) + +# Set up database backend +MARCONI_BACKEND=${MARCONI_BACKEND:-mongodb} + + +# Set Marconi repository +MARCONI_REPO=${MARCONI_REPO:-${GIT_BASE}/openstack/marconi.git} +MARCONI_BRANCH=${MARCONI_BRANCH:-master} + +# Set client library repository +MARCONICLIENT_REPO=${MARCONICLIENT_REPO:-${GIT_BASE}/openstack/python-marconiclient.git} +MARCONICLIENT_BRANCH=${MARCONICLIENT_BRANCH:-master} + +# Tell Tempest this project is present +TEMPEST_SERVICES+=,marconi + + +# Functions +# --------- + +# cleanup_marconi() - Remove residual data files, anything left over from previous +# runs that a clean run would need to clean up +function cleanup_marconi() { + mongo marconi --eval "db.dropDatabase();" +} + +# configure_marconiclient() - Set config files, create data dirs, etc +function configure_marconiclient() { + setup_develop $MARCONICLIENT_DIR +} + +# configure_marconi() - Set config files, create data dirs, etc +function configure_marconi() { + setup_develop $MARCONI_DIR + + [ ! -d $MARCONI_CONF_DIR ] && sudo mkdir -m 755 -p $MARCONI_CONF_DIR + sudo chown $USER $MARCONI_CONF_DIR + + [ ! -d $MARCONI_API_LOG_DIR ] && sudo mkdir -m 755 -p $MARCONI_API_LOG_DIR + sudo chown $USER $MARCONI_API_LOG_DIR + + iniset $MARCONI_CONF DEFAULT verbose True + iniset $MARCONI_CONF 'drivers:transport:wsgi' bind '0.0.0.0' + + # Install the policy file for the API server + cp $MARCONI_DIR/etc/marconi/policy.json $MARCONI_CONF_DIR + iniset $MARCONI_CONF DEFAULT policy_file $MARCONI_CONF_DIR/policy.json + + iniset $MARCONI_CONF keystone_authtoken auth_protocol http + iniset $MARCONI_CONF keystone_authtoken admin_user marconi + iniset $MARCONI_CONF keystone_authtoken admin_password $SERVICE_PASSWORD + iniset $MARCONI_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME + iniset $MARCONI_CONF keystone_authtoken signing_dir $MARCONI_AUTH_CACHE_DIR + + if [[ "$MARCONI_BACKEND" = 'mongodb' ]]; then + iniset $MARCONI_CONF database connection mongodb://localhost:27017/marconi + configure_mongodb + cleanup_marconi + fi +} + +function configure_mongodb() { + # Set nssize to 2GB. This increases the number of namespaces supported + # # per database. + sudo sed -i '/--nssize/!s/OPTIONS=\"/OPTIONS=\"--nssize 2047 /' /etc/sysconfig/mongod + + restart_service mongod +} + +# init_marconi() - Initialize etc. +function init_marconi() { + # Create cache dir + sudo mkdir -p $MARCONI_AUTH_CACHE_DIR + sudo chown $STACK_USER $MARCONI_AUTH_CACHE_DIR + rm -f $MARCONI_AUTH_CACHE_DIR/* +} + +# install_marconi() - Collect source and prepare +function install_marconi() { + git_clone $MARCONI_REPO $MARCONI_DIR $MARCONI_BRANCH + setup_develop $MARCONI_DIR +} + +# install_marconiclient() - Collect source and prepare +function install_marconiclient() { + git_clone $MARCONICLIENT_REPO $MARCONICLIENT_DIR $MARCONICLIENT_BRANCH + setup_develop $MARCONICLIENT_DIR +} + +# start_marconi() - Start running processes, including screen +function start_marconi() { + screen_it marconi-server "marconi-server --config-file $MARCONI_CONF" +} + +# stop_marconi() - Stop running processes +function stop_marconi() { + # Kill the marconi screen windows + for serv in marconi-server; do + screen -S $SCREEN_NAME -p $serv -X kill + done +} + +function create_marconi_accounts() { + SERVICE_TENANT=$(keystone tenant-list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }") + ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") + + MARCONI_USER=$(get_id keystone user-create --name=marconi \ + --pass="$SERVICE_PASSWORD" \ + --tenant-id $SERVICE_TENANT \ + --email=marconi@example.com) + keystone user-role-add --tenant-id $SERVICE_TENANT \ + --user-id $MARCONI_USER \ + --role-id $ADMIN_ROLE + if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then + MARCONI_SERVICE=$(keystone service-create \ + --name=marconi \ + --type=queuing \ + --description="Marconi Service" \ + | grep " id " | get_field 2) + keystone endpoint-create \ + --region RegionOne \ + --service_id $MARCONI_SERVICE \ + --publicurl "http://$SERVICE_HOST:8888" \ + --adminurl "http://$SERVICE_HOST:8888" \ + --internalurl "http://$SERVICE_HOST:8888" + fi + +} + + +# Restore xtrace +$XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/neutron b/lib/neutron index 4a3d1b06a6..81db2a74d1 100644 --- a/lib/neutron +++ b/lib/neutron @@ -1,30 +1,32 @@ # lib/neutron -# functions - funstions specific to neutron +# functions - functions specific to neutron # Dependencies: # ``functions`` file # ``DEST`` must be defined +# ``STACK_USER`` must be defined # ``stack.sh`` calls the entry points in this order: # -# install_neutron -# install_neutronclient -# install_neutron_agent_packages -# install_neutron_third_party -# configure_neutron -# init_neutron -# configure_neutron_third_party -# init_neutron_third_party -# start_neutron_third_party -# create_nova_conf_neutron -# start_neutron_service_and_check -# create_neutron_initial_network -# setup_neutron_debug -# start_neutron_agents +# - install_neutron +# - install_neutronclient +# - install_neutron_agent_packages +# - install_neutron_third_party +# - configure_neutron +# - init_neutron +# - configure_neutron_third_party +# - init_neutron_third_party +# - start_neutron_third_party +# - create_neutron_cache_dir +# - create_nova_conf_neutron +# - start_neutron_service_and_check +# - create_neutron_initial_network +# - setup_neutron_debug +# - start_neutron_agents # # ``unstack.sh`` calls the entry points in this order: # -# stop_neutron +# - stop_neutron # Functions in lib/neutron are classified into the following categories: # @@ -67,7 +69,7 @@ set +o xtrace # Gateway and subnet defaults, in case they are not customized in localrc NETWORK_GATEWAY=${NETWORK_GATEWAY:-10.0.0.1} -PUBLIC_NETWORK_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.225} +PUBLIC_NETWORK_GATEWAY=${PUBLIC_NETWORK_GATEWAY:-172.24.4.1} PRIVATE_SUBNET_NAME=${PRIVATE_SUBNET_NAME:-"private-subnet"} PUBLIC_SUBNET_NAME=${PUBLIC_SUBNET_NAME:-"public-subnet"} @@ -79,8 +81,8 @@ NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron} # Support entry points installation of console scripts if [[ -d $NEUTRON_DIR/bin/neutron-server ]]; then NEUTRON_BIN_DIR=$NEUTRON_DIR/bin - else -NEUTRON_BIN_DIR=$(get_python_exec_prefix) +else + NEUTRON_BIN_DIR=$(get_python_exec_prefix) fi NEUTRON_CONF_DIR=/etc/neutron @@ -88,7 +90,7 @@ NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"} # Default Neutron Plugin -Q_PLUGIN=${Q_PLUGIN:-openvswitch} +Q_PLUGIN=${Q_PLUGIN:-ml2} # Default Neutron Port Q_PORT=${Q_PORT:-9696} # Default Neutron Host @@ -110,6 +112,17 @@ Q_ALLOW_OVERLAPPING_IP=${Q_ALLOW_OVERLAPPING_IP:-True} Q_USE_DEBUG_COMMAND=${Q_USE_DEBUG_COMMAND:-False} # The name of the default q-l3 router Q_ROUTER_NAME=${Q_ROUTER_NAME:-router1} +# nova vif driver that all plugins should use +NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} + +# The next two variables are configured by plugin +# e.g. _configure_neutron_l3_agent or lib/neutron_plugins/* +# +# The plugin supports L3. +Q_L3_ENABLED=${Q_L3_ENABLED:-False} +# L3 routers exist per tenant +Q_L3_ROUTER_PER_TENANT=${Q_L3_ROUTER_PER_TENANT:-False} + # List of config file names in addition to the main plugin config file # See _configure_neutron_common() for details about setting it up declare -a Q_PLUGIN_EXTRA_CONF_FILES @@ -202,13 +215,19 @@ source $TOP_DIR/lib/neutron_plugins/$Q_PLUGIN # Hardcoding for 1 service plugin for now source $TOP_DIR/lib/neutron_plugins/services/loadbalancer +# Agent metering service plugin functions +# ------------------------------------------- + +# Hardcoding for 1 service plugin for now +source $TOP_DIR/lib/neutron_plugins/services/metering + # VPN service plugin functions # ------------------------------------------- # Hardcoding for 1 service plugin for now source $TOP_DIR/lib/neutron_plugins/services/vpn # Firewall Service Plugin functions -# -------------------------------- +# --------------------------------- source $TOP_DIR/lib/neutron_plugins/services/firewall # Use security group or not @@ -218,6 +237,10 @@ else Q_USE_SECGROUP=False fi +# Tell Tempest this project is present +TEMPEST_SERVICES+=,neutron + + # Functions # --------- @@ -231,6 +254,9 @@ function configure_neutron() { if is_service_enabled q-lbaas; then _configure_neutron_lbaas fi + if is_service_enabled q-metering; then + _configure_neutron_metering + fi if is_service_enabled q-vpn; then _configure_neutron_vpn fi @@ -268,6 +294,7 @@ function create_nova_conf_neutron() { if [[ "$Q_USE_SECGROUP" == "True" ]]; then LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver + iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER iniset $NOVA_CONF DEFAULT security_group_api neutron fi @@ -281,6 +308,14 @@ function create_nova_conf_neutron() { fi } +# create_neutron_cache_dir() - Part of the _neutron_setup_keystone() process +function create_neutron_cache_dir() { + # Create cache dir + sudo mkdir -p $NEUTRON_AUTH_CACHE_DIR + sudo chown $STACK_USER $NEUTRON_AUTH_CACHE_DIR + rm -f $NEUTRON_AUTH_CACHE_DIR/* +} + # create_neutron_accounts() - Set up common required neutron accounts # Tenant User Roles @@ -297,7 +332,7 @@ function create_neutron_accounts() { NEUTRON_USER=$(keystone user-create \ --name=neutron \ --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ + --tenant-id $SERVICE_TENANT \ --email=neutron@example.com \ | grep " id " | get_field 2) keystone user-role-add \ @@ -322,10 +357,11 @@ function create_neutron_accounts() { function create_neutron_initial_network() { TENANT_ID=$(keystone tenant-list | grep " demo " | get_field 1) + die_if_not_set $LINENO TENANT_ID "Failure retrieving TENANT_ID for demo" # Create a small network # Since neutron command is executed in admin context at this point, - # ``--tenant_id`` needs to be specified. + # ``--tenant-id`` needs to be specified. if is_baremetal; then if [[ "$PUBLIC_INTERFACE" == '' || "$OVS_PHYSICAL_BRIDGE" == '' ]]; then die $LINENO "Neutron settings for baremetal not set.. exiting" @@ -335,28 +371,36 @@ function create_neutron_initial_network() { sudo ip addr del $IP dev $PUBLIC_INTERFACE sudo ip addr add $IP dev $OVS_PHYSICAL_BRIDGE done - NET_ID=$(neutron net-create $PHYSICAL_NETWORK --tenant_id $TENANT_ID --provider:network_type flat --provider:physical_network "$PHYSICAL_NETWORK" | grep ' id ' | get_field 2) - SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --gateway $NETWORK_GATEWAY --name $PRIVATE_SUBNET_NAME $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2) + NET_ID=$(neutron net-create $PHYSICAL_NETWORK --tenant-id $TENANT_ID --provider:network_type flat --provider:physical_network "$PHYSICAL_NETWORK" | grep ' id ' | get_field 2) + die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PHYSICAL_NETWORK $TENANT_ID" + SUBNET_ID=$(neutron subnet-create --tenant-id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --gateway $NETWORK_GATEWAY --name $PRIVATE_SUBNET_NAME $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2) + die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $TENANT_ID" sudo ifconfig $OVS_PHYSICAL_BRIDGE up sudo route add default gw $NETWORK_GATEWAY dev $OVS_PHYSICAL_BRIDGE else - NET_ID=$(neutron net-create --tenant_id $TENANT_ID "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2) - SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 --gateway $NETWORK_GATEWAY --name $PRIVATE_SUBNET_NAME $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2) + NET_ID=$(neutron net-create --tenant-id $TENANT_ID "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2) + die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PHYSICAL_NETWORK $TENANT_ID" + SUBNET_ID=$(neutron subnet-create --tenant-id $TENANT_ID --ip_version 4 --gateway $NETWORK_GATEWAY --name $PRIVATE_SUBNET_NAME $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2) + die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $TENANT_ID" fi if [[ "$Q_L3_ENABLED" == "True" ]]; then # Create a router, and add the private subnet as one of its interfaces if [[ "$Q_L3_ROUTER_PER_TENANT" == "True" ]]; then # create a tenant-owned router. - ROUTER_ID=$(neutron router-create --tenant_id $TENANT_ID $Q_ROUTER_NAME | grep ' id ' | get_field 2) + ROUTER_ID=$(neutron router-create --tenant-id $TENANT_ID $Q_ROUTER_NAME | grep ' id ' | get_field 2) + die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $TENANT_ID $Q_ROUTER_NAME" else # Plugin only supports creating a single router, which should be admin owned. ROUTER_ID=$(neutron router-create $Q_ROUTER_NAME | grep ' id ' | get_field 2) + die_if_not_set $LINENO ROUTER_ID "Failure creating ROUTER_ID for $Q_ROUTER_NAME" fi neutron router-interface-add $ROUTER_ID $SUBNET_ID # Create an external network, and a subnet. Configure the external network as router gw EXT_NET_ID=$(neutron net-create "$PUBLIC_NETWORK_NAME" -- --router:external=True | grep ' id ' | get_field 2) + die_if_not_set $LINENO EXT_NET_ID "Failure creating EXT_NET_ID for $PUBLIC_NETWORK_NAME" EXT_GW_IP=$(neutron subnet-create --ip_version 4 ${Q_FLOATING_ALLOCATION_POOL:+--allocation-pool $Q_FLOATING_ALLOCATION_POOL} --gateway $PUBLIC_NETWORK_GATEWAY --name $PUBLIC_SUBNET_NAME $EXT_NET_ID $FLOATING_RANGE -- --enable_dhcp=False | grep 'gateway_ip' | get_field 2) + die_if_not_set $LINENO EXT_GW_IP "Failure creating EXT_GW_IP" neutron router-gateway-set $ROUTER_ID $EXT_NET_ID if is_service_enabled q-l3; then @@ -366,6 +410,7 @@ function create_neutron_initial_network() { sudo ip addr add $EXT_GW_IP/$CIDR_LEN dev $PUBLIC_BRIDGE sudo ip link set $PUBLIC_BRIDGE up ROUTER_GW_IP=`neutron port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F '"' '{ print $8; }'` + die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP" sudo route add -net $FIXED_RANGE gw $ROUTER_GW_IP fi if [[ "$Q_USE_NAMESPACE" == "False" ]]; then @@ -373,7 +418,7 @@ function create_neutron_initial_network() { iniset $Q_L3_CONF_FILE DEFAULT router_id $ROUTER_ID fi fi - fi + fi } # init_neutron() - Initialize databases, etc. @@ -404,7 +449,7 @@ function install_neutron_agent_packages() { fi if is_service_enabled q-lbaas; then - neutron_agent_lbaas_install_agent_packages + neutron_agent_lbaas_install_agent_packages fi } @@ -414,13 +459,13 @@ function start_neutron_service_and_check() { local cfg_file local CFG_FILE_OPTIONS="--config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE" for cfg_file in ${Q_PLUGIN_EXTRA_CONF_FILES[@]}; do - CFG_FILE_OPTIONS+=" --config-file /$cfg_file" + CFG_FILE_OPTIONS+=" --config-file /$cfg_file" done # Start the Neutron service screen_it q-svc "cd $NEUTRON_DIR && python $NEUTRON_BIN_DIR/neutron-server $CFG_FILE_OPTIONS" echo "Waiting for Neutron to start..." - if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://$Q_HOST:$Q_PORT; do sleep 1; done"; then - die $LINENO "Neutron did not start" + if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$Q_HOST:$Q_PORT; do sleep 1; done"; then + die $LINENO "Neutron did not start" fi } @@ -451,6 +496,10 @@ function start_neutron_agents() { if is_service_enabled q-lbaas; then screen_it q-lbaas "cd $NEUTRON_DIR && python $AGENT_LBAAS_BINARY --config-file $NEUTRON_CONF --config-file=$LBAAS_AGENT_CONF_FILENAME" fi + + if is_service_enabled q-metering; then + screen_it q-metering "cd $NEUTRON_DIR && python $AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME" + fi } # stop_neutron() - Stop running processes (non-screen) @@ -460,8 +509,20 @@ function stop_neutron() { [ ! -z "$pid" ] && sudo kill -9 $pid fi if is_service_enabled q-meta; then - pid=$(ps aux | awk '/neutron-ns-metadata-proxy/ { print $2 }') - [ ! -z "$pid" ] && sudo kill -9 $pid + sudo pkill -9 -f neutron-ns-metadata-proxy || : + fi + + if is_service_enabled q-lbaas; then + neutron_lbaas_stop + fi + if is_service_enabled q-fwaas; then + neutron_fwaas_stop + fi + if is_service_enabled q-vpn; then + neutron_vpn_stop + fi + if is_service_enabled q-metering; then + neutron_metering_stop fi } @@ -473,7 +534,7 @@ function cleanup_neutron() { fi # delete all namespaces created by neutron - for ns in $(sudo ip netns list | grep -o -e qdhcp-[0-9a-f\-]* -e qrouter-[0-9a-f\-]*); do + for ns in $(sudo ip netns list | grep -o -E '(qdhcp|qrouter|qlbaas)-[0-9a-f-]*'); do sudo ip netns delete ${ns} done } @@ -494,6 +555,7 @@ function _configure_neutron_common() { # For main plugin config file, set ``Q_PLUGIN_CONF_PATH``, ``Q_PLUGIN_CONF_FILENAME``. # For addition plugin config files, set ``Q_PLUGIN_EXTRA_CONF_PATH``, # ``Q_PLUGIN_EXTRA_CONF_FILES``. For example: + # # ``Q_PLUGIN_EXTRA_CONF_FILES=(file1, file2)`` neutron_plugin_configure_common @@ -536,7 +598,7 @@ function _configure_neutron_common() { # Format logging if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then - setup_colorized_logging $NEUTRON_CONF DEFAULT + setup_colorized_logging $NEUTRON_CONF DEFAULT project_id fi _neutron_setup_rootwrap @@ -552,9 +614,6 @@ function _configure_neutron_debug_command() { iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT verbose False iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT debug False iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT use_namespaces $Q_USE_NAMESPACE - iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT root_helper "$Q_RR_COMMAND" - # Intermediate fix until Neutron patch lands and then line above will - # be cleaned. iniset $NEUTRON_TEST_CONFIG_FILE agent root_helper "$Q_RR_COMMAND" _neutron_setup_interface_driver $NEUTRON_TEST_CONFIG_FILE @@ -630,6 +689,11 @@ function _configure_neutron_lbaas() { neutron_agent_lbaas_configure_agent } +function _configure_neutron_metering() { + neutron_agent_metering_configure_common + neutron_agent_metering_configure_agent +} + function _configure_neutron_fwaas() { neutron_fwaas_configure_common neutron_fwaas_configure_driver @@ -693,6 +757,16 @@ function _configure_neutron_service() { # Utility Functions #------------------ +# _neutron_service_plugin_class_add() - add service plugin class +function _neutron_service_plugin_class_add() { + local service_plugin_class=$1 + if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then + Q_SERVICE_PLUGIN_CLASSES=$service_plugin_class + elif [[ ! ,${Q_SERVICE_PLUGIN_CLASSES}, =~ ,${service_plugin_class}, ]]; then + Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$service_plugin_class" + fi +} + # _neutron_setup_rootwrap() - configure Neutron's rootwrap function _neutron_setup_rootwrap() { if [[ "$Q_USE_ROOTWRAP" == "False" ]]; then @@ -712,9 +786,9 @@ function _neutron_setup_rootwrap() { # Set up ``rootwrap.conf``, pointing to ``$NEUTRON_CONF_DIR/rootwrap.d`` # location moved in newer versions, prefer new location if test -r $NEUTRON_DIR/etc/neutron/rootwrap.conf; then - sudo cp -p $NEUTRON_DIR/etc/neutron/rootwrap.conf $Q_RR_CONF_FILE + sudo cp -p $NEUTRON_DIR/etc/neutron/rootwrap.conf $Q_RR_CONF_FILE else - sudo cp -p $NEUTRON_DIR/etc/rootwrap.conf $Q_RR_CONF_FILE + sudo cp -p $NEUTRON_DIR/etc/rootwrap.conf $Q_RR_CONF_FILE fi sudo sed -e "s:^filters_path=.*$:filters_path=$Q_CONF_ROOTWRAP_D:" -i $Q_RR_CONF_FILE sudo chown root:root $Q_RR_CONF_FILE @@ -724,7 +798,7 @@ function _neutron_setup_rootwrap() { # Set up the rootwrap sudoers for neutron TEMPFILE=`mktemp` - echo "$USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE + echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/neutron-rootwrap @@ -757,9 +831,7 @@ function _neutron_setup_keystone() { if [[ -z $skip_auth_cache ]]; then iniset $conf_file $section signing_dir $NEUTRON_AUTH_CACHE_DIR # Create cache dir - sudo mkdir -p $NEUTRON_AUTH_CACHE_DIR - sudo chown $STACK_USER $NEUTRON_AUTH_CACHE_DIR - rm -f $NEUTRON_AUTH_CACHE_DIR/* + create_neutron_cache_dir fi } @@ -848,11 +920,11 @@ function _ssh_check_neutron() { # please refer to ``lib/neutron_thirdparty/README.md`` for details NEUTRON_THIRD_PARTIES="" for f in $TOP_DIR/lib/neutron_thirdparty/*; do - third_party=$(basename $f) - if is_service_enabled $third_party; then - source $TOP_DIR/lib/neutron_thirdparty/$third_party - NEUTRON_THIRD_PARTIES="$NEUTRON_THIRD_PARTIES,$third_party" - fi + third_party=$(basename $f) + if is_service_enabled $third_party; then + source $TOP_DIR/lib/neutron_thirdparty/$third_party + NEUTRON_THIRD_PARTIES="$NEUTRON_THIRD_PARTIES,$third_party" + fi done function _neutron_third_party_do() { @@ -886,10 +958,16 @@ function stop_neutron_third_party() { _neutron_third_party_do stop } +# check_neutron_third_party_integration() - Check that third party integration is sane +function check_neutron_third_party_integration() { + _neutron_third_party_do check +} + # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/neutron_plugins/bigswitch_floodlight b/lib/neutron_plugins/bigswitch_floodlight index 24507312c7..93ec497bb9 100644 --- a/lib/neutron_plugins/bigswitch_floodlight +++ b/lib/neutron_plugins/bigswitch_floodlight @@ -9,7 +9,7 @@ source $TOP_DIR/lib/neutron_plugins/ovs_base source $TOP_DIR/lib/neutron_thirdparty/bigswitch_floodlight # for third party service specific configuration values function neutron_plugin_create_nova_conf() { - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} + : } function neutron_plugin_install_agent_packages() { diff --git a/lib/neutron_plugins/brocade b/lib/neutron_plugins/brocade index f9275cacc2..8e18d04984 100644 --- a/lib/neutron_plugins/brocade +++ b/lib/neutron_plugins/brocade @@ -38,7 +38,7 @@ function neutron_plugin_configure_l3_agent() { } function neutron_plugin_configure_plugin_agent() { - AGENT_BINARY="$NEUTON_BIN_DIR/neutron-linuxbridge-agent" + AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-linuxbridge-agent" } function neutron_plugin_setup_interface_driver() { diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent index 88c49c5b5e..85e8c085be 100644 --- a/lib/neutron_plugins/linuxbridge_agent +++ b/lib/neutron_plugins/linuxbridge_agent @@ -11,7 +11,7 @@ function is_neutron_ovs_base_plugin() { } function neutron_plugin_create_nova_conf() { - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} + : } function neutron_plugin_install_agent_packages() { diff --git a/lib/neutron_plugins/midonet b/lib/neutron_plugins/midonet index 0ad760b289..f95fcb75b9 100644 --- a/lib/neutron_plugins/midonet +++ b/lib/neutron_plugins/midonet @@ -12,7 +12,7 @@ function is_neutron_ovs_base_plugin() { } function neutron_plugin_create_nova_conf() { - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"midonet.nova.virt.libvirt.vif.MidonetVifDriver"} + NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} } function neutron_plugin_install_agent_packages() { @@ -32,19 +32,18 @@ function neutron_plugin_configure_debug_command() { function neutron_plugin_configure_dhcp_agent() { DHCP_DRIVER=${DHCP_DRIVER:-"neutron.plugins.midonet.agent.midonet_driver.DhcpNoOpDriver"} - DHCP_INTERFACE_DRIVER=${DHCP_INTEFACE_DRIVER:-"neutron.plugins.midonet.agent.midonet_driver.MidonetInterfaceDriver"} + neutron_plugin_setup_interface_driver $Q_DHCP_CONF_FILE iniset $Q_DHCP_CONF_FILE DEFAULT dhcp_driver $DHCP_DRIVER - iniset $Q_DHCP_CONF_FILE DEFAULT interface_driver $DHCP_INTERFACE_DRIVER iniset $Q_DHCP_CONF_FILE DEFAULT use_namespaces True iniset $Q_DHCP_CONF_FILE DEFAULT enable_isolated_metadata True } function neutron_plugin_configure_l3_agent() { - die $LINENO "q-l3 must not be executed with MidoNet plugin!" + die $LINENO "q-l3 must not be executed with MidoNet plugin!" } function neutron_plugin_configure_plugin_agent() { - die $LINENO "q-agt must not be executed with MidoNet plugin!" + die $LINENO "q-agt must not be executed with MidoNet plugin!" } function neutron_plugin_configure_service() { @@ -63,11 +62,14 @@ function neutron_plugin_configure_service() { if [[ "$MIDONET_PROVIDER_ROUTER_ID" != "" ]]; then iniset /$Q_PLUGIN_CONF_FILE MIDONET provider_router_id $MIDONET_PROVIDER_ROUTER_ID fi + + Q_L3_ENABLED=True + Q_L3_ROUTER_PER_TENANT=True } function neutron_plugin_setup_interface_driver() { - # May change in the future - : + local conf_file=$1 + iniset $conf_file DEFAULT interface_driver neutron.agent.linux.interface.MidonetInterfaceDriver } function has_neutron_plugin_security_group() { diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2 index 8d2e303854..ab4e3474a6 100644 --- a/lib/neutron_plugins/ml2 +++ b/lib/neutron_plugins/ml2 @@ -34,10 +34,13 @@ Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS=${Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS:-} ML2_L3_PLUGIN=${ML2_L3_PLUGIN:-neutron.services.l3_router.l3_router_plugin.L3RouterPlugin} function populate_ml2_config() { - OPTS=$1 - CONF=$2 - SECTION=$3 + CONF=$1 + SECTION=$2 + OPTS=$3 + if [ -z "$OPTS" ]; then + return + fi for I in "${OPTS[@]}"; do # Replace the first '=' with ' ' for iniset syntax iniset $CONF $SECTION ${I/=/ } @@ -51,11 +54,7 @@ function neutron_plugin_configure_common() { Q_PLUGIN_CLASS="neutron.plugins.ml2.plugin.Ml2Plugin" # The ML2 plugin delegates L3 routing/NAT functionality to # the L3 service plugin which must therefore be specified. - if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then - Q_SERVICE_PLUGIN_CLASSES=$ML2_L3_PLUGIN - else - Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$ML2_L3_PLUGIN" - fi + _neutron_service_plugin_class_add $ML2_L3_PLUGIN } function neutron_plugin_configure_service() { @@ -102,19 +101,17 @@ function neutron_plugin_configure_service() { # Since we enable the tunnel TypeDrivers, also enable a local_ip iniset /$Q_PLUGIN_CONF_FILE ovs local_ip $HOST_IP - populate_ml2_config mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS /$Q_PLUGIN_CONF_FILE ml2 + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 mechanism_drivers=$Q_ML2_PLUGIN_MECHANISM_DRIVERS - populate_ml2_config type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS /$Q_PLUGIN_CONF_FILE ml2 + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 type_drivers=$Q_ML2_PLUGIN_TYPE_DRIVERS - populate_ml2_config $Q_SRV_EXTRA_OPTS /$Q_PLUGIN_CONF_FILE ml2 + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2 $Q_SRV_EXTRA_OPTS - populate_ml2_config $Q_ML2_PLUGIN_GRE_TYPE_OPTIONS /$Q_PLUGIN_CONF_FILE ml2_type_gre + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_gre $Q_ML2_PLUGIN_GRE_TYPE_OPTIONS - populate_ml2_config $Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS /$Q_PLUGIN_CONF_FILE ml2_type_vxlan + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_vxlan $Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS - if [ "$Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS" != "" ]; then - populate_ml2_config $Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS /$Q_PLUGIN_CONF_FILE ml2_type_vlan - fi + populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_vlan $Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS } function has_neutron_plugin_security_group() { diff --git a/lib/neutron_plugins/nec b/lib/neutron_plugins/nec index 79d41dbf77..d8d8b7ce7e 100644 --- a/lib/neutron_plugins/nec +++ b/lib/neutron_plugins/nec @@ -55,21 +55,26 @@ function neutron_plugin_configure_l3_agent() { _neutron_ovs_base_configure_l3_agent } -function neutron_plugin_configure_plugin_agent() { +function _quantum_plugin_setup_bridge() { if [[ "$SKIP_OVS_BRIDGE_SETUP" = "True" ]]; then return fi # Set up integration bridge _neutron_ovs_base_setup_bridge $OVS_BRIDGE - sudo ovs-vsctl --no-wait set-controller $OVS_BRIDGE tcp:$OFC_OFP_HOST:$OFC_OFP_PORT # Generate datapath ID from HOST_IP - local dpid=$(printf "0x%07d%03d%03d%03d\n" ${HOST_IP//./ }) + local dpid=$(printf "%07d%03d%03d%03d\n" ${HOST_IP//./ }) sudo ovs-vsctl --no-wait set Bridge $OVS_BRIDGE other-config:datapath-id=$dpid sudo ovs-vsctl --no-wait set-fail-mode $OVS_BRIDGE secure + sudo ovs-vsctl --no-wait set-controller $OVS_BRIDGE tcp:$OFC_OFP_HOST:$OFC_OFP_PORT if [ -n "$OVS_INTERFACE" ]; then sudo ovs-vsctl --no-wait -- --may-exist add-port $OVS_BRIDGE $OVS_INTERFACE fi _neutron_setup_ovs_tunnels $OVS_BRIDGE +} + +function neutron_plugin_configure_plugin_agent() { + _quantum_plugin_setup_bridge + AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-nec-agent" _neutron_ovs_base_configure_firewall_driver @@ -101,15 +106,15 @@ function _neutron_setup_ovs_tunnels() { local id=0 GRE_LOCAL_IP=${GRE_LOCAL_IP:-$HOST_IP} if [ -n "$GRE_REMOTE_IPS" ]; then - for ip in ${GRE_REMOTE_IPS//:/ } - do - if [[ "$ip" == "$GRE_LOCAL_IP" ]]; then - continue - fi - sudo ovs-vsctl --no-wait add-port $bridge gre$id -- \ - set Interface gre$id type=gre options:remote_ip=$ip - id=`expr $id + 1` - done + for ip in ${GRE_REMOTE_IPS//:/ } + do + if [[ "$ip" == "$GRE_LOCAL_IP" ]]; then + continue + fi + sudo ovs-vsctl --no-wait add-port $bridge gre$id -- \ + set Interface gre$id type=gre options:remote_ip=$ip + id=`expr $id + 1` + done fi } diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base index 2666d8e8ba..89db29d07f 100644 --- a/lib/neutron_plugins/ovs_base +++ b/lib/neutron_plugins/ovs_base @@ -73,13 +73,7 @@ function _neutron_ovs_base_configure_l3_agent() { } function _neutron_ovs_base_configure_nova_vif_driver() { - # The hybrid VIF driver needs to be specified when Neutron Security Group - # is enabled (until vif_security attributes are supported in VIF extension) - if [[ "$Q_USE_SECGROUP" == "True" ]]; then - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtHybridOVSBridgeDriver"} - else - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} - fi + : } # Restore xtrace diff --git a/lib/neutron_plugins/plumgrid b/lib/neutron_plugins/plumgrid index 9d3c92ff51..bccd301011 100644 --- a/lib/neutron_plugins/plumgrid +++ b/lib/neutron_plugins/plumgrid @@ -6,11 +6,8 @@ MY_XTRACE=$(set +o | grep xtrace) set +o xtrace -#source $TOP_DIR/lib/neutron_plugins/ovs_base - function neutron_plugin_create_nova_conf() { - - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"} + : } function neutron_plugin_setup_interface_driver() { @@ -24,11 +21,17 @@ function neutron_plugin_configure_common() { Q_PLUGIN_CLASS="neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin.NeutronPluginPLUMgridV2" PLUMGRID_DIRECTOR_IP=${PLUMGRID_DIRECTOR_IP:-localhost} PLUMGRID_DIRECTOR_PORT=${PLUMGRID_DIRECTOR_PORT:-7766} + PLUMGRID_ADMIN=${PLUMGRID_ADMIN:-username} + PLUMGRID_PASSWORD=${PLUMGRID_PASSWORD:-password} + PLUMGRID_TIMEOUT=${PLUMGRID_TIMEOUT:-70} } function neutron_plugin_configure_service() { iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector director_server $PLUMGRID_DIRECTOR_IP iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector director_server_port $PLUMGRID_DIRECTOR_PORT + iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector username $PLUMGRID_ADMIN + iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector password $PLUMGRID_PASSWORD + iniset /$Q_PLUGIN_CONF_FILE PLUMgridDirector servertimeout $PLUMGRID_TIMEOUT } function neutron_plugin_configure_debug_command() { diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall index 1597e8577d..8273e54e6c 100644 --- a/lib/neutron_plugins/services/firewall +++ b/lib/neutron_plugins/services/firewall @@ -8,11 +8,7 @@ set +o xtrace FWAAS_PLUGIN=neutron.services.firewall.fwaas_plugin.FirewallPlugin function neutron_fwaas_configure_common() { - if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then - Q_SERVICE_PLUGIN_CLASSES=$FWAAS_PLUGIN - else - Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$FWAAS_PLUGIN" - fi + _neutron_service_plugin_class_add $FWAAS_PLUGIN } function neutron_fwaas_configure_driver() { @@ -23,5 +19,9 @@ function neutron_fwaas_configure_driver() { iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver" } +function neutron_fwaas_stop() { + : +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_plugins/services/loadbalancer b/lib/neutron_plugins/services/loadbalancer index c38f904b69..5d7a94e5d8 100644 --- a/lib/neutron_plugins/services/loadbalancer +++ b/lib/neutron_plugins/services/loadbalancer @@ -19,11 +19,7 @@ function neutron_agent_lbaas_install_agent_packages() { } function neutron_agent_lbaas_configure_common() { - if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then - Q_SERVICE_PLUGIN_CLASSES=$LBAAS_PLUGIN - else - Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$LBAAS_PLUGIN" - fi + _neutron_service_plugin_class_add $LBAAS_PLUGIN } function neutron_agent_lbaas_configure_agent() { @@ -45,5 +41,10 @@ function neutron_agent_lbaas_configure_agent() { fi } +function neutron_lbaas_stop() { + pids=$(ps aux | awk '/haproxy/ { print $2 }') + [ ! -z "$pids" ] && sudo kill $pids +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_plugins/services/metering b/lib/neutron_plugins/services/metering new file mode 100644 index 0000000000..37952bbabd --- /dev/null +++ b/lib/neutron_plugins/services/metering @@ -0,0 +1,30 @@ +# Neutron metering plugin +# --------------------------- + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +AGENT_METERING_BINARY="$NEUTRON_BIN_DIR/neutron-metering-agent" +METERING_PLUGIN="neutron.services.metering.metering_plugin.MeteringPlugin" + +function neutron_agent_metering_configure_common() { + _neutron_service_plugin_class_add $METERING_PLUGIN +} + +function neutron_agent_metering_configure_agent() { + METERING_AGENT_CONF_PATH=/etc/neutron/services/metering + mkdir -p $METERING_AGENT_CONF_PATH + + METERING_AGENT_CONF_FILENAME="$METERING_AGENT_CONF_PATH/metering_agent.ini" + + cp $NEUTRON_DIR/etc/metering_agent.ini $METERING_AGENT_CONF_FILENAME +} + +function neutron_metering_stop() { + : +} + +# Restore xtrace +$MY_XTRACE diff --git a/lib/neutron_plugins/services/vpn b/lib/neutron_plugins/services/vpn index b8f5c7d56b..02370e7f85 100644 --- a/lib/neutron_plugins/services/vpn +++ b/lib/neutron_plugins/services/vpn @@ -15,10 +15,17 @@ function neutron_vpn_install_agent_packages() { } function neutron_vpn_configure_common() { - if [[ $Q_SERVICE_PLUGIN_CLASSES == '' ]]; then - Q_SERVICE_PLUGIN_CLASSES=$VPN_PLUGIN - else - Q_SERVICE_PLUGIN_CLASSES="$Q_SERVICE_PLUGIN_CLASSES,$VPN_PLUGIN" + _neutron_service_plugin_class_add $VPN_PLUGIN +} + +function neutron_vpn_stop() { + local ipsec_data_dir=$DATA_DIR/neutron/ipsec + local pids + if [ -d $ipsec_data_dir ]; then + pids=$(find $ipsec_data_dir -name 'pluto.pid' -exec cat {} \;) + fi + if [ -n "$pids" ]; then + sudo kill $pids fi } diff --git a/lib/neutron_plugins/nicira b/lib/neutron_plugins/vmware_nsx similarity index 52% rename from lib/neutron_plugins/nicira rename to lib/neutron_plugins/vmware_nsx index e9deb64e11..d506cb6f8d 100644 --- a/lib/neutron_plugins/nicira +++ b/lib/neutron_plugins/vmware_nsx @@ -1,5 +1,5 @@ -# Neutron Nicira NVP plugin -# --------------------------- +# Neutron VMware NSX plugin +# ------------------------- # Save trace setting MY_XTRACE=$(set +o | grep xtrace) @@ -9,10 +9,10 @@ source $TOP_DIR/lib/neutron_plugins/ovs_base function setup_integration_bridge() { _neutron_ovs_base_setup_bridge $OVS_BRIDGE - # Set manager to NVP controller (1st of list) - if [[ "$NVP_CONTROLLERS" != "" ]]; then + # Set manager to NSX controller (1st of list) + if [[ "$NSX_CONTROLLERS" != "" ]]; then # Get the first controller - controllers=(${NVP_CONTROLLERS//,/ }) + controllers=(${NSX_CONTROLLERS//,/ }) OVS_MGR_IP=${controllers[0]} else die $LINENO "Error - No controller specified. Unable to set a manager for OVS" @@ -21,12 +21,11 @@ function setup_integration_bridge() { } function is_neutron_ovs_base_plugin() { - # NVP uses OVS, but not the l3-agent + # NSX uses OVS, but not the l3-agent return 0 } function neutron_plugin_create_nova_conf() { - NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtOpenVswitchDriver"} # if n-cpu is enabled, then setup integration bridge if is_service_enabled n-cpu; then setup_integration_bridge @@ -34,14 +33,15 @@ function neutron_plugin_create_nova_conf() { } function neutron_plugin_install_agent_packages() { - # Nicira Plugin does not run q-agt, but it currently needs dhcp and metadata agents + # VMware NSX Plugin does not run q-agt, but it currently needs dhcp and metadata agents _neutron_ovs_base_install_agent_packages } function neutron_plugin_configure_common() { - Q_PLUGIN_CONF_PATH=etc/neutron/plugins/nicira - Q_PLUGIN_CONF_FILENAME=nvp.ini - Q_DB_NAME="neutron_nvp" + Q_PLUGIN_CONF_PATH=etc/neutron/plugins/vmware + Q_PLUGIN_CONF_FILENAME=nsx.ini + Q_DB_NAME="neutron_nsx" + # TODO(armando-migliaccio): rename this once the code rename is complete Q_PLUGIN_CLASS="neutron.plugins.nicira.NeutronPlugin.NvpPluginV2" } @@ -58,66 +58,77 @@ function neutron_plugin_configure_dhcp_agent() { } function neutron_plugin_configure_l3_agent() { - # Nicira plugin does not run L3 agent - die $LINENO "q-l3 should must not be executed with Nicira plugin!" + # VMware NSX plugin does not run L3 agent + die $LINENO "q-l3 should must not be executed with VMware NSX plugin!" } function neutron_plugin_configure_plugin_agent() { - # Nicira plugin does not run L2 agent - die $LINENO "q-agt must not be executed with Nicira plugin!" + # VMware NSX plugin does not run L2 agent + die $LINENO "q-agt must not be executed with VMware NSX plugin!" } function neutron_plugin_configure_service() { if [[ "$MAX_LP_PER_BRIDGED_LS" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE nvp max_lp_per_bridged_ls $MAX_LP_PER_BRIDGED_LS + iniset /$Q_PLUGIN_CONF_FILE nsx max_lp_per_bridged_ls $MAX_LP_PER_BRIDGED_LS fi if [[ "$MAX_LP_PER_OVERLAY_LS" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE nvp max_lp_per_overlay_ls $MAX_LP_PER_OVERLAY_LS + iniset /$Q_PLUGIN_CONF_FILE nsx max_lp_per_overlay_ls $MAX_LP_PER_OVERLAY_LS fi if [[ "$FAILOVER_TIME" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE nvp failover_time $FAILOVER_TIME + iniset /$Q_PLUGIN_CONF_FILE nsx failover_time $FAILOVER_TIME fi if [[ "$CONCURRENT_CONNECTIONS" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE nvp concurrent_connections $CONCURRENT_CONNECTIONS + iniset /$Q_PLUGIN_CONF_FILE nsx concurrent_connections $CONCURRENT_CONNECTIONS fi if [[ "$DEFAULT_TZ_UUID" != "" ]]; then iniset /$Q_PLUGIN_CONF_FILE DEFAULT default_tz_uuid $DEFAULT_TZ_UUID else - die $LINENO "The nicira plugin won't work without a default transport zone." + die $LINENO "The VMware NSX plugin won't work without a default transport zone." fi if [[ "$DEFAULT_L3_GW_SVC_UUID" != "" ]]; then iniset /$Q_PLUGIN_CONF_FILE DEFAULT default_l3_gw_service_uuid $DEFAULT_L3_GW_SVC_UUID Q_L3_ENABLED=True Q_L3_ROUTER_PER_TENANT=True - iniset /$Q_PLUGIN_CONF_FILE nvp metadata_mode access_network + iniset /$Q_PLUGIN_CONF_FILE nsx metadata_mode access_network fi if [[ "$DEFAULT_L2_GW_SVC_UUID" != "" ]]; then iniset /$Q_PLUGIN_CONF_FILE DEFAULT default_l2_gw_service_uuid $DEFAULT_L2_GW_SVC_UUID fi - # NVP_CONTROLLERS must be a comma separated string - if [[ "$NVP_CONTROLLERS" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT nvp_controllers $NVP_CONTROLLERS + # NSX_CONTROLLERS must be a comma separated string + if [[ "$NSX_CONTROLLERS" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT nsx_controllers $NSX_CONTROLLERS else - die $LINENO "The nicira plugin needs at least an NVP controller." + die $LINENO "The VMware NSX plugin needs at least an NSX controller." fi - if [[ "$NVP_USER" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT nvp_user $NVP_USER + if [[ "$NSX_USER" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT nsx_user $NSX_USER fi - if [[ "$NVP_PASSWORD" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT nvp_password $NVP_PASSWORD + if [[ "$NSX_PASSWORD" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT nsx_password $NSX_PASSWORD fi - if [[ "$NVP_REQ_TIMEOUT" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT req_timeout $NVP_REQ_TIMEOUT + if [[ "$NSX_REQ_TIMEOUT" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT req_timeout $NSX_REQ_TIMEOUT fi - if [[ "$NVP_HTTP_TIMEOUT" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT http_timeout $NVP_HTTP_TIMEOUT + if [[ "$NSX_HTTP_TIMEOUT" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT http_timeout $NSX_HTTP_TIMEOUT fi - if [[ "$NVP_RETRIES" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT retries $NVP_RETRIES + if [[ "$NSX_RETRIES" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT retries $NSX_RETRIES fi - if [[ "$NVP_REDIRECTS" != "" ]]; then - iniset /$Q_PLUGIN_CONF_FILE DEFAULT redirects $NVP_REDIRECTS + if [[ "$NSX_REDIRECTS" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT redirects $NSX_REDIRECTS + fi + if [[ "$AGENT_MODE" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE nsx agent_mode $AGENT_MODE + if [[ "$AGENT_MODE" == "agentless" ]]; then + if [[ "$DEFAULT_SERVICE_CLUSTER_UUID" != "" ]]; then + iniset /$Q_PLUGIN_CONF_FILE DEFAULT default_service_cluster_uuid $DEFAULT_SERVICE_CLUSTER_UUID + else + die $LINENO "Agentless mode requires a service cluster." + fi + iniset /$Q_PLUGIN_CONF_FILE nsx_metadata metadata_server_address $Q_META_DATA_IP + fi fi } diff --git a/lib/neutron_thirdparty/README.md b/lib/neutron_thirdparty/README.md index b289f58c5d..2460e5cac7 100644 --- a/lib/neutron_thirdparty/README.md +++ b/lib/neutron_thirdparty/README.md @@ -34,3 +34,6 @@ functions to be implemented * ``stop_``: stop running processes (non-screen) + +* ``check_``: + verify that the integration between neutron server and third-party components is sane diff --git a/lib/neutron_thirdparty/bigswitch_floodlight b/lib/neutron_thirdparty/bigswitch_floodlight index ebde0673b8..1fd4fd801a 100644 --- a/lib/neutron_thirdparty/bigswitch_floodlight +++ b/lib/neutron_thirdparty/bigswitch_floodlight @@ -45,5 +45,9 @@ function stop_bigswitch_floodlight() { : } +function check_bigswitch_floodlight() { + : +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 00ae87aa0a..961abc95fd 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -1,3 +1,4 @@ +# proto is https or ssh #! /bin/bash # Contrail NFV @@ -16,7 +17,7 @@ function install_contrail() { # basic dependencies if ! which repo > /dev/null 2>&1 ; then - wget http://commondatastorage.googleapis.com/git-repo-downloads/repo + wget -N http://commondatastorage.googleapis.com/git-repo-downloads/repo chmod 0755 repo sudo mv repo /usr/bin fi @@ -24,6 +25,7 @@ function install_contrail() { # dependencies if is_ubuntu; then apt_get install patch scons flex bison make vim + apt_get install chkconfig apt_get install libexpat-dev libgettextpo0 libcurl4-openssl-dev apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev @@ -60,15 +62,22 @@ function install_contrail() { sudo pip install netifaces fabric argparse sudo pip install stevedore xmltodict python-keystoneclient sudo pip install kazoo pyinotify + sudo pip install bottle + CONTRAIL_REPO_PROTO=${CONTRAIL_REPO_PROTO:-ssh} CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} - mkdir -p $CONTRAIL_SRC + mkdir -p $CONTRAIL_SRC/third_party contrail_cwd=$(pwd) cd $CONTRAIL_SRC if [ ! -d $CONTRAIL_SRC/.repo ]; then git config --global --get user.name || git config --global user.name "Anonymous" git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" - repo init -u git@github.com:Juniper/contrail-vnc + if [ "$CONTRAIL_REPO_PROTO" == "ssh" ]; then + repo init -u git@github.com:Juniper/contrail-vnc + else + repo init -u https://github.com/Juniper/contrail-vnc + sed -i 's/fetch=".."/fetch=\"https:\/\/github.com\/Juniper\/\"/' .repo/manifest.xml + fi fi repo sync python third_party/fetch_packages.py @@ -80,6 +89,9 @@ function install_contrail() { echo "Installing contrail modules" sudo pip install --upgrade $(find $CONTRAIL_SRC/build/debug -name "*.tar.gz" -print) + # install VIF driver + sudo pip install $CONTRAIL_SRC/build/noarch/nova_contrail_vif/dist/nova_contrail_vif*.tar.gz + # install neutron patch after VNC api is built and installed # test_install_neutron_patch @@ -130,18 +142,18 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/third_party/irond-0.3.0-bin ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip + wget -N http://trust.f4.hs-hannover.de/download/iron/archive/irond-0.3.0-bin.zip unzip irond-0.3.0-bin.zip chmod -w irond-0.3.0-bin/ifmap.properties cd ${contrail_cwd} fi - if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.5 ]; then + if [ ! -d $CONTRAIL_SRC/third_party/zookeeper-3.4.6 ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.5.tar.gz - tar xvzf zookeeper-3.4.5.tar.gz - cd zookeeper-3.4.5 + wget -N http://apache.mirrors.hoobly.com/zookeeper/stable/zookeeper-3.4.6.tar.gz + tar xvzf zookeeper-3.4.6.tar.gz + cd zookeeper-3.4.6 cp conf/zoo_sample.cfg conf/zoo.cfg cd ${contrail_cwd} fi @@ -150,7 +162,7 @@ function install_contrail() { if ! python -c 'import ncclient' >/dev/null 2>&1; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/third_party - wget https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz + wget -N https://code.grnet.gr/attachments/download/1172/ncclient-v0.3.2.tar.gz sudo pip install ncclient-v0.3.2.tar.gz cd ${contrail_cwd} fi @@ -314,7 +326,7 @@ function start_contrail() { screen_it cass "sudo cassandra -f" - screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.5; ./bin/zkServer.sh start" + screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.6; ./bin/zkServer.sh start" screen_it ifmap "cd $CONTRAIL_SRC/third_party/irond-0.3.0-bin; java -jar ./irond.jar" sleep 2 @@ -324,7 +336,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --reset_config --conf_file /etc/contrail/api_server.conf" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" @@ -335,7 +347,7 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --map-server-url https://${IFMAP_SERVER}:${IFMAP_PORT} --map-user ${IFMAP_USER} --map-password ${IFMAP_PASWD} --hostname ${HOSTNAME} --host-ip ${HOSTIP} --bgp-port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --collector ${COLLECTOR}" + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --collectors ${COLLECTOR}" # collector services # redis-uve @@ -350,7 +362,7 @@ function start_contrail() { # collector/vizd source /etc/contrail/vizd_param - screen_it vizd "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/analytics/vizd --cassandra-server-list ${CASSANDRA_SERVER_LIST} --host-ip ${HOST_IP} ${LOG_FILE} ${LOG_LOCAL}" + screen_it vizd "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/analytics/vizd --DEFAULT.cassandra_server_list ${CASSANDRA_SERVER_LIST} --DEFAULT.hostip ${HOST_IP} --DEFAULT.log_file /var/log/contrail/collector.log" sleep 2 source /etc/contrail/opserver_param @@ -358,7 +370,7 @@ function start_contrail() { sleep 2 source /etc/contrail/qed_param - screen_it qed "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/query_engine/qed --collectors ${COLLECTORS} --cassandra-server-list ${CASSANDRA_SERVER_LIST} --redis-ip ${REDIS_SERVER} --redis-port ${REDIS_SERVER_PORT} ${LOG_FILE} ${LOG_LOCAL}" + screen_it qed "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/query_engine/qed --collectors ${COLLECTORS} --cassandra_server_list ${CASSANDRA_SERVER_LIST} --REDIS.server ${REDIS_SERVER} --REDIS.port ${REDIS_SERVER_PORT} log_file /var/log/contrail/qe.log ${LOG_LOCAL}" sleep 2 # Provision Vrouter - must be run after API server and schema transformer are up @@ -405,8 +417,6 @@ END chmod a+x $TOP_DIR/bin/vnsw.hlpr screen_it agent "sudo $TOP_DIR/bin/vnsw.hlpr" - screen_it vif "python /opt/stack/nova/plugins/contrail/contrail_vif.py" - if is_service_enabled q-meta; then # set up a proxy route in contrail from 169.254.169.254:80 to # my metadata server at port 8775 @@ -425,13 +435,18 @@ END } function configure_contrail() { - test_install_nova_patch + : } function init_contrail() { : } +function check_contrail() { + : +} + + function stop_contrail() { SCREEN=$(which screen) if [[ -n "$SCREEN" ]]; then diff --git a/lib/neutron_thirdparty/midonet b/lib/neutron_thirdparty/midonet index 7928bca31f..e672528a2d 100644 --- a/lib/neutron_thirdparty/midonet +++ b/lib/neutron_thirdparty/midonet @@ -56,5 +56,9 @@ function stop_midonet() { : } +function check_midonet() { + : +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_thirdparty/nicira b/lib/neutron_thirdparty/nicira deleted file mode 100644 index 5a20934a1b..0000000000 --- a/lib/neutron_thirdparty/nicira +++ /dev/null @@ -1,52 +0,0 @@ -# Nicira NVP -# ---------- - -# This third-party addition can be used to configure connectivity between a DevStack instance -# and an NVP Gateway in dev/test environments. In order to use this correctly, the following -# env variables need to be set (e.g. in your localrc file): -# -# * enable_service nicira --> to execute this third-party addition -# * PUBLIC_BRIDGE --> bridge used for external connectivity, typically br-ex -# * NVP_GATEWAY_NETWORK_INTERFACE --> interface used to communicate with the NVP Gateway -# * NVP_GATEWAY_NETWORK_CIDR --> CIDR to configure br-ex, e.g. 172.24.4.211/24 - -# Save trace setting -MY_XTRACE=$(set +o | grep xtrace) -set +o xtrace - -# This is the interface that connects the Devstack instance -# to an network that allows it to talk to the gateway for -# testing purposes -NVP_GATEWAY_NETWORK_INTERFACE=${NVP_GATEWAY_NETWORK_INTERFACE:-eth2} - -function configure_nicira() { - : -} - -function init_nicira() { - die_if_not_set $LINENO NVP_GATEWAY_NETWORK_CIDR "Please, specify CIDR for the gateway network interface." - # Make sure the interface is up, but not configured - sudo ifconfig $NVP_GATEWAY_NETWORK_INTERFACE up - sudo ip addr flush $NVP_GATEWAY_NETWORK_INTERFACE - # Use the PUBLIC Bridge to route traffic to the NVP gateway - # NOTE(armando-migliaccio): if running in a nested environment this will work - # only with mac learning enabled, portsecurity and security profiles disabled - sudo ovs-vsctl -- --may-exist add-port $PUBLIC_BRIDGE $NVP_GATEWAY_NETWORK_INTERFACE - nvp_gw_net_if_mac=$(ip link show $NVP_GATEWAY_NETWORK_INTERFACE | awk '/ether/ {print $2}') - sudo ifconfig $PUBLIC_BRIDGE $NVP_GATEWAY_NETWORK_CIDR hw ether $nvp_gw_net_if_mac -} - -function install_nicira() { - : -} - -function start_nicira() { - : -} - -function stop_nicira() { - : -} - -# Restore xtrace -$MY_XTRACE diff --git a/lib/neutron_thirdparty/ryu b/lib/neutron_thirdparty/ryu index 3b825a10c1..5edf273361 100644 --- a/lib/neutron_thirdparty/ryu +++ b/lib/neutron_thirdparty/ryu @@ -75,5 +75,9 @@ function stop_ryu() { : } +function check_ryu() { + : +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_thirdparty/trema b/lib/neutron_thirdparty/trema index 09dc46bd83..2b125646dc 100644 --- a/lib/neutron_thirdparty/trema +++ b/lib/neutron_thirdparty/trema @@ -28,7 +28,7 @@ TREMA_TMP_DIR=$TREMA_DATA_DIR/trema TREMA_LOG_LEVEL=${TREMA_LOG_LEVEL:-info} TREMA_SS_CONFIG=$TREMA_SS_ETC_DIR/sliceable.conf -TREMA_SS_APACHE_CONFIG=/etc/apache2/sites-available/sliceable_switch +TREMA_SS_APACHE_CONFIG=/etc/apache2/sites-available/sliceable_switch.conf # configure_trema - Set config files, create data dirs, etc function configure_trema() { @@ -62,12 +62,12 @@ function init_trema() { sudo sed -i -e "s|/home/sliceable_switch/script|$TREMA_SS_SCRIPT_DIR|" \ $TREMA_SS_APACHE_CONFIG sudo a2enmod rewrite actions - sudo a2ensite sliceable_switch + sudo a2ensite sliceable_switch.conf cp $TREMA_SS_DIR/sliceable_switch_null.conf $TREMA_SS_CONFIG sed -i -e "s|^\$apps_dir.*$|\$apps_dir = \"$TREMA_DIR/apps\"|" \ - -e "s|^\$db_dir.*$|\$db_dir = \"$TREMA_SS_DB_DIR\"|" \ - $TREMA_SS_CONFIG + -e "s|^\$db_dir.*$|\$db_dir = \"$TREMA_SS_DB_DIR\"|" \ + $TREMA_SS_CONFIG } function gem_install() { @@ -109,5 +109,9 @@ function stop_trema() { sudo TREMA_TMP=$TREMA_TMP_DIR trema killall } +function check_trema() { + : +} + # Restore xtrace $MY_XTRACE diff --git a/lib/neutron_thirdparty/vmware_nsx b/lib/neutron_thirdparty/vmware_nsx new file mode 100644 index 0000000000..4eb177a458 --- /dev/null +++ b/lib/neutron_thirdparty/vmware_nsx @@ -0,0 +1,86 @@ +# VMware NSX +# ---------- + +# This third-party addition can be used to configure connectivity between a DevStack instance +# and an NSX Gateway in dev/test environments. In order to use this correctly, the following +# env variables need to be set (e.g. in your localrc file): +# +# * enable_service vmware_nsx --> to execute this third-party addition +# * PUBLIC_BRIDGE --> bridge used for external connectivity, typically br-ex +# * NSX_GATEWAY_NETWORK_INTERFACE --> interface used to communicate with the NSX Gateway +# * NSX_GATEWAY_NETWORK_CIDR --> CIDR to configure br-ex, e.g. 172.24.4.211/24 + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + +# This is the interface that connects the Devstack instance +# to an network that allows it to talk to the gateway for +# testing purposes +NSX_GATEWAY_NETWORK_INTERFACE=${NSX_GATEWAY_NETWORK_INTERFACE:-eth2} +# Re-declare floating range as it's needed also in stop_vmware_nsx, which +# is invoked by unstack.sh +FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.0/24} + +function configure_vmware_nsx() { + : +} + +function init_vmware_nsx() { + if ! is_set NSX_GATEWAY_NETWORK_CIDR; then + NSX_GATEWAY_NETWORK_CIDR=$PUBLIC_NETWORK_GATEWAY/${FLOATING_RANGE#*/} + echo "The IP address to set on br-ex was not specified. " + echo "Defaulting to "$NSX_GATEWAY_NETWORK_CIDR + fi + # Make sure the interface is up, but not configured + sudo ip link set $NSX_GATEWAY_NETWORK_INTERFACE up + # Save and then flush the IP addresses on the interface + addresses=$(ip addr show dev $NSX_GATEWAY_NETWORK_INTERFACE | grep inet | awk {'print $2'}) + sudo ip addr flush $NSX_GATEWAY_NETWORK_INTERFACE + # Use the PUBLIC Bridge to route traffic to the NSX gateway + # NOTE(armando-migliaccio): if running in a nested environment this will work + # only with mac learning enabled, portsecurity and security profiles disabled + # The public bridge might not exist for the NSX plugin if Q_USE_DEBUG_COMMAND is off + # Try to create it anyway + sudo ovs-vsctl --no-wait -- --may-exist add-br $PUBLIC_BRIDGE + sudo ovs-vsctl -- --may-exist add-port $PUBLIC_BRIDGE $NSX_GATEWAY_NETWORK_INTERFACE + nsx_gw_net_if_mac=$(ip link show $NSX_GATEWAY_NETWORK_INTERFACE | awk '/ether/ {print $2}') + sudo ip link set address $nsx_gw_net_if_mac dev $PUBLIC_BRIDGE + for address in $addresses; do + sudo ip addr add dev $PUBLIC_BRIDGE $address + done + sudo ip addr add dev $PUBLIC_BRIDGE $NSX_GATEWAY_NETWORK_CIDR +} + +function install_vmware_nsx() { + : +} + +function start_vmware_nsx() { + : +} + +function stop_vmware_nsx() { + if ! is_set NSX_GATEWAY_NETWORK_CIDR; then + NSX_GATEWAY_NETWORK_CIDR=$PUBLIC_NETWORK_GATEWAY/${FLOATING_RANGE#*/} + echo "The IP address expected on br-ex was not specified. " + echo "Defaulting to "$NSX_GATEWAY_NETWORK_CIDR + fi + sudo ip addr del $NSX_GATEWAY_NETWORK_CIDR dev $PUBLIC_BRIDGE + # Save and then flush remaining addresses on the interface + addresses=$(ip addr show dev $PUBLIC_BRIDGE | grep inet | awk {'print $2'}) + sudo ip addr flush $PUBLIC_BRIDGE + # Try to detach physical interface from PUBLIC_BRIDGE + sudo ovs-vsctl del-port $NSX_GATEWAY_NETWORK_INTERFACE + # Restore addresses on NSX_GATEWAY_NETWORK_INTERFACE + for address in $addresses; do + sudo ip addr add dev $NSX_GATEWAY_NETWORK_INTERFACE $address + done +} + +function check_vmware_nsx() { + neutron-check-nsx-config $NEUTRON_CONF_DIR/plugins/vmware/nsx.ini +} + +# Restore xtrace +$MY_XTRACE diff --git a/lib/nova b/lib/nova index db98afee3f..1234bdfb3f 100644 --- a/lib/nova +++ b/lib/nova @@ -2,22 +2,23 @@ # Functions to control the configuration and operation of the **Nova** service # Dependencies: -# ``functions`` file -# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined -# ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined -# ``LIBVIRT_TYPE`` must be defined -# ``INSTANCE_NAME_PREFIX``, ``VOLUME_NAME_PREFIX`` must be defined -# ``KEYSTONE_TOKEN_FORMAT`` must be defined +# +# - ``functions`` file +# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined +# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined +# - ``LIBVIRT_TYPE`` must be defined +# - ``INSTANCE_NAME_PREFIX``, ``VOLUME_NAME_PREFIX`` must be defined +# - ``KEYSTONE_TOKEN_FORMAT`` must be defined # ``stack.sh`` calls the entry points in this order: # -# install_nova -# configure_nova -# create_nova_conf -# init_nova -# start_nova -# stop_nova -# cleanup_nova +# - install_nova +# - configure_nova +# - create_nova_conf +# - init_nova +# - start_nova +# - stop_nova +# - cleanup_nova # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -62,40 +63,34 @@ NOVA_ROOTWRAP=$(get_rootwrap_location nova) # NOTE: Set API_RATE_LIMIT="False" to turn OFF rate limiting API_RATE_LIMIT=${API_RATE_LIMIT:-"True"} +# Option to enable/disable config drive +# NOTE: Set FORCE_CONFIG_DRIVE="False" to turn OFF config drive +FORCE_CONFIG_DRIVE=${FORCE_CONFIG_DRIVE:-"always"} + # Nova supports pluggable schedulers. The default ``FilterScheduler`` # should work in most cases. SCHEDULER=${SCHEDULER:-nova.scheduler.filter_scheduler.FilterScheduler} QEMU_CONF=/etc/libvirt/qemu.conf -NOVNC_DIR=$DEST/noVNC -SPICE_DIR=$DEST/spice-html5 +# Set default defaults here as some hypervisor drivers override these +PUBLIC_INTERFACE_DEFAULT=br100 +GUEST_INTERFACE_DEFAULT=eth0 +FLAT_NETWORK_BRIDGE_DEFAULT=br100 + +# Get hypervisor configuration +# ---------------------------- + +NOVA_PLUGINS=$TOP_DIR/lib/nova_plugins +if is_service_enabled nova && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then + # Load plugin + source $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER +fi # Nova Network Configuration # -------------------------- -# Set defaults according to the virt driver -if [ "$VIRT_DRIVER" = 'xenserver' ]; then - PUBLIC_INTERFACE_DEFAULT=eth2 - GUEST_INTERFACE_DEFAULT=eth1 - # Allow ``build_domU.sh`` to specify the flat network bridge via kernel args - FLAT_NETWORK_BRIDGE_DEFAULT=$(sed -e 's/.* flat_network_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline) - if is_service_enabled neutron; then - XEN_INTEGRATION_BRIDGE=$(sed -e 's/.* xen_integration_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline) - fi -elif [ "$VIRT_DRIVER" = 'baremetal' ]; then - NETWORK_MANAGER=${NETWORK_MANAGER:-FlatManager} - PUBLIC_INTERFACE_DEFAULT=eth0 - FLAT_INTERFACE=${FLAT_INTERFACE:-eth0} - FLAT_NETWORK_BRIDGE_DEFAULT=br100 - STUB_NETWORK=${STUB_NETWORK:-False} -else - PUBLIC_INTERFACE_DEFAULT=br100 - GUEST_INTERFACE_DEFAULT=eth0 - FLAT_NETWORK_BRIDGE_DEFAULT=br100 -fi - NETWORK_MANAGER=${NETWORK_MANAGER:-${NET_MAN:-FlatDHCPManager}} PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-$PUBLIC_INTERFACE_DEFAULT} VLAN_INTERFACE=${VLAN_INTERFACE:-$GUEST_INTERFACE_DEFAULT} @@ -127,6 +122,9 @@ MULTI_HOST=`trueorfalse False $MULTI_HOST` TEST_FLOATING_POOL=${TEST_FLOATING_POOL:-test} TEST_FLOATING_RANGE=${TEST_FLOATING_RANGE:-192.168.253.0/29} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,nova + # Functions # --------- @@ -200,7 +198,7 @@ function configure_nova_rootwrap() { # Set up the rootwrap sudoers for nova TEMPFILE=`mktemp` - echo "$USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE + echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE sudo chown root:root $TEMPFILE sudo mv $TEMPFILE /etc/sudoers.d/nova-rootwrap @@ -219,26 +217,23 @@ function configure_nova() { configure_nova_rootwrap if is_service_enabled n-api; then - # Use the sample http middleware configuration supplied in the - # Nova sources. This paste config adds the configuration required - # for Nova to validate Keystone tokens. - # Remove legacy paste config if present rm -f $NOVA_DIR/bin/nova-api-paste.ini # Get the sample configuration file in place cp $NOVA_DIR/etc/nova/api-paste.ini $NOVA_CONF_DIR - iniset $NOVA_API_PASTE_INI filter:authtoken auth_host $KEYSTONE_AUTH_HOST - if is_service_enabled tls-proxy; then - iniset $NOVA_API_PASTE_INI filter:authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL - fi - iniset $NOVA_API_PASTE_INI filter:authtoken admin_tenant_name $SERVICE_TENANT_NAME - iniset $NOVA_API_PASTE_INI filter:authtoken admin_user nova - iniset $NOVA_API_PASTE_INI filter:authtoken admin_password $SERVICE_PASSWORD + # Comment out the keystone configs in Nova's api-paste.ini. + # We are using nova.conf to configure this instead. + inicomment $NOVA_API_PASTE_INI filter:authtoken auth_host + inicomment $NOVA_API_PASTE_INI filter:authtoken auth_protocol + inicomment $NOVA_API_PASTE_INI filter:authtoken admin_tenant_name + inicomment $NOVA_API_PASTE_INI filter:authtoken cafile + inicomment $NOVA_API_PASTE_INI filter:authtoken admin_user + inicomment $NOVA_API_PASTE_INI filter:authtoken admin_password fi - iniset $NOVA_API_PASTE_INI filter:authtoken signing_dir $NOVA_AUTH_CACHE_DIR + inicomment $NOVA_API_PASTE_INI filter:authtoken signing_dir if is_service_enabled n-cpu; then # Force IP forwarding on, just on case @@ -282,83 +277,6 @@ function configure_nova() { fi fi - # Prepare directories and packages for baremetal driver - if is_baremetal; then - configure_baremetal_nova_dirs - fi - - if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then - if is_service_enabled neutron && is_neutron_ovs_base_plugin && ! sudo grep -q '^cgroup_device_acl' $QEMU_CONF; then - # Add /dev/net/tun to cgroup_device_acls, needed for type=ethernet interfaces - cat </etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla -[libvirt Management Access] -Identity=unix-group:$LIBVIRT_GROUP -Action=org.libvirt.unix.manage -ResultAny=yes -ResultInactive=yes -ResultActive=yes -EOF" - elif is_suse && [[ $os_RELEASE = 12.2 || "$os_VENDOR" = "SUSE LINUX" ]]; then - # openSUSE < 12.3 or SLE - # Work around the fact that polkit-default-privs overrules pklas - # with 'unix-group:$group'. - sudo bash -c "cat </etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla -[libvirt Management Access] -Identity=unix-user:$USER -Action=org.libvirt.unix.manage -ResultAny=yes -ResultInactive=yes -ResultActive=yes -EOF" - else - # Starting with fedora 18 and opensuse-12.3 enable stack-user to - # virsh -c qemu:///system by creating a policy-kit rule for - # stack-user using the new Javascript syntax - rules_dir=/etc/polkit-1/rules.d - sudo mkdir -p $rules_dir - sudo bash -c "cat < $rules_dir/50-libvirt-$STACK_USER.rules -polkit.addRule(function(action, subject) { - if (action.id == 'org.libvirt.unix.manage' && - subject.user == '"$STACK_USER"') { - return polkit.Result.YES; - } -}); -EOF" - unset rules_dir - fi - fi - - # The user that nova runs as needs to be member of **libvirtd** group otherwise - # nova-compute will be unable to use libvirt. - if ! getent group $LIBVIRT_GROUP >/dev/null; then - sudo groupadd $LIBVIRT_GROUP - fi - add_user_to_group $STACK_USER $LIBVIRT_GROUP - - # libvirt detects various settings on startup, as we potentially changed - # the system configuration (modules, filesystems), we need to restart - # libvirt to detect those changes. - restart_service $LIBVIRT_DAEMON - fi - # Instance Storage # ---------------- @@ -376,6 +294,14 @@ EOF" fi fi fi + + # Rebuild the config file from scratch + create_nova_conf + + if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then + # Configure hypervisor plugin + configure_nova_hypervisor + fi } # create_nova_accounts() - Set up common required nova accounts @@ -395,7 +321,7 @@ create_nova_accounts() { NOVA_USER=$(keystone user-create \ --name=nova \ --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ + --tenant-id $SERVICE_TENANT \ --email=nova@example.com \ | grep " id " | get_field 2) keystone user-role-add \ @@ -415,7 +341,7 @@ create_nova_accounts() { --adminurl "$NOVA_SERVICE_PROTOCOL://$NOVA_SERVICE_HOST:$NOVA_SERVICE_PORT/v2/\$(tenant_id)s" \ --internalurl "$NOVA_SERVICE_PROTOCOL://$NOVA_SERVICE_HOST:$NOVA_SERVICE_PORT/v2/\$(tenant_id)s" NOVA_V3_SERVICE=$(keystone service-create \ - --name=nova \ + --name=novav3 \ --type=computev3 \ --description="Nova Compute Service V3" \ | grep " id " | get_field 2) @@ -454,15 +380,8 @@ function create_nova_conf() { iniset $NOVA_CONF DEFAULT osapi_compute_workers "4" iniset $NOVA_CONF DEFAULT ec2_workers "4" iniset $NOVA_CONF DEFAULT metadata_workers "4" + iniset $NOVA_CONF conductor workers "4" iniset $NOVA_CONF DEFAULT sql_connection `database_connection_url nova` - if is_baremetal; then - iniset $NOVA_CONF baremetal sql_connection `database_connection_url nova_bm` - fi - if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then - iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE" - iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none" - iniset $NOVA_CONF DEFAULT use_usb_tablet "False" - fi iniset $NOVA_CONF DEFAULT instance_name_template "${INSTANCE_NAME_PREFIX}%08x" iniset $NOVA_CONF osapi_v3 enabled "True" @@ -478,7 +397,20 @@ function create_nova_conf() { # Set the service port for a proxy to take the original iniset $NOVA_CONF DEFAULT osapi_compute_listen_port "$NOVA_SERVICE_PORT_INT" fi + + # Add keystone authtoken configuration + + iniset $NOVA_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST + iniset $NOVA_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT + iniset $NOVA_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $NOVA_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME + iniset $NOVA_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA + iniset $NOVA_CONF keystone_authtoken admin_user nova + iniset $NOVA_CONF keystone_authtoken admin_password $SERVICE_PASSWORD fi + + iniset $NOVA_CONF keystone_authtoken signing_dir $NOVA_AUTH_CACHE_DIR + if is_service_enabled cinder; then iniset $NOVA_CONF DEFAULT volume_api_class "nova.volume.cinder.API" fi @@ -499,6 +431,9 @@ function create_nova_conf() { if [ "$API_RATE_LIMIT" != "True" ]; then iniset $NOVA_CONF DEFAULT api_rate_limit "False" fi + if [ "$FORCE_CONFIG_DRIVE" != "False" ]; then + iniset $NOVA_CONF DEFAULT force_config_drive "$FORCE_CONFIG_DRIVE" + fi # Format logging if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then setup_colorized_logging $NOVA_CONF DEFAULT @@ -510,6 +445,7 @@ function create_nova_conf() { iniset $NOVA_CONF DEFAULT instance_usage_audit "True" iniset $NOVA_CONF DEFAULT instance_usage_audit_period "hour" iniset $NOVA_CONF DEFAULT notify_on_state_change "vm_and_task_state" + iniset $NOVA_CONF DEFAULT notification_driver "nova.openstack.common.notifier.rpc_notifier" fi # Provide some transition from ``EXTRA_FLAGS`` to ``EXTRA_OPTS`` @@ -534,33 +470,29 @@ function create_nova_conf() { SPICEHTML5PROXY_URL=${SPICEHTML5PROXY_URL:-"http://$SERVICE_HOST:6082/spice_auto.html"} iniset $NOVA_CONF spice html5proxy_base_url "$SPICEHTML5PROXY_URL" fi - if [ "$VIRT_DRIVER" = 'xenserver' ]; then - VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=169.254.0.1} - else - VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=127.0.0.1} - fi if is_service_enabled n-novnc || is_service_enabled n-xvnc; then - # Address on which instance vncservers will listen on compute hosts. - # For multi-host, this should be the management ip of the compute host. - VNCSERVER_LISTEN=${VNCSERVER_LISTEN=127.0.0.1} - iniset $NOVA_CONF DEFAULT vnc_enabled true - iniset $NOVA_CONF DEFAULT vncserver_listen "$VNCSERVER_LISTEN" - iniset $NOVA_CONF DEFAULT vncserver_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS" + # Address on which instance vncservers will listen on compute hosts. + # For multi-host, this should be the management ip of the compute host. + VNCSERVER_LISTEN=${VNCSERVER_LISTEN=127.0.0.1} + VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=127.0.0.1} + iniset $NOVA_CONF DEFAULT vnc_enabled true + iniset $NOVA_CONF DEFAULT vncserver_listen "$VNCSERVER_LISTEN" + iniset $NOVA_CONF DEFAULT vncserver_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS" else - iniset $NOVA_CONF DEFAULT vnc_enabled false + iniset $NOVA_CONF DEFAULT vnc_enabled false fi if is_service_enabled n-spice; then - # Address on which instance spiceservers will listen on compute hosts. - # For multi-host, this should be the management ip of the compute host. - SPICESERVER_PROXYCLIENT_ADDRESS=${SPICESERVER_PROXYCLIENT_ADDRESS=127.0.0.1} - SPICESERVER_LISTEN=${SPICESERVER_LISTEN=127.0.0.1} - iniset $NOVA_CONF spice enabled true - iniset $NOVA_CONF spice server_listen "$SPICESERVER_LISTEN" - iniset $NOVA_CONF spice server_proxyclient_address "$SPICESERVER_PROXYCLIENT_ADDRESS" + # Address on which instance spiceservers will listen on compute hosts. + # For multi-host, this should be the management ip of the compute host. + SPICESERVER_PROXYCLIENT_ADDRESS=${SPICESERVER_PROXYCLIENT_ADDRESS=127.0.0.1} + SPICESERVER_LISTEN=${SPICESERVER_LISTEN=127.0.0.1} + iniset $NOVA_CONF spice enabled true + iniset $NOVA_CONF spice server_listen "$SPICESERVER_LISTEN" + iniset $NOVA_CONF spice server_proxyclient_address "$SPICESERVER_PROXYCLIENT_ADDRESS" else - iniset $NOVA_CONF spice enabled false + iniset $NOVA_CONF spice enabled false fi iniset $NOVA_CONF DEFAULT ec2_dmz_host "$EC2_DMZ_HOST" @@ -673,36 +605,31 @@ function install_novaclient() { # install_nova() - Collect source and prepare function install_nova() { - if is_service_enabled n-cpu; then - if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then - install_nova_hypervisor - elif [[ "$VIRT_DRIVER" = 'libvirt' ]]; then - if is_ubuntu; then - install_package kvm - install_package libvirt-bin - install_package python-libvirt - elif is_fedora || is_suse; then - install_package kvm - install_package libvirt - install_package libvirt-python - else - exit_distro_not_supported "libvirt installation" - fi + if is_service_enabled n-cpu && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then + install_nova_hypervisor + fi + + if is_service_enabled n-novnc; then + # a websockets/html5 or flash powered VNC console for vm instances + NOVNC_FROM_PACKAGE=`trueorfalse False $NOVNC_FROM_PACKAGE` + if [ "$NOVNC_FROM_PACKAGE" = "True" ]; then + NOVNC_WEB_DIR=/usr/share/novnc + install_package novnc + else + NOVNC_WEB_DIR=$DEST/noVNC + git_clone $NOVNC_REPO $NOVNC_WEB_DIR $NOVNC_BRANCH + fi + fi - # Install and configure **LXC** if specified. LXC is another approach to - # splitting a system into many smaller parts. LXC uses cgroups and chroot - # to simulate multiple systems. - if [[ "$LIBVIRT_TYPE" == "lxc" ]]; then - if is_ubuntu; then - if [[ "$DISTRO" > natty ]]; then - install_package cgroup-lite - fi - else - ### FIXME(dtroyer): figure this out - echo "RPM-based cgroup not implemented yet" - yum_install libcgroup-tools - fi - fi + if is_service_enabled n-spice; then + # a websockets/html5 or flash powered SPICE console for vm instances + SPICE_FROM_PACKAGE=`trueorfalse True $SPICE_FROM_PACKAGE` + if [ "$SPICE_FROM_PACKAGE" = "True" ]; then + SPICE_WEB_DIR=/usr/share/spice-html5 + install_package spice-html5 + else + SPICE_WEB_DIR=$DEST/spice-html5 + git_clone $SPICE_REPO $SPICE_WEB_DIR $SPICE_BRANCH fi fi @@ -722,7 +649,7 @@ function start_nova_api() { screen_it n-api "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-api" echo "Waiting for nova-api to start..." if ! wait_for_service $SERVICE_TIMEOUT http://$SERVICE_HOST:$service_port; then - die $LINENO "nova-api did not start" + die $LINENO "nova-api did not start" fi # Start proxies if enabled @@ -731,49 +658,74 @@ function start_nova_api() { fi } -# start_nova() - Start running processes, including screen -function start_nova() { - NOVA_CONF_BOTTOM=$NOVA_CONF - - # ``screen_it`` checks ``is_service_enabled``, it is not needed here - screen_it n-cond "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-conductor" - +# start_nova_compute() - Start the compute process +function start_nova_compute() { if is_service_enabled n-cell; then - NOVA_CONF_BOTTOM=$NOVA_CELLS_CONF - screen_it n-cond "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-conductor --config-file $NOVA_CELLS_CONF" - screen_it n-cell-region "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cells --config-file $NOVA_CONF" - screen_it n-cell-child "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cells --config-file $NOVA_CELLS_CONF" + local compute_cell_conf=$NOVA_CELLS_CONF + else + local compute_cell_conf=$NOVA_CONF fi if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then + # Enable client side traces for libvirt + local log_filters="1:libvirt 1:qemu 1:conf 1:security 3:event 3:json 3:file 1:util" + local log_outputs="1:file:/var/log/libvirt/libvirtd.log" + # Enable server side traces for libvirtd + if ! grep -q "log_filters=\"$log_filters\"" /etc/libvirt/libvirtd.conf; then + echo "log_filters=\"$log_filters\"" | sudo tee -a /etc/libvirt/libvirtd.conf + fi + if ! grep -q "log_outputs=\"$log_outputs\"" /etc/libvirt/libvirtd.conf; then + echo "log_outputs=\"$log_outputs\"" | sudo tee -a /etc/libvirt/libvirtd.conf + fi + # The group **$LIBVIRT_GROUP** is added to the current user in this script. # Use 'sg' to execute nova-compute as a member of the **$LIBVIRT_GROUP** group. - screen_it n-cpu "cd $NOVA_DIR && sg $LIBVIRT_GROUP '$NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM'" + screen_it n-cpu "cd $NOVA_DIR && sg $LIBVIRT_GROUP '$NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf'" elif [[ "$VIRT_DRIVER" = 'fake' ]]; then - for i in `seq 1 $NUMBER_FAKE_NOVA_COMPUTE` - do - screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM" - done + for i in `seq 1 $NUMBER_FAKE_NOVA_COMPUTE`; do + screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf --config-file <(echo -e '[DEFAULT]\nhost=${HOSTNAME}${i}')" + done else if is_service_enabled n-cpu && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then start_nova_hypervisor fi - screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $NOVA_CONF_BOTTOM" + screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf" + fi +} + +# start_nova() - Start running processes, including screen +function start_nova_rest() { + local api_cell_conf=$NOVA_CONF + if is_service_enabled n-cell; then + local compute_cell_conf=$NOVA_CELLS_CONF + else + local compute_cell_conf=$NOVA_CONF fi - screen_it n-crt "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cert" - screen_it n-net "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-network --config-file $NOVA_CONF_BOTTOM" - screen_it n-sch "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-scheduler --config-file $NOVA_CONF_BOTTOM" - screen_it n-api-meta "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-api-metadata --config-file $NOVA_CONF_BOTTOM" - screen_it n-novnc "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-novncproxy --config-file $NOVA_CONF --web $NOVNC_DIR" - screen_it n-xvnc "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-xvpvncproxy --config-file $NOVA_CONF" - screen_it n-spice "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-spicehtml5proxy --config-file $NOVA_CONF --web $SPICE_DIR" - screen_it n-cauth "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-consoleauth" + # ``screen_it`` checks ``is_service_enabled``, it is not needed here + screen_it n-cond "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-conductor --config-file $compute_cell_conf" + screen_it n-cell-region "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cells --config-file $api_cell_conf" + screen_it n-cell-child "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cells --config-file $compute_cell_conf" + + screen_it n-crt "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-cert --config-file $api_cell_conf" + screen_it n-net "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-network --config-file $compute_cell_conf" + screen_it n-sch "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-scheduler --config-file $compute_cell_conf" + screen_it n-api-meta "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-api-metadata --config-file $compute_cell_conf" + + screen_it n-novnc "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-novncproxy --config-file $api_cell_conf --web $NOVNC_WEB_DIR" + screen_it n-xvnc "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-xvpvncproxy --config-file $api_cell_conf" + screen_it n-spice "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-spicehtml5proxy --config-file $api_cell_conf --web $SPICE_WEB_DIR" + screen_it n-cauth "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-consoleauth --config-file $api_cell_conf" # Starting the nova-objectstore only if swift3 service is not enabled. # Swift will act as s3 objectstore. is_service_enabled swift3 || \ - screen_it n-obj "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-objectstore" + screen_it n-obj "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-objectstore --config-file $api_cell_conf" +} + +function start_nova() { + start_nova_compute + start_nova_rest } # stop_nova() - Stop running processes (non-screen) @@ -781,8 +733,8 @@ function stop_nova() { # Kill the nova screen windows # Some services are listed here twice since more than one instance # of a service may be running in certain configs. - for serv in n-api n-cpu n-crt n-net n-sch n-novnc n-xvnc n-cauth n-spice n-cond n-cond n-cell n-cell n-api-meta; do - screen -S $SCREEN_NAME -p $serv -X kill + for serv in n-api n-cpu n-crt n-net n-sch n-novnc n-xvnc n-cauth n-spice n-cond n-cell n-cell n-api-meta; do + screen_stop $serv done if is_service_enabled n-cpu && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then stop_nova_hypervisor @@ -793,6 +745,7 @@ function stop_nova() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/nova_plugins/hypervisor-baremetal b/lib/nova_plugins/hypervisor-baremetal new file mode 100644 index 0000000000..660c977bde --- /dev/null +++ b/lib/nova_plugins/hypervisor-baremetal @@ -0,0 +1,93 @@ +# lib/nova_plugins/hypervisor-baremetal +# Configure the baremetal hypervisor + +# Enable with: +# VIRT_DRIVER=baremetal + +# Dependencies: +# ``functions`` file +# ``nova`` configuration + +# install_nova_hypervisor - install any external requirements +# configure_nova_hypervisor - make configuration changes, including those to other services +# start_nova_hypervisor - start any external services +# stop_nova_hypervisor - stop any external services +# cleanup_nova_hypervisor - remove transient data and cache + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + +NETWORK_MANAGER=${NETWORK_MANAGER:-FlatManager} +PUBLIC_INTERFACE_DEFAULT=eth0 +FLAT_INTERFACE=${FLAT_INTERFACE:-eth0} +FLAT_NETWORK_BRIDGE_DEFAULT=br100 +STUB_NETWORK=${STUB_NETWORK:-False} + + +# Entry Points +# ------------ + +# clean_nova_hypervisor - Clean up an installation +function cleanup_nova_hypervisor() { + # This function intentionally left blank + : +} + +# configure_nova_hypervisor - Set config files, create data dirs, etc +function configure_nova_hypervisor() { + configure_baremetal_nova_dirs + + iniset $NOVA_CONF baremetal sql_connection `database_connection_url nova_bm` + LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"} + iniset $NOVA_CONF DEFAULT compute_driver nova.virt.baremetal.driver.BareMetalDriver + iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER + iniset $NOVA_CONF DEFAULT scheduler_host_manager nova.scheduler.baremetal_host_manager.BaremetalHostManager + iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0 + iniset $NOVA_CONF DEFAULT reserved_host_memory_mb 0 + iniset $NOVA_CONF baremetal instance_type_extra_specs cpu_arch:$BM_CPU_ARCH + iniset $NOVA_CONF baremetal driver $BM_DRIVER + iniset $NOVA_CONF baremetal power_manager $BM_POWER_MANAGER + iniset $NOVA_CONF baremetal tftp_root /tftpboot + if [[ "$BM_DNSMASQ_FROM_NOVA_NETWORK" = "True" ]]; then + BM_DNSMASQ_CONF=$NOVA_CONF_DIR/dnsmasq-for-baremetal-from-nova-network.conf + sudo cp "$FILES/dnsmasq-for-baremetal-from-nova-network.conf" "$BM_DNSMASQ_CONF" + iniset $NOVA_CONF DEFAULT dnsmasq_config_file "$BM_DNSMASQ_CONF" + fi + + # Define extra baremetal nova conf flags by defining the array ``EXTRA_BAREMETAL_OPTS``. + for I in "${EXTRA_BAREMETAL_OPTS[@]}"; do + # Attempt to convert flags to options + iniset $NOVA_CONF baremetal ${I/=/ } + done +} + +# install_nova_hypervisor() - Install external components +function install_nova_hypervisor() { + # This function intentionally left blank + : +} + +# start_nova_hypervisor - Start any required external services +function start_nova_hypervisor() { + # This function intentionally left blank + : +} + +# stop_nova_hypervisor - Stop any external services +function stop_nova_hypervisor() { + # This function intentionally left blank + : +} + + +# Restore xtrace +$MY_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/nova_plugins/hypervisor-docker b/lib/nova_plugins/hypervisor-docker index 4c8fc279b0..0153953d6c 100644 --- a/lib/nova_plugins/hypervisor-docker +++ b/lib/nova_plugins/hypervisor-docker @@ -2,11 +2,13 @@ # Configure the Docker hypervisor # Enable with: -# VIRT_DRIVER=docker +# +# VIRT_DRIVER=docker # Dependencies: -# ``functions`` file -# ``nova`` and ``glance`` configurations +# +# - ``functions`` file +# - ``nova`` and ``glance`` configurations # install_nova_hypervisor - install any external requirements # configure_nova_hypervisor - make configuration changes, including those to other services @@ -24,8 +26,6 @@ set +o xtrace # Set up default directories DOCKER_DIR=$DEST/docker -DOCKER_REPO=${DOCKER_REPO:-https://github.com/dotcloud/openstack-docker.git} -DOCKER_BRANCH=${DOCKER_BRANCH:-master} DOCKER_UNIX_SOCKET=/var/run/docker.sock DOCKER_PID_FILE=/var/run/docker.pid @@ -37,7 +37,6 @@ DOCKER_REGISTRY_IMAGE=${DOCKER_REGISTRY_IMAGE:-http://get.docker.io/images/opens DOCKER_REGISTRY_IMAGE_NAME=docker-registry DOCKER_REPOSITORY_NAME=${SERVICE_HOST}:${DOCKER_REGISTRY_PORT}/${DOCKER_IMAGE_NAME} -DOCKER_PACKAGE_VERSION=${DOCKER_PACKAGE_VERSION:-0.6.1} DOCKER_APT_REPO=${DOCKER_APT_REPO:-https://get.docker.io/ubuntu} @@ -54,14 +53,8 @@ function cleanup_nova_hypervisor() { # configure_nova_hypervisor - Set config files, create data dirs, etc function configure_nova_hypervisor() { - git_clone $DOCKER_REPO $DOCKER_DIR $DOCKER_BRANCH - - ln -snf ${DOCKER_DIR}/nova-driver $NOVA_DIR/nova/virt/docker - iniset $NOVA_CONF DEFAULT compute_driver docker.DockerDriver iniset $GLANCE_API_CONF DEFAULT container_formats ami,ari,aki,bare,ovf,docker - - sudo cp -p ${DOCKER_DIR}/nova-driver/docker.filters $NOVA_CONF_DIR/rootwrap.d } # install_nova_hypervisor() - Install external components diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt new file mode 100644 index 0000000000..6f90f4ac17 --- /dev/null +++ b/lib/nova_plugins/hypervisor-libvirt @@ -0,0 +1,166 @@ +# lib/nova_plugins/hypervisor-libvirt +# Configure the libvirt hypervisor + +# Enable with: +# VIRT_DRIVER=libvirt + +# Dependencies: +# ``functions`` file +# ``nova`` configuration +# ``STACK_USER`` has to be defined + +# install_nova_hypervisor - install any external requirements +# configure_nova_hypervisor - make configuration changes, including those to other services +# start_nova_hypervisor - start any external services +# stop_nova_hypervisor - stop any external services +# cleanup_nova_hypervisor - remove transient data and cache + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + + +# Entry Points +# ------------ + +# clean_nova_hypervisor - Clean up an installation +function cleanup_nova_hypervisor() { + # This function intentionally left blank + : +} + +# configure_nova_hypervisor - Set config files, create data dirs, etc +function configure_nova_hypervisor() { + if is_service_enabled neutron && is_neutron_ovs_base_plugin && ! sudo grep -q '^cgroup_device_acl' $QEMU_CONF; then + # Add /dev/net/tun to cgroup_device_acls, needed for type=ethernet interfaces + cat </etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla +[libvirt Management Access] +Identity=unix-group:$LIBVIRT_GROUP +Action=org.libvirt.unix.manage +ResultAny=yes +ResultInactive=yes +ResultActive=yes +EOF" + elif is_suse && [[ $os_RELEASE = 12.2 || "$os_VENDOR" = "SUSE LINUX" ]]; then + # openSUSE < 12.3 or SLE + # Work around the fact that polkit-default-privs overrules pklas + # with 'unix-group:$group'. + sudo bash -c "cat </etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla +[libvirt Management Access] +Identity=unix-user:$STACK_USER +Action=org.libvirt.unix.manage +ResultAny=yes +ResultInactive=yes +ResultActive=yes +EOF" + else + # Starting with fedora 18 and opensuse-12.3 enable stack-user to + # virsh -c qemu:///system by creating a policy-kit rule for + # stack-user using the new Javascript syntax + rules_dir=/etc/polkit-1/rules.d + sudo mkdir -p $rules_dir + sudo bash -c "cat < $rules_dir/50-libvirt-$STACK_USER.rules +polkit.addRule(function(action, subject) { + if (action.id == 'org.libvirt.unix.manage' && + subject.user == '"$STACK_USER"') { + return polkit.Result.YES; + } +}); +EOF" + unset rules_dir + fi + fi + + # The user that nova runs as needs to be member of **libvirtd** group otherwise + # nova-compute will be unable to use libvirt. + if ! getent group $LIBVIRT_GROUP >/dev/null; then + sudo groupadd $LIBVIRT_GROUP + fi + add_user_to_group $STACK_USER $LIBVIRT_GROUP + + # libvirt detects various settings on startup, as we potentially changed + # the system configuration (modules, filesystems), we need to restart + # libvirt to detect those changes. + restart_service $LIBVIRT_DAEMON + + iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE" + iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none" + iniset $NOVA_CONF DEFAULT use_usb_tablet "False" + iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver" + LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"} + iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER" + # Power architecture currently does not support graphical consoles. + if is_arch "ppc64"; then + iniset $NOVA_CONF DEFAULT vnc_enabled "false" + fi +} + +# install_nova_hypervisor() - Install external components +function install_nova_hypervisor() { + if is_ubuntu; then + install_package kvm + install_package libvirt-bin + install_package python-libvirt + elif is_fedora || is_suse; then + install_package kvm + install_package libvirt + install_package libvirt-python + fi + + # Install and configure **LXC** if specified. LXC is another approach to + # splitting a system into many smaller parts. LXC uses cgroups and chroot + # to simulate multiple systems. + if [[ "$LIBVIRT_TYPE" == "lxc" ]]; then + if is_ubuntu; then + if [[ "$DISTRO" > natty ]]; then + install_package cgroup-lite + fi + else + ### FIXME(dtroyer): figure this out + echo "RPM-based cgroup not implemented yet" + yum_install libcgroup-tools + fi + fi +} + +# start_nova_hypervisor - Start any required external services +function start_nova_hypervisor() { + # This function intentionally left blank + : +} + +# stop_nova_hypervisor - Stop any external services +function stop_nova_hypervisor() { + # This function intentionally left blank + : +} + + +# Restore xtrace +$MY_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/nova_plugins/hypervisor-openvz b/lib/nova_plugins/hypervisor-openvz new file mode 100644 index 0000000000..fc5ed0cd11 --- /dev/null +++ b/lib/nova_plugins/hypervisor-openvz @@ -0,0 +1,67 @@ +# lib/nova_plugins/hypervisor-openvz +# Configure the openvz hypervisor + +# Enable with: +# VIRT_DRIVER=openvz + +# Dependencies: +# ``functions`` file +# ``nova`` configuration + +# install_nova_hypervisor - install any external requirements +# configure_nova_hypervisor - make configuration changes, including those to other services +# start_nova_hypervisor - start any external services +# stop_nova_hypervisor - stop any external services +# cleanup_nova_hypervisor - remove transient data and cache + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + + +# Entry Points +# ------------ + +# clean_nova_hypervisor - Clean up an installation +function cleanup_nova_hypervisor() { + # This function intentionally left blank + : +} + +# configure_nova_hypervisor - Set config files, create data dirs, etc +function configure_nova_hypervisor() { + iniset $NOVA_CONF DEFAULT compute_driver "openvz.OpenVzDriver" + iniset $NOVA_CONF DEFAULT connection_type "openvz" + LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"} + iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER" +} + +# install_nova_hypervisor() - Install external components +function install_nova_hypervisor() { + # This function intentionally left blank + : +} + +# start_nova_hypervisor - Start any required external services +function start_nova_hypervisor() { + # This function intentionally left blank + : +} + +# stop_nova_hypervisor - Stop any external services +function stop_nova_hypervisor() { + # This function intentionally left blank + : +} + + +# Restore xtrace +$MY_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/nova_plugins/hypervisor-xenserver b/lib/nova_plugins/hypervisor-xenserver new file mode 100644 index 0000000000..f47994f187 --- /dev/null +++ b/lib/nova_plugins/hypervisor-xenserver @@ -0,0 +1,85 @@ +# lib/nova_plugins/hypervisor-xenserver +# Configure the XenServer hypervisor + +# Enable with: +# VIRT_DRIVER=xenserver + +# Dependencies: +# ``functions`` file +# ``nova`` configuration + +# install_nova_hypervisor - install any external requirements +# configure_nova_hypervisor - make configuration changes, including those to other services +# start_nova_hypervisor - start any external services +# stop_nova_hypervisor - stop any external services +# cleanup_nova_hypervisor - remove transient data and cache + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + +PUBLIC_INTERFACE_DEFAULT=eth2 +GUEST_INTERFACE_DEFAULT=eth1 +# Allow ``build_domU.sh`` to specify the flat network bridge via kernel args +FLAT_NETWORK_BRIDGE_DEFAULT=$(sed -e 's/.* flat_network_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline) +if is_service_enabled neutron; then + XEN_INTEGRATION_BRIDGE=$(sed -e 's/.* xen_integration_bridge=\([[:alnum:]]*\).*$/\1/g' /proc/cmdline) +fi + +VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=169.254.0.1} + + +# Entry Points +# ------------ + +# clean_nova_hypervisor - Clean up an installation +function cleanup_nova_hypervisor() { + # This function intentionally left blank + : +} + +# configure_nova_hypervisor - Set config files, create data dirs, etc +function configure_nova_hypervisor() { + if [ -z "$XENAPI_CONNECTION_URL" ]; then + die $LINENO "XENAPI_CONNECTION_URL is not specified" + fi + read_password XENAPI_PASSWORD "ENTER A PASSWORD TO USE FOR XEN." + iniset $NOVA_CONF DEFAULT compute_driver "xenapi.XenAPIDriver" + iniset $NOVA_CONF DEFAULT xenapi_connection_url "$XENAPI_CONNECTION_URL" + iniset $NOVA_CONF DEFAULT xenapi_connection_username "$XENAPI_USER" + iniset $NOVA_CONF DEFAULT xenapi_connection_password "$XENAPI_PASSWORD" + iniset $NOVA_CONF DEFAULT flat_injected "False" + # Need to avoid crash due to new firewall support + XEN_FIREWALL_DRIVER=${XEN_FIREWALL_DRIVER:-"nova.virt.firewall.IptablesFirewallDriver"} + iniset $NOVA_CONF DEFAULT firewall_driver "$XEN_FIREWALL_DRIVER" +} + +# install_nova_hypervisor() - Install external components +function install_nova_hypervisor() { + # This function intentionally left blank + : +} + +# start_nova_hypervisor - Start any required external services +function start_nova_hypervisor() { + # This function intentionally left blank + : +} + +# stop_nova_hypervisor - Stop any external services +function stop_nova_hypervisor() { + # This function intentionally left blank + : +} + + +# Restore xtrace +$MY_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/oslo b/lib/oslo index f77a4fa941..f644ed76c3 100644 --- a/lib/oslo +++ b/lib/oslo @@ -6,11 +6,12 @@ # pre-released versions of oslo libraries. # Dependencies: -# ``functions`` file +# +# - ``functions`` file # ``stack.sh`` calls the entry points in this order: # -# install_oslo +# - install_oslo # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -21,6 +22,7 @@ set +o xtrace # -------- OSLOCFG_DIR=$DEST/oslo.config OSLOMSG_DIR=$DEST/oslo.messaging +OSLORWRAP_DIR=$DEST/oslo.rootwrap # Entry Points # ------------ @@ -36,6 +38,9 @@ function install_oslo() { git_clone $OSLOMSG_REPO $OSLOMSG_DIR $OSLOMSG_BRANCH setup_develop $OSLOMSG_DIR + + git_clone $OSLORWRAP_REPO $OSLORWRAP_DIR $OSLORWRAP_BRANCH + setup_develop $OSLORWRAP_DIR } # cleanup_oslo() - purge possibly old versions of oslo @@ -52,6 +57,7 @@ function cleanup_oslo() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/rpc_backend b/lib/rpc_backend index ff87aae2af..f59c80096f 100644 --- a/lib/rpc_backend +++ b/lib/rpc_backend @@ -3,15 +3,16 @@ # rpc backend settings # Dependencies: -# ``functions`` file -# ``RABBIT_{HOST|PASSWORD}`` must be defined when RabbitMQ is used +# +# - ``functions`` file +# - ``RABBIT_{HOST|PASSWORD}`` must be defined when RabbitMQ is used # ``stack.sh`` calls the entry points in this order: # -# check_rpc_backend -# install_rpc_backend -# restart_rpc_backend -# iniset_rpc_backend +# - check_rpc_backend +# - install_rpc_backend +# - restart_rpc_backend +# - iniset_rpc_backend # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -63,7 +64,7 @@ function cleanup_rpc_backend { if is_service_enabled rabbit; then # Obliterate rabbitmq-server uninstall_package rabbitmq-server - sudo killall epmd + sudo killall epmd || sudo killall -9 epmd if is_ubuntu; then # And the Erlang runtime too sudo aptitude purge -y ~nerlang @@ -86,10 +87,6 @@ function cleanup_rpc_backend { else exit_distro_not_supported "zeromq installation" fi - - # Necessary directory for socket location. - sudo mkdir -p /var/run/openstack - sudo chown $STACK_USER /var/run/openstack fi } @@ -106,9 +103,9 @@ function install_rpc_backend() { if is_fedora; then install_package qpid-cpp-server if [[ $DISTRO =~ (rhel6) ]]; then - # RHEL6 leaves "auth=yes" in /etc/qpidd.conf, it needs to - # be no or you get GSS authentication errors as it - # attempts to default to this. + # RHEL6 leaves "auth=yes" in /etc/qpidd.conf, it needs to + # be no or you get GSS authentication errors as it + # attempts to default to this. sudo sed -i.bak 's/^auth=yes$/auth=no/' /etc/qpidd.conf fi elif is_ubuntu; then @@ -131,6 +128,9 @@ function install_rpc_backend() { else exit_distro_not_supported "zeromq installation" fi + # Necessary directory for socket location. + sudo mkdir -p /var/run/openstack + sudo chown $STACK_USER /var/run/openstack fi } @@ -192,15 +192,15 @@ function qpid_is_supported() { GetDistro fi - # Qpid was introduced to Ubuntu in precise, disallow it on oneiric; it is - # not in openSUSE either right now. - ( ! ([[ "$DISTRO" = "oneiric" ]] || is_suse) ) + # Qpid is not in openSUSE + ( ! is_suse ) } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/savanna b/lib/savanna new file mode 100644 index 0000000000..6f42311971 --- /dev/null +++ b/lib/savanna @@ -0,0 +1,138 @@ +# lib/savanna + +# Dependencies: +# ``functions`` file +# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined + +# ``stack.sh`` calls the entry points in this order: +# +# install_savanna +# configure_savanna +# start_savanna +# stop_savanna + +# Save trace setting +XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + +# Set up default repos +SAVANNA_REPO=${SAVANNA_REPO:-${GIT_BASE}/openstack/savanna.git} +SAVANNA_BRANCH=${SAVANNA_BRANCH:-master} + +# Set up default directories +SAVANNA_DIR=$DEST/savanna +SAVANNA_CONF_DIR=${SAVANNA_CONF_DIR:-/etc/savanna} +SAVANNA_CONF_FILE=${SAVANNA_CONF_DIR}/savanna.conf +SAVANNA_DEBUG=${SAVANNA_DEBUG:-True} + +SAVANNA_SERVICE_HOST=${SAVANNA_SERVICE_HOST:-$SERVICE_HOST} +SAVANNA_SERVICE_PORT=${SAVANNA_SERVICE_PORT:-8386} +SAVANNA_SERVICE_PROTOCOL=${SAVANNA_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL} + +# Support entry points installation of console scripts +if [[ -d $SAVANNA_DIR/bin ]]; then + SAVANNA_BIN_DIR=$SAVANNA_DIR/bin +else + SAVANNA_BIN_DIR=$(get_python_exec_prefix) +fi + +# Tell Tempest this project is present +TEMPEST_SERVICES+=,savanna + + +# Functions +# --------- + +# create_savanna_accounts() - Set up common required savanna accounts +# +# Tenant User Roles +# ------------------------------ +# service savanna admin +function create_savanna_accounts() { + + SERVICE_TENANT=$(keystone tenant-list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }") + ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") + + SAVANNA_USER=$(keystone user-create \ + --name=savanna \ + --pass="$SERVICE_PASSWORD" \ + --tenant-id $SERVICE_TENANT \ + --email=savanna@example.com \ + | grep " id " | get_field 2) + keystone user-role-add \ + --tenant-id $SERVICE_TENANT \ + --user-id $SAVANNA_USER \ + --role-id $ADMIN_ROLE + + if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then + SAVANNA_SERVICE=$(keystone service-create \ + --name=savanna \ + --type=data_processing \ + --description="Savanna Data Processing" \ + | grep " id " | get_field 2) + keystone endpoint-create \ + --region RegionOne \ + --service_id $SAVANNA_SERVICE \ + --publicurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s" \ + --adminurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s" \ + --internalurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s" + fi +} + +# configure_savanna() - Set config files, create data dirs, etc +function configure_savanna() { + + if [[ ! -d $SAVANNA_CONF_DIR ]]; then + sudo mkdir -p $SAVANNA_CONF_DIR + fi + sudo chown $STACK_USER $SAVANNA_CONF_DIR + + # Copy over savanna configuration file and configure common parameters. + cp $SAVANNA_DIR/etc/savanna/savanna.conf.sample $SAVANNA_CONF_FILE + + iniset $SAVANNA_CONF_FILE DEFAULT os_admin_password $SERVICE_PASSWORD + iniset $SAVANNA_CONF_FILE DEFAULT os_admin_username savanna + iniset $SAVANNA_CONF_FILE DEFAULT os_admin_tenant_name $SERVICE_TENANT_NAME + iniset $SAVANNA_CONF_FILE DEFAULT debug $SAVANNA_DEBUG + + iniset $SAVANNA_CONF_FILE database connection `database_connection_url savanna` + + if is_service_enabled neutron; then + iniset $SAVANNA_CONF_FILE DEFAULT use_neutron true + iniset $SAVANNA_CONF_FILE DEFAULT use_floating_ips true + fi + + iniset $SAVANNA_CONF_FILE DEFAULT use_syslog $SYSLOG + + recreate_database savanna utf8 + $SAVANNA_BIN_DIR/savanna-db-manage --config-file $SAVANNA_CONF_FILE upgrade head +} + +# install_savanna() - Collect source and prepare +function install_savanna() { + git_clone $SAVANNA_REPO $SAVANNA_DIR $SAVANNA_BRANCH + setup_develop $SAVANNA_DIR +} + +# start_savanna() - Start running processes, including screen +function start_savanna() { + screen_it savanna "cd $SAVANNA_DIR && $SAVANNA_BIN_DIR/savanna-api --config-file $SAVANNA_CONF_FILE" +} + +# stop_savanna() - Stop running processes +function stop_savanna() { + # Kill the Savanna screen windows + screen -S $SCREEN_NAME -p savanna -X kill +} + + +# Restore xtrace +$XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/savanna-dashboard b/lib/savanna-dashboard new file mode 100644 index 0000000000..7713a78637 --- /dev/null +++ b/lib/savanna-dashboard @@ -0,0 +1,71 @@ +# lib/savanna-dashboard + +# Dependencies: +# +# - ``functions`` file +# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined +# - ``SERVICE_HOST`` + +# ``stack.sh`` calls the entry points in this order: +# +# - install_savanna_dashboard +# - configure_savanna_dashboard +# - cleanup_savanna_dashboard + +# Save trace setting +XTRACE=$(set +o | grep xtrace) +set +o xtrace + +source $TOP_DIR/lib/horizon + +# Defaults +# -------- + +# Set up default repos +SAVANNA_DASHBOARD_REPO=${SAVANNA_DASHBOARD_REPO:-${GIT_BASE}/openstack/savanna-dashboard.git} +SAVANNA_DASHBOARD_BRANCH=${SAVANNA_DASHBOARD_BRANCH:-master} + +SAVANNA_PYTHONCLIENT_REPO=${SAVANNA_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-savannaclient.git} +SAVANNA_PYTHONCLIENT_BRANCH=${SAVANNA_PYTHONCLIENT_BRANCH:-master} + +# Set up default directories +SAVANNA_DASHBOARD_DIR=$DEST/savanna-dashboard +SAVANNA_PYTHONCLIENT_DIR=$DEST/python-savannaclient + +# Functions +# --------- + +function configure_savanna_dashboard() { + + echo -e "SAVANNA_URL = \"http://$SERVICE_HOST:8386/v1.1\"\nAUTO_ASSIGNMENT_ENABLED = False" >> $HORIZON_DIR/openstack_dashboard/local/local_settings.py + echo -e "HORIZON_CONFIG['dashboards'] += ('savanna',)\nINSTALLED_APPS += ('savannadashboard',)" >> $HORIZON_DIR/openstack_dashboard/settings.py + + if is_service_enabled neutron; then + echo -e "SAVANNA_USE_NEUTRON = True" >> $HORIZON_DIR/openstack_dashboard/local/local_settings.py + fi +} + +# install_savanna_dashboard() - Collect source and prepare +function install_savanna_dashboard() { + install_python_savannaclient + git_clone $SAVANNA_DASHBOARD_REPO $SAVANNA_DASHBOARD_DIR $SAVANNA_DASHBOARD_BRANCH + setup_develop $SAVANNA_DASHBOARD_DIR +} + +function install_python_savannaclient() { + git_clone $SAVANNA_PYTHONCLIENT_REPO $SAVANNA_PYTHONCLIENT_DIR $SAVANNA_PYTHONCLIENT_BRANCH + setup_develop $SAVANNA_PYTHONCLIENT_DIR +} + +# Cleanup file settings.py from Savanna +function cleanup_savanna_dashboard() { + sed -i '/savanna/d' $HORIZON_DIR/openstack_dashboard/settings.py +} + +# Restore xtrace +$XTRACE + +# Local variables: +# mode: shell-script +# End: + diff --git a/lib/stackforge b/lib/stackforge new file mode 100644 index 0000000000..718b818ff6 --- /dev/null +++ b/lib/stackforge @@ -0,0 +1,67 @@ +# lib/stackforge +# +# Functions to install stackforge libraries that we depend on so +# that we can try their git versions during devstack gate. +# +# This is appropriate for python libraries that release to pypi and are +# expected to be used beyond OpenStack like, but are requirements +# for core services in global-requirements. +# * wsme +# * pecan +# +# This is not appropriate for stackforge projects which are early stage +# OpenStack tools + +# Dependencies: +# ``functions`` file + +# ``stack.sh`` calls the entry points in this order: +# +# install_stackforge + +# Save trace setting +XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- +WSME_DIR=$DEST/wsme +PECAN_DIR=$DEST/pecan + +# Entry Points +# ------------ + +# install_stackforge() - Collect source and prepare +function install_stackforge() { + # TODO(sdague): remove this once we get to Icehouse, this just makes + # for a smoother transition of existing users. + cleanup_stackforge + + git_clone $WSME_REPO $WSME_DIR $WSME_BRANCH + setup_develop_no_requirements_update $WSME_DIR + + git_clone $PECAN_REPO $PECAN_DIR $PECAN_BRANCH + setup_develop_no_requirements_update $PECAN_DIR +} + +# cleanup_stackforge() - purge possibly old versions of stackforge libraries +function cleanup_stackforge() { + # this means we've got an old version installed, lets get rid of it + # otherwise python hates itself + for lib in wsme pecan; do + if ! python -c "import $lib" 2>/dev/null; then + echo "Found old $lib... removing to ensure consistency" + local PIP_CMD=$(get_pip_command) + pip_install $lib + sudo $PIP_CMD uninstall -y $lib + fi + done +} + +# Restore xtrace +$XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/swift b/lib/swift index 9c80802ba9..afdf995d2e 100644 --- a/lib/swift +++ b/lib/swift @@ -2,22 +2,24 @@ # Functions to control the configuration and operation of the **Swift** service # Dependencies: -# ``functions`` file -# ``apache`` file -# ``DEST``, ``SCREEN_NAME``, `SWIFT_HASH` must be defined -# ``STACK_USER`` must be defined -# ``SWIFT_DATA_DIR`` or ``DATA_DIR`` must be defined -# ``lib/keystone`` file +# +# - ``functions`` file +# - ``apache`` file +# - ``DEST``, ``SCREEN_NAME``, `SWIFT_HASH` must be defined +# - ``STACK_USER`` must be defined +# - ``SWIFT_DATA_DIR`` or ``DATA_DIR`` must be defined +# - ``lib/keystone`` file +# # ``stack.sh`` calls the entry points in this order: # -# install_swift -# _config_swift_apache_wsgi -# configure_swift -# init_swift -# start_swift -# stop_swift -# cleanup_swift -# _cleanup_swift_apache_wsgi +# - install_swift +# - _config_swift_apache_wsgi +# - configure_swift +# - init_swift +# - start_swift +# - stop_swift +# - cleanup_swift +# - _cleanup_swift_apache_wsgi # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -39,6 +41,7 @@ SWIFT3_DIR=$DEST/swift3 # Set ``SWIFT_DATA_DIR`` to the location of swift drives and objects. # Default is the common DevStack data directory. SWIFT_DATA_DIR=${SWIFT_DATA_DIR:-${DATA_DIR}/swift} +SWIFT_DISK_IMAGE=${SWIFT_DATA_DIR}/drives/images/swift.img # Set ``SWIFT_CONF_DIR`` to the location of the configuration files. # Default is ``/etc/swift``. @@ -55,10 +58,10 @@ fi # swift data. Set ``SWIFT_LOOPBACK_DISK_SIZE`` to the disk size in # kilobytes. # Default is 1 gigabyte. -SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=1048576 -# if tempest enabled the default size is 4 Gigabyte. +SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=1G +# if tempest enabled the default size is 6 Gigabyte. if is_service_enabled tempest; then - SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=${SWIFT_LOOPBACK_DISK_SIZE:-4194304} + SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=${SWIFT_LOOPBACK_DISK_SIZE:-6G} fi SWIFT_LOOPBACK_DISK_SIZE=${SWIFT_LOOPBACK_DISK_SIZE:-$SWIFT_LOOPBACK_DISK_SIZE_DEFAULT} @@ -67,6 +70,14 @@ SWIFT_LOOPBACK_DISK_SIZE=${SWIFT_LOOPBACK_DISK_SIZE:-$SWIFT_LOOPBACK_DISK_SIZE_D # Default is ``staticweb, tempurl, formpost`` SWIFT_EXTRAS_MIDDLEWARE=${SWIFT_EXTRAS_MIDDLEWARE:-tempurl formpost staticweb} +# Set ``SWIFT_EXTRAS_MIDDLEWARE_LAST`` to extras middlewares that need to be at +# the end of the pipeline. +SWIFT_EXTRAS_MIDDLEWARE_LAST=${SWIFT_EXTRAS_MIDDLEWARE_LAST} + +# Set ``SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH`` to extras middlewares that need to be at +# the beginning of the pipeline, before authentication middlewares. +SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH=${SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH:-crossdomain} + # The ring uses a configurable number of bits from a path’s MD5 hash as # a partition index that designates a device. The number of bits kept # from the hash is known as the partition power, and 2 to the partition @@ -85,6 +96,13 @@ SWIFT_PARTITION_POWER_SIZE=${SWIFT_PARTITION_POWER_SIZE:-9} SWIFT_REPLICAS=${SWIFT_REPLICAS:-1} SWIFT_REPLICAS_SEQ=$(seq ${SWIFT_REPLICAS}) +# Set ``SWIFT_LOG_TOKEN_LENGTH`` to configure how many characters of an auth +# token should be placed in the logs. When keystone is used with PKI tokens, +# the token values can be huge, seemingly larger the 2K, at the least. We +# restrict it here to a default of 12 characters, which should be enough to +# trace through the logs when looking for its use. +SWIFT_LOG_TOKEN_LENGTH=${SWIFT_LOG_TOKEN_LENGTH:-12} + # Set ``OBJECT_PORT_BASE``, ``CONTAINER_PORT_BASE``, ``ACCOUNT_PORT_BASE`` # Port bases used in port number calclution for the service "nodes" # The specified port number will be used, the additinal ports calculated by @@ -93,23 +111,26 @@ OBJECT_PORT_BASE=${OBJECT_PORT_BASE:-6013} CONTAINER_PORT_BASE=${CONTAINER_PORT_BASE:-6011} ACCOUNT_PORT_BASE=${ACCOUNT_PORT_BASE:-6012} +# Tell Tempest this project is present +TEMPEST_SERVICES+=,swift + # Functions # --------- # cleanup_swift() - Remove residual data files function cleanup_swift() { - rm -f ${SWIFT_CONF_DIR}{*.builder,*.ring.gz,backups/*.builder,backups/*.ring.gz} - if egrep -q ${SWIFT_DATA_DIR}/drives/sdb1 /proc/mounts; then - sudo umount ${SWIFT_DATA_DIR}/drives/sdb1 - fi - if [[ -e ${SWIFT_DATA_DIR}/drives/images/swift.img ]]; then - rm ${SWIFT_DATA_DIR}/drives/images/swift.img - fi - rm -rf ${SWIFT_DATA_DIR}/run/ - if is_apache_enabled_service swift; then - _cleanup_swift_apache_wsgi - fi + rm -f ${SWIFT_CONF_DIR}{*.builder,*.ring.gz,backups/*.builder,backups/*.ring.gz} + if egrep -q ${SWIFT_DATA_DIR}/drives/sdb1 /proc/mounts; then + sudo umount ${SWIFT_DATA_DIR}/drives/sdb1 + fi + if [[ -e ${SWIFT_DISK_IMAGE} ]]; then + rm ${SWIFT_DISK_IMAGE} + fi + rm -rf ${SWIFT_DATA_DIR}/run/ + if is_apache_enabled_service swift; then + _cleanup_swift_apache_wsgi + fi } # _cleanup_swift_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file @@ -187,7 +208,7 @@ function _config_swift_apache_wsgi() { sudo cp ${SWIFT_DIR}/examples/apache2/account-server.template ${apache_vhost_dir}/account-server-${node_number} sudo sed -e " - /^#/d;/^$/d; + /^#/d;/^$/d; s/%PORT%/$account_port/g; s/%SERVICENAME%/account-server-${node_number}/g; s/%APACHE_NAME%/${APACHE_NAME}/g; @@ -197,7 +218,7 @@ function _config_swift_apache_wsgi() { sudo cp ${SWIFT_DIR}/examples/wsgi/account-server.wsgi.template ${SWIFT_APACHE_WSGI_DIR}/account-server-${node_number}.wsgi sudo sed -e " - /^#/d;/^$/d; + /^#/d;/^$/d; s/%SERVICECONF%/account-server\/${node_number}.conf/g; " -i ${SWIFT_APACHE_WSGI_DIR}/account-server-${node_number}.wsgi done @@ -205,7 +226,7 @@ function _config_swift_apache_wsgi() { # configure_swift() - Set config files, create data dirs and loop image function configure_swift() { - local swift_pipeline=" " + local swift_pipeline="${SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH}" local node_number local swift_node_config local swift_log_dir @@ -214,7 +235,7 @@ function configure_swift() { swift-init --run-dir=${SWIFT_DATA_DIR}/run all stop || true sudo mkdir -p ${SWIFT_CONF_DIR}/{object,container,account}-server - sudo chown -R $USER: ${SWIFT_CONF_DIR} + sudo chown -R ${STACK_USER}: ${SWIFT_CONF_DIR} if [[ "$SWIFT_CONF_DIR" != "/etc/swift" ]]; then # Some swift tools are hard-coded to use ``/etc/swift`` and are apparently not going to be fixed. @@ -227,7 +248,7 @@ function configure_swift() { # setup) we configure it with our version of rsync. sed -e " s/%GROUP%/${USER_GROUP}/; - s/%USER%/$USER/; + s/%USER%/${STACK_USER}/; s,%SWIFT_DATA_DIR%,$SWIFT_DATA_DIR,; " $FILES/swift/rsyncd.conf | sudo tee /etc/rsyncd.conf # rsyncd.conf just prepared for 4 nodes @@ -241,7 +262,7 @@ function configure_swift() { cp ${SWIFT_DIR}/etc/proxy-server.conf-sample ${SWIFT_CONFIG_PROXY_SERVER} iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT user - iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT user ${USER} + iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT user ${STACK_USER} iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT swift_dir iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT swift_dir ${SWIFT_CONF_DIR} @@ -255,15 +276,34 @@ function configure_swift() { iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT bind_port ${SWIFT_DEFAULT_BIND_PORT:-8080} + # Devstack is commonly run in a small slow environment, so bump the + # timeouts up. + # node_timeout is how long between read operations a node takes to + # respond to the proxy server + # conn_timeout is all about how long it takes a connect() system call to + # return + iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server node_timeout 120 + iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server conn_timeout 20 + + # Configure Ceilometer + if is_service_enabled ceilometer; then + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:ceilometer use "egg:ceilometer#swift" + SWIFT_EXTRAS_MIDDLEWARE_LAST="${SWIFT_EXTRAS_MIDDLEWARE_LAST} ceilometer" + fi + + # Restrict the length of auth tokens in the swift proxy-server logs. + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:proxy-logging reveal_sensitive_prefix ${SWIFT_LOG_TOKEN_LENGTH} + # By default Swift will be installed with keystone and tempauth middleware # and add the swift3 middleware if its configured for it. The token for - # tempauth would be prefixed with the reseller_prefix setting TEMPAUTH_ the - # token for keystoneauth would have the standard reseller_prefix AUTH_ + # tempauth would be prefixed with the reseller_prefix setting `TEMPAUTH_` the + # token for keystoneauth would have the standard reseller_prefix `AUTH_` if is_service_enabled swift3;then - swift_pipeline=" swift3 s3token " + swift_pipeline+=" swift3 s3token " fi swift_pipeline+=" authtoken keystoneauth tempauth " sed -i "/^pipeline/ { s/tempauth/${swift_pipeline} ${SWIFT_EXTRAS_MIDDLEWARE}/ ;}" ${SWIFT_CONFIG_PROXY_SERVER} + sed -i "/^pipeline/ { s/proxy-server/${SWIFT_EXTRAS_MIDDLEWARE_LAST} proxy-server/ ; }" ${SWIFT_CONFIG_PROXY_SERVER} iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth account_autocreate iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server account_autocreate true @@ -271,16 +311,24 @@ function configure_swift() { iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix "TEMPAUTH" + # Configure Crossdomain + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:crossdomain use "egg:swift#crossdomain" + # Configure Keystone sed -i '/^# \[filter:authtoken\]/,/^# \[filter:keystoneauth\]$/ s/^#[ \t]*//' ${SWIFT_CONFIG_PROXY_SERVER} iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_host $KEYSTONE_AUTH_HOST iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_port $KEYSTONE_AUTH_PORT iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken cafile $KEYSTONE_SSL_CA iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/ iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken admin_tenant_name $SERVICE_TENANT_NAME iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken admin_user swift iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken admin_password $SERVICE_PASSWORD iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken signing_dir $SWIFT_AUTH_CACHE_DIR + # This causes the authtoken middleware to use the same python logging + # adapter provided by the swift proxy-server, so that request transaction + # IDs will included in all of its log messages. + iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:authtoken log_name swift iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:keystoneauth use iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:keystoneauth operator_roles @@ -295,6 +343,7 @@ paste.filter_factory = keystone.middleware.s3_token:filter_factory auth_port = ${KEYSTONE_AUTH_PORT} auth_host = ${KEYSTONE_AUTH_HOST} auth_protocol = ${KEYSTONE_AUTH_PROTOCOL} +cafile = ${KEYSTONE_SSL_CA} auth_token = ${SERVICE_TOKEN} admin_token = ${SERVICE_TOKEN} @@ -306,7 +355,7 @@ EOF cp ${SWIFT_DIR}/etc/swift.conf-sample ${SWIFT_CONF_DIR}/swift.conf iniset ${SWIFT_CONF_DIR}/swift.conf swift-hash swift_hash_path_suffix ${SWIFT_HASH} - # This function generates an object/account/proxy configuration + # This function generates an object/container/account configuration # emulating 4 nodes on different ports function generate_swift_config() { local swift_node_config=$1 @@ -318,7 +367,7 @@ EOF node_path=${SWIFT_DATA_DIR}/${node_number} iniuncomment ${swift_node_config} DEFAULT user - iniset ${swift_node_config} DEFAULT user ${USER} + iniset ${swift_node_config} DEFAULT user ${STACK_USER} iniuncomment ${swift_node_config} DEFAULT bind_port iniset ${swift_node_config} DEFAULT bind_port ${bind_port} @@ -332,6 +381,9 @@ EOF iniuncomment ${swift_node_config} DEFAULT log_facility iniset ${swift_node_config} DEFAULT log_facility LOG_LOCAL${log_facility} + iniuncomment ${swift_node_config} DEFAULT workers + iniset ${swift_node_config} DEFAULT workers 1 + iniuncomment ${swift_node_config} DEFAULT disable_fallocate iniset ${swift_node_config} DEFAULT disable_fallocate true @@ -389,7 +441,7 @@ EOF swift_log_dir=${SWIFT_DATA_DIR}/logs rm -rf ${swift_log_dir} mkdir -p ${swift_log_dir}/hourly - sudo chown -R $USER:adm ${swift_log_dir} + sudo chown -R ${STACK_USER}:adm ${swift_log_dir} sed "s,%SWIFT_LOGDIR%,${swift_log_dir}," $FILES/swift/rsyslog.conf | sudo \ tee /etc/rsyslog.d/10-swift.conf if is_apache_enabled_service swift; then @@ -404,33 +456,32 @@ function create_swift_disk() { # First do a bit of setup by creating the directories and # changing the permissions so we can run it as our user. - USER_GROUP=$(id -g) + USER_GROUP=$(id -g ${STACK_USER}) sudo mkdir -p ${SWIFT_DATA_DIR}/{drives,cache,run,logs} - sudo chown -R $USER:${USER_GROUP} ${SWIFT_DATA_DIR} + sudo chown -R ${STACK_USER}:${USER_GROUP} ${SWIFT_DATA_DIR} # Create a loopback disk and format it to XFS. - if [[ -e ${SWIFT_DATA_DIR}/drives/images/swift.img ]]; then + if [[ -e ${SWIFT_DISK_IMAGE} ]]; then if egrep -q ${SWIFT_DATA_DIR}/drives/sdb1 /proc/mounts; then sudo umount ${SWIFT_DATA_DIR}/drives/sdb1 - sudo rm -f ${SWIFT_DATA_DIR}/drives/images/swift.img + sudo rm -f ${SWIFT_DISK_IMAGE} fi fi mkdir -p ${SWIFT_DATA_DIR}/drives/images - sudo touch ${SWIFT_DATA_DIR}/drives/images/swift.img - sudo chown $USER: ${SWIFT_DATA_DIR}/drives/images/swift.img + sudo touch ${SWIFT_DISK_IMAGE} + sudo chown ${STACK_USER}: ${SWIFT_DISK_IMAGE} - dd if=/dev/zero of=${SWIFT_DATA_DIR}/drives/images/swift.img \ - bs=1024 count=0 seek=${SWIFT_LOOPBACK_DISK_SIZE} + truncate -s ${SWIFT_LOOPBACK_DISK_SIZE} ${SWIFT_DISK_IMAGE} # Make a fresh XFS filesystem - mkfs.xfs -f -i size=1024 ${SWIFT_DATA_DIR}/drives/images/swift.img + mkfs.xfs -f -i size=1024 ${SWIFT_DISK_IMAGE} # Mount the disk with mount options to make it as efficient as possible mkdir -p ${SWIFT_DATA_DIR}/drives/sdb1 if ! egrep -q ${SWIFT_DATA_DIR}/drives/sdb1 /proc/mounts; then sudo mount -t xfs -o loop,noatime,nodiratime,nobarrier,logbufs=8 \ - ${SWIFT_DATA_DIR}/drives/images/swift.img ${SWIFT_DATA_DIR}/drives/sdb1 + ${SWIFT_DISK_IMAGE} ${SWIFT_DATA_DIR}/drives/sdb1 fi # Create a link to the above mount and @@ -442,9 +493,9 @@ function create_swift_disk() { node_device=${node}/sdb1 [[ -d $node ]] && continue [[ -d $drive ]] && continue - sudo install -o ${USER} -g $USER_GROUP -d $drive - sudo install -o ${USER} -g $USER_GROUP -d $node_device - sudo chown -R $USER: ${node} + sudo install -o ${STACK_USER} -g $USER_GROUP -d $drive + sudo install -o ${STACK_USER} -g $USER_GROUP -d $node_device + sudo chown -R ${STACK_USER}: ${node} done } # create_swift_accounts() - Set up standard swift accounts and extra @@ -466,7 +517,7 @@ function create_swift_accounts() { ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") SWIFT_USER=$(keystone user-create --name=swift --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT --email=swift@example.com | grep " id " | get_field 2) + --tenant-id $SERVICE_TENANT --email=swift@example.com | grep " id " | get_field 2) keystone user-role-add --tenant-id $SERVICE_TENANT --user-id $SWIFT_USER --role-id $ADMIN_ROLE if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then @@ -481,14 +532,19 @@ function create_swift_accounts() { fi SWIFT_TENANT_TEST1=$(keystone tenant-create --name=swifttenanttest1 | grep " id " | get_field 2) + die_if_not_set $LINENO SWIFT_TENANT_TEST1 "Failure creating SWIFT_TENANT_TEST1" SWIFT_USER_TEST1=$(keystone user-create --name=swiftusertest1 --pass=testing --email=test@example.com | grep " id " | get_field 2) + die_if_not_set $LINENO SWIFT_USER_TEST1 "Failure creating SWIFT_USER_TEST1" keystone user-role-add --user-id $SWIFT_USER_TEST1 --role-id $ADMIN_ROLE --tenant-id $SWIFT_TENANT_TEST1 SWIFT_USER_TEST3=$(keystone user-create --name=swiftusertest3 --pass=testing3 --email=test3@example.com | grep " id " | get_field 2) + die_if_not_set $LINENO SWIFT_USER_TEST3 "Failure creating SWIFT_USER_TEST3" keystone user-role-add --user-id $SWIFT_USER_TEST3 --role-id $ANOTHER_ROLE --tenant-id $SWIFT_TENANT_TEST1 SWIFT_TENANT_TEST2=$(keystone tenant-create --name=swifttenanttest2 | grep " id " | get_field 2) + die_if_not_set $LINENO SWIFT_TENANT_TEST2 "Failure creating SWIFT_TENANT_TEST2" SWIFT_USER_TEST2=$(keystone user-create --name=swiftusertest2 --pass=testing2 --email=test2@example.com | grep " id " | get_field 2) + die_if_not_set $LINENO SWIFT_USER_TEST2 "Failure creating SWIFT_USER_TEST2" keystone user-role-add --user-id $SWIFT_USER_TEST2 --role-id $ADMIN_ROLE --tenant-id $SWIFT_TENANT_TEST2 } @@ -566,26 +622,26 @@ function start_swift() { return 0 fi - # By default with only one replica we are launching the proxy, - # container, account and object server in screen in foreground and - # other services in background. If we have SWIFT_REPLICAS set to something - # greater than one we first spawn all the swift services then kill the proxy - # service so we can run it in foreground in screen. ``swift-init ... - # {stop|restart}`` exits with '1' if no servers are running, ignore it just - # in case - swift-init --run-dir=${SWIFT_DATA_DIR}/run all restart || true - if [[ ${SWIFT_REPLICAS} == 1 ]]; then + # By default with only one replica we are launching the proxy, + # container, account and object server in screen in foreground and + # other services in background. If we have SWIFT_REPLICAS set to something + # greater than one we first spawn all the swift services then kill the proxy + # service so we can run it in foreground in screen. ``swift-init ... + # {stop|restart}`` exits with '1' if no servers are running, ignore it just + # in case + swift-init --run-dir=${SWIFT_DATA_DIR}/run all restart || true + if [[ ${SWIFT_REPLICAS} == 1 ]]; then todo="object container account" - fi - for type in proxy ${todo}; do - swift-init --run-dir=${SWIFT_DATA_DIR}/run ${type} stop || true - done - screen_it s-proxy "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-proxy-server ${SWIFT_CONF_DIR}/proxy-server.conf -v" - if [[ ${SWIFT_REPLICAS} == 1 ]]; then - for type in object container account; do - screen_it s-${type} "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-${type}-server ${SWIFT_CONF_DIR}/${type}-server/1.conf -v" - done - fi + fi + for type in proxy ${todo}; do + swift-init --run-dir=${SWIFT_DATA_DIR}/run ${type} stop || true + done + screen_it s-proxy "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-proxy-server ${SWIFT_CONF_DIR}/proxy-server.conf -v" + if [[ ${SWIFT_REPLICAS} == 1 ]]; then + for type in object container account; do + screen_it s-${type} "cd $SWIFT_DIR && $SWIFT_DIR/bin/swift-${type}-server ${SWIFT_CONF_DIR}/${type}-server/1.conf -v" + done + fi } # stop_swift() - Stop running processes (non-screen) @@ -599,13 +655,16 @@ function stop_swift() { if type -p swift-init >/dev/null; then swift-init --run-dir=${SWIFT_DATA_DIR}/run all stop || true fi - # Dump the proxy server - sudo pkill -f swift-proxy-server + for type in proxy object container account; do + # Dump all of the servers + pkill -f swift- + done } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/tempest b/lib/tempest index 646d42b8bd..ee996657c2 100644 --- a/lib/tempest +++ b/lib/tempest @@ -2,34 +2,39 @@ # Install and configure Tempest # Dependencies: -# ``functions`` file -# ``lib/nova`` service is running -# -# - ``DEST``, ``FILES`` -# - ``ADMIN_PASSWORD`` -# - ``DEFAULT_IMAGE_NAME`` -# - ``S3_SERVICE_PORT`` -# - ``SERVICE_HOST`` -# - ``BASE_SQL_CONN`` ``lib/database`` declares -# - ``PUBLIC_NETWORK_NAME`` -# - ``Q_USE_NAMESPACE`` -# - ``Q_ROUTER_NAME`` -# - ``VIRT_DRIVER`` -# - ``LIBVIRT_TYPE`` -# - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone +# +# - ``functions`` file +# - ``lib/nova`` service is running +# - Global vars that are assumed to be defined: +# - ``DEST``, ``FILES`` +# - ``ADMIN_PASSWORD`` +# - ``DEFAULT_IMAGE_NAME`` +# - ``S3_SERVICE_PORT`` +# - ``SERVICE_HOST`` +# - ``BASE_SQL_CONN`` ``lib/database`` declares +# - ``PUBLIC_NETWORK_NAME`` +# - ``Q_USE_NAMESPACE`` +# - ``Q_ROUTER_NAME`` +# - ``Q_L3_ENABLED`` +# - ``VIRT_DRIVER`` +# - ``LIBVIRT_TYPE`` +# - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone +# # Optional Dependencies: -# ALT_* (similar vars exists in keystone_data.sh) -# ``LIVE_MIGRATION_AVAILABLE`` -# ``USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION`` -# ``DEFAULT_INSTANCE_TYPE`` -# ``DEFAULT_INSTANCE_USER`` -# ``CINDER_MULTI_LVM_BACKEND`` -# ``HEAT_CREATE_TEST_IMAGE`` +# +# - ``ALT_*`` (similar vars exists in keystone_data.sh) +# - ``LIVE_MIGRATION_AVAILABLE`` +# - ``USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION`` +# - ``DEFAULT_INSTANCE_TYPE`` +# - ``DEFAULT_INSTANCE_USER`` +# - ``CINDER_MULTI_LVM_BACKEND`` +# - ``HEAT_CREATE_TEST_IMAGE`` +# # ``stack.sh`` calls the entry points in this order: # -# install_tempest -# configure_tempest -# init_tempest +# - install_tempest +# - configure_tempest +# - init_tempest # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -48,7 +53,7 @@ TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest} NOVA_SOURCE_DIR=$DEST/nova BUILD_INTERVAL=1 -BUILD_TIMEOUT=400 +BUILD_TIMEOUT=196 BOTO_MATERIALS_PATH="$FILES/images/s3-materials/cirros-0.3.1" @@ -69,12 +74,14 @@ function configure_tempest() { local password local line local flavors + local available_flavors local flavors_ref local flavor_lines local public_network_id local public_router_id local tenant_networks_reachable local boto_instance_type="m1.tiny" + local ssh_connect_method="fixed" # TODO(afazekas): # sudo python setup.py deploy @@ -138,10 +145,24 @@ function configure_tempest() { # If the ``DEFAULT_INSTANCE_TYPE`` not declared, use the new behavior # Tempest creates instane types for himself if [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then - nova flavor-create m1.nano 42 64 0 1 + available_flavors=$(nova flavor-list) + if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then + if is_arch "ppc64"; then + # qemu needs at least 128MB of memory to boot on ppc64 + nova flavor-create m1.nano 42 128 0 1 + else + nova flavor-create m1.nano 42 64 0 1 + fi + fi flavor_ref=42 boto_instance_type=m1.nano - nova flavor-create m1.micro 84 128 0 1 + if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then + if is_arch "ppc64"; then + nova flavor-create m1.micro 84 256 0 1 + else + nova flavor-create m1.micro 84 128 0 1 + fi + fi flavor_ref_alt=84 else # Check Nova for existing flavors and, if set, look for the @@ -182,18 +203,23 @@ function configure_tempest() { if [ "$Q_USE_NAMESPACE" != "False" ]; then tenant_networks_reachable=false + if ! is_service_enabled n-net; then + ssh_connect_method="floating" + fi else tenant_networks_reachable=true fi - if is_service_enabled q-l3; then + ssh_connect_method=${TEMPEST_SSH_CONNECT_METHOD:-$ssh_connect_method} + + if [ "$Q_L3_ENABLED" = "True" ]; then public_network_id=$(neutron net-list | grep $PUBLIC_NETWORK_NAME | \ awk '{print $2}') if [ "$Q_USE_NAMESPACE" == "False" ]; then # If namespaces are disabled, devstack will create a single # public router that tempest should be configured to use. public_router_id=$(neutron router-list | awk "/ $Q_ROUTER_NAME / \ - { print \$2 }") + { print \$2 }") fi fi @@ -230,6 +256,11 @@ function configure_tempest() { # Compute iniset $TEMPEST_CONF compute change_password_available False + # Note(nati) current tempest don't create network for each tenant + # so reuse same tenant for now + if is_service_enabled neutron; then + TEMPEST_ALLOW_TENANT_ISOLATION=${TEMPEST_ALLOW_TENANT_ISOLATION:-False} + fi iniset $TEMPEST_CONF compute allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True} iniset $TEMPEST_CONF compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED iniset $TEMPEST_CONF compute network_for_ssh $PRIVATE_NETWORK_NAME @@ -243,6 +274,7 @@ function configure_tempest() { iniset $TEMPEST_CONF compute flavor_ref_alt $flavor_ref_alt iniset $TEMPEST_CONF compute live_migration_available ${LIVE_MIGRATION_AVAILABLE:-False} iniset $TEMPEST_CONF compute use_block_migration_for_live_migration ${USE_BLOCK_MIGRATION_FOR_LIVE_MIGRATION:-False} + iniset $TEMPEST_CONF compute ssh_connect_method $ssh_connect_method # Compute admin iniset $TEMPEST_CONF "compute-admin" password "$password" # DEPRECATED @@ -251,6 +283,7 @@ function configure_tempest() { iniset $TEMPEST_CONF network tenant_networks_reachable "$tenant_networks_reachable" iniset $TEMPEST_CONF network public_network_id "$public_network_id" iniset $TEMPEST_CONF network public_router_id "$public_router_id" + iniset $TEMPEST_CONF network default_network "$FIXED_RANGE" # boto iniset $TEMPEST_CONF boto ec2_url "http://$SERVICE_HOST:8773/services/Cloud" @@ -261,7 +294,9 @@ function configure_tempest() { iniset $TEMPEST_CONF boto ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # Orchestration test image - if [ $HEAT_CREATE_TEST_IMAGE == "True" ]; then + if [[ ! -z "$HEAT_FETCHED_TEST_IMAGE" ]]; then + iniset $TEMPEST_CONF orchestration image_ref "$HEAT_FETCHED_TEST_IMAGE" + elif [[ "$HEAT_CREATE_TEST_IMAGE" = "True" ]]; then disk_image_create /usr/share/tripleo-image-elements "vm fedora heat-cfntools" "i386" "fedora-vm-heat-cfntools-tempest" iniset $TEMPEST_CONF orchestration image_ref "fedora-vm-heat-cfntools-tempest" fi @@ -290,8 +325,11 @@ function configure_tempest() { # cli iniset $TEMPEST_CONF cli cli_dir $NOVA_BIN_DIR + # Networking + iniset $TEMPEST_CONF network-feature-enabled api_extensions "${NETWORK_API_EXTENSIONS:-all}" + # service_available - for service in nova cinder glance neutron swift heat horizon ; do + for service in ${TEMPEST_SERVICES//,/ }; do if is_service_enabled $service ; then iniset $TEMPEST_CONF service_available $service "True" else @@ -323,15 +361,15 @@ function init_tempest() { local disk_image="$image_dir/${base_image_name}-blank.img" # if the cirros uec downloaded and the system is uec capable if [ -f "$kernel" -a -f "$ramdisk" -a -f "$disk_image" -a "$VIRT_DRIVER" != "openvz" \ - -a \( "$LIBVIRT_TYPE" != "lxc" -o "$VIRT_DRIVER" != "libvirt" \) ]; then - echo "Prepare aki/ari/ami Images" - ( #new namespace - # tenant:demo ; user: demo - source $TOP_DIR/accrc/demo/demo - euca-bundle-image -i "$kernel" --kernel true -d "$BOTO_MATERIALS_PATH" - euca-bundle-image -i "$ramdisk" --ramdisk true -d "$BOTO_MATERIALS_PATH" - euca-bundle-image -i "$disk_image" -d "$BOTO_MATERIALS_PATH" - ) 2>&1 &1 # Dependencies: -# ``functions`` file -# ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined -# +# +# - ``functions`` file +# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined +# - # ``stack.sh`` calls the entry points in this order: # -# install_XXXX -# configure_XXXX -# init_XXXX -# start_XXXX -# stop_XXXX -# cleanup_XXXX +# - install_XXXX +# - configure_XXXX +# - init_XXXX +# - start_XXXX +# - stop_XXXX +# - cleanup_XXXX # Save trace setting XTRACE=$(set +o | grep xtrace) @@ -79,6 +80,7 @@ function stop_XXXX() { # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/tls b/lib/tls index f7dcffa32d..6134fa1bad 100644 --- a/lib/tls +++ b/lib/tls @@ -1,25 +1,29 @@ # lib/tls # Functions to control the configuration and operation of the TLS proxy service -# Dependencies: # !! source _before_ any services that use ``SERVICE_HOST`` -# ``functions`` file -# ``DEST``, ``DATA_DIR`` must be defined -# ``HOST_IP``, ``SERVICE_HOST`` -# ``KEYSTONE_TOKEN_FORMAT`` must be defined +# +# Dependencies: +# +# - ``functions`` file +# - ``DEST``, ``DATA_DIR`` must be defined +# - ``HOST_IP``, ``SERVICE_HOST`` +# - ``KEYSTONE_TOKEN_FORMAT`` must be defined # Entry points: -# configure_CA -# init_CA - -# configure_proxy -# start_tls_proxy +# +# - configure_CA +# - init_CA -# make_root_ca -# make_int_ca -# new_cert $INT_CA_DIR int-server "abc" -# start_tls_proxy HOST_IP 5000 localhost 5000 +# - configure_proxy +# - start_tls_proxy +# - make_root_ca +# - make_int_ca +# - new_cert $INT_CA_DIR int-server "abc" +# - start_tls_proxy HOST_IP 5000 localhost 5000 +# - ensure_certificates +# - is_ssl_enabled_service # Defaults # -------- @@ -306,6 +310,53 @@ function make_root_CA() { } +# Certificate Input Configuration +# =============================== + +# check to see if the service(s) specified are to be SSL enabled. +# +# Multiple services specified as arguments are ``OR``'ed together; the test +# is a short-circuit boolean, i.e it returns on the first match. +# +# Uses global ``SSL_ENABLED_SERVICES`` +function is_ssl_enabled_service() { + services=$@ + for service in ${services}; do + [[ ,${SSL_ENABLED_SERVICES}, =~ ,${service}, ]] && return 0 + done + return 1 +} + + +# Ensure that the certificates for a service are in place. This function does +# not check that a service is SSL enabled, this should already have been +# completed. +# +# The function expects to find a certificate, key and CA certificate in the +# variables {service}_SSL_CERT, {service}_SSL_KEY and {service}_SSL_CA. For +# example for keystone this would be KEYSTONE_SSL_CERT, KEYSTONE_SSL_KEY and +# KEYSTONE_SSL_CA. If it does not find these certificates the program will +# quit. +function ensure_certificates() { + local service=$1 + + local cert_var="${service}_SSL_CERT" + local key_var="${service}_SSL_KEY" + local ca_var="${service}_SSL_CA" + + local cert=${!cert_var} + local key=${!key_var} + local ca=${!ca_var} + + if [[ !($cert && $key && $ca) ]]; then + die $LINENO "Missing either the ${cert_var} ${key_var} or ${ca_var}" \ + "variable to enable SSL for ${service}" + fi + + cat $ca >> $SSL_BUNDLE_FILE +} + + # Proxy Functions # =============== @@ -321,6 +372,7 @@ function start_tls_proxy() { } -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/lib/trove b/lib/trove index e64ca5f6ac..1fd011a530 100644 --- a/lib/trove +++ b/lib/trove @@ -29,9 +29,39 @@ TROVE_DIR=$DEST/trove TROVECLIENT_DIR=$DEST/python-troveclient TROVE_CONF_DIR=/etc/trove TROVE_LOCAL_CONF_DIR=$TROVE_DIR/etc/trove -TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT//v$IDENTITY_API_VERSION TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove} -TROVE_BIN_DIR=/usr/local/bin + +# Support entry points installation of console scripts +if [[ -d $TROVE_DIR/bin ]]; then + TROVE_BIN_DIR=$TROVE_DIR/bin +else + TROVE_BIN_DIR=$(get_python_exec_prefix) +fi + +# Tell Tempest this project is present +TEMPEST_SERVICES+=,trove + + +# Functions +# --------- + +# Test if any Trove services are enabled +# is_trove_enabled +function is_trove_enabled { + [[ ,${ENABLED_SERVICES} =~ ,"tr-" ]] && return 0 + return 1 +} + +# setup_trove_logging() - Adds logging configuration to conf files +function setup_trove_logging() { + local CONF=$1 + iniset $CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL + iniset $CONF DEFAULT use_syslog $SYSLOG + if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then + # Add color to logging output + setup_colorized_logging $CONF DEFAULT tenant user + fi +} # create_trove_accounts() - Set up common required trove accounts @@ -45,14 +75,15 @@ create_trove_accounts() { SERVICE_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }") if [[ "$ENABLED_SERVICES" =~ "trove" ]]; then - TROVE_USER=$(keystone user-create --name=trove \ - --pass="$SERVICE_PASSWORD" \ - --tenant_id $SERVICE_TENANT \ - --email=trove@example.com \ - | grep " id " | get_field 2) + TROVE_USER=$(keystone user-create \ + --name=trove \ + --pass="$SERVICE_PASSWORD" \ + --tenant-id $SERVICE_TENANT \ + --email=trove@example.com \ + | grep " id " | get_field 2) keystone user-role-add --tenant-id $SERVICE_TENANT \ - --user-id $TROVE_USER \ - --role-id $SERVICE_ROLE + --user-id $TROVE_USER \ + --role-id $SERVICE_ROLE if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then TROVE_SERVICE=$(keystone service-create \ --name=trove \ @@ -101,6 +132,7 @@ function configure_trove() { iniset $TROVE_API_PASTE_INI filter:tokenauth auth_host $KEYSTONE_AUTH_HOST iniset $TROVE_API_PASTE_INI filter:tokenauth auth_port $KEYSTONE_AUTH_PORT iniset $TROVE_API_PASTE_INI filter:tokenauth auth_protocol $KEYSTONE_AUTH_PROTOCOL + iniset $TROVE_API_PASTE_INI filter:tokenauth cafile $KEYSTONE_SSL_CA iniset $TROVE_API_PASTE_INI filter:tokenauth admin_tenant_name $SERVICE_TENANT_NAME iniset $TROVE_API_PASTE_INI filter:tokenauth admin_user trove iniset $TROVE_API_PASTE_INI filter:tokenauth admin_password $SERVICE_PASSWORD @@ -109,16 +141,24 @@ function configure_trove() { # (Re)create trove conf files rm -f $TROVE_CONF_DIR/trove.conf rm -f $TROVE_CONF_DIR/trove-taskmanager.conf + rm -f $TROVE_CONF_DIR/trove-conductor.conf + iniset $TROVE_CONF_DIR/trove.conf DEFAULT rabbit_password $RABBIT_PASSWORD iniset $TROVE_CONF_DIR/trove.conf DEFAULT sql_connection `database_connection_url trove` iniset $TROVE_CONF_DIR/trove.conf DEFAULT add_addresses True iniset $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample DEFAULT rabbit_password $RABBIT_PASSWORD iniset $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample DEFAULT sql_connection `database_connection_url trove` + iniset $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample DEFAULT control_exchange trove sed -i "s/localhost/$NETWORK_GATEWAY/g" $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample + setup_trove_logging $TROVE_CONF_DIR/trove.conf + setup_trove_logging $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample + # (Re)create trove taskmanager conf file if needed if is_service_enabled tr-tmgr; then + TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT//v$IDENTITY_API_VERSION + iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT rabbit_password $RABBIT_PASSWORD iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT sql_connection `database_connection_url trove` iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT taskmanager_manager trove.taskmanager.manager.Manager @@ -126,6 +166,19 @@ function configure_trove() { iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT nova_proxy_admin_tenant_name trove iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT nova_proxy_admin_pass $RADMIN_USER_PASS iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT + setup_trove_logging $TROVE_CONF_DIR/trove-taskmanager.conf + fi + + # (Re)create trove conductor conf file if needed + if is_service_enabled tr-cond; then + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT rabbit_password $RABBIT_PASSWORD + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT sql_connection `database_connection_url trove` + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT nova_proxy_admin_user radmin + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT nova_proxy_admin_tenant_name trove + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT nova_proxy_admin_pass $RADMIN_USER_PASS + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT + iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT control_exchange trove + setup_trove_logging $TROVE_CONF_DIR/trove-conductor.conf fi } @@ -145,26 +198,28 @@ function init_trove() { recreate_database trove utf8 #Initialize the trove database - $TROVE_DIR/bin/trove-manage db_sync + $TROVE_BIN_DIR/trove-manage db_sync } # start_trove() - Start running processes, including screen function start_trove() { - screen_it tr-api "cd $TROVE_DIR; bin/trove-api --config-file=$TROVE_CONF_DIR/trove.conf --debug 2>&1" - screen_it tr-tmgr "cd $TROVE_DIR; bin/trove-taskmanager --config-file=$TROVE_CONF_DIR/trove-taskmanager.conf --debug 2>&1" + screen_it tr-api "cd $TROVE_DIR; $TROVE_BIN_DIR/trove-api --config-file=$TROVE_CONF_DIR/trove.conf --debug 2>&1" + screen_it tr-tmgr "cd $TROVE_DIR; $TROVE_BIN_DIR/trove-taskmanager --config-file=$TROVE_CONF_DIR/trove-taskmanager.conf --debug 2>&1" + screen_it tr-cond "cd $TROVE_DIR; $TROVE_BIN_DIR/trove-conductor --config-file=$TROVE_CONF_DIR/trove-conductor.conf --debug 2>&1" } # stop_trove() - Stop running processes function stop_trove() { # Kill the trove screen windows - for serv in tr-api tr-tmgr; do - screen -S $SCREEN_NAME -p $serv -X kill + for serv in tr-api tr-tmgr tr-cond; do + screen_stop $serv done } # Restore xtrace $XTRACE -# Local variables: -# mode: shell-script -# End: +# Tell emacs to use shell-script-mode +## Local variables: +## mode: shell-script +## End: diff --git a/openrc b/openrc index 3de7e3958f..784b00e51b 100644 --- a/openrc +++ b/openrc @@ -18,7 +18,7 @@ if [[ -n "$2" ]]; then fi # Find the other rc files -RC_DIR=$(cd $(dirname "$BASH_SOURCE") && pwd) +RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd) # Import common functions source $RC_DIR/functions @@ -58,6 +58,7 @@ export OS_NO_CACHE=${OS_NO_CACHE:-1} HOST_IP=${HOST_IP:-127.0.0.1} SERVICE_HOST=${SERVICE_HOST:-$HOST_IP} SERVICE_PROTOCOL=${SERVICE_PROTOCOL:-http} +KEYSTONE_AUTH_PROTOCOL=${KEYSTONE_AUTH_PROTOCOL:-$SERVICE_PROTOCOL} # Some exercises call glance directly. On a single-node installation, Glance # should be listening on HOST_IP. If its running elsewhere, it can be set here @@ -71,13 +72,18 @@ export OS_IDENTITY_API_VERSION=${IDENTITY_API_VERSION:-2.0} # the user/tenant has access to - including nova, glance, keystone, swift, ... # We currently recommend using the 2.0 *identity api*. # -export OS_AUTH_URL=$SERVICE_PROTOCOL://$SERVICE_HOST:5000/v${OS_IDENTITY_API_VERSION} +export OS_AUTH_URL=$KEYSTONE_AUTH_PROTOCOL://$SERVICE_HOST:5000/v${OS_IDENTITY_API_VERSION} # Set the pointer to our CA certificate chain. Harmless if TLS is not used. -export OS_CACERT=$INT_CA_DIR/ca-chain.pem +export OS_CACERT=${OS_CACERT:-$INT_CA_DIR/ca-chain.pem} # Currently novaclient needs you to specify the *compute api* version. This # needs to match the config of your catalog returned by Keystone. export NOVA_VERSION=${NOVA_VERSION:-1.1} # In the future this will change names: export COMPUTE_API_VERSION=${COMPUTE_API_VERSION:-$NOVA_VERSION} + +# Currently cinderclient needs you to specify the *volume api* version. This +# needs to match the config of your catalog returned by Keystone. +export CINDER_VERSION=${CINDER_VERSION:-2} +export OS_VOLUME_API_VERSION=${OS_VOLUME_API_VERSION:-$CINDER_VERSION} diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000000..9d9d18661e --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# +# 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. +# +# +# this runs a series of unit tests for devstack to ensure it's functioning + +if [[ -n $@ ]]; then + FILES=$@ +else + LIBS=`find lib -type f | grep -v \.md` + SCRIPTS=`find . -type f -name \*\.sh` + EXTRA="functions" + FILES="$SCRIPTS $LIBS $EXTRA" +fi + +echo "Running bash8..." + +./tools/bash8.py $FILES diff --git a/samples/localrc b/samples/local.conf similarity index 81% rename from samples/localrc rename to samples/local.conf index fd7221a0ae..c8126c22af 100644 --- a/samples/localrc +++ b/samples/local.conf @@ -1,19 +1,22 @@ -# Sample ``localrc`` for user-configurable variables in ``stack.sh`` +# Sample ``local.conf`` for user-configurable variables in ``stack.sh`` # NOTE: Copy this file to the root ``devstack`` directory for it to # work properly. -# ``localrc`` is a user-maintained setings file that is sourced from ``stackrc``. +# ``local.conf`` is a user-maintained setings file that is sourced from ``stackrc``. # This gives it the ability to override any variables set in ``stackrc``. # Also, most of the settings in ``stack.sh`` are written to only be set if no -# value has already been set; this lets ``localrc`` effectively override the +# value has already been set; this lets ``local.conf`` effectively override the # default values. # This is a collection of some of the settings we have found to be useful # in our DevStack development environments. Additional settings are described -# in http://devstack.org/localrc.html +# in http://devstack.org/local.conf.html # These should be considered as samples and are unsupported DevStack code. +# The ``localrc`` section replaces the old ``localrc`` configuration file. +# Note that if ``localrc`` is present it will be used in favor of this section. +[[local|localrc]] # Minimal Contents # ---------------- @@ -22,7 +25,7 @@ # there are a few minimal variables set: # If the ``*_PASSWORD`` variables are not set here you will be prompted to enter -# values for them by ``stack.sh`` and they will be added to ``localrc``. +# values for them by ``stack.sh`` and they will be added to ``local.conf``. ADMIN_PASSWORD=nomoresecrete MYSQL_PASSWORD=stackdb RABBIT_PASSWORD=stackqueue @@ -83,7 +86,8 @@ SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2000f5 # Set this to 1 to save some resources: SWIFT_REPLICAS=1 -# The data for Swift is stored in the source tree by default (``$DEST/swift/data``) -# and can be moved by setting ``SWIFT_DATA_DIR``. The directory will be created +# The data for Swift is stored by default in (``$DEST/data/swift``), +# or (``$DATA_DIR/swift``) if ``DATA_DIR`` has been set, and can be +# moved by setting ``SWIFT_DATA_DIR``. The directory will be created # if it does not exist. SWIFT_DATA_DIR=$DEST/data diff --git a/samples/local.sh b/samples/local.sh index 970cbb97e0..664cb663fe 100755 --- a/samples/local.sh +++ b/samples/local.sh @@ -23,45 +23,47 @@ source $TOP_DIR/stackrc # Destination path for installation ``DEST`` DEST=${DEST:-/opt/stack} +if is_service_enabled nova; then -# Import ssh keys -# --------------- + # Import ssh keys + # --------------- -# Import keys from the current user into the default OpenStack user (usually -# ``demo``) + # Import keys from the current user into the default OpenStack user (usually + # ``demo``) -# Get OpenStack auth -source $TOP_DIR/openrc + # Get OpenStack user auth + source $TOP_DIR/openrc -# Add first keypair found in localhost:$HOME/.ssh -for i in $HOME/.ssh/id_rsa.pub $HOME/.ssh/id_dsa.pub; do - if [[ -r $i ]]; then - nova keypair-add --pub_key=$i `hostname` - break - fi -done + # Add first keypair found in localhost:$HOME/.ssh + for i in $HOME/.ssh/id_rsa.pub $HOME/.ssh/id_dsa.pub; do + if [[ -r $i ]]; then + nova keypair-add --pub_key=$i `hostname` + break + fi + done -# Create A Flavor -# --------------- + # Create A Flavor + # --------------- -# Get OpenStack admin auth -source $TOP_DIR/openrc admin admin + # Get OpenStack admin auth + source $TOP_DIR/openrc admin admin -# Name of new flavor -# set in ``localrc`` with ``DEFAULT_INSTANCE_TYPE=m1.micro`` -MI_NAME=m1.micro + # Name of new flavor + # set in ``localrc`` with ``DEFAULT_INSTANCE_TYPE=m1.micro`` + MI_NAME=m1.micro -# Create micro flavor if not present -if [[ -z $(nova flavor-list | grep $MI_NAME) ]]; then - nova flavor-create $MI_NAME 6 128 0 1 -fi + # Create micro flavor if not present + if [[ -z $(nova flavor-list | grep $MI_NAME) ]]; then + nova flavor-create $MI_NAME 6 128 0 1 + fi -# Other Uses -# ---------- + # Other Uses + # ---------- -# Add tcp/22 and icmp to default security group -nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 -nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 + # Add tcp/22 and icmp to default security group + nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 + nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +fi diff --git a/stack.sh b/stack.sh index 88d55e1ac8..45d47c819c 100755 --- a/stack.sh +++ b/stack.sh @@ -3,7 +3,7 @@ # ``stack.sh`` is an opinionated OpenStack developer installation. It # installs and configures various combinations of **Ceilometer**, **Cinder**, # **Glance**, **Heat**, **Horizon**, **Keystone**, **Nova**, **Neutron**, -# **Swift**, and **Trove** +# and **Swift** # This script allows you to specify configuration options of what git # repositories to use, enabled services, network configuration and various @@ -12,7 +12,7 @@ # developer install. # To keep this script simple we assume you are running on a recent **Ubuntu** -# (12.04 Precise or newer) or **Fedora** (F16 or newer) machine. (It may work +# (12.04 Precise or newer) or **Fedora** (F18 or newer) machine. (It may work # on other platforms but support for those platforms is left to those who added # them to DevStack.) It should work in a VM or physical server. Additionally # we maintain a list of ``apt`` and ``rpm`` dependencies and other configuration @@ -23,12 +23,22 @@ # Make sure custom grep options don't get in the way unset GREP_OPTIONS +# Sanitize language settings to avoid commands bailing out +# with "unsupported locale setting" errors. +unset LANG +unset LANGUAGE +LC_ALL=C +export LC_ALL + # Keep track of the devstack directory TOP_DIR=$(cd $(dirname "$0") && pwd) # Import common functions source $TOP_DIR/functions +# Import config functions +source $TOP_DIR/lib/config + # Determine what system we are running on. This provides ``os_VENDOR``, # ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME`` # and ``DISTRO`` @@ -38,6 +48,25 @@ GetDistro # Global Settings # =============== +# Check for a ``localrc`` section embedded in ``local.conf`` and extract if +# ``localrc`` does not already exist + +# Phase: local +rm -f $TOP_DIR/.localrc.auto +if [[ -r $TOP_DIR/local.conf ]]; then + LRC=$(get_meta_section_files $TOP_DIR/local.conf local) + for lfile in $LRC; do + if [[ "$lfile" == "localrc" ]]; then + if [[ -r $TOP_DIR/localrc ]]; then + warn $LINENO "localrc and local.conf:[[local]] both exist, using localrc" + else + echo "# Generated file, do not edit" >$TOP_DIR/.localrc.auto + get_meta_section $TOP_DIR/local.conf local $lfile >>$TOP_DIR/.localrc.auto + fi + fi + done +fi + # ``stack.sh`` is customizable by setting environment variables. Override a # default setting via export:: # @@ -109,7 +138,7 @@ disable_negated_services # Warn users who aren't on an explicitly supported distro, but allow them to # override check and attempt installation with ``FORCE=yes ./stack`` -if [[ ! ${DISTRO} =~ (oneiric|precise|quantal|raring|saucy|7.0|wheezy|sid|testing|jessie|f16|f17|f18|f19|opensuse-12.2|rhel6) ]]; then +if [[ ! ${DISTRO} =~ (precise|raring|saucy|trusty|7.0|wheezy|sid|testing|jessie|f18|f19|f20|opensuse-12.2|rhel6) ]]; then echo "WARNING: this script has not been tested on $DISTRO" if [[ "$FORCE" != "yes" ]]; then die $LINENO "If you wish to run this script anyway run with FORCE=yes" @@ -150,8 +179,8 @@ fi if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then # Installing Open vSwitch on RHEL6 requires enabling the RDO repo. - RHEL6_RDO_REPO_RPM=${RHEL6_RDO_REPO_RPM:-"http://rdo.fedorapeople.org/openstack/openstack-grizzly/rdo-release-grizzly-3.noarch.rpm"} - RHEL6_RDO_REPO_ID=${RHEL6_RDO_REPO_ID:-"openstack-grizzly"} + RHEL6_RDO_REPO_RPM=${RHEL6_RDO_REPO_RPM:-"http://rdo.fedorapeople.org/openstack-havana/rdo-release-havana.rpm"} + RHEL6_RDO_REPO_ID=${RHEL6_RDO_REPO_ID:-"openstack-havana"} if ! yum repolist enabled $RHEL6_RDO_REPO_ID | grep -q $RHEL6_RDO_REPO_ID; then echo "RDO repo not detected; installing" yum_install $RHEL6_RDO_REPO_RPM || \ @@ -172,66 +201,36 @@ fi # ----------- # OpenStack is designed to be run as a non-root user; Horizon will fail to run -# as **root** since Apache will not serve content from **root** user). If -# ``stack.sh`` is run as **root**, it automatically creates a **stack** user with -# sudo privileges and runs as that user. +# as **root** since Apache will not serve content from **root** user). +# ``stack.sh`` must not be run as **root**. It aborts and suggests one course of +# action to create a suitable user account. if [[ $EUID -eq 0 ]]; then - ROOTSLEEP=${ROOTSLEEP:-10} echo "You are running this script as root." - echo "In $ROOTSLEEP seconds, we will create a user '$STACK_USER' and run as that user" - sleep $ROOTSLEEP - - # Give the non-root user the ability to run as **root** via ``sudo`` - is_package_installed sudo || install_package sudo - if ! getent group $STACK_USER >/dev/null; then - echo "Creating a group called $STACK_USER" - groupadd $STACK_USER - fi - if ! getent passwd $STACK_USER >/dev/null; then - echo "Creating a user called $STACK_USER" - useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USER - fi - - echo "Giving stack user passwordless sudo privileges" - # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one - grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" >> /etc/sudoers - ( umask 226 && echo "$STACK_USER ALL=(ALL) NOPASSWD:ALL" \ - > /etc/sudoers.d/50_stack_sh ) - - echo "Copying files to $STACK_USER user" - STACK_DIR="$DEST/${TOP_DIR##*/}" - cp -r -f -T "$TOP_DIR" "$STACK_DIR" - safe_chown -R $STACK_USER "$STACK_DIR" - cd "$STACK_DIR" - if [[ "$SHELL_AFTER_RUN" != "no" ]]; then - exec sudo -u $STACK_USER bash -l -c "set -e; bash stack.sh; bash" - else - exec sudo -u $STACK_USER bash -l -c "set -e; source stack.sh" - fi + echo "Cut it out." + echo "Really." + echo "If you need an account to run DevStack, do this (as root, heh) to create $STACK_USER:" + echo "$TOP_DIR/tools/create-stack-user.sh" exit 1 -else - # We're not **root**, make sure ``sudo`` is available - is_package_installed sudo || die "Sudo is required. Re-run stack.sh as root ONE TIME ONLY to set up sudo." +fi - # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one - sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers +# We're not **root**, make sure ``sudo`` is available +is_package_installed sudo || install_package sudo - # Set up devstack sudoers - TEMPFILE=`mktemp` - echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE - # Some binaries might be under /sbin or /usr/sbin, so make sure sudo will - # see them by forcing PATH - echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE - chmod 0440 $TEMPFILE - sudo chown root:root $TEMPFILE - sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh +# UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one +sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || + echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers + +# Set up devstack sudoers +TEMPFILE=`mktemp` +echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE +# Some binaries might be under /sbin or /usr/sbin, so make sure sudo will +# see them by forcing PATH +echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE +chmod 0440 $TEMPFILE +sudo chown root:root $TEMPFILE +sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh - # Remove old file - sudo rm -f /etc/sudoers.d/stack_sh_nova -fi # Create the destination directory and ensure it is writable by the user # and read/executable by everybody for daemons (e.g. apache run for horizon) @@ -242,6 +241,13 @@ safe_chmod 0755 $DEST # a basic test for $DEST path permissions (fatal on error unless skipped) check_path_perm_sanity ${DEST} +# Certain services such as rabbitmq require that the local hostname resolves +# correctly. Make sure it exists in /etc/hosts so that is always true. +LOCAL_HOSTNAME=`hostname -s` +if [ -z "`grep ^127.0.0.1 /etc/hosts | grep $LOCAL_HOSTNAME`" ]; then + sudo sed -i "s/\(^127.0.0.1.*\)/\1 $LOCAL_HOSTNAME/" /etc/hosts +fi + # Set ``OFFLINE`` to ``True`` to configure ``stack.sh`` to run cleanly without # Internet access. ``stack.sh`` must have been previously run with Internet # access to install prerequisites and fetch repositories. @@ -268,7 +274,7 @@ safe_chown -R $STACK_USER $DATA_DIR # from either range when attempting to guess the IP to use for the host. # Note that setting FIXED_RANGE may be necessary when running DevStack # in an OpenStack cloud that uses either of these address ranges internally. -FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.224/28} +FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.0/24} FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24} FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256} @@ -292,21 +298,33 @@ SYSLOG_PORT=${SYSLOG_PORT:-516} SYSSTAT_FILE=${SYSSTAT_FILE:-"sysstat.dat"} SYSSTAT_INTERVAL=${SYSSTAT_INTERVAL:-"1"} +PIDSTAT_FILE=${PIDSTAT_FILE:-"pidstat.txt"} +PIDSTAT_INTERVAL=${PIDSTAT_INTERVAL:-"5"} + # Use color for logging output (only available if syslog is not used) LOG_COLOR=`trueorfalse True $LOG_COLOR` # Service startup timeout SERVICE_TIMEOUT=${SERVICE_TIMEOUT:-60} +# Reset the bundle of CA certificates +SSL_BUNDLE_FILE="$DATA_DIR/ca-bundle.pem" +rm -f $SSL_BUNDLE_FILE + # Configure Projects # ================== -# Source project function libraries +# Import apache functions source $TOP_DIR/lib/apache + +# Import TLS functions source $TOP_DIR/lib/tls + +# Source project function libraries source $TOP_DIR/lib/infra source $TOP_DIR/lib/oslo +source $TOP_DIR/lib/stackforge source $TOP_DIR/lib/horizon source $TOP_DIR/lib/keystone source $TOP_DIR/lib/glance @@ -319,13 +337,15 @@ source $TOP_DIR/lib/neutron source $TOP_DIR/lib/baremetal source $TOP_DIR/lib/ldap source $TOP_DIR/lib/ironic -source $TOP_DIR/lib/trove -# Look for Nova hypervisor plugin -NOVA_PLUGINS=$TOP_DIR/lib/nova_plugins -if is_service_enabled nova && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then - # Load plugin - source $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER +# Extras Source +# -------------- + +# Phase: source +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i source + done fi # Set the destination directories for other OpenStack projects @@ -436,6 +456,7 @@ if is_service_enabled s-proxy; then read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH." fi + # Configure logging # ----------------- @@ -592,7 +613,9 @@ echo_summary "Installing package prerequisites" source $TOP_DIR/tools/install_prereqs.sh # Configure an appropriate python environment -$TOP_DIR/tools/install_pip.sh +if [[ "$OFFLINE" != "True" ]]; then + $TOP_DIR/tools/install_pip.sh +fi # Do the ugly hacks for borken packages and distros $TOP_DIR/tools/fixup_stuff.sh @@ -631,6 +654,11 @@ install_infra # Install oslo libraries that have graduated install_oslo +# Install stackforge libraries for testing +if is_service_enabled stackforge_libs; then + install_stackforge +fi + # Install clients libraries install_keystoneclient install_glanceclient @@ -690,16 +718,6 @@ if is_service_enabled nova; then configure_nova fi -if is_service_enabled n-novnc; then - # a websockets/html5 or flash powered VNC console for vm instances - git_clone $NOVNC_REPO $NOVNC_DIR $NOVNC_BRANCH -fi - -if is_service_enabled n-spice; then - # a websockets/html5 or flash powered SPICE console for vm instances - git_clone $SPICE_REPO $SPICE_DIR $SPICE_BRANCH -fi - if is_service_enabled horizon; then # dashboard install_horizon @@ -720,12 +738,6 @@ if is_service_enabled heat; then configure_heat fi -if is_service_enabled trove; then - install_trove - install_troveclient - cleanup_trove -fi - if is_service_enabled tls-proxy; then configure_CA init_CA @@ -736,12 +748,24 @@ fi if is_service_enabled ir-api ir-cond; then install_ironic + install_ironicclient configure_ironic fi +# Extras Install +# -------------- + +# Phase: install +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i stack install + done +fi + if [[ $TRACK_DEPENDS = True ]]; then $DEST/.venv/bin/pip freeze > $DEST/requires-post-pip if ! diff -Nru $DEST/requires-pre-pip $DEST/requires-post-pip > $DEST/requires.diff; then + echo "Detect some changes for installed packages of pip, in depend tracking mode" cat $DEST/requires.diff fi echo "Ran stack.sh in depend tracking mode, bailing out now" @@ -793,6 +817,17 @@ fi restart_rpc_backend +# Export Certicate Authority Bundle +# --------------------------------- + +# If certificates were used and written to the SSL bundle file then these +# should be exported so clients can validate their connections. + +if [ -f $SSL_BUNDLE_FILE ]; then + export OS_CACERT=$SSL_BUNDLE_FILE +fi + + # Configure database # ------------------ @@ -832,15 +867,34 @@ init_service_check # ------- # If enabled, systat has to start early to track OpenStack service startup. -if is_service_enabled sysstat;then +if is_service_enabled sysstat; then + # what we want to measure + # -u : cpu statitics + # -q : load + # -b : io load rates + # -w : process creation and context switch rates + SYSSTAT_OPTS="-u -q -b -w" + if [[ -n ${SCREEN_LOGDIR} ]]; then + screen_it sysstat "cd $TOP_DIR; ./tools/sar_filter.py $SYSSTAT_OPTS -o $SCREEN_LOGDIR/$SYSSTAT_FILE $SYSSTAT_INTERVAL" + else + screen_it sysstat "./tools/sar_filter.py $SYSSTAT_OPTS $SYSSTAT_INTERVAL" + fi +fi + +if is_service_enabled pidstat; then + # Per-process stats + PIDSTAT_OPTS="-l -p ALL -T ALL" if [[ -n ${SCREEN_LOGDIR} ]]; then - screen_it sysstat "sar -o $SCREEN_LOGDIR/$SYSSTAT_FILE $SYSSTAT_INTERVAL" + screen_it pidstat "cd $TOP_DIR; pidstat $PIDSTAT_OPTS $PIDSTAT_INTERVAL > $SCREEN_LOGDIR/$PIDSTAT_FILE" else - screen_it sysstat "sar $SYSSTAT_INTERVAL" + screen_it pidstat "pidstat $PIDSTAT_OPTS $PIDSTAT_INTERVAL" fi fi +# Start Services +# ============== + # Keystone # -------- @@ -866,8 +920,8 @@ if is_service_enabled key; then create_cinder_accounts create_neutron_accounts - if is_service_enabled trove; then - create_trove_accounts + if is_service_enabled ceilometer; then + create_ceilometer_accounts fi if is_service_enabled swift || is_service_enabled s-proxy; then @@ -911,6 +965,7 @@ if is_service_enabled g-reg; then init_glance fi + # Ironic # ------ @@ -919,6 +974,7 @@ if is_service_enabled ir-api ir-cond; then init_ironic fi + # Neutron # ------- @@ -944,11 +1000,6 @@ fi # Nova # ---- -if is_service_enabled nova; then - echo_summary "Configuring Nova" - configure_nova -fi - if is_service_enabled n-net q-dhcp; then # Delete traces of nova networks from prior runs # Do not kill any dnsmasq instance spawned by NetworkManager @@ -991,8 +1042,6 @@ fi if is_service_enabled nova; then echo_summary "Configuring Nova" - # Rebuild the config file from scratch - create_nova_conf init_nova # Additional Nova configuration that is dependent on other services @@ -1002,104 +1051,6 @@ if is_service_enabled nova; then create_nova_conf_nova_network fi - - if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then - # Configure hypervisor plugin - configure_nova_hypervisor - - - # XenServer - # --------- - - elif [ "$VIRT_DRIVER" = 'xenserver' ]; then - echo_summary "Using XenServer virtualization driver" - if [ -z "$XENAPI_CONNECTION_URL" ]; then - die $LINENO "XENAPI_CONNECTION_URL is not specified" - fi - read_password XENAPI_PASSWORD "ENTER A PASSWORD TO USE FOR XEN." - iniset $NOVA_CONF DEFAULT compute_driver "xenapi.XenAPIDriver" - iniset $NOVA_CONF DEFAULT xenapi_connection_url "$XENAPI_CONNECTION_URL" - iniset $NOVA_CONF DEFAULT xenapi_connection_username "$XENAPI_USER" - iniset $NOVA_CONF DEFAULT xenapi_connection_password "$XENAPI_PASSWORD" - iniset $NOVA_CONF DEFAULT flat_injected "False" - # Need to avoid crash due to new firewall support - XEN_FIREWALL_DRIVER=${XEN_FIREWALL_DRIVER:-"nova.virt.firewall.IptablesFirewallDriver"} - iniset $NOVA_CONF DEFAULT firewall_driver "$XEN_FIREWALL_DRIVER" - - - # OpenVZ - # ------ - - elif [ "$VIRT_DRIVER" = 'openvz' ]; then - echo_summary "Using OpenVZ virtualization driver" - iniset $NOVA_CONF DEFAULT compute_driver "openvz.OpenVzDriver" - iniset $NOVA_CONF DEFAULT connection_type "openvz" - LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"} - iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER" - - - # Bare Metal - # ---------- - - elif [ "$VIRT_DRIVER" = 'baremetal' ]; then - echo_summary "Using BareMetal driver" - LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.firewall.NoopFirewallDriver"} - iniset $NOVA_CONF DEFAULT compute_driver nova.virt.baremetal.driver.BareMetalDriver - iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER - iniset $NOVA_CONF DEFAULT scheduler_host_manager nova.scheduler.baremetal_host_manager.BaremetalHostManager - iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0 - iniset $NOVA_CONF DEFAULT reserved_host_memory_mb 0 - iniset $NOVA_CONF baremetal instance_type_extra_specs cpu_arch:$BM_CPU_ARCH - iniset $NOVA_CONF baremetal driver $BM_DRIVER - iniset $NOVA_CONF baremetal power_manager $BM_POWER_MANAGER - iniset $NOVA_CONF baremetal tftp_root /tftpboot - if [[ "$BM_DNSMASQ_FROM_NOVA_NETWORK" = "True" ]]; then - BM_DNSMASQ_CONF=$NOVA_CONF_DIR/dnsmasq-for-baremetal-from-nova-network.conf - sudo cp "$FILES/dnsmasq-for-baremetal-from-nova-network.conf" "$BM_DNSMASQ_CONF" - iniset $NOVA_CONF DEFAULT dnsmasq_config_file "$BM_DNSMASQ_CONF" - fi - - # Define extra baremetal nova conf flags by defining the array ``EXTRA_BAREMETAL_OPTS``. - for I in "${EXTRA_BAREMETAL_OPTS[@]}"; do - # Attempt to convert flags to options - iniset $NOVA_CONF baremetal ${I/=/ } - done - - - # PowerVM - # ------- - - elif [ "$VIRT_DRIVER" = 'powervm' ]; then - echo_summary "Using PowerVM driver" - POWERVM_MGR_TYPE=${POWERVM_MGR_TYPE:-"ivm"} - POWERVM_MGR_HOST=${POWERVM_MGR_HOST:-"powervm.host"} - POWERVM_MGR_USER=${POWERVM_MGR_USER:-"padmin"} - POWERVM_MGR_PASSWD=${POWERVM_MGR_PASSWD:-"password"} - POWERVM_IMG_REMOTE_PATH=${POWERVM_IMG_REMOTE_PATH:-"/tmp"} - POWERVM_IMG_LOCAL_PATH=${POWERVM_IMG_LOCAL_PATH:-"/tmp"} - iniset $NOVA_CONF DEFAULT compute_driver nova.virt.powervm.PowerVMDriver - iniset $NOVA_CONF DEFAULT powervm_mgr_type $POWERVM_MGR_TYPE - iniset $NOVA_CONF DEFAULT powervm_mgr $POWERVM_MGR_HOST - iniset $NOVA_CONF DEFAULT powervm_mgr_user $POWERVM_MGR_USER - iniset $NOVA_CONF DEFAULT powervm_mgr_passwd $POWERVM_MGR_PASSWD - iniset $NOVA_CONF DEFAULT powervm_img_remote_path $POWERVM_IMG_REMOTE_PATH - iniset $NOVA_CONF DEFAULT powervm_img_local_path $POWERVM_IMG_LOCAL_PATH - - - # Default libvirt - # --------------- - - else - echo_summary "Using libvirt virtualization driver" - iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver" - LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"} - iniset $NOVA_CONF DEFAULT firewall_driver "$LIBVIRT_FIREWALL_DRIVER" - # Power architecture currently does not support graphical consoles. - if is_arch "ppc64"; then - iniset $NOVA_CONF DEFAULT vnc_enabled "false" - fi - fi - init_nova_cells fi @@ -1109,11 +1060,30 @@ if is_service_enabled nova && is_baremetal; then prepare_baremetal_toolchain configure_baremetal_nova_dirs if [[ "$BM_USE_FAKE_ENV" = "True" ]]; then - create_fake_baremetal_env + create_fake_baremetal_env fi fi +# Extras Configuration +# ==================== + +# Phase: post-config +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i stack post-config + done +fi + + +# Local Configuration +# =================== + +# Apply configuration from local.conf if it exists for layer 2 services +# Phase: post-config +merge_config_group $TOP_DIR/local.conf post-config + + # Launch Services # =============== @@ -1140,8 +1110,10 @@ fi # Create an access key and secret key for nova ec2 register image if is_service_enabled key && is_service_enabled swift3 && is_service_enabled nova; then NOVA_USER_ID=$(keystone user-list | grep ' nova ' | get_field 1) + die_if_not_set $LINENO NOVA_USER_ID "Failure retrieving NOVA_USER_ID for nova" NOVA_TENANT_ID=$(keystone tenant-list | grep " $SERVICE_TENANT_NAME " | get_field 1) - CREDS=$(keystone ec2-credentials-create --user_id $NOVA_USER_ID --tenant_id $NOVA_TENANT_ID) + die_if_not_set $LINENO NOVA_TENANT_ID "Failure retrieving NOVA_TENANT_ID for $SERVICE_TENANT_NAME" + CREDS=$(keystone ec2-credentials-create --user-id $NOVA_USER_ID --tenant-id $NOVA_TENANT_ID) ACCESS_KEY=$(echo "$CREDS" | awk '/ access / { print $4 }') SECRET_KEY=$(echo "$CREDS" | awk '/ secret / { print $4 }') iniset $NOVA_CONF DEFAULT s3_access_key "$ACCESS_KEY" @@ -1149,6 +1121,15 @@ if is_service_enabled key && is_service_enabled swift3 && is_service_enabled nov iniset $NOVA_CONF DEFAULT s3_affix_tenant "True" fi +# Create a randomized default value for the keymgr's fixed_key +if is_service_enabled nova; then + FIXED_KEY="" + for i in $(seq 1 64); + do FIXED_KEY+=$(echo "obase=16; $(($RANDOM % 16))" | bc); + done; + iniset $NOVA_CONF keymgr fixed_key "$FIXED_KEY" +fi + if is_service_enabled zeromq; then echo_summary "Starting zermomq receiver" screen_it zeromq "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-rpc-zmq-receiver" @@ -1160,6 +1141,35 @@ if is_service_enabled n-api; then start_nova_api fi +if is_service_enabled q-svc; then + echo_summary "Starting Neutron" + start_neutron_service_and_check + check_neutron_third_party_integration +elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then + NM_CONF=${NOVA_CONF} + if is_service_enabled n-cell; then + NM_CONF=${NOVA_CELLS_CONF} + fi + + # Create a small network + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS + + # Create some floating ips + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME + + # Create a second pool + $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL +fi + +if is_service_enabled neutron; then + start_neutron_agents +fi +# Once neutron agents are started setup initial network elements +if is_service_enabled q-svc; then + echo_summary "Creating initial neutron network elements" + create_neutron_initial_network + setup_neutron_debug +fi if is_service_enabled nova; then echo_summary "Starting Nova" start_nova @@ -1183,18 +1193,6 @@ if is_service_enabled heat; then start_heat fi -# Configure and launch the trove service api, and taskmanager -if is_service_enabled trove; then - # Initialize trove - echo_summary "Configuring Trove" - configure_troveclient - configure_trove - init_trove - - # Start the trove API and trove taskmgr components - echo_summary "Starting Trove" - start_trove -fi # Create account rc files # ======================= @@ -1204,7 +1202,13 @@ fi # which is helpful in image bundle steps. if is_service_enabled nova && is_service_enabled key; then - $TOP_DIR/tools/create_userrc.sh -PA --target-dir $TOP_DIR/accrc + USERRC_PARAMS="-PA --target-dir $TOP_DIR/accrc" + + if [ -f $SSL_BUNDLE_FILE ]; then + USERRC_PARAMS="$USERRC_PARAMS --os-cacert $SSL_BUNDLE_FILE" + fi + + $TOP_DIR/tools/create_userrc.sh $USERRC_PARAMS fi @@ -1219,33 +1223,33 @@ fi # See https://help.ubuntu.com/community/CloudInit for more on cloud-init # # Override ``IMAGE_URLS`` with a comma-separated list of UEC images. -# * **oneiric**: http://uec-images.ubuntu.com/oneiric/current/oneiric-server-cloudimg-amd64.tar.gz # * **precise**: http://uec-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64.tar.gz if is_service_enabled g-reg; then TOKEN=$(keystone token-get | grep ' id ' | get_field 2) + die_if_not_set $LINENO TOKEN "Keystone fail to get token" if is_baremetal; then - echo_summary "Creating and uploading baremetal images" + echo_summary "Creating and uploading baremetal images" - # build and upload separate deploy kernel & ramdisk - upload_baremetal_deploy $TOKEN + # build and upload separate deploy kernel & ramdisk + upload_baremetal_deploy $TOKEN - # upload images, separating out the kernel & ramdisk for PXE boot - for image_url in ${IMAGE_URLS//,/ }; do - upload_baremetal_image $image_url $TOKEN - done + # upload images, separating out the kernel & ramdisk for PXE boot + for image_url in ${IMAGE_URLS//,/ }; do + upload_baremetal_image $image_url $TOKEN + done else - echo_summary "Uploading images" + echo_summary "Uploading images" - # Option to upload legacy ami-tty, which works with xenserver - if [[ -n "$UPLOAD_LEGACY_TTY" ]]; then - IMAGE_URLS="${IMAGE_URLS:+${IMAGE_URLS},}https://github.com/downloads/citrix-openstack/warehouse/tty.tgz" - fi + # Option to upload legacy ami-tty, which works with xenserver + if [[ -n "$UPLOAD_LEGACY_TTY" ]]; then + IMAGE_URLS="${IMAGE_URLS:+${IMAGE_URLS},}https://github.com/downloads/citrix-openstack/warehouse/tty.tgz" + fi - for image_url in ${IMAGE_URLS//,/ }; do - upload_image $image_url $TOKEN - done + for image_url in ${IMAGE_URLS//,/ }; do + upload_image $image_url $TOKEN + done fi fi @@ -1257,7 +1261,7 @@ fi if is_service_enabled nova && is_baremetal; then # create special flavor for baremetal if we know what images to associate [[ -n "$BM_DEPLOY_KERNEL_ID" ]] && [[ -n "$BM_DEPLOY_RAMDISK_ID" ]] && \ - create_baremetal_flavor $BM_DEPLOY_KERNEL_ID $BM_DEPLOY_RAMDISK_ID + create_baremetal_flavor $BM_DEPLOY_KERNEL_ID $BM_DEPLOY_RAMDISK_ID # otherwise user can manually add it later by calling nova-baremetal-manage [[ -n "$BM_FIRST_MAC" ]] && add_baremetal_node @@ -1272,27 +1276,43 @@ if is_service_enabled nova && is_baremetal; then fi # ensure callback daemon is running sudo pkill nova-baremetal-deploy-helper || true - screen_it baremetal "nova-baremetal-deploy-helper" + screen_it baremetal "cd ; nova-baremetal-deploy-helper" fi # Save some values we generated for later use CURRENT_RUN_TIME=$(date "+$TIMESTAMP_FORMAT") echo "# $CURRENT_RUN_TIME" >$TOP_DIR/.stackenv for i in BASE_SQL_CONN ENABLED_SERVICES HOST_IP LOGFILE \ - SERVICE_HOST SERVICE_PROTOCOL STACK_USER TLS_IP; do + SERVICE_HOST SERVICE_PROTOCOL STACK_USER TLS_IP KEYSTONE_AUTH_PROTOCOL OS_CACERT; do echo $i=${!i} >>$TOP_DIR/.stackenv done +# Local Configuration +# =================== + +# Apply configuration from local.conf if it exists for layer 2 services +# Phase: extra +merge_config_group $TOP_DIR/local.conf extra + + # Run extras # ========== +# Phase: extra if [[ -d $TOP_DIR/extras.d ]]; then for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i stack + [[ -r $i ]] && source $i stack extra done fi +# Local Configuration +# =================== + +# Apply configuration from local.conf if it exists for layer 2 services +# Phase: post-extra +merge_config_group $TOP_DIR/local.conf post-extra + # Run local script # ================ @@ -1306,31 +1326,6 @@ fi # Check the status of running services service_check -if is_service_enabled q-svc; then - echo_summary "Starting Neutron" - - start_neutron_service_and_check - create_neutron_initial_network - setup_neutron_debug -elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then - NM_CONF=${NOVA_CONF} - if is_service_enabled n-cell; then - NM_CONF=${NOVA_CELLS_CONF} - fi - - # Create a small network - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS - - # Create some floating ips - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME - - # Create a second pool - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL -fi - -if is_service_enabled neutron; then - start_neutron_agents -fi # Fin # === @@ -1381,5 +1376,66 @@ if [[ -n "$DEPRECATED_TEXT" ]]; then echo_summary "WARNING: $DEPRECATED_TEXT" fi +# Specific warning for deprecated configs +if [[ -n "$EXTRA_OPTS" ]]; then + echo "" + echo_summary "WARNING: EXTRA_OPTS is used" + echo "You are using EXTRA_OPTS to pass configuration into nova.conf." + echo "Please convert that configuration in localrc to a nova.conf section in local.conf:" + echo " +[[post-config|\$NOVA_CONF]] +[DEFAULT] +" + for I in "${EXTRA_OPTS[@]}"; do + # Replace the first '=' with ' ' for iniset syntax + echo ${I} + done +fi + +if [[ -n "$EXTRA_BAREMETAL_OPTS" ]]; then + echo "" + echo_summary "WARNING: EXTRA_OPTS is used" + echo "You are using EXTRA_OPTS to pass configuration into nova.conf." + echo "Please convert that configuration in localrc to a nova.conf section in local.conf:" + echo " +[[post-config|\$NOVA_CONF]] +[baremetal] +" + for I in "${EXTRA_BAREMETAL_OPTS[@]}"; do + # Replace the first '=' with ' ' for iniset syntax + echo ${I} + done +fi + +if [[ -n "$Q_DHCP_EXTRA_DEFAULT_OPTS" ]]; then + echo "" + echo_summary "WARNING: Q_DHCP_EXTRA_DEFAULT_OPTS is used" + echo "You are using Q_DHCP_EXTRA_DEFAULT_OPTS to pass configuration into $Q_DHCP_CONF_FILE." + echo "Please convert that configuration in localrc to a $Q_DHCP_CONF_FILE section in local.conf:" + echo " +[[post-config|\$Q_DHCP_CONF_FILE]] +[DEFAULT] +" + for I in "${Q_DHCP_EXTRA_DEFAULT_OPTS[@]}"; do + # Replace the first '=' with ' ' for iniset syntax + echo ${I} + done +fi + +if [[ -n "$Q_SRV_EXTRA_DEFAULT_OPTS" ]]; then + echo "" + echo_summary "WARNING: Q_SRV_EXTRA_DEFAULT_OPTS is used" + echo "You are using Q_SRV_EXTRA_DEFAULT_OPTS to pass configuration into $NEUTRON_CONF." + echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:" + echo " +[[post-config|\$NEUTRON_CONF]] +[DEFAULT] +" + for I in "${Q_SRV_EXTRA_DEFAULT_OPTS[@]}"; do + # Replace the first '=' with ' ' for iniset syntax + echo ${I} + done +fi + # Indicate how long this took to run (bash maintained variable ``SECONDS``) echo_summary "stack.sh completed in $SECONDS seconds." diff --git a/stackrc b/stackrc index 9d5d37b393..197b4cfc46 100644 --- a/stackrc +++ b/stackrc @@ -1,7 +1,7 @@ # stackrc # # Find the other rc files -RC_DIR=$(cd $(dirname "$BASH_SOURCE") && pwd) +RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd) # Destination path for installation DEST=/opt/stack @@ -9,6 +9,9 @@ DEST=/opt/stack # Destination for working data DATA_DIR=${DEST}/data +# Destination for status files +SERVICE_DIR=${DEST}/status + # Determine stack user if [[ $EUID -eq 0 ]]; then STACK_USER=stack @@ -33,8 +36,12 @@ fi # # Optional, to enable tempest configuration as part of devstack # enable_service tempest ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,cinder,c-sch,c-api,c-vol,n-sch,n-novnc,n-xvnc,n-cauth,horizon,rabbit,tempest,mysql -ENABLED_SERVICES=$ENABLED_SERVICES,cass,ifmap,apiSrv,schema,svc-mon,zk,control,agent,disco,vif,redis -ENABLED_SERVICES=$ENABLED_SERVICES,redis-u,redis-q,redis-s,vizd,opserver,qed + +# Tell Tempest which services are available. The default is set here as +# Tempest falls late in the configuration sequence. This differs from +# ``ENABLED_SERVICES`` in that the project names are used here rather than +# the service names, i.e.: TEMPEST_SERVICES="key,glance,nova" +TEMPEST_SERVICES="" # Set the default Nova APIs to enable NOVA_ENABLED_APIS=ec2,osapi_compute,metadata @@ -50,8 +57,12 @@ IDENTITY_API_VERSION=2.0 USE_SCREEN=True # allow local overrides of env variables, including repo config -if [ -f $RC_DIR/localrc ]; then +if [[ -f $RC_DIR/localrc ]]; then + # Old-style user-supplied config source $RC_DIR/localrc +elif [[ -f $RC_DIR/.localrc.auto ]]; then + # New-style user-supplied config extracted from local.conf + source $RC_DIR/.localrc.auto fi @@ -60,7 +71,7 @@ fi # Base GIT Repo URL # Another option is http://review.openstack.org/p -GIT_BASE=${GIT_BASE:-https://github.com} +GIT_BASE=${GIT_BASE:-git://git.openstack.org} # metering service CEILOMETER_REPO=${CEILOMETER_REPO:-${GIT_BASE}/openstack/ceilometer.git} @@ -102,6 +113,10 @@ HORIZON_BRANCH=${HORIZON_BRANCH:-master} IRONIC_REPO=${IRONIC_REPO:-${GIT_BASE}/openstack/ironic.git} IRONIC_BRANCH=${IRONIC_BRANCH:-master} +# ironic client +IRONICCLIENT_REPO=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git} +IRONICCLIENT_BRANCH=${IRONICCLIENT_BRANCH:-master} + # unified auth system (manages accounts/tokens) KEYSTONE_REPO=${KEYSTONE_REPO:-${GIT_BASE}/openstack/keystone.git} KEYSTONE_BRANCH=${KEYSTONE_BRANCH:-master} @@ -130,6 +145,10 @@ OSLOCFG_BRANCH=${OSLOCFG_BRANCH:-master} OSLOMSG_REPO=${OSLOMSG_REPO:-${GIT_BASE}/openstack/oslo.messaging.git} OSLOMSG_BRANCH=${OSLOMSG_BRANCH:-master} +# oslo.rootwrap +OSLORWRAP_REPO=${OSLORWRAP_REPO:-${GIT_BASE}/openstack/oslo.rootwrap.git} +OSLORWRAP_BRANCH=${OSLORWRAP_BRANCH:-master} + # pbr drives the setuptools configs PBR_REPO=${PBR_REPO:-${GIT_BASE}/openstack-dev/pbr.git} PBR_BRANCH=${PBR_BRANCH:-master} @@ -162,7 +181,7 @@ TEMPEST_BRANCH=${TEMPEST_BRANCH:-master} # diskimage-builder -BM_IMAGE_BUILD_REPO=${BM_IMAGE_BUILD_REPO:-${GIT_BASE}/stackforge/diskimage-builder.git} +BM_IMAGE_BUILD_REPO=${BM_IMAGE_BUILD_REPO:-${GIT_BASE}/openstack/diskimage-builder.git} BM_IMAGE_BUILD_BRANCH=${BM_IMAGE_BUILD_BRANCH:-master} # bm_poseur @@ -172,11 +191,11 @@ BM_POSEUR_REPO=${BM_POSEUR_REPO:-${GIT_BASE}/tripleo/bm_poseur.git} BM_POSEUR_BRANCH=${BM_POSEUR_BRANCH:-master} # a websockets/html5 or flash powered VNC console for vm instances -NOVNC_REPO=${NOVNC_REPO:-${GIT_BASE}/kanaka/noVNC.git} +NOVNC_REPO=${NOVNC_REPO:-https://github.com/kanaka/noVNC.git} NOVNC_BRANCH=${NOVNC_BRANCH:-master} # ryu service -RYU_REPO=${RYU_REPO:-${GIT_BASE}/osrg/ryu.git} +RYU_REPO=${RYU_REPO:-https://github.com/osrg/ryu.git} RYU_BRANCH=${RYU_BRANCH:-master} # a websockets/html5 or flash powered SPICE console for vm instances @@ -191,6 +210,16 @@ TROVE_BRANCH=${TROVE_BRANCH:-master} TROVECLIENT_REPO=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git} TROVECLIENT_BRANCH=${TROVECLIENT_BRANCH:-master} +# stackforge libraries that are used by OpenStack core services +# wsme +WSME_REPO=${WSME_REPO:-${GIT_BASE}/stackforge/wsme.git} +WSME_BRANCH=${WSME_BRANCH:-master} + +# pecan +PECAN_REPO=${PECAN_REPO:-${GIT_BASE}/stackforge/pecan.git} +PECAN_BRANCH=${PECAN_BRANCH:-master} + + # Nova hypervisor configuration. We default to libvirt with **kvm** but will # drop back to **qemu** if we are unable to load the kvm module. ``stack.sh`` can # also install an **LXC**, **OpenVZ** or **XenAPI** based system. If xenserver-core @@ -261,11 +290,18 @@ case "$VIRT_DRIVER" in vsphere) DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-debian-2.6.32-i686} IMAGE_URLS=${IMAGE_URLS:-"http://partnerweb.vmware.com/programs/vmdkimage/debian-2.6.32-i686.vmdk"};; + xenserver) + DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.0-x86_64-disk} + IMAGE_URLS=${IMAGE_URLS:-"https://github.com/downloads/citrix-openstack/warehouse/cirros-0.3.0-x86_64-disk.vhd.tgz"};; *) # Default to Cirros with kernel, ramdisk and disk image DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.1-x86_64-uec} IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-uec.tar.gz"};; esac +HEAT_FETCHED_TEST_IMAGE=${HEAT_FETCHED_TEST_IMAGE:-""} +if [[ "$HEAT_FETCHED_TEST_IMAGE" == "Fedora-i386-20-20131211.1-sda" ]]; then + IMAGE_URLS+=",https://dl.fedoraproject.org/pub/fedora/linux/releases/20/Images/i386/$HEAT_FETCHED_TEST_IMAGE.qcow2" +fi # 10Gb default volume backing file size VOLUME_BACKING_FILE_SIZE=${VOLUME_BACKING_FILE_SIZE:-10250M} @@ -291,6 +327,9 @@ SCREEN_NAME=${SCREEN_NAME:-stack} # Do not install packages tagged with 'testonly' by default INSTALL_TESTONLY_PACKAGES=${INSTALL_TESTONLY_PACKAGES:-False} +# Undo requirements changes by global requirements +UNDO_REQUIREMENTS=${UNDO_REQUIREMENTS:-True} + # Local variables: # mode: shell-script # End: diff --git a/tests/functions.sh b/tests/functions.sh index 7d486d4cc5..95dafe1028 100755 --- a/tests/functions.sh +++ b/tests/functions.sh @@ -38,195 +38,6 @@ if [[ $? = 0 ]]; then fi -echo "Testing INI functions" - -cat >test.ini <test1c.conf <test2a.conf <test.conf <test.ini <[ \t]+)', line) + if m: + if re.search('\t', m.group('indent')): + print_error('E002: Tab indents', line) + if (len(m.group('indent')) % 4) != 0: + print_error('E003: Indent not multiple of 4', line) + + +def starts_multiline(line): + m = re.search("[^<]<<\s*(?P\w+)", line) + if m: + return m.group('token') + else: + return False + + +def end_of_multiline(line, token): + if token: + return re.search("^%s\s*$" % token, line) is not None + return False + + +def check_files(files): + in_multiline = False + logical_line = "" + token = False + for line in fileinput.input(files): + # NOTE(sdague): multiline processing of heredocs is interesting + if not in_multiline: + logical_line = line + token = starts_multiline(line) + if token: + in_multiline = True + continue + else: + logical_line = logical_line + line + if not end_of_multiline(line, token): + continue + else: + in_multiline = False + + check_no_trailing_whitespace(logical_line) + check_indents(logical_line) + + +def get_options(): + parser = argparse.ArgumentParser( + description='A bash script style checker') + parser.add_argument('files', metavar='file', nargs='+', + help='files to scan for errors') + return parser.parse_args() + + +def main(): + opts = get_options() + check_files(opts.files) + + if ERRORS > 0: + print("%d bash8 error(s) found" % ERRORS) + return 1 + else: + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/build_bm_multi.sh b/tools/build_bm_multi.sh index 52b9b4ea32..328d5762fc 100755 --- a/tools/build_bm_multi.sh +++ b/tools/build_bm_multi.sh @@ -22,8 +22,8 @@ run_bm STACKMASTER $HEAD_HOST "ENABLED_SERVICES=g-api,g-reg,key,n-api,n-sch,n-vn if [ ! "$TERMINATE" = "1" ]; then echo "Waiting for head node ($HEAD_HOST) to start..." if ! timeout 60 sh -c "while ! wget -q -O- http://$HEAD_HOST | grep -q username; do sleep 1; done"; then - echo "Head node did not start" - exit 1 + echo "Head node did not start" + exit 1 fi fi diff --git a/tools/build_docs.sh b/tools/build_docs.sh new file mode 100755 index 0000000000..c566e6356f --- /dev/null +++ b/tools/build_docs.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash + +# **build_docs.sh** - Build the gh-pages docs for DevStack +# +# - Install shocco if not found on PATH +# - Clone MASTER_REPO branch MASTER_BRANCH +# - Re-creates ``docs`` directory from existing repo + new generated script docs + +# Usage: +## build_docs.sh [[-b branch] [-p] repo] | . +## -b branch The DevStack branch to check out (default is master; ignored if +## repo is not specified) +## -p Push the resulting docs tree to the source repo; fatal error if +## repo is not specified +## repo The DevStack repository to clone (default is DevStack github repo) +## If a repo is not supplied use the current directory +## (assumed to be a DevStack checkout) as the source. +## . Use the current repo and branch (do not use with -p to +## prevent stray files in the workspace being added tot he docs) + +# Defaults +# -------- + +# Source repo/branch for DevStack +MASTER_REPO=${MASTER_REPO:-https://github.com/openstack-dev/devstack.git} +MASTER_BRANCH=${MASTER_BRANCH:-master} + +# http://devstack.org is a GitHub gh-pages site in the https://github.com/cloudbuilders/devtack.git repo +GH_PAGES_REPO=git@github.com:cloudbuilders/devstack.git + +# Keep track of the devstack directory +TOP_DIR=$(cd $(dirname "$0")/.. && pwd) + +# Uses this shocco branch: https://github.com/dtroyer/shocco/tree/rst_support +SHOCCO=${SHOCCO:-shocco} +if ! which shocco; then + if [[ ! -x $TOP_DIR/shocco/shocco ]]; then + if [[ -z "$INSTALL_SHOCCO" ]]; then + echo "shocco not found in \$PATH, please set environment variable SHOCCO" + exit 1 + fi + echo "Installing local copy of shocco" + if ! which pygmentize; then + sudo pip install Pygments + fi + if ! which rst2html.py; then + sudo pip install docutils + fi + git clone -b rst_support https://github.com/dtroyer/shocco shocco + cd shocco + ./configure + make + cd .. + fi + SHOCCO=$TOP_DIR/shocco/shocco +fi + +# Process command-line args +while getopts b:p c; do + case $c in + b) MASTER_BRANCH=$OPTARG + ;; + p) PUSH_REPO=1 + ;; + esac +done +shift `expr $OPTIND - 1` + +# Sanity check the args +if [[ "$1" == "." ]]; then + REPO="" + if [[ -n $PUSH_REPO ]]; then + echo "Push not allowed from an active workspace" + unset PUSH_REPO + fi +else + if [[ -z "$1" ]]; then + REPO=$MASTER_REPO + else + REPO=$1 + fi +fi + +# Check out a specific DevStack branch +if [[ -n $REPO ]]; then + # Make a workspace + TMP_ROOT=$(mktemp -d devstack-docs-XXXX) + echo "Building docs in $TMP_ROOT" + cd $TMP_ROOT + + # Get the master branch + git clone $REPO devstack + cd devstack + git checkout $MASTER_BRANCH +fi + +# Processing +# ---------- + +# Assumption is we are now in the DevStack repo workspace to be processed + +# Pull the latest docs branch from devstack.org repo +if ! [ -d docs ]; then + git clone -b gh-pages $GH_PAGES_REPO docs +fi + +# Build list of scripts to process +FILES="" +for f in $(find . -name .git -prune -o \( -type f -name \*.sh -not -path \*shocco/\* -print \)); do + echo $f + FILES+="$f " + mkdir -p docs/`dirname $f`; + $SHOCCO $f > docs/$f.html +done +for f in $(find functions lib samples -type f -name \*); do + echo $f + FILES+="$f " + mkdir -p docs/`dirname $f`; + $SHOCCO $f > docs/$f.html +done +echo "$FILES" >docs-files + +# Switch to the gh_pages repo +cd docs + +# Collect the new generated pages +find . -name \*.html -print0 | xargs -0 git add + +# Push our changes back up to the docs branch +if ! git diff-index HEAD --quiet; then + git commit -a -m "Update script docs" + if [[ -n $PUSH ]]; then + git push + fi +fi + +# Clean up or report the temp workspace +if [[ -n REPO && -n $PUSH_REPO ]]; then + rm -rf $TMP_ROOT +else + if [[ -z "$TMP_ROOT" ]]; then + TMP_ROOT="$(pwd)" + fi + echo "Built docs in $TMP_ROOT" +fi diff --git a/tools/build_ramdisk.sh b/tools/build_ramdisk.sh index 2c45568531..737255578a 100755 --- a/tools/build_ramdisk.sh +++ b/tools/build_ramdisk.sh @@ -22,7 +22,7 @@ cleanup() { umount $MNTDIR rmdir $MNTDIR fi - if [ -n "$DEV_FILE_TMP" -a -e "$DEV_FILE_TMP "]; then + if [ -n "$DEV_FILE_TMP" -a -e "$DEV_FILE_TMP" ]; then rm -f $DEV_FILE_TMP fi if [ -n "$IMG_FILE_TMP" -a -e "$IMG_FILE_TMP" ]; then @@ -84,11 +84,10 @@ if [ ! -r $CACHEDIR/$DIST_NAME-base.img ]; then $TOOLS_DIR/get_uec_image.sh $DIST_NAME $CACHEDIR/$DIST_NAME-base.img fi -# Finds the next available NBD device -# Exits script if error connecting or none free +# Finds and returns full device path for the next available NBD device. +# Exits script if error connecting or none free. # map_nbd image -# Returns full nbd device path -function map_nbd { +function map_nbd() { for i in `seq 0 15`; do if [ ! -e /sys/block/nbd$i/pid ]; then NBD=/dev/nbd$i @@ -156,7 +155,7 @@ if [ ! -r $IMG_FILE ]; then # Pre-create the image file # FIXME(dt): This should really get the partition size to - # pre-create the image file + # pre-create the image file dd if=/dev/zero of=$IMG_FILE_TMP bs=1 count=1 seek=$((2*1024*1024*1024)) # Create filesystem image for RAM disk dd if=${NBD}p1 of=$IMG_FILE_TMP bs=1M diff --git a/tools/build_tempest.sh b/tools/build_tempest.sh index 1758e7da33..6c527f5962 100755 --- a/tools/build_tempest.sh +++ b/tools/build_tempest.sh @@ -2,7 +2,7 @@ # # **build_tempest.sh** -# Checkout and prepare a Tempest repo: https://github.com/openstack/tempest.git +# Checkout and prepare a Tempest repo: git://git.openstack.org/openstack/tempest.git function usage { echo "$0 - Check out and prepare a Tempest repo" diff --git a/tools/build_uec.sh b/tools/build_uec.sh deleted file mode 100755 index 6c4a26c2e3..0000000000 --- a/tools/build_uec.sh +++ /dev/null @@ -1,302 +0,0 @@ -#!/usr/bin/env bash - -# **build_uec.sh** - -# Make sure that we have the proper version of ubuntu (only works on oneiric) -if ! egrep -q "oneiric" /etc/lsb-release; then - echo "This script only works with ubuntu oneiric." - exit 1 -fi - -# Keep track of the current directory -TOOLS_DIR=$(cd $(dirname "$0") && pwd) -TOP_DIR=$(cd $TOOLS_DIR/..; pwd) - -# Import common functions -. $TOP_DIR/functions - -cd $TOP_DIR - -# Source params -source ./stackrc - -# Ubuntu distro to install -DIST_NAME=${DIST_NAME:-oneiric} - -# Configure how large the VM should be -GUEST_SIZE=${GUEST_SIZE:-10G} - -# exit on error to stop unexpected errors -set -o errexit -set -o xtrace - -# Abort if localrc is not set -if [ ! -e $TOP_DIR/localrc ]; then - echo "You must have a localrc with ALL necessary passwords defined before proceeding." - echo "See stack.sh for required passwords." - exit 1 -fi - -# Install deps if needed -DEPS="kvm libvirt-bin kpartx cloud-utils curl" -apt_get install -y --force-yes $DEPS || true # allow this to fail gracefully for concurrent builds - -# Where to store files and instances -WORK_DIR=${WORK_DIR:-/opt/uecstack} - -# Where to store images -image_dir=$WORK_DIR/images/$DIST_NAME -mkdir -p $image_dir - -# Start over with a clean base image, if desired -if [ $CLEAN_BASE ]; then - rm -f $image_dir/disk -fi - -# Get the base image if it does not yet exist -if [ ! -e $image_dir/disk ]; then - $TOOLS_DIR/get_uec_image.sh -r $GUEST_SIZE $DIST_NAME $image_dir/disk $image_dir/kernel -fi - -# Copy over dev environment if COPY_ENV is set. -# This will also copy over your current devstack. -if [ $COPY_ENV ]; then - cd $TOOLS_DIR - ./copy_dev_environment_to_uec.sh $image_dir/disk -fi - -# Option to warm the base image with software requirements. -if [ $WARM_CACHE ]; then - cd $TOOLS_DIR - ./warm_apts_for_uec.sh $image_dir/disk -fi - -# Name of our instance, used by libvirt -GUEST_NAME=${GUEST_NAME:-devstack} - -# Mop up after previous runs -virsh destroy $GUEST_NAME || true - -# Where this vm is stored -vm_dir=$WORK_DIR/instances/$GUEST_NAME - -# Create vm dir and remove old disk -mkdir -p $vm_dir -rm -f $vm_dir/disk - -# Create a copy of the base image -qemu-img create -f qcow2 -b $image_dir/disk $vm_dir/disk - -# Back to devstack -cd $TOP_DIR - -GUEST_NETWORK=${GUEST_NETWORK:-1} -GUEST_RECREATE_NET=${GUEST_RECREATE_NET:-yes} -GUEST_IP=${GUEST_IP:-192.168.$GUEST_NETWORK.50} -GUEST_CIDR=${GUEST_CIDR:-$GUEST_IP/24} -GUEST_NETMASK=${GUEST_NETMASK:-255.255.255.0} -GUEST_GATEWAY=${GUEST_GATEWAY:-192.168.$GUEST_NETWORK.1} -GUEST_MAC=${GUEST_MAC:-"02:16:3e:07:69:`printf '%02X' $GUEST_NETWORK`"} -GUEST_RAM=${GUEST_RAM:-1524288} -GUEST_CORES=${GUEST_CORES:-1} - -# libvirt.xml configuration -NET_XML=$vm_dir/net.xml -NET_NAME=${NET_NAME:-devstack-$GUEST_NETWORK} -cat > $NET_XML < - $NET_NAME - - - - - - - - -EOF - -if [[ "$GUEST_RECREATE_NET" == "yes" ]]; then - virsh net-destroy $NET_NAME || true - # destroying the network isn't enough to delete the leases - rm -f /var/lib/libvirt/dnsmasq/$NET_NAME.leases - virsh net-create $vm_dir/net.xml -fi - -# libvirt.xml configuration -LIBVIRT_XML=$vm_dir/libvirt.xml -cat > $LIBVIRT_XML < - $GUEST_NAME - $GUEST_RAM - - hvm - $image_dir/kernel - root=/dev/vda ro console=ttyS0 init=/usr/lib/cloud-init/uncloud-init ds=nocloud-net;s=http://192.168.$GUEST_NETWORK.1:4567/ ubuntu-pass=ubuntu - - - - - - $GUEST_CORES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EOF - - -rm -rf $vm_dir/uec -cp -r $TOOLS_DIR/uec $vm_dir/uec - -# set metadata -cat > $vm_dir/uec/meta-data< $vm_dir/uec/user-data<> $vm_dir/uec/user-data< localrc < /opt/stack/.ssh/authorized_keys -chown -R $STACK_USER /opt/stack -chmod 700 /opt/stack/.ssh -chmod 600 /opt/stack/.ssh/authorized_keys - -grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" >> /etc/sudoers -( umask 226 && echo "stack ALL=(ALL) NOPASSWD:ALL" \ - > /etc/sudoers.d/50_stack_sh ) -EOF -fi - -# Run stack.sh -cat >> $vm_dir/uec/user-data</dev/null; then + echo "Creating a group called $STACK_USER" + groupadd $STACK_USER +fi + +if ! getent passwd $STACK_USER >/dev/null; then + echo "Creating a user called $STACK_USER" + useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USER +fi + +echo "Giving stack user passwordless sudo privileges" +# UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one +grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || + echo "#includedir /etc/sudoers.d" >> /etc/sudoers +( umask 226 && echo "$STACK_USER ALL=(ALL) NOPASSWD:ALL" \ + > /etc/sudoers.d/50_stack_sh ) diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh index 619d63f7ff..5f4c48660b 100755 --- a/tools/create_userrc.sh +++ b/tools/create_userrc.sh @@ -6,6 +6,9 @@ # Warning: This script just for development purposes +set -o errexit +set -o xtrace + ACCOUNT_DIR=./accrc display_help() @@ -40,6 +43,7 @@ Optional Arguments --os-tenant-name --os-tenant-id --os-auth-url +--os-cacert --target-dir --skip-tenant --debug @@ -50,7 +54,7 @@ $0 -P -C mytenant -u myuser -p mypass EOF } -if ! options=$(getopt -o hPAp:u:r:C: -l os-username:,os-password:,os-tenant-name:,os-tenant-id:,os-auth-url:,target-dir:,skip-tenant:,help,debug -- "$@") +if ! options=$(getopt -o hPAp:u:r:C: -l os-username:,os-password:,os-tenant-name:,os-tenant-id:,os-auth-url:,target-dir:,skip-tenant:,os-cacert:,help,debug -- "$@") then #parse error display_help @@ -77,6 +81,7 @@ do --os-tenant-id) export OS_TENANT_ID=$2; shift ;; --skip-tenant) SKIP_TENANT="$SKIP_TENANT$2,"; shift ;; --os-auth-url) export OS_AUTH_URL=$2; shift ;; + --os-cacert) export OS_CACERT=$2; shift ;; --target-dir) ACCOUNT_DIR=$2; shift ;; --debug) set -o xtrace ;; -u) MODE=${MODE:-one}; USER_NAME=$2; shift ;; @@ -102,15 +107,15 @@ if [ -z "$OS_PASSWORD" ]; then fi if [ -z "$OS_TENANT_NAME" -a -z "$OS_TENANT_ID" ]; then - export OS_TENANT_NAME=admin + export OS_TENANT_NAME=admin fi if [ -z "$OS_USERNAME" ]; then - export OS_USERNAME=admin + export OS_USERNAME=admin fi if [ -z "$OS_AUTH_URL" ]; then - export OS_AUTH_URL=http://localhost:5000/v2.0/ + export OS_AUTH_URL=http://localhost:5000/v2.0/ fi USER_PASS=${USER_PASS:-$OS_PASSWORD} @@ -138,10 +143,14 @@ s3=`keystone endpoint-get --service s3 | awk '/\|[[:space:]]*s3.publicURL/ {prin mkdir -p "$ACCOUNT_DIR" ACCOUNT_DIR=`readlink -f "$ACCOUNT_DIR"` EUCALYPTUS_CERT=$ACCOUNT_DIR/cacert.pem -mv "$EUCALYPTUS_CERT" "$EUCALYPTUS_CERT.old" &>/dev/null +if [ -e "$EUCALYPTUS_CERT" ]; then + mv "$EUCALYPTUS_CERT" "$EUCALYPTUS_CERT.old" +fi if ! nova x509-get-root-cert "$EUCALYPTUS_CERT"; then echo "Failed to update the root certificate: $EUCALYPTUS_CERT" >&2 - mv "$EUCALYPTUS_CERT.old" "$EUCALYPTUS_CERT" &>/dev/null + if [ -e "$EUCALYPTUS_CERT.old" ]; then + mv "$EUCALYPTUS_CERT.old" "$EUCALYPTUS_CERT" + fi fi @@ -168,12 +177,20 @@ function add_entry(){ local ec2_cert="$rcfile-cert.pem" local ec2_private_key="$rcfile-pk.pem" # Try to preserve the original file on fail (best effort) - mv -f "$ec2_private_key" "$ec2_private_key.old" &>/dev/null - mv -f "$ec2_cert" "$ec2_cert.old" &>/dev/null + if [ -e "$ec2_private_key" ]; then + mv -f "$ec2_private_key" "$ec2_private_key.old" + fi + if [ -e "$ec2_cert" ]; then + mv -f "$ec2_cert" "$ec2_cert.old" + fi # It will not create certs when the password is incorrect if ! nova --os-password "$user_passwd" --os-username "$user_name" --os-tenant-name "$tenant_name" x509-create-cert "$ec2_private_key" "$ec2_cert"; then - mv -f "$ec2_private_key.old" "$ec2_private_key" &>/dev/null - mv -f "$ec2_cert.old" "$ec2_cert" &>/dev/null + if [ -e "$ec2_private_key.old" ]; then + mv -f "$ec2_private_key.old" "$ec2_private_key" + fi + if [ -e "$ec2_cert.old" ]; then + mv -f "$ec2_cert.old" "$ec2_cert" + fi fi cat >"$rcfile" < /etc/apt/sources.list.d/docker.list" apt_get update -install_package --force-yes lxc-docker=${DOCKER_PACKAGE_VERSION} socat +install_package --force-yes lxc-docker socat # Start the daemon - restart just in case the package ever auto-starts... restart_service docker echo "Waiting for docker daemon to start..." DOCKER_GROUP=$(groups | cut -d' ' -f1) -CONFIGURE_CMD="while ! /bin/echo -e 'GET /v1.3/version HTTP/1.0\n\n' | socat - unix-connect:$DOCKER_UNIX_SOCKET | grep -q '200 OK'; do +CONFIGURE_CMD="while ! /bin/echo -e 'GET /v1.3/version HTTP/1.0\n\n' | socat - unix-connect:$DOCKER_UNIX_SOCKET 2>/dev/null | grep -q '200 OK'; do # Set the right group on docker unix socket before retrying sudo chgrp $DOCKER_GROUP $DOCKER_UNIX_SOCKET sudo chmod g+rw $DOCKER_UNIX_SOCKET diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh index 87922c8ece..a28e10ef2d 100755 --- a/tools/fixup_stuff.sh +++ b/tools/fixup_stuff.sh @@ -5,17 +5,23 @@ # fixup_stuff.sh # # All distro and package specific hacks go in here +# # - prettytable 0.7.2 permissions are 600 in the package and # pip 1.4 doesn't fix it (1.3 did) +# # - httplib2 0.8 permissions are 600 in the package and # pip 1.4 doesn't fix it (1.3 did) +# # - RHEL6: +# # - set selinux not enforcing # - (re)start messagebus daemon # - remove distro packages python-crypto and python-lxml # - pre-install hgtools to work around a bug in RHEL6 distribute # - install nose 1.1 from EPEL +set -o errexit +set -o xtrace # Keep track of the current directory TOOLS_DIR=$(cd $(dirname "$0") && pwd) @@ -33,25 +39,51 @@ FILES=$TOP_DIR/files # Python Packages # --------------- -# Pre-install affected packages so we can fix the permissions -pip_install prettytable -pip_install httplib2 +# get_package_path python-package # in import notation +function get_package_path() { + local package=$1 + echo $(python -c "import os; import $package; print(os.path.split(os.path.realpath($package.__file__))[0])") +} -SITE_DIRS=$(python -c "import site; import os; print os.linesep.join(site.getsitepackages())") -for dir in $SITE_DIRS; do - # Fix prettytable 0.7.2 permissions - if [[ -r $dir/prettytable.py ]]; then - sudo chmod +r $dir/prettytable-0.7.2*/* - fi +# Pre-install affected packages so we can fix the permissions +# These can go away once we are confident that pip 1.4.1+ is available everywhere + +# Fix prettytable 0.7.2 permissions +# Don't specify --upgrade so we use the existing package if present +pip_install 'prettytable>0.7' +PACKAGE_DIR=$(get_package_path prettytable) +# Only fix version 0.7.2 +dir=$(echo $PACKAGE_DIR/prettytable-0.7.2*) +if [[ -d $dir ]]; then + sudo chmod +r $dir/* +fi - # Fix httplib2 0.8 permissions - httplib_dir=httplib2-0.8.egg-info - if [[ -d $dir/$httplib_dir ]]; then - sudo chmod +r $dir/$httplib_dir/* - fi +# Fix httplib2 0.8 permissions +# Don't specify --upgrade so we use the existing package if present +pip_install httplib2 +PACKAGE_DIR=$(get_package_path httplib2) +# Only fix version 0.8 +dir=$(echo $PACKAGE_DIR-0.8*) +if [[ -d $dir ]]; then + sudo chmod +r $dir/* +fi -done +# Ubuntu 12.04 +# ----- +# We can regularly get kernel crashes on the 12.04 default kernel, so attempt +# to install a new kernel +if [[ ${DISTRO} =~ (precise) ]]; then + # Finally, because we suspect the Precise kernel is problematic, install a new kernel + UPGRADE_KERNEL=$(trueorfalse False $UPGRADE_KERNEL) + if [[ $UPGRADE_KERNEL == "True" ]]; then + if [[ ! `uname -r` =~ (^3\.11) ]]; then + apt_get install linux-generic-lts-saucy + echo "Installing Saucy LTS kernel, please reboot before proceeding" + exit 1 + fi + fi +fi # RHEL6 @@ -60,8 +92,7 @@ done if [[ $DISTRO =~ (rhel6) ]]; then # Disable selinux to avoid configuring to allow Apache access - # to Horizon files or run nodejs (LP#1175444) - # FIXME(dtroyer): see if this can be skipped without node or if Horizon is not enabled + # to Horizon files (LP#1175444) if selinuxenabled; then sudo setenforce 0 fi @@ -78,7 +109,7 @@ if [[ $DISTRO =~ (rhel6) ]]; then # fresh system via Anaconda and the dependency chain # ``cas`` -> ``python-paramiko`` -> ``python-crypto``. # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info`` - # file but leave most of the actual library files behind in + # file but leave most of the actual library files behind in # ``/usr/lib64/python2.6/Crypto``. Later ``pip install pycrypto`` # will install over the packaged files resulting # in a useless mess of old, rpm-packaged files and pip-installed files. diff --git a/tools/get_uec_image.sh b/tools/get_uec_image.sh index 3c62064ad6..da13f4b875 100755 --- a/tools/get_uec_image.sh +++ b/tools/get_uec_image.sh @@ -64,12 +64,10 @@ IMG_FILE_TMP=`mktemp $IMG_FILE.XXXXXX` KERNEL=$3 case $DIST_NAME in + saucy) ;; + raring) ;; quantal) ;; precise) ;; - oneiric) ;; - natty) ;; - maverick) ;; - lucid) ;; *) echo "Unknown release: $DIST_NAME" usage ;; diff --git a/tools/info.sh b/tools/info.sh index 14ab8f6306..3ab7966ab4 100755 --- a/tools/info.sh +++ b/tools/info.sh @@ -85,8 +85,8 @@ done # Packages # -------- -# - We are going to check packages only for the services needed. -# - We are parsing the packages files and detecting metadatas. +# - Only check packages for the services enabled +# - Parse version info from the package metadata, not the package/file names for p in $(get_packages $ENABLED_SERVICES); do if [[ "$os_PACKAGE" = "deb" ]]; then @@ -141,9 +141,15 @@ rm $FREEZE_FILE # Dump localrc with 'localrc|' prepended and comments and passwords left out if [[ -r $TOP_DIR/localrc ]]; then + RC=$TOP_DIR/localrc +elif [[ -f $RC_DIR/.localrc.auto ]]; then + RC=$TOP_DIR/.localrc.auto +fi +if [[ -n $RC ]]; then sed -e ' - /PASSWORD/d; + /^[ \t]*$/d; + /PASSWORD/s/=.*$/=\/; /^#/d; s/^/localrc\|/; - ' $TOP_DIR/localrc + ' $RC fi diff --git a/tools/install_pip.sh b/tools/install_pip.sh index fc1c19584b..d714d33530 100755 --- a/tools/install_pip.sh +++ b/tools/install_pip.sh @@ -9,6 +9,9 @@ # Assumptions: # - update pip to $INSTALL_PIP_VERSION +set -o errexit +set -o xtrace + # Keep track of the current directory TOOLS_DIR=$(cd $(dirname "$0") && pwd) TOP_DIR=`cd $TOOLS_DIR/..; pwd` @@ -23,6 +26,7 @@ FILES=$TOP_DIR/files # Handle arguments +USE_GET_PIP=${USE_GET_PIP:-0} INSTALL_PIP_VERSION=${INSTALL_PIP_VERSION:-"1.4.1"} while [[ -n "$1" ]]; do case $1 in @@ -47,10 +51,12 @@ GetDistro echo "Distro: $DISTRO" function get_versions() { - PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null) + PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null || true) if [[ -n $PIP ]]; then PIP_VERSION=$($PIP --version | awk '{ print $2}') echo "pip: $PIP_VERSION" + else + echo "pip: Not Installed" fi } @@ -58,18 +64,18 @@ function get_versions() { function install_get_pip() { if [[ ! -r $FILES/get-pip.py ]]; then (cd $FILES; \ - curl $PIP_GET_PIP_URL; \ + curl -O $PIP_GET_PIP_URL; \ ) fi - sudo python $FILES/get-pip.py + sudo -E python $FILES/get-pip.py } function install_pip_tarball() { (cd $FILES; \ curl -O $PIP_TAR_URL; \ - tar xvfz pip-$INSTALL_PIP_VERSION.tar.gz; \ + tar xvfz pip-$INSTALL_PIP_VERSION.tar.gz 1>/dev/null; \ cd pip-$INSTALL_PIP_VERSION; \ - sudo python setup.py install; \ + sudo -E python setup.py install 1>/dev/null; \ ) } @@ -81,7 +87,7 @@ get_versions # Eradicate any and all system packages uninstall_package python-pip -if [[ -n "$USE_GET_PIP" ]]; then +if [[ "$USE_GET_PIP" == "1" ]]; then install_get_pip else install_pip_tarball diff --git a/tools/install_prereqs.sh b/tools/install_prereqs.sh index 68f11ce35e..0c65fd9b00 100755 --- a/tools/install_prereqs.sh +++ b/tools/install_prereqs.sh @@ -55,7 +55,7 @@ export_proxy_variables # ================ # Install package requirements -install_package $(get_packages $ENABLED_SERVICES) +install_package $(get_packages general $ENABLED_SERVICES) if [[ -n "$SYSLOG" && "$SYSLOG" != "False" ]]; then if is_ubuntu || is_fedora; then diff --git a/tools/jenkins/adapters/euca.sh b/tools/jenkins/adapters/euca.sh index b49ce9f21f..a7e635c694 100755 --- a/tools/jenkins/adapters/euca.sh +++ b/tools/jenkins/adapters/euca.sh @@ -5,4 +5,5 @@ set -o errexit TOP_DIR=$(cd ../../.. && pwd) HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2` +die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP" ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises && ./euca.sh' diff --git a/tools/jenkins/adapters/floating_ips.sh b/tools/jenkins/adapters/floating_ips.sh index a97f93578a..8da1eeb97a 100755 --- a/tools/jenkins/adapters/floating_ips.sh +++ b/tools/jenkins/adapters/floating_ips.sh @@ -5,4 +5,5 @@ set -o errexit TOP_DIR=$(cd ../../.. && pwd) HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2` +die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP" ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises && ./floating_ips.sh' diff --git a/tools/jenkins/adapters/volumes.sh b/tools/jenkins/adapters/volumes.sh index ec292097fa..0a0b6c0548 100755 --- a/tools/jenkins/adapters/volumes.sh +++ b/tools/jenkins/adapters/volumes.sh @@ -5,4 +5,5 @@ set -o errexit TOP_DIR=$(cd ../../.. && pwd) HEAD_IP=`cat $TOP_DIR/addresses | grep HEAD | cut -d "=" -f2` +die_if_not_set $LINENO HEAD_IP "Failure retrieving HEAD_IP" ssh stack@$HEAD_IP 'cd devstack && source openrc && cd exercises && ./volumes.sh' diff --git a/tools/jenkins/jenkins_home/build_jenkins.sh b/tools/jenkins/jenkins_home/build_jenkins.sh index e0e774ee9e..a556db0f1d 100755 --- a/tools/jenkins/jenkins_home/build_jenkins.sh +++ b/tools/jenkins/jenkins_home/build_jenkins.sh @@ -6,8 +6,8 @@ set -o errexit # Make sure only root can run our script if [[ $EUID -ne 0 ]]; then - echo "This script must be run as root" - exit 1 + echo "This script must be run as root" + exit 1 fi # This directory @@ -31,15 +31,15 @@ apt-get install -y --force-yes $DEPS # Install jenkins if [ ! -e /var/lib/jenkins ]; then - echo "Jenkins installation failed" - exit 1 + echo "Jenkins installation failed" + exit 1 fi # Make sure user has configured a jenkins ssh pubkey if [ ! -e /var/lib/jenkins/.ssh/id_rsa.pub ]; then - echo "Public key for jenkins is missing. This is used to ssh into your instances." - echo "Please run "su -c ssh-keygen jenkins" before proceeding" - exit 1 + echo "Public key for jenkins is missing. This is used to ssh into your instances." + echo "Please run "su -c ssh-keygen jenkins" before proceeding" + exit 1 fi # Setup sudo @@ -96,7 +96,7 @@ PLUGINS=http://hudson-ci.org/downloads/plugins/build-timeout/1.6/build-timeout.h # Configure plugins for plugin in ${PLUGINS//,/ }; do - name=`basename $plugin` + name=`basename $plugin` dest=/var/lib/jenkins/plugins/$name if [ ! -e $dest ]; then curl -L $plugin -o $dest diff --git a/tools/sar_filter.py b/tools/sar_filter.py new file mode 100755 index 0000000000..ed8c19687c --- /dev/null +++ b/tools/sar_filter.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2014 Samsung Electronics Corp. 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. + +import re +import subprocess +import sys + + +def is_data_line(line): + timestamp, data = parse_line(line) + return re.search('\d\.d', data) + + +def parse_line(line): + m = re.search('(\d\d:\d\d:\d\d \w\w)(\s+((\S+)\s*)+)', line) + if m: + date = m.group(1) + data = m.group(2).rstrip() + return date, data + else: + return None, None + + +process = subprocess.Popen( + "sar %s" % " ".join(sys.argv[1:]), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + +# Poll process for new output until finished + +start_time = "" +header = "" +data_line = "" +printed_header = False +current_ts = None +while True: + nextline = process.stdout.readline() + if nextline == '' and process.poll() is not None: + break + + date, data = parse_line(nextline) + # stop until we get to the first set of real lines + if not date: + continue + + # now we eat the header lines, and only print out the header + # if we've never seen them before + if not start_time: + start_time = date + header += "%s %s" % (date, data) + elif date == start_time: + header += " %s" % data + elif not printed_header: + printed_header = True + print header + + # now we know this is a data line, printing out if the timestamp + # has changed, and stacking up otherwise. + nextline = process.stdout.readline() + date, data = parse_line(nextline) + if date != current_ts: + current_ts = date + print data_line + data_line = "%s %s" % (date, data) + else: + data_line += " %s" % data + + sys.stdout.flush() diff --git a/tools/upload_image.sh b/tools/upload_image.sh index dd21c9f2a8..d81a5c8dab 100755 --- a/tools/upload_image.sh +++ b/tools/upload_image.sh @@ -33,6 +33,7 @@ fi # Get a token to authenticate to glance TOKEN=$(keystone token-get | grep ' id ' | get_field 2) +die_if_not_set $LINENO TOKEN "Keystone fail to get token" # Glance connection info. Note the port must be specified. GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$GLANCE_HOST:9292} diff --git a/tools/xen/README.md b/tools/xen/README.md index 06192ed2b7..ee1abcc091 100644 --- a/tools/xen/README.md +++ b/tools/xen/README.md @@ -70,6 +70,9 @@ the `XENAPI_PASSWORD` must be your dom0 root password. Of course, use real passwords if this machine is exposed. cat > ./localrc <$STAGING_DIR/etc/rc.local -# network restart required for getting the right gateway -/etc/init.d/networking restart -chown -R $STACK_USER /opt/stack -su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" $STACK_USER -exit 0 +# Create an upstart job (task) for devstack, which can interact with the console +cat >$STAGING_DIR/etc/init/devstack.conf << EOF +start on stopped rc RUNLEVEL=[2345] + +console output +task + +pre-start script + rm -f /var/run/devstack.succeeded +end script + +script + initctl stop hvc0 || true + + # Read any leftover characters from standard input + while read -n 1 -s -t 0.1 -r ignored; do + true + done + + clear + + chown -R $STACK_USER /opt/stack + + if su -c "/opt/stack/run.sh" $STACK_USER; then + touch /var/run/devstack.succeeded + fi + + # Update /etc/issue + { + echo "OpenStack VM - Installed by DevStack" + IPADDR=\$(ip -4 address show eth0 | sed -n 's/.*inet \\([0-9\.]\\+\\).*/\1/p') + echo " Management IP: \$IPADDR" + echo -n " Devstack run: " + if [ -e /var/run/devstack.succeeded ]; then + echo "SUCCEEDED" + else + echo "FAILED" + fi + echo "" + } > /etc/issue + initctl start hvc0 > /dev/null 2>&1 +end script EOF # Configure the hostname @@ -138,8 +173,9 @@ fi # Configure run.sh cat <$STAGING_DIR/opt/stack/run.sh #!/bin/bash +set -eux cd /opt/stack/devstack -killall screen -VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=$MULTI_HOST HOST_IP_IFACE=$HOST_IP_IFACE $STACKSH_PARAMS ./stack.sh +./unstack.sh || true +./stack.sh EOF chmod 755 $STAGING_DIR/opt/stack/run.sh diff --git a/tools/xen/devstackubuntupreseed.cfg b/tools/xen/devstackubuntupreseed.cfg index c559b1e9f5..6a1ae89fd9 100644 --- a/tools/xen/devstackubuntupreseed.cfg +++ b/tools/xen/devstackubuntupreseed.cfg @@ -34,7 +34,7 @@ d-i netcfg/choose_interface select auto # If you have a slow dhcp server and the installer times out waiting for # it, this might be useful. -#d-i netcfg/dhcp_timeout string 60 +d-i netcfg/dhcp_timeout string 120 # If you prefer to configure the network manually, uncomment this line and # the static network configuration below. diff --git a/tools/xen/functions b/tools/xen/functions index a5c4b70bc3..97c56bc1af 100644 --- a/tools/xen/functions +++ b/tools/xen/functions @@ -1,5 +1,14 @@ #!/bin/bash +function die_with_error { + local err_msg + + err_msg="$1" + + echo "$err_msg" >&2 + exit 1 +} + function xapi_plugin_location { for PLUGIN_DIR in "/etc/xapi.d/plugins/" "/usr/lib/xcp/plugins/" "/usr/lib/xapi/plugins"; do if [ -d $PLUGIN_DIR ]; then @@ -11,7 +20,7 @@ function xapi_plugin_location { } function zip_snapshot_location { - echo $1 | sed "s:\.git$::;s:$:/zipball/$2:g" + echo $1 | sed "s,^git://,http://,g;s:\.git$::;s:$:/zipball/$2:g" } function create_directory_for_kernels { @@ -41,7 +50,9 @@ function extract_remote_zipball { local EXTRACTED_FILES=$(mktemp -d) { - wget -nv $ZIPBALL_URL -O $LOCAL_ZIPBALL --no-check-certificate + if ! wget -nv $ZIPBALL_URL -O $LOCAL_ZIPBALL --no-check-certificate; then + die_with_error "Failed to download [$ZIPBALL_URL]" + fi unzip -q -o $LOCAL_ZIPBALL -d $EXTRACTED_FILES rm -f $LOCAL_ZIPBALL } >&2 @@ -69,11 +80,17 @@ function install_xapi_plugins_from { } function get_local_sr { - xe sr-list name-label="Local storage" --minimal + xe pool-list params=default-SR minimal=true } function get_local_sr_path { - echo "/var/run/sr-mount/$(get_local_sr)" + pbd_path="/var/run/sr-mount/$(get_local_sr)" + pbd_device_config_path=`xe pbd-list sr-uuid=$(get_local_sr) params=device-config | grep " path: "` + if [ -n "$pbd_device_config_path" ]; then + pbd_uuid=`xe pbd-list sr-uuid=$(get_local_sr) minimal=true` + pbd_path=`xe pbd-param-get uuid=$pbd_uuid param-name=device-config param-key=path || echo ""` + fi + echo $pbd_path } function find_ip_by_name() { @@ -131,14 +148,14 @@ function _network_exists() { local name_label name_label=$1 - ! [ -z $(xe network-list name-label="$name_label" --minimal) ] + ! [ -z "$(xe network-list name-label="$name_label" --minimal)" ] } function _bridge_exists() { local bridge bridge=$1 - ! [ -z $(xe network-list bridge="$bridge" --minimal) ] + ! [ -z "$(xe network-list bridge="$bridge" --minimal)" ] } function _network_uuid() { @@ -287,3 +304,35 @@ function set_vm_memory() { dynamic-max=${memory}MiB \ uuid=$vm } + +function max_vcpus() { + local vm_name_label + + vm_name_label="$1" + + local vm + local host + local cpu_count + + host=$(xe host-list --minimal) + vm=$(_vm_uuid "$vm_name_label") + + cpu_count=$(xe host-param-get \ + param-name=cpu_info \ + uuid=$host | + sed -e 's/^.*cpu_count: \([0-9]*\);.*$/\1/g') + + if [ -z "$cpu_count" ]; then + # get dom0's vcpu count + cpu_count=$(cat /proc/cpuinfo | grep processor | wc -l) + fi + + # Assert cpu_count is not empty + [ -n "$cpu_count" ] + + # Assert ithas a numeric nonzero value + expr "$cpu_count" + 0 + + xe vm-param-set uuid=$vm VCPUs-max=$cpu_count + xe vm-param-set uuid=$vm VCPUs-at-startup=$cpu_count +} diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh index 110bbd998c..41b184c6ac 100755 --- a/tools/xen/install_os_domU.sh +++ b/tools/xen/install_os_domU.sh @@ -44,9 +44,9 @@ source $THIS_DIR/xenrc xe_min() { - local cmd="$1" - shift - xe "$cmd" --minimal "$@" + local cmd="$1" + shift + xe "$cmd" --minimal "$@" } # @@ -96,6 +96,10 @@ create_directory_for_images # # Configure Networking # + +MGT_NETWORK=`xe pif-list management=true params=network-uuid minimal=true` +MGT_BRIDGE_OR_NET_NAME=`xe network-list uuid=$MGT_NETWORK params=bridge minimal=true` + setup_network "$VM_BRIDGE_OR_NET_NAME" setup_network "$MGT_BRIDGE_OR_NET_NAME" setup_network "$PUB_BRIDGE_OR_NET_NAME" @@ -107,12 +111,15 @@ if is_service_enabled neutron; then fi if parameter_is_specified "FLAT_NETWORK_BRIDGE"; then - cat >&2 << EOF -ERROR: FLAT_NETWORK_BRIDGE is specified in localrc file -This is considered as an error, as its value will be derived from the -VM_BRIDGE_OR_NET_NAME variable's value. + if [ "$(bridge_for "$VM_BRIDGE_OR_NET_NAME")" != "$(bridge_for "$FLAT_NETWORK_BRIDGE")" ]; then + cat >&2 << EOF +ERROR: FLAT_NETWORK_BRIDGE is specified in localrc file, and either no network +found on XenServer by searching for networks by that value as name-label or +bridge name or the network found does not match the network specified by +VM_BRIDGE_OR_NET_NAME. Please check your localrc file. EOF - exit 1 + exit 1 + fi fi if ! xenapi_is_listening_on "$MGT_BRIDGE_OR_NET_NAME"; then @@ -128,8 +135,8 @@ HOST_IP=$(xenapi_ip_on "$MGT_BRIDGE_OR_NET_NAME") # Set up ip forwarding, but skip on xcp-xapi if [ -a /etc/sysconfig/network ]; then if ! grep -q "FORWARD_IPV4=YES" /etc/sysconfig/network; then - # FIXME: This doesn't work on reboot! - echo "FORWARD_IPV4=YES" >> /etc/sysconfig/network + # FIXME: This doesn't work on reboot! + echo "FORWARD_IPV4=YES" >> /etc/sysconfig/network fi fi # Also, enable ip forwarding in rc.local, since the above trick isn't working @@ -203,6 +210,7 @@ if [ -z "$templateuuid" ]; then # # Install Ubuntu over network # + UBUNTU_INST_BRIDGE_OR_NET_NAME=${UBUNTU_INST_BRIDGE_OR_NET_NAME:-"$MGT_BRIDGE_OR_NET_NAME"} # always update the preseed file, incase we have a newer one PRESEED_URL=${PRESEED_URL:-""} @@ -263,6 +271,15 @@ $THIS_DIR/prepare_guest_template.sh "$GUEST_NAME" # Set virtual machine parameters set_vm_memory "$GUEST_NAME" "$OSDOMU_MEM_MB" +# Max out VCPU count for better performance +max_vcpus "$GUEST_NAME" + +# Wipe out all network cards +destroy_all_vifs_of "$GUEST_NAME" + +# Add only one interface to prepare the guest template +add_interface "$GUEST_NAME" "$MGT_BRIDGE_OR_NET_NAME" "0" + # start the VM to run the prepare steps xe vm-start vm="$GUEST_NAME" @@ -296,7 +313,7 @@ if is_service_enabled neutron; then "xen_integration_bridge=${XEN_INTEGRATION_BRIDGE}" fi -FLAT_NETWORK_BRIDGE=$(bridge_for "$VM_BRIDGE_OR_NET_NAME") +FLAT_NETWORK_BRIDGE="${FLAT_NETWORK_BRIDGE:-$(bridge_for "$VM_BRIDGE_OR_NET_NAME")}" append_kernel_cmdline "$GUEST_NAME" "flat_network_bridge=${FLAT_NETWORK_BRIDGE}" # Add a separate xvdb, if it was requested @@ -350,25 +367,20 @@ COPYENV=${COPYENV:-1} if [ "$WAIT_TILL_LAUNCH" = "1" ] && [ -e ~/.ssh/id_rsa.pub ] && [ "$COPYENV" = "1" ]; then set +x - echo "VM Launched - Waiting for startup script" - # wait for log to appear - while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "[ -e run.sh.log ]"; do + echo "VM Launched - Waiting for devstack to start" + while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "service devstack status | grep -q running"; do sleep 10 done - echo -n "Running" - while [ `ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS pgrep -c run.sh` -ge 1 ] - do + echo -n "devstack is running" + while ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "service devstack status | grep -q running"; do sleep 10 echo -n "." done echo "done!" set -x - # output the run.sh.log - ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS 'cat run.sh.log' - - # Fail if the expected text is not found - ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS 'cat run.sh.log' | grep -q 'stack.sh completed in' + # Fail if devstack did not succeed + ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS 'test -e /var/run/devstack.succeeded' set +x echo "################################################################################" @@ -382,11 +394,12 @@ else echo "" echo "All Finished!" echo "Now, you can monitor the progress of the stack.sh installation by " - echo "tailing /opt/stack/run.sh.log from within your domU." + echo "looking at the console of your domU / checking the log files." echo "" echo "ssh into your domU now: 'ssh stack@$OS_VM_MANAGEMENT_ADDRESS' using your password" - echo "and then do: 'tail -f /opt/stack/run.sh.log'" + echo "and then do: 'sudo service devstack status' to check if devstack is still running." + echo "Check that /var/run/devstack.succeeded exists" echo "" - echo "When the script completes, you can then visit the OpenStack Dashboard" + echo "When devstack completes, you can visit the OpenStack Dashboard" echo "at http://$OS_VM_SERVICES_ADDRESS, and contact other services at the usual ports." fi diff --git a/tools/xen/mocks b/tools/xen/mocks index 94b0ca4d02..3b9b05c747 100644 --- a/tools/xen/mocks +++ b/tools/xen/mocks @@ -35,7 +35,7 @@ function mktemp { function wget { if [[ $@ =~ "failurl" ]]; then - exit 1 + return 1 fi echo "wget $@" >> $LIST_OF_ACTIONS } @@ -73,10 +73,14 @@ function [ { done return 1 fi - echo "Mock test does not implement the requested function" + echo "Mock test does not implement the requested function: ${1:-}" exit 1 } +function die_with_error { + echo "$1" >> $DEAD_MESSAGES +} + function xe { cat $XE_RESPONSE { diff --git a/tools/xen/prepare_guest_template.sh b/tools/xen/prepare_guest_template.sh index 6ea6f6321d..546ac99cd9 100755 --- a/tools/xen/prepare_guest_template.sh +++ b/tools/xen/prepare_guest_template.sh @@ -79,3 +79,7 @@ bash /opt/stack/prepare_guest.sh \\ "$GUEST_PASSWORD" "$XS_TOOLS_PATH" "$STACK_USER" \\ > /opt/stack/prepare_guest.log 2>&1 EOF + +# Need to set barrier=0 to avoid a Xen bug +# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/824089 +sed -i -e 's/errors=/barrier=0,errors=/' $STAGING_DIR/etc/fstab diff --git a/tools/xen/scripts/install-os-vpx.sh b/tools/xen/scripts/install-os-vpx.sh index 7469e0c10b..7b0d891493 100755 --- a/tools/xen/scripts/install-os-vpx.sh +++ b/tools/xen/scripts/install-os-vpx.sh @@ -42,69 +42,69 @@ EOF get_params() { - while getopts "hbn:r:l:t:" OPTION; - do - case $OPTION in - h) usage - exit 1 - ;; - n) - BRIDGE=$OPTARG - ;; - l) - NAME_LABEL=$OPTARG - ;; - t) - TEMPLATE_NAME=$OPTARG - ;; - ?) - usage - exit - ;; - esac - done - if [[ -z $BRIDGE ]] - then - BRIDGE=xenbr0 - fi - - if [[ -z $TEMPLATE_NAME ]]; then - echo "Please specify a template name" >&2 - exit 1 - fi - - if [[ -z $NAME_LABEL ]]; then - echo "Please specify a name-label for the new VM" >&2 - exit 1 - fi + while getopts "hbn:r:l:t:" OPTION; + do + case $OPTION in + h) usage + exit 1 + ;; + n) + BRIDGE=$OPTARG + ;; + l) + NAME_LABEL=$OPTARG + ;; + t) + TEMPLATE_NAME=$OPTARG + ;; + ?) + usage + exit + ;; + esac + done + if [[ -z $BRIDGE ]] + then + BRIDGE=xenbr0 + fi + + if [[ -z $TEMPLATE_NAME ]]; then + echo "Please specify a template name" >&2 + exit 1 + fi + + if [[ -z $NAME_LABEL ]]; then + echo "Please specify a name-label for the new VM" >&2 + exit 1 + fi } xe_min() { - local cmd="$1" - shift - xe "$cmd" --minimal "$@" + local cmd="$1" + shift + xe "$cmd" --minimal "$@" } find_network() { - result=$(xe_min network-list bridge="$1") - if [ "$result" = "" ] - then - result=$(xe_min network-list name-label="$1") - fi - echo "$result" + result=$(xe_min network-list bridge="$1") + if [ "$result" = "" ] + then + result=$(xe_min network-list name-label="$1") + fi + echo "$result" } create_vif() { - local v="$1" - echo "Installing VM interface on [$BRIDGE]" - local out_network_uuid=$(find_network "$BRIDGE") - xe vif-create vm-uuid="$v" network-uuid="$out_network_uuid" device="0" + local v="$1" + echo "Installing VM interface on [$BRIDGE]" + local out_network_uuid=$(find_network "$BRIDGE") + xe vif-create vm-uuid="$v" network-uuid="$out_network_uuid" device="0" } @@ -112,20 +112,20 @@ create_vif() # Make the VM auto-start on server boot. set_auto_start() { - local v="$1" - xe vm-param-set uuid="$v" other-config:auto_poweron=true + local v="$1" + xe vm-param-set uuid="$v" other-config:auto_poweron=true } destroy_vifs() { - local v="$1" - IFS=, - for vif in $(xe_min vif-list vm-uuid="$v") - do - xe vif-destroy uuid="$vif" - done - unset IFS + local v="$1" + IFS=, + for vif in $(xe_min vif-list vm-uuid="$v") + do + xe vif-destroy uuid="$vif" + done + unset IFS } diff --git a/tools/xen/scripts/uninstall-os-vpx.sh b/tools/xen/scripts/uninstall-os-vpx.sh index ac260949c4..1ed249433a 100755 --- a/tools/xen/scripts/uninstall-os-vpx.sh +++ b/tools/xen/scripts/uninstall-os-vpx.sh @@ -22,63 +22,63 @@ set -ex # By default, don't remove the templates REMOVE_TEMPLATES=${REMOVE_TEMPLATES:-"false"} if [ "$1" = "--remove-templates" ]; then - REMOVE_TEMPLATES=true + REMOVE_TEMPLATES=true fi xe_min() { - local cmd="$1" - shift - xe "$cmd" --minimal "$@" + local cmd="$1" + shift + xe "$cmd" --minimal "$@" } destroy_vdi() { - local vbd_uuid="$1" - local type=$(xe_min vbd-list uuid=$vbd_uuid params=type) - local dev=$(xe_min vbd-list uuid=$vbd_uuid params=userdevice) - local vdi_uuid=$(xe_min vbd-list uuid=$vbd_uuid params=vdi-uuid) + local vbd_uuid="$1" + local type=$(xe_min vbd-list uuid=$vbd_uuid params=type) + local dev=$(xe_min vbd-list uuid=$vbd_uuid params=userdevice) + local vdi_uuid=$(xe_min vbd-list uuid=$vbd_uuid params=vdi-uuid) - if [ "$type" == 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ]; then - xe vdi-destroy uuid=$vdi_uuid - fi + if [ "$type" == 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ]; then + xe vdi-destroy uuid=$vdi_uuid + fi } uninstall() { - local vm_uuid="$1" - local power_state=$(xe_min vm-list uuid=$vm_uuid params=power-state) + local vm_uuid="$1" + local power_state=$(xe_min vm-list uuid=$vm_uuid params=power-state) - if [ "$power_state" != "halted" ]; then - xe vm-shutdown vm=$vm_uuid force=true - fi + if [ "$power_state" != "halted" ]; then + xe vm-shutdown vm=$vm_uuid force=true + fi - for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do - destroy_vdi "$v" - done + for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do + destroy_vdi "$v" + done - xe vm-uninstall vm=$vm_uuid force=true >/dev/null + xe vm-uninstall vm=$vm_uuid force=true >/dev/null } uninstall_template() { - local vm_uuid="$1" + local vm_uuid="$1" - for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do - destroy_vdi "$v" - done + for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g'); do + destroy_vdi "$v" + done - xe template-uninstall template-uuid=$vm_uuid force=true >/dev/null + xe template-uninstall template-uuid=$vm_uuid force=true >/dev/null } # remove the VMs and their disks for u in $(xe_min vm-list other-config:os-vpx=true | sed -e 's/,/ /g'); do - uninstall "$u" + uninstall "$u" done # remove the templates if [ "$REMOVE_TEMPLATES" == "true" ]; then - for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g'); do - uninstall_template "$u" - done + for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g'); do + uninstall_template "$u" + done fi diff --git a/tools/xen/test_functions.sh b/tools/xen/test_functions.sh index 534723833d..373d996760 100755 --- a/tools/xen/test_functions.sh +++ b/tools/xen/test_functions.sh @@ -29,6 +29,9 @@ function before_each_test { XE_CALLS=$(mktemp) truncate -s 0 $XE_CALLS + + DEAD_MESSAGES=$(mktemp) + truncate -s 0 $DEAD_MESSAGES } # Teardown @@ -64,6 +67,10 @@ function assert_xe_param { grep -qe "^$1\$" $XE_CALLS } +function assert_died_with { + diff -u <(echo "$1") $DEAD_MESSAGES +} + function mock_out { local FNNAME="$1" local OUTPUT="$2" @@ -109,16 +116,22 @@ function test_no_plugin_directory_found { grep "[ -d /usr/lib/xcp/plugins/ ]" $LIST_OF_ACTIONS } -function test_zip_snapshot_location { +function test_zip_snapshot_location_http { diff \ - <(zip_snapshot_location "https://github.com/openstack/nova.git" "master") \ - <(echo "https://github.com/openstack/nova/zipball/master") + <(zip_snapshot_location "http://github.com/openstack/nova.git" "master") \ + <(echo "http://github.com/openstack/nova/zipball/master") +} + +function test_zip_snapsot_location_git { + diff \ + <(zip_snapshot_location "git://github.com/openstack/nova.git" "master") \ + <(echo "http://github.com/openstack/nova/zipball/master") } function test_create_directory_for_kernels { ( . mocks - mock_out get_local_sr uuid1 + mock_out get_local_sr_path /var/run/sr-mount/uuid1 create_directory_for_kernels ) @@ -141,7 +154,7 @@ EOF function test_create_directory_for_images { ( . mocks - mock_out get_local_sr uuid1 + mock_out get_local_sr_path /var/run/sr-mount/uuid1 create_directory_for_images ) @@ -179,7 +192,7 @@ function test_extract_remote_zipball_wget_fail { local IGNORE IGNORE=$(. mocks && extract_remote_zipball "failurl") - assert_previous_command_failed + assert_died_with "Failed to download [failurl]" } function test_find_nova_plugins { @@ -199,8 +212,7 @@ function test_get_local_sr { [ "$RESULT" == "uuid123" ] - assert_xe_min - assert_xe_param "sr-list" "name-label=Local storage" + assert_xe_param "pool-list" params=default-SR minimal=true } function test_get_local_sr_path { diff --git a/tools/xen/xenrc b/tools/xen/xenrc index f698be1085..cd282341cb 100644 --- a/tools/xen/xenrc +++ b/tools/xen/xenrc @@ -13,16 +13,20 @@ CLEAN_TEMPLATES=${CLEAN_TEMPLATES:-false} # Size of image VDI_MB=${VDI_MB:-5000} -OSDOMU_MEM_MB=2048 + +# Devstack now contains many components. 3GB ram is not enough to prevent +# swapping and memory fragmentation - the latter of which can cause failures +# such as blkfront failing to plug a VBD and lead to random test fails. +# +# Set to 4GB so an 8GB XenServer VM can have a 1GB Dom0 and leave 3GB for VMs +OSDOMU_MEM_MB=4096 OSDOMU_VDI_GB=8 # Network mapping. Specify bridge names or network names. Network names may # differ across localised versions of XenServer. If a given bridge/network # was not found, a new network will be created with the specified name. -# The management network is specified by the bridge name. xenbr0 is usually -# the name of the bridge of the network associated with the hypervisor's eth0. -MGT_BRIDGE_OR_NET_NAME="xenbr0" +# Get the management network from the XS installation VM_BRIDGE_OR_NET_NAME="OpenStack VM Network" PUB_BRIDGE_OR_NET_NAME="OpenStack Public Network" XEN_INT_BRIDGE_OR_NET_NAME="OpenStack VM Integration Network" @@ -59,8 +63,8 @@ PUB_IP=${PUB_IP:-172.24.4.10} PUB_NETMASK=${PUB_NETMASK:-255.255.255.0} # Ubuntu install settings -UBUNTU_INST_RELEASE="precise" -UBUNTU_INST_TEMPLATE_NAME="Ubuntu 12.04 (64-bit) for DevStack" +UBUNTU_INST_RELEASE="saucy" +UBUNTU_INST_TEMPLATE_NAME="Ubuntu 13.10 (64-bit) for DevStack" # For 12.04 use "precise" and update template name # However, for 12.04, you should be using # XenServer 6.1 and later or XCP 1.6 or later @@ -72,7 +76,6 @@ UBUNTU_INST_HTTP_PROXY="" UBUNTU_INST_LOCALE="en_US" UBUNTU_INST_KEYBOARD="us" # network configuration for ubuntu netinstall -UBUNTU_INST_BRIDGE_OR_NET_NAME=${UBUNTU_INST_BRIDGE_OR_NET_NAME:-"$MGT_BRIDGE_OR_NET_NAME"} UBUNTU_INST_IP="dhcp" UBUNTU_INST_NAMESERVERS="" UBUNTU_INST_NETMASK="" diff --git a/unstack.sh b/unstack.sh index 05d9fb7c83..92d0642c38 100755 --- a/unstack.sh +++ b/unstack.sh @@ -24,17 +24,48 @@ source $TOP_DIR/stackrc # Destination path for service data DATA_DIR=${DATA_DIR:-${DEST}/data} +if [[ $EUID -eq 0 ]]; then + echo "You are running this script as root." + echo "It might work but you will have a better day running it as $STACK_USER" + exit 1 +fi + + +# Configure Projects +# ================== + # Import apache functions source $TOP_DIR/lib/apache -# Get project function libraries -source $TOP_DIR/lib/baremetal -source $TOP_DIR/lib/cinder +# Import TLS functions +source $TOP_DIR/lib/tls + +# Source project function libraries +source $TOP_DIR/lib/infra +source $TOP_DIR/lib/oslo +source $TOP_DIR/lib/stackforge source $TOP_DIR/lib/horizon +source $TOP_DIR/lib/keystone +source $TOP_DIR/lib/glance +source $TOP_DIR/lib/nova +source $TOP_DIR/lib/cinder source $TOP_DIR/lib/swift +source $TOP_DIR/lib/ceilometer +source $TOP_DIR/lib/heat source $TOP_DIR/lib/neutron +source $TOP_DIR/lib/baremetal +source $TOP_DIR/lib/ldap source $TOP_DIR/lib/ironic -source $TOP_DIR/lib/trove + +# Extras Source +# -------------- + +# Phase: source +if [[ -d $TOP_DIR/extras.d ]]; then + for i in $TOP_DIR/extras.d/*.sh; do + [[ -r $i ]] && source $i source + done +fi # Determine what system we are running on. This provides ``os_VENDOR``, # ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME`` @@ -47,6 +78,7 @@ fi # Run extras # ========== +# Phase: unstack if [[ -d $TOP_DIR/extras.d ]]; then for i in $TOP_DIR/extras.d/*.sh; do [[ -r $i ]] && source $i unstack @@ -58,21 +90,26 @@ if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then teardown_neutron_debug fi -# Shut down devstack's screen to get the bulk of OpenStack services in one shot -SCREEN=$(which screen) -if [[ -n "$SCREEN" ]]; then - SESSION=$(screen -ls | awk '/[0-9].stack/ { print $1 }') - if [[ -n "$SESSION" ]]; then - screen -X -S $SESSION quit - fi +# Call service stop + +if is_service_enabled heat; then + stop_heat +fi + +if is_service_enabled ceilometer; then + stop_ceilometer +fi + +if is_service_enabled nova; then + stop_nova +fi + +if is_service_enabled g-api g-reg; then + stop_glance fi -# Shut down Nova hypervisor plugins after Nova -NOVA_PLUGINS=$TOP_DIR/lib/nova_plugins -if is_service_enabled nova && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then - # Load plugin - source $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER - stop_nova_hypervisor +if is_service_enabled key; then + stop_keystone fi # Swift runs daemons @@ -106,6 +143,7 @@ SCSI_PERSIST_DIR=$CINDER_STATE_PATH/volumes/* # Get the iSCSI volumes if is_service_enabled cinder; then + stop_cinder cleanup_cinder fi @@ -135,4 +173,13 @@ if is_service_enabled trove; then cleanup_trove fi +# Clean up the remainder of the screen processes +SCREEN=$(which screen) +if [[ -n "$SCREEN" ]]; then + SESSION=$(screen -ls | awk '/[0-9].stack/ { print $1 }') + if [[ -n "$SESSION" ]]; then + screen -X -S $SESSION quit + fi +fi + cleanup_tmp From 1d5001f70aa27210a8099b001f33537a1055943d Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Tue, 22 Apr 2014 10:38:35 +0530 Subject: [PATCH 132/179] Generate agent configuration in INI format instead of XML format --- contrail/contrail_config_templates.py | 334 ++++++++++++++++++++++---- contrail/setup_contrail.py | 10 +- lib/neutron_thirdparty/contrail | 2 +- 3 files changed, 292 insertions(+), 54 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 9861384428..e36f3219d6 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -227,65 +227,303 @@ agent_param_template = string.Template(""" LOG=/var/log/contrail.log -CONFIG=/etc/contrail/agent.conf +CONFIG=/etc/contrail/vnswad.conf prog=/usr/bin/vnswad kmod=vrouter/vrouter.ko pname=vnswad LIBDIR=/usr/lib64 VHOST_CFG=/etc/sysconfig/network-scripts/ifcfg-vhost0 -VROUTER_LOGFILE=--log-file=/var/log/vrouter.log +VROUTER_LOGFILE=--DEFAULT.log_file=/var/log/vrouter.log COLLECTOR=$__contrail_collector__ $__contrail_dev__ """) -agent_conf_template = string.Template(""" - - - - - - vhost0 - $__contrail_box_ip__ - $__contrail_gateway__ - - - $__contrail_intf__ - - - $__contrail_box_ip__ - - - $__contrail_control_ip__ - - - +vnswad_conf_template = string.Template(""" +# +# Vnswad configuration options +# + +[COLLECTOR] +# IP address and port to be used to connect to collector. If IP is not configured, +# value provided by discovery service will be used. (Optional) +# port=8086 +# server= + +[CONTROL-NODE] +# IP address to be used to connect to control-node. Maximum of 2 IP addresses +# (separated by a space) can be provided. If no IP is configured then the +# value provided by discovery service will be used. (Optional) +server=$__contrail_control_ip__ + +[DEFAULT] +# Everything in this section is optional + +# Enable/disable debug logging. Possible values are 0 (disable) and 1 (enable) +# debug=0 + +# Aging time for flow-records in seconds +# flow_cache_timeout=0 + +# Hostname of compute-node. If this is not configured value from `hostname` +# will be taken +# hostname= + +# Http server port for inspecting vnswad state (useful for debugging) +# http_server_port=8085 + +# Category for logging. Default value is '*' +# log_category= + +# Local log file name +# log_file=/var/log/contrail/vrouter.log + +# Log severity levels. Possible values are SYS_EMERG, SYS_ALERT, SYS_CRIT, +# SYS_ERR, SYS_WARN, SYS_NOTICE, SYS_INFO and SYS_DEBUG. Default is SYS_DEBUG +# log_level=SYS_DEBUG + +# Enable/Disable local file logging. Possible values are 0 (disable) and 1 (enable) +# log_local=0 + +# Encapsulation type for tunnel. Possible values are MPLSoGRE, MPLSoUDP, VXLAN +# tunnel_type= + +[DISCOVERY] +# If COLLECTOR and/or CONTROL-NODE and/or DNS is not specified this section is +# mandatory. Else this section is optional + +# IP address of discovery server +# server=x.x.x.x + +# Number of control-nodes info to be provided by Discovery service. Possible +# values are 1 and 2 +# max_control_nodes= + +[DNS] +# IP address to be used to connect to dns-node. Maximum of 2 IP addresses +# (separated by a space) can be provided. If no IP is configured then the +# value provided by discovery service will be used. (Optional) +# server=10.0.0.1 10.0.0.2 + +[HYPERVISOR] +# Everything in this section is optional + +# Hypervisor type. Possible values are kvm, xen and vmware +# type=kvm + +# Link-local IP address and prefix in ip/prefix_len format (for xen) +# xen_ll_ip= + +# Link-local interface name when hypervisor type is Xen +# xen_ll_interface= + +# Physical interface name when hypervisor type is vmware +# vmware_physical_interface= + +[LINK-LOCAL] +# Everything in this section is optional + +# Maximum number of link-local flows allowed across all VMs +# max_system_flows=4096 +# Maximum number of link-local flows allowed per VM +# max_vm_flows=1024 + +[METADATA] +# Shared secret for metadata proxy service (Optional) +# metadata_proxy_secret=contrail + +[NETWORKS] +# control-channel IP address used by WEB-UI to connect to vnswad to fetch +# required information (Optional) +control_network_ip=$__contrail_control_ip__ + +[VIRTUAL-HOST-INTERFACE] +# Everything in this section is mandatory + +# name of virtual host interface +name=vhost0 + +# IP address and prefix in ip/prefix_len format +ip=$__contrail_box_ip__ + +# Gateway IP address for virtual host +gateway=$__contrail_gateway__ + +# Physical interface name to which virtual host interface maps to +physical_interface=$__contrail_intf__ + +# We can have multiple gateway sections with different indices in the +# following format +[GATEWAY-0] +# Name of the routing_instance for which the gateway is being configured +# routing_instance=default-domain:admin:public:public + +# Gateway interface name +# interface=vgw + +# Virtual network ip blocks for which gateway service is required. Each IP +# block is represented as ip/prefix. Multiple IP blocks are represented by +# separating each with a space +# ip_blocks=1.1.1.1/24 + +[GATEWAY-1] +# Name of the routing_instance for which the gateway is being configured +# routing_instance=default-domain:admin:public1:public1 + +# Gateway interface name +# interface=vgw1 + +# Virtual network ip blocks for which gateway service is required. Each IP +# block is represented as ip/prefix. Multiple IP blocks are represented by +# separating each with a space +# ip_blocks=2.2.1.0/24 2.2.2.0/24 + +# Routes to be exported in routing_instance. Each route is represented as +# ip/prefix. Multiple routes are represented by separating each with a space +# routes=10.10.10.1/24 11.11.11.1/24 """) -agent_vgw_conf_template = string.Template(""" - - - - - - vhost0 - $__contrail_box_ip__ - $__contrail_gateway__ - - - $__contrail_intf__ - - - $__contrail_control_ip__ - - - $__contrail_control_ip__ - - - $__contrail_vgw_interface__ - $__contrail_vgw_public_subnet__ - - - +vnswad_vgw_conf_template = string.Template(""" +# +# Vnswad configuration options +# + +[COLLECTOR] +# IP address and port to be used to connect to collector. If IP is not configured, +# value provided by discovery service will be used. (Optional) +# port=8086 +# server= + +[CONTROL-NODE] +# IP address to be used to connect to control-node. Maximum of 2 IP addresses +# (separated by a space) can be provided. If no IP is configured then the +# value provided by discovery service will be used. (Optional) +server=$__contrail_control_ip__ + +[DEFAULT] +# Everything in this section is optional + +# Enable/disable debug logging. Possible values are 0 (disable) and 1 (enable) +# debug=0 + +# Aging time for flow-records in seconds +# flow_cache_timeout=0 + +# Hostname of compute-node. If this is not configured value from `hostname` +# will be taken +# hostname= + +# Http server port for inspecting vnswad state (useful for debugging) +# http_server_port=8085 + +# Category for logging. Default value is '*' +# log_category= + +# Local log file name +# log_file=/var/log/contrail/vrouter.log + +# Log severity levels. Possible values are SYS_EMERG, SYS_ALERT, SYS_CRIT, +# SYS_ERR, SYS_WARN, SYS_NOTICE, SYS_INFO and SYS_DEBUG. Default is SYS_DEBUG +# log_level=SYS_DEBUG + +# Enable/Disable local file logging. Possible values are 0 (disable) and 1 (enable) +# log_local=0 + +# Encapsulation type for tunnel. Possible values are MPLSoGRE, MPLSoUDP, VXLAN +# tunnel_type= + +[DISCOVERY] +# If COLLECTOR and/or CONTROL-NODE and/or DNS is not specified this section is +# mandatory. Else this section is optional + +# IP address of discovery server +# server=x.x.x.x + +# Number of control-nodes info to be provided by Discovery service. Possible +# values are 1 and 2 +# max_control_nodes= + +[DNS] +# IP address to be used to connect to dns-node. Maximum of 2 IP addresses +# (separated by a space) can be provided. If no IP is configured then the +# value provided by discovery service will be used. (Optional) +# server=10.0.0.1 10.0.0.2 + +[HYPERVISOR] +# Everything in this section is optional + +# Hypervisor type. Possible values are kvm, xen and vmware +# type=kvm + +# Link-local IP address and prefix in ip/prefix_len format (for xen) +# xen_ll_ip= + +# Link-local interface name when hypervisor type is Xen +# xen_ll_interface= + +# Physical interface name when hypervisor type is vmware +# vmware_physical_interface= + +[LINK-LOCAL] +# Everything in this section is optional + +# Maximum number of link-local flows allowed across all VMs +# max_system_flows=4096 +# Maximum number of link-local flows allowed per VM +# max_vm_flows=1024 + +[METADATA] +# Shared secret for metadata proxy service (Optional) +# metadata_proxy_secret=contrail + +[NETWORKS] +# control-channel IP address used by WEB-UI to connect to vnswad to fetch +# required information (Optional) +control_network_ip=$__contrail_control_ip__ + +[VIRTUAL-HOST-INTERFACE] +# Everything in this section is mandatory + +# name of virtual host interface +name=vhost0 + +# IP address and prefix in ip/prefix_len format +ip=$__contrail_box_ip__ + +# Gateway IP address for virtual host +gateway=$__contrail_gateway__ + +# Physical interface name to which virtual host interface maps to +physical_interface=$__contrail_intf__ + +# We can have multiple gateway sections with different indices in the +# following format +[GATEWAY-0] +# Name of the routing_instance for which the gateway is being configured +routing_instance=$__contrail_vgw_public_network__ + +# Gateway interface name +interface=$__contrail_vgw_interface__ + +# Virtual network ip blocks for which gateway service is required. Each IP +# block is represented as ip/prefix. Multiple IP blocks are represented by +# separating each with a space +ip_blocks=$__contrail_vgw_public_subnet__ + +[GATEWAY-1] +# Name of the routing_instance for which the gateway is being configured +# routing_instance=default-domain:admin:public1:public1 + +# Gateway interface name +# interface=vgw1 + +# Virtual network ip blocks for which gateway service is required. Each IP +# block is represented as ip/prefix. Multiple IP blocks are represented by +# separating each with a space +# ip_blocks=2.2.1.0/24 2.2.2.0/24 + +# Routes to be exported in routing_instance. Each route is represented as +# ip/prefix. Multiple routes are represented by separating each with a space +# routes=10.10.10.1/24 11.11.11.1/24 """) ifconfig_vhost0_template = string.Template(""" diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 40ee681915..43a4a57c77 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -751,8 +751,8 @@ def fixup_config_files(self): '__contrail_instances__' : ncontrols, '__contrail_control_ip__' : cfgm_ip, } - self._template_substitute_write(agent_conf_template, - template_vals, "agent.conf") + self._template_substitute_write(vnswad_conf_template, + template_vals, "vnswad.conf") else: template_vals = { '__contrail_box_ip__' : cidr, @@ -765,10 +765,10 @@ def fixup_config_files(self): '__contrail_vgw_public_subnet__' : vgw_public_subnet, '__contrail_vgw_public_network__' : vgw_public_network, } - self._template_substitute_write(agent_vgw_conf_template, - template_vals, "agent.conf") + self._template_substitute_write(vnswad_vgw_conf_template, + template_vals, "vnswad.conf") - self.run_shell("sudo mv agent.conf /etc/contrail/agent.conf") + self.run_shell("sudo mv vnswad.conf /etc/contrail/vnswad.conf") ## make ifcfg-vhost0 with open ('%s/ifcfg-vhost0' % temp_dir_name, 'w') as f: diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index a788a2ed12..3a3933980e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -382,7 +382,7 @@ EOF2 cat > $TOP_DIR/bin/vnsw.hlpr < Date: Wed, 23 Apr 2014 22:23:47 -0700 Subject: [PATCH 133/179] change agent conf section name from LINK-LOCAL to FLOWS --- contrail/contrail_config_templates.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index e36f3219d6..7d31ce2308 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -319,13 +319,17 @@ # Physical interface name when hypervisor type is vmware # vmware_physical_interface= -[LINK-LOCAL] +[FLOWS] # Everything in this section is optional +# Maximum number of flows allowed in the vrouter, across all VMs +# max_system_flows= +# Maximum number of flows allowed per VM +# max_vm_flows= # Maximum number of link-local flows allowed across all VMs -# max_system_flows=4096 +# max_system_linklocal_flows=4096 # Maximum number of link-local flows allowed per VM -# max_vm_flows=1024 +# max_vm_linklocal_flows=1024 [METADATA] # Shared secret for metadata proxy service (Optional) @@ -463,13 +467,17 @@ # Physical interface name when hypervisor type is vmware # vmware_physical_interface= -[LINK-LOCAL] +[FLOWS] # Everything in this section is optional +# Maximum number of flows allowed in the vrouter, across all VMs +# max_system_flows= +# Maximum number of flows allowed per VM +# max_vm_flows= # Maximum number of link-local flows allowed across all VMs -# max_system_flows=4096 +# max_system_linklocal_flows=4096 # Maximum number of link-local flows allowed per VM -# max_vm_flows=1024 +# max_vm_linklocal_flows=1024 [METADATA] # Shared secret for metadata proxy service (Optional) From 5cacb8c6a48bdc87c9fa8528ae60c84a3f162d65 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 24 Apr 2014 13:49:06 +0000 Subject: [PATCH 134/179] Add simple test script to create a couple of networks and launch VM --- contrail/test_network_simple.sh | 67 +++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100755 contrail/test_network_simple.sh diff --git a/contrail/test_network_simple.sh b/contrail/test_network_simple.sh new file mode 100755 index 0000000000..b6c8855f13 --- /dev/null +++ b/contrail/test_network_simple.sh @@ -0,0 +1,67 @@ +#! /bin/bash +# +# test_network_simple.sh +# +# Set up a couple of test VMs on two networks on a single +# node setup +# +# uses localrc-single +# + + +set -ex + +die() { + echo "ERROR: " "$@" >&2 + exit 1 +} + +. ./openrc admin demo + +# allow ping and ssh +nova secgroup-list +nova secgroup-list-rules default +nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 +nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +nova secgroup-list-rules default + +# net1 +eval $(neutron net-create -f shell -c id net1 | sed -ne '/^id=/p') +net1_id=$id +echo "net1_id=$net1_id" +neutron subnet-create --name net1-subnet1 $net1_id 10.1.0.0/24 + +# net2 (cloud) +eval $(neutron net-create -f shell -c id net2 | sed -ne '/^id=/p') +net2_id=$id +echo "net2_id=$net2_id" +neutron subnet-create --name net2-subnet1 $net2_id 10.2.0.0/24 + +# if the net_policy_join script exists, then use it to join net1 and net2 +# use ${BASH_SOURCE[0]} instead of $0, because it works when this script is sourced +THIS_DIR=$(dirname ${BASH_SOURCE[0]}) +PATH=$THIS_DIR:$PATH +if which net_policy_join.py; then + net_policy_join.py $net1_id $net2_id +fi + + +# stock image form vms +image=cirros-0.3.1-x86_64-uec # default stock image + +yes | ssh-keygen -N "" -f sshkey +nova keypair-add --pub-key sshkey.pub sshkey + +flavor=m1.tiny +vmargs="--image $image --flavor $flavor --key-name sshkey" + +# vm1: net1 +nova boot $vmargs --nic net-id=$net1_id vm1 + +# vm2: net2 +nova boot $vmargs --nic net-id=$net2_id vm2 + +# show where the vms ended up +nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host + +set +ex From 0e284646bb8c11d1c236a87340ffc2ea0fd0ce6b Mon Sep 17 00:00:00 2001 From: Hari Date: Fri, 25 Apr 2014 11:17:55 -0700 Subject: [PATCH 135/179] update the vnswad config template - FLOWS section --- contrail/contrail_config_templates.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 7d31ce2308..542536fb57 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -322,10 +322,8 @@ [FLOWS] # Everything in this section is optional -# Maximum number of flows allowed in the vrouter, across all VMs -# max_system_flows= -# Maximum number of flows allowed per VM -# max_vm_flows= +# Maximum flows allowed per VM (given as % of maximum system flows) +# max_vm_flows=100 # Maximum number of link-local flows allowed across all VMs # max_system_linklocal_flows=4096 # Maximum number of link-local flows allowed per VM @@ -470,10 +468,8 @@ [FLOWS] # Everything in this section is optional -# Maximum number of flows allowed in the vrouter, across all VMs -# max_system_flows= -# Maximum number of flows allowed per VM -# max_vm_flows= +# Maximum flows allowed per VM (given as % of maximum system flows) +# max_vm_flows=100 # Maximum number of link-local flows allowed across all VMs # max_system_linklocal_flows=4096 # Maximum number of link-local flows allowed per VM From 915d505790289ad8adc20d6decf32051a8fffd77 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Apr 2014 14:50:35 -0700 Subject: [PATCH 136/179] a few fixes to analytics daemons startup --- contrail/localrc-single | 5 +++++ contrail/setup_contrail.py | 13 ++----------- lib/neutron_thirdparty/contrail | 9 +++------ 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index f326e0b2b5..c20f6184ec 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -18,6 +18,11 @@ enable_service agent enable_service disco enable_service redis enable_service contrail +enable_service redis-u +enable_service redis-q +enable_service vizd +enable_service opserver +enable_service qed disable_service n-net enable_service q-svc diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 3bc56d9e21..a88d4a70f0 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -473,36 +473,27 @@ def fixup_config_files(self): # collector in Phase 2 if 'collector' in self._args.role: - self.run_shell("wget http://download.redis.io/releases/redis-2.6.14.tar.gz") - self.run_shell("tar xvzf redis-2.6.14.tar.gz redis-2.6.14/sentinel.conf") - self.run_shell("cp redis-2.6.14/sentinel.conf /opt/stack/sentinel.conf") - self.run_shell("rm -rf redis-2.6.14 redis-2.6.14.tar.gz") - REDIS_SENTINEL_BASE="/opt/stack/sentinel.conf" REDIS_UVE="/etc/contrail/redis-uve.conf" REDIS_QUERY="/etc/contrail/redis-query.conf" - REDIS_SENTINEL="/etc/contrail/sentinel.conf" if os.path.isfile('/etc/redis/redis.conf'): REDIS_CONF="/etc/redis/redis.conf" else: REDIS_CONF="/etc/redis.conf" self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_UVE)) self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_QUERY)) - self.run_shell("cp %s %s" %(REDIS_SENTINEL_BASE, REDIS_SENTINEL)) self.replace_in_file(REDIS_UVE, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-uve.pid') self.replace_in_file(REDIS_UVE, 'port 6379', 'port 6381') self.replace_in_file(REDIS_UVE, 'bind 127.0.0.1', '#bind 127.0.0.1') - self.replace_in_file(REDIS_UVE, 'logfile /var/log/redis/redis.log', 'logfile /var/log/redis/redis-uve.log') + self.replace_in_file(REDIS_UVE, 'logfile /var/log/redis/redis-server.log', 'logfile /var/log/redis/redis-uve.log') self.replace_in_file(REDIS_UVE, 'dbfilename dump.rdb', 'dbfilename dump-uve.rdb') self.replace_in_file(REDIS_QUERY, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-query.pid') self.replace_in_file(REDIS_QUERY, 'port 6379', 'port 6380') self.replace_in_file(REDIS_QUERY, 'bind 127.0.0.1', '#bind 127.0.0.1') - self.replace_in_file(REDIS_QUERY, 'logfile /var/log/redis/redis.log', 'logfile /var/log/redis/redis-query.log') + self.replace_in_file(REDIS_QUERY, 'logfile /var/log/redis/redis-server.log', 'logfile /var/log/redis/redis-query.log') self.replace_in_file(REDIS_QUERY, 'dbfilename dump.rdb', 'dbfilename dump-query.rdb') - self.replace_in_file(REDIS_SENTINEL, 'sentinel monitor mymaster 127.0.0.1 6379 2', 'sentinel monitor mymaster '+collector_ip+' 6381 1') - template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, '__contrail_host_ip__': self._args.collector_ip, '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 3cb01ada0c..d30c4f5f18 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -336,7 +336,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD} --reset_config" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" @@ -347,7 +347,7 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --collectors ${COLLECTOR}" + screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --DEFAULT.collectors ${COLLECTOR}:${COLLECTOR_PORT}" # collector services # redis-uve @@ -356,9 +356,6 @@ function start_contrail() { # redis-query screen_it redis-q "sudo redis-server /etc/contrail/redis-query.conf" sleep 2 - # redis-sentinel - screen_it redis-s "sudo redis-server /etc/contrail/sentinel.conf --sentinel" - sleep 2 # collector/vizd source /etc/contrail/vizd_param @@ -370,7 +367,7 @@ function start_contrail() { sleep 2 source /etc/contrail/qed_param - screen_it qed "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/query_engine/qed --collectors ${COLLECTORS} --cassandra_server_list ${CASSANDRA_SERVER_LIST} --REDIS.server ${REDIS_SERVER} --REDIS.port ${REDIS_SERVER_PORT} log_file /var/log/contrail/qe.log ${LOG_LOCAL}" + screen_it qed "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/query_engine/qed --DEFAULT.collectors ${COLLECTORS} --DEFAULT.cassandra_server_list ${CASSANDRA_SERVER_LIST} --REDIS.server ${REDIS_SERVER} --REDIS.port ${REDIS_SERVER_PORT} --DEFAULT.log_file /var/log/contrail/qe.log --DEFAULT.log_local" sleep 2 # Provision Vrouter - must be run after API server and schema transformer are up From 29bc4288ce54f78a78b28940971d98657735a155 Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Mon, 28 Apr 2014 10:02:50 +0000 Subject: [PATCH 137/179] Add localrc variables to change Cassandra memory options --- contrail/localrc-single | 3 +++ lib/neutron_thirdparty/contrail | 13 +++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index f326e0b2b5..43d5e4cdec 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -51,3 +51,6 @@ NEUTRON_BRANCH=master # use contrail VIF driver with NOVA NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver + +CASS_MAX_HEAP_SIZE=1G +CASS_HEAP_NEWSIZE=200M diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 3a3933980e..95456b16a2 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -11,6 +11,10 @@ set -o xtrace BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80} BS_FL_OF_PORT=${BS_FL_OF_PORT:-6633} +# Cassandra JAVA Memory Options +CASS_MAX_HEAP_SIZE=${CASS_MAX_HEAP_SIZE:-1G} +CASS_HEAP_NEWSIZE=${CASS_HEAP_NEWSIZE:-200M} + function install_contrail() { sudo mkdir -p /var/log/contrail sudo chmod 777 /var/log/contrail @@ -115,9 +119,6 @@ function install_contrail() { apt_get update apt_get install --force-yes cassandra - # fix cassandra's stack size issues - test_install_cassandra_patch - # don't start cassandra at boot. I'll screen_it later sudo service cassandra stop sudo update-rc.d -f cassandra remove @@ -196,10 +197,6 @@ function apply_patch() { fi } -function test_install_cassandra_patch() { - apply_patch $TOP_DIR/contrail/cassandra-env.sh.patch /etc/cassandra sudo -} - function test_install_neutron_patch() { apply_patch $TOP_DIR/contrail/neutron_v4.patch $DEST/neutron } @@ -318,7 +315,7 @@ function start_contrail() { redis-cli flushall screen_it redis "sudo redis-server $REDIS_CONF" - screen_it cass "sudo $CASS_PATH -f" + screen_it cass "export MAX_HEAP_SIZE=$CASS_MAX_HEAP_SIZE; export HEAP_NEWSIZE=$CASS_HEAP_NEWSIZE; sudo $CASS_PATH -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.6; ./bin/zkServer.sh start" From 573afc2cef05e488f495019071e0cef257dab192 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 29 Apr 2014 12:04:30 +0000 Subject: [PATCH 138/179] simple test script - allow some delay for VM to come up before poking --- contrail/contrail_config_templates.py | 4 ++-- contrail/test_network_simple.sh | 3 +++ lib/neutron_thirdparty/contrail | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 542536fb57..9887615bc9 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -14,8 +14,8 @@ auth=keystone multi_tenancy=$__contrail_multi_tenancy__ log_file=$__contrail_log_file__ -disc_server_ip=$__contrail_disc_server_ip__ -disc_server_port=$__contrail_disc_server_port__ +#disc_server_ip=$__contrail_disc_server_ip__ +#disc_server_port=$__contrail_disc_server_port__ [SECURITY] use_certs=$__contrail_use_certs__ diff --git a/contrail/test_network_simple.sh b/contrail/test_network_simple.sh index b6c8855f13..94f8bb67e7 100755 --- a/contrail/test_network_simple.sh +++ b/contrail/test_network_simple.sh @@ -61,6 +61,9 @@ nova boot $vmargs --nic net-id=$net1_id vm1 # vm2: net2 nova boot $vmargs --nic net-id=$net2_id vm2 +# allow VM to come up +sleep 2 + # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 3a3933980e..db392922cd 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -330,7 +330,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --reset_config --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" From 2889f3ee3ad22432dc0c8fd25ac49afea9dc0ec7 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 29 Apr 2014 12:07:06 +0000 Subject: [PATCH 139/179] Revert "simple test script - allow some delay for VM to come up before poking" This reverts commit 573afc2cef05e488f495019071e0cef257dab192. --- contrail/contrail_config_templates.py | 4 ++-- contrail/test_network_simple.sh | 3 --- lib/neutron_thirdparty/contrail | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 9887615bc9..542536fb57 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -14,8 +14,8 @@ auth=keystone multi_tenancy=$__contrail_multi_tenancy__ log_file=$__contrail_log_file__ -#disc_server_ip=$__contrail_disc_server_ip__ -#disc_server_port=$__contrail_disc_server_port__ +disc_server_ip=$__contrail_disc_server_ip__ +disc_server_port=$__contrail_disc_server_port__ [SECURITY] use_certs=$__contrail_use_certs__ diff --git a/contrail/test_network_simple.sh b/contrail/test_network_simple.sh index 94f8bb67e7..b6c8855f13 100755 --- a/contrail/test_network_simple.sh +++ b/contrail/test_network_simple.sh @@ -61,9 +61,6 @@ nova boot $vmargs --nic net-id=$net1_id vm1 # vm2: net2 nova boot $vmargs --nic net-id=$net2_id vm2 -# allow VM to come up -sleep 2 - # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index db392922cd..3a3933980e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -330,7 +330,7 @@ function start_contrail() { sleep 2 # find the directory where vnc_cfg_api_server was installed and start vnc_cfg_api_server.py - screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --reset_config --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" + screen_it apiSrv "python $(pywhere vnc_cfg_api_server)/vnc_cfg_api_server.py --conf_file /etc/contrail/api_server.conf --rabbit_password ${RABBIT_PASSWORD}" echo "Waiting for api-server to start..." if ! timeout $SERVICE_TIMEOUT sh -c "while ! http_proxy= wget -q -O- http://${SERVICE_HOST}:8082; do sleep 1; done"; then echo "api-server did not start" From 11aa4e46f6f1da681c92c87e54d2b6983af77a4e Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 29 Apr 2014 12:09:38 +0000 Subject: [PATCH 140/179] simple test script - allow some delay for VM to come up before poking --- contrail/test_network_simple.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrail/test_network_simple.sh b/contrail/test_network_simple.sh index b6c8855f13..94f8bb67e7 100755 --- a/contrail/test_network_simple.sh +++ b/contrail/test_network_simple.sh @@ -61,6 +61,9 @@ nova boot $vmargs --nic net-id=$net1_id vm1 # vm2: net2 nova boot $vmargs --nic net-id=$net2_id vm2 +# allow VM to come up +sleep 2 + # show where the vms ended up nova list --fields name,status,Networks,OS-EXT-SRV-ATTR:host From 2c952597531818ed008ca34c75654e6007a16b88 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 30 Apr 2014 15:04:37 +0000 Subject: [PATCH 141/179] Workaround for oslo.config not installing for some reason --- lib/neutron_thirdparty/contrail | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 95456b16a2..d918df8c2a 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -172,6 +172,13 @@ function install_contrail() { python $TOP_DIR/contrail/setup_contrail.py --physical_interface=$PHYSICAL_INTERFACE --cfgm_ip $SERVICE_HOST $contrail_gw_interface ) + # oslo.config + if ! python -c 'import oslo.config' >/dev/null 2>&1; then + contrail_cwd=$(pwd) + cd /opt/stack/oslo.config + sudo python setup.py install + cd ${contrail_cwd} + fi } function apply_patch() { From 2c98c1c03b6a18b193ead4e6a5905470f929d159 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 30 Apr 2014 15:05:05 +0000 Subject: [PATCH 142/179] Allow script to rerun --- contrail/test_network_simple.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/contrail/test_network_simple.sh b/contrail/test_network_simple.sh index 94f8bb67e7..10531b3edc 100755 --- a/contrail/test_network_simple.sh +++ b/contrail/test_network_simple.sh @@ -20,9 +20,12 @@ die() { # allow ping and ssh nova secgroup-list -nova secgroup-list-rules default -nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 -nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +if ! nova secgroup-list-rules default | grep tcp | grep 22; then + nova secgroup-add-rule default tcp 22 22 0.0.0.0/0 +fi +if ! nova secgroup-list-rules default | grep icmp | grep "\-1"; then + nova secgroup-add-rule default icmp -1 -1 0.0.0.0/0 +fi nova secgroup-list-rules default # net1 From 3d22ce3ee39077c198813ba38cff4ed52a66d00c Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 2 May 2014 10:40:45 +0000 Subject: [PATCH 143/179] fix for https://bugs.launchpad.net/opencontrail/+bug/1271735; run control-node as root --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index d918df8c2a..e1f0a2d4a5 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -345,7 +345,7 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "export LD_LIBRARY_PATH=/opt/stack/contrail/build/lib; $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + screen_it control "sudo LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" # Provision Vrouter - must be run after API server and schema transformer are up sleep 2 From 1cb5b1e0be7a68fb80df7de487df1077412d4eb1 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 2 May 2014 11:29:03 +0000 Subject: [PATCH 144/179] fix for https://bugs.launchpad.net/opencontrail/+bug/1271735; fix path --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e1f0a2d4a5..b6b7672f47 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -345,7 +345,7 @@ function start_contrail() { screen_it svc-mon "python $(pywhere svc_monitor)/svc_monitor.py --reset_config --conf_file /etc/contrail/svc_monitor.conf" source /etc/contrail/control_param - screen_it control "sudo LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" + screen_it control "sudo PATH=$PATH:$TOP_DIR/bin LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL}" # Provision Vrouter - must be run after API server and schema transformer are up sleep 2 From 9a5f5434951518d1adccf9d65b2bfb32feb85a1b Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 2 May 2014 11:35:15 +0000 Subject: [PATCH 145/179] Fix for https://bugs.launchpad.net/opencontrail/+bug/1311670; fix passing env variable to sudo --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index b6b7672f47..cc48b0feb5 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -322,7 +322,7 @@ function start_contrail() { redis-cli flushall screen_it redis "sudo redis-server $REDIS_CONF" - screen_it cass "export MAX_HEAP_SIZE=$CASS_MAX_HEAP_SIZE; export HEAP_NEWSIZE=$CASS_HEAP_NEWSIZE; sudo $CASS_PATH -f" + screen_it cass "sudo MAX_HEAP_SIZE=$CASS_MAX_HEAP_SIZE HEAP_NEWSIZE=$CASS_HEAP_NEWSIZE $CASS_PATH -f" screen_it zk "cd $CONTRAIL_SRC/third_party/zookeeper-3.4.6; ./bin/zkServer.sh start" From 295542c21c96e8ab12647283430bab081f0fdc28 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 May 2014 08:57:23 -0700 Subject: [PATCH 146/179] change the name of vrouter conf file --- contrail/setup_contrail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index a88d4a70f0..05324813e9 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -827,7 +827,7 @@ def fixup_config_files(self): self._template_substitute_write(vnswad_vgw_conf_template, template_vals, "vnswad.conf") - self.run_shell("sudo mv vnswad.conf /etc/contrail/vnswad.conf") + self.run_shell("sudo mv vnswad.conf /etc/contrail/contrail-vrouter-agent.conf") ## make ifcfg-vhost0 with open ('%s/ifcfg-vhost0' % temp_dir_name, 'w') as f: From f6a0057d560896716b7a9b4da6612e9ebd979cff Mon Sep 17 00:00:00 2001 From: Numan Siddique Date: Fri, 9 May 2014 19:20:22 +0530 Subject: [PATCH 147/179] qed_param file has invalid host_ip. Fixed it --- contrail/setup_contrail.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 05324813e9..f1ba867a79 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -506,6 +506,7 @@ def fixup_config_files(self): template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), + '__contrail_host_ip__': collector_ip, '__contrail_log_local__': '--log-local', '__contrail_log_file__': '--log-file=/var/log/contrail/qe.log', '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), From 19a993407c55029dabdd0294591185c0c20d1a9f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 9 May 2014 09:29:04 -0700 Subject: [PATCH 148/179] add webui processes to devstack --- contrail/contrail_config_templates.py | 4 +-- contrail/setup_contrail.py | 38 +++++++++++++-------------- lib/neutron_thirdparty/contrail | 25 +++++++++++++++++- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index dafd389c4e..d8e03f4973 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -250,8 +250,8 @@ [COLLECTOR] # IP address and port to be used to connect to collector. If IP is not configured, # value provided by discovery service will be used. (Optional) -# port=8086 -# server= +port=$__contrail_collector_port__ +server=$__contrail_collector_ip__ [CONTROL-NODE] # IP address to be used to connect to control-node. Maximum of 2 IP addresses diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 05324813e9..31045cded0 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -176,7 +176,7 @@ def _parse_args(self, args_str): self._args.openstack_mgmt_ip = self._args.cfgm_ip self._args.database_listen_ip = self._args.cfgm_ip self._args.cassandra_ip_list = ['127.0.0.1'] - self._args.role = ['config', 'openstack', 'control', 'compute', 'collector'] + self._args.role = ['config', 'openstack', 'control', 'compute', 'collector', 'webui'] #end _parse_args @@ -809,6 +809,8 @@ def fixup_config_files(self): '__contrail_disc_ip__' : discovery_ip, '__contrail_instances__' : ncontrols, '__contrail_control_ip__' : cfgm_ip, + '__contrail_collector_ip__' : collector_ip, + '__contrail_collector_port__' : '8086', } self._template_substitute_write(vnswad_conf_template, template_vals, "vnswad.conf") @@ -820,6 +822,8 @@ def fixup_config_files(self): '__contrail_disc_ip__' : discovery_ip, '__contrail_instances__' : ncontrols, '__contrail_control_ip__' : cfgm_ip, + '__contrail_collector_ip__' : collector_ip, + '__contrail_collector_port__' : '8086', '__contrail_vgw_interface__' : vgw_interface, '__contrail_vgw_public_subnet__' : vgw_public_subnet, '__contrail_vgw_public_network__' : vgw_public_network, @@ -880,25 +884,19 @@ def fixup_config_files(self): # role == compute && !cfgm if 'webui' in self._args.role: - openstack_ip = self._args.openstack_ip - self.run_shell("sudo sed \"s/config.cnfg.server_ip.*/config.cnfg.server_ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(cfgm_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - self.run_shell("sudo sed \"s/config.networkManager.ip.*/config.networkManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(cfgm_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - self.run_shell("sudo sed \"s/config.imageManager.ip.*/config.imageManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - self.run_shell("sudo sed \"s/config.computeManager.ip.*/config.computeManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - self.run_shell("sudo sed \"s/config.identityManager.ip.*/config.identityManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - self.run_shell("sudo sed \"s/config.storageManager.ip.*/config.storageManager.ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(openstack_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - if collector_ip: - self.run_shell("sudo sed \"s/config.analytics.server_ip.*/config.analytics.server_ip = '%s';/g\" /etc/contrail/config.global.js > config.global.js.new" %(collector_ip)) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") - if self._args.cassandra_ip_list: - self.run_shell("sudo sed \"s/config.cassandra.server_ips.*/config.cassandra.server_ips = %s;/g\" /etc/contrail/config.global.js > config.global.js.new" %(str(self._args.cassandra_ip_list))) - self.run_shell("sudo mv config.global.js.new /etc/contrail/config.global.js") + REDIS_WEBUI="/etc/contrail/redis-webui.conf" + if os.path.isfile('/etc/redis/redis.conf'): + REDIS_CONF="/etc/redis/redis.conf" + else: + REDIS_CONF="/etc/redis.conf" + self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_WEBUI)) + + self.replace_in_file(REDIS_WEBUI, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-webui.pid') + self.replace_in_file(REDIS_WEBUI, 'port 6379', 'port 6383') + self.replace_in_file(REDIS_WEBUI, 'bind 127.0.0.1', '#bind 127.0.0.1') + self.replace_in_file(REDIS_WEBUI, 'logfile /var/log/redis/redis-server.log', 'logfile /var/log/redis/redis-webui.log') + self.replace_in_file(REDIS_WEBUI, 'dbfilename dump.rdb', 'dbfilename dump-webui.rdb') + """ if 'config' in self._args.role and self._args.use_certs: diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 63bd30c87b..0d0bc94b69 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -187,6 +187,22 @@ function install_contrail() { sudo python setup.py install cd ${contrail_cwd} fi + if ! which node > /dev/null 2>&1 ; then + wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + tar -xf node-v0.8.15.tar.gz + contrail_cwd=$(pwd) + cd node-v0.8.15 + ./configure; make; sudo make install + cd ${contrail_cwd} + rm -rf node-v0.8.15.tar.gz + rm -rf node-v0.8.15 + fi + if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/contrail-web-core + ./fetch_packages.sh + make prod-env + fi } function apply_patch() { @@ -374,12 +390,15 @@ function start_contrail() { screen_it qed "sudo PATH=$PATH:$TOP_DIR/bin LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/query_engine/qed --DEFAULT.collectors ${COLLECTORS} --DEFAULT.cassandra_server_list ${CASSANDRA_SERVER_LIST} --REDIS.server ${REDIS_SERVER} --REDIS.port ${REDIS_SERVER_PORT} --DEFAULT.log_file /var/log/contrail/qe.log --DEFAULT.log_local" sleep 2 + #provision control + python /opt/stack/contrail/controller/src/config/utils/provision_control.py --api_server_ip $SERVICE_HOST --api_server_port 8082 --host_name $HOSTNAME --host_ip $HOST_IP + # Provision Vrouter - must be run after API server and schema transformer are up sleep 2 admin_user=${CONTRAIL_ADMIN_USERNAME:-"admin"} admin_passwd=${ADMIN_PASSWORD:-"contrail123"} admin_tenant=${CONTRAIL_ADMIN_TENANT:-"admin"} - python $TOP_DIR/contrail/provision_vrouter.py --host_name $HOSTNAME --host_ip $HOST_IP --api_server_ip $SERVICE_HOST --oper add --admin_user $admin_user --admin_password $admin_passwd --admin_tenant_name $admin_tenant + python /opt/stack/contrail/controller/src/config/utils/provision_vrouter.py --host_name $HOSTNAME --host_ip $HOST_IP --api_server_ip $SERVICE_HOST --oper add --admin_user $admin_user --admin_password $admin_passwd --admin_tenant_name $admin_tenant # vrouter test_insert_vrouter @@ -430,6 +449,10 @@ END --oper add fi + screen_it redis-w "sudo redis-server /etc/contrail/redis-webui.conf" + + screen_it ui-jobs "sudo node /opt/stack/contrail/contrail-web-core/jobServerStart.js" + screen_it ui-webs "sudo node /opt/stack/contrail/contrail-web-core/webServerStart.js" # restore saved screen settings SCREEN_NAME=$SAVED_SCREEN_NAME From cc5cd0fd60ce28d2a83de415d988821e15bab711 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 9 May 2014 09:32:26 -0700 Subject: [PATCH 149/179] enable webui processes --- contrail/localrc-single | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrail/localrc-single b/contrail/localrc-single index 2ac3ee91f1..30cbe44208 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -23,6 +23,9 @@ enable_service redis-q enable_service vizd enable_service opserver enable_service qed +enable_service redis-w +enable_service ui-jobs +enable_service ui-webs disable_service n-net enable_service q-svc From 9e7c4191115b436ca4eb6561965accc3701a89a7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 11 May 2014 20:37:09 -0700 Subject: [PATCH 150/179] qed does not require HOST_IP --- contrail/contrail_config_templates.py | 1 - 1 file changed, 1 deletion(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index d8e03f4973..845833a262 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -189,7 +189,6 @@ REDIS_SERVER_PORT=$__contrail_redis_server_port__ DISCOVERY=$__contrail_discovery_ip__ COLLECTORS=$__contrail_collectors__ -HOST_IP=$__contrail_host_ip__ LISTEN_PORT=$__contrail_listen_port__ HTTP_SERVER_PORT=$__contrail_http_server_port__ LOG_FILE=$__contrail_log_file__ From 142c03b8d26c7cac5ce0b93040236e78b333d6ad Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 11 May 2014 21:57:18 -0700 Subject: [PATCH 151/179] web ui processes need to be started in web-core directory --- lib/neutron_thirdparty/contrail | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 0d0bc94b69..0fd5983981 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -451,8 +451,8 @@ END screen_it redis-w "sudo redis-server /etc/contrail/redis-webui.conf" - screen_it ui-jobs "sudo node /opt/stack/contrail/contrail-web-core/jobServerStart.js" - screen_it ui-webs "sudo node /opt/stack/contrail/contrail-web-core/webServerStart.js" + screen_it ui-jobs "cd /opt/stack/contrail/contrail-web-core; sudo node jobServerStart.js" + screen_it ui-webs "cd /opt/stack/contrail/contrail-web-core; sudo node webServerStart.js" # restore saved screen settings SCREEN_NAME=$SAVED_SCREEN_NAME From 60a710e14029c8c02bf69a92e3cc039ded089e60 Mon Sep 17 00:00:00 2001 From: Ananth Suryanarayana Date: Mon, 12 May 2014 14:19:12 -0700 Subject: [PATCH 152/179] o Add an option to skip repo sync o Default PHYSICAL_INTERFACE to eth0 o Default to use https for git clone --- contrail/localrc-single | 4 ++-- lib/neutron_thirdparty/contrail | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index 30cbe44208..18636bc90d 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -45,7 +45,7 @@ ADMIN_PASSWORD=contrail123 ENABLE_CONTRAIL=yes Q_PLUGIN=contrail -PHYSICAL_INTERFACE=eth1 +PHYSICAL_INTERFACE=eth0 # use contrail forked neutron repo NEUTRON_REPO=https://github.com/dsetia/neutron.git @@ -55,7 +55,7 @@ NEUTRON_BRANCH=master # CONTRAIL_REPO_PROTO=https # proto for openstack bits. Use HTTPS if git is firewalled -# GIT_BASE=https://git.openstack.org +GIT_BASE=https://git.openstack.org # use contrail VIF driver with NOVA NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 0fd5983981..e77e3212ac 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -83,8 +83,13 @@ function install_contrail() { sed -i 's/fetch=".."/fetch=\"https:\/\/github.com\/Juniper\/\"/' .repo/manifest.xml fi fi - repo sync - python third_party/fetch_packages.py + + # If CONTRAIL_REPO_SETUP_SKIP is not set, sync the repo. + if [ -z $CONTRAIL_REPO_SYNC_SKIP ]; then + repo sync + python third_party/fetch_packages.py + fi + (cd third_party/thrift-*; touch configure.ac README ChangeLog; autoreconf --force --install) scons cd ${contrail_cwd} From aeba372450391c28b64bcf82cdffa07f7b1779de Mon Sep 17 00:00:00 2001 From: Ananth Suryanarayana Date: Mon, 12 May 2014 18:06:35 -0700 Subject: [PATCH 153/179] Use sudo tee when piping output --- contrail/setup_contrail.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 56a335dedc..888b9fa982 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -427,7 +427,7 @@ def fixup_config_files(self): # generate service token self.service_token = self._args.service_token if not self.service_token: - self.run_shell("sudo openssl rand -hex 10 > /etc/contrail/service.token") + self.run_shell("sudo openssl rand -hex 10 | sudo tee /etc/contrail/service.token > /dev/null") tok_fd = open('/etc/contrail/service.token') self.service_token = tok_fd.read() tok_fd.close() @@ -441,7 +441,7 @@ def fixup_config_files(self): """ # Disable selinux - self.run_shell("sudo sed 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config > config.new") + self.run_shell("sudo sed 's/SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config | sudo tee config.new > /dev/null") self.run_shell("sudo mv config.new /etc/selinux/config") self.run_shell("setenforce 0") @@ -706,7 +706,7 @@ def fixup_config_files(self): self.run_shell("echo 'api-server:api-server' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'schema-transformer:schema-transformer' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'svc-monitor:svc-monitor' >> %s/basicauthusers.properties" % dir) - self.run_shell("sudo sed -e '/%s:/d' -e '/%s.dns:/d' %s/%s > %s/%s.new" \ + self.run_shell("sudo sed -e '/%s:/d' -e '/%s.dns:/d' %s/%s | sudo tee %s/%s.new > /dev/null" \ %(control_ip, control_ip, dir, 'basicauthusers.properties', dir, 'basicauthusers.properties')) self.run_shell("echo '%s:%s' >> %s/%s.new" \ @@ -729,20 +729,20 @@ def fixup_config_files(self): self.run_shell('sudo cp /etc/libvirt/qemu.conf qemu.conf') self.run_shell('sudo chown %s qemu.conf' % whoami) if dist == 'centos': - self.run_shell('sudo echo "clear_emulator_capabilities = 1" >> qemu.conf') - self.run_shell('sudo echo \'user = "root"\' >> qemu.conf') - self.run_shell('sudo echo \'group = "root"\' >> qemu.conf') - self.run_shell('sudo echo \'cgroup_device_acl = [\' >> qemu.conf') - self.run_shell('sudo echo \' "/dev/null", "/dev/full", "/dev/zero",\' >> qemu.conf') - self.run_shell('sudo echo \' "/dev/random", "/dev/urandom",\' >> qemu.conf') - self.run_shell('sudo echo \' "/dev/ptmx", "/dev/kvm", "/dev/kqemu",\' >> qemu.conf') - self.run_shell('sudo echo \' "/dev/rtc", "/dev/hpet","/dev/net/tun",\' >> qemu.conf') - self.run_shell('sudo echo \']\' >> qemu.conf') + self.run_shell('sudo echo "clear_emulator_capabilities = 1" | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \'user = "root"\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \'group = "root"\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \'cgroup_device_acl = [\' | sudo tee -a qemu.conf') + self.run_shell('sudo echo \' "/dev/null", "/dev/full", "/dev/zero",\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \' "/dev/random", "/dev/urandom",\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \' "/dev/ptmx", "/dev/kvm", "/dev/kqemu",\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \' "/dev/rtc", "/dev/hpet","/dev/net/tun",\' | sudo tee -a qemu.conf > /dev/null') + self.run_shell('sudo echo \']\' | sudo tee -a qemu.conf > /dev/null') self.run_shell('sudo cp qemu.conf /etc/libvirt/qemu.conf') self._fixed_qemu_conf = True # add "alias bridge off" in /etc/modprobe.conf for Centos if dist == 'centos': - self.run_shell('sudo echo "alias bridge off" > /etc/modprobe.conf') + self.run_shell('sudo echo "alias bridge off" | sudo tee /etc/modprobe.conf > /dev/null') if 'compute' in self._args.role : openstack_ip = self._args.openstack_ip From 00a6e72d83b6f6346ddb528e6c2a1c0d21cd16b2 Mon Sep 17 00:00:00 2001 From: Ananth Suryanarayana Date: Mon, 12 May 2014 23:05:45 -0700 Subject: [PATCH 154/179] do not fetch node-v0.8.15.tar.gz if is already there. Also reduce timeouts for gpg --- lib/neutron_thirdparty/contrail | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e77e3212ac..b0034d2b03 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -124,9 +124,9 @@ function install_contrail() { # See http://wiki.apache.org/cassandra/DebianPackaging echo "deb http://www.apache.org/dist/cassandra/debian 12x main" | \ sudo tee /etc/apt/sources.list.d/cassandra.list - gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D + gpg --keyserver-options timeout=1 --keyserver pgp.mit.edu --recv-keys F758CE318D77295D gpg --export --armor F758CE318D77295D | sudo apt-key add - - gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 + gpg --keyserver-options timeout=1 --keyserver pgp.mit.edu --recv-keys 2B5C1B00 gpg --export --armor 2B5C1B00 | sudo apt-key add - apt_get update @@ -193,7 +193,9 @@ function install_contrail() { cd ${contrail_cwd} fi if ! which node > /dev/null 2>&1 ; then - wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + if [ ! -f node-v0.8.15.tar.gz]; then + wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + fi tar -xf node-v0.8.15.tar.gz contrail_cwd=$(pwd) cd node-v0.8.15 From 5a7380dab4ddfca1f1f811cd9e7a7c6b69b3dc7a Mon Sep 17 00:00:00 2001 From: Praveen K V Date: Wed, 14 May 2014 08:48:44 +0530 Subject: [PATCH 155/179] Handle change in path for vnswad --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e77e3212ac..29030201bc 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -437,7 +437,7 @@ EOF2 cat > $TOP_DIR/bin/vnsw.hlpr < Date: Wed, 14 May 2014 16:24:13 +0000 Subject: [PATCH 156/179] Add dependency for libvirt-bin to ensure /etc/libvirt/qemu.conf exists before contrail provisioning --- lib/neutron_thirdparty/contrail | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e77e3212ac..623cd73565 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -34,6 +34,7 @@ function install_contrail() { apt_get install python-dev autoconf automake build-essential libtool apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities + apt_get install libvirt-bin if ! which redis-server > /dev/null 2>&1 ; then sudo apt-get install libjemalloc1 @@ -50,6 +51,7 @@ function install_contrail() { sudo yum -y install libevent libevent-devel libxml2-devel libxslt-devel sudo yum -y install tunctl sudo yum -y install java-1.7.0-openjdk + sudo yum -y install libvirt-bin if ! which redis-server > /dev/null 2>&1 ; then wget http://mir01.syntis.net/atomic/fedora/17/x86_64/RPMS/redis-2.6.13-3.fc17.art.x86_64.rpm From 4cab62571ae2a8ffaa30402be8f68da96120a8c8 Mon Sep 17 00:00:00 2001 From: Biswajit Mandal Date: Thu, 5 Jun 2014 08:51:56 +0530 Subject: [PATCH 157/179] Changing the dev-stack web-ui dev-env based on new packaging scheme --- lib/neutron_thirdparty/contrail | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index fbe4e87474..f1ca2282c8 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -207,8 +207,8 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/contrail-web-core - ./fetch_packages.sh - make prod-env + make fetch-pkgs-prod + make dev-env REPO=webController fi } From df36c17d35ff011de5b68ad550991624f1e329e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89douard=20Thuleau?= Date: Wed, 4 Jun 2014 11:53:40 +0200 Subject: [PATCH 158/179] Use the OpenContrail Neutron plugin Use the OpenContrail Neutron plugin instead of the Neutron fork and make some cleanup on unsued file and code. --- contrail/README | 4 +- contrail/localrc-multinode-compute | 5 - contrail/localrc-multinode-server | 5 - contrail/localrc-single | 5 - contrail/neutron_v3.patch | 4706 ---------------------------- contrail/neutron_v4.patch | 3931 ----------------------- contrail/nova_v3.patch | 3252 ------------------- contrail/nova_v4.patch | 3252 ------------------- lib/neutron_plugins/contrail | 3 +- lib/neutron_thirdparty/contrail | 17 +- 10 files changed, 6 insertions(+), 15174 deletions(-) delete mode 100644 contrail/neutron_v3.patch delete mode 100644 contrail/neutron_v4.patch delete mode 100644 contrail/nova_v3.patch delete mode 100644 contrail/nova_v4.patch diff --git a/contrail/README b/contrail/README index 193653935e..f3c54669f0 100644 --- a/contrail/README +++ b/contrail/README @@ -10,8 +10,8 @@ Notes: 1) You will need to install kernel-devel package to compile OpenContrail Vrouter module 2) Stack.sh will create an additional screen "contrail" for contrail modules. -3) This fork includes Neutron and Nova patches. These patches have been - seperately submitted for review. +3) This fork use Nova and Neutron upstream master repositories and the + OpenContrail Nova VIF driver and Neutron plugin repositories. 4) OpenStack + OpenContrail has been tested on FC17, Ubuntu 12.04 and 13.10 5) Repo tool uses SSH by default. Use ssh-agent to forward keys to target running devstack or upload host's SSH keys to the github account. diff --git a/contrail/localrc-multinode-compute b/contrail/localrc-multinode-compute index a4a8431602..f4e088e436 100644 --- a/contrail/localrc-multinode-compute +++ b/contrail/localrc-multinode-compute @@ -6,7 +6,6 @@ SERVICE_HOST=192.168.56.119 # control1 # the interface that contrail's vhost0 should take over PHYSICAL_INTERFACE=eth0 -ENABLE_CONTRAIL=yes Q_PLUGIN=contrail STACK_DIR=$(cd $(dirname $0) && pwd) @@ -34,10 +33,6 @@ SERVICE_TOKEN=contrail123 SERVICE_PASSWORD=contrail123 ADMIN_PASSWORD=contrail123 DATABASE_TYPE=mysql -# -# use contrail forked neutron repo -NEUTRON_REPO=https://github.com/dsetia/neutron.git -NEUTRON_BRANCH=master # repo proto is https or (default) ssh. Leave commented for ssh # CONTRAIL_REPO_PROTO=https diff --git a/contrail/localrc-multinode-server b/contrail/localrc-multinode-server index 79f191c183..f270ec1793 100644 --- a/contrail/localrc-multinode-server +++ b/contrail/localrc-multinode-server @@ -6,7 +6,6 @@ CONTRAIL_VGW_INTERFACE=vgw CONTRAIL_VGW_PUBLIC_SUBNET=10.99.99.0/24 # CONTRAIL_VGW_PUBLIC_NETWORK=default-domain:demo:public:public -ENABLE_CONTRAIL=yes PHYSICAL_INTERFACE=eth0 MULTI_HOST=True @@ -51,10 +50,6 @@ SERVICE_TOKEN=contrail123 SERVICE_PASSWORD=contrail123 ADMIN_PASSWORD=contrail123 -# use contrail forked neutron repo -NEUTRON_REPO=https://github.com/dsetia/neutron.git -NEUTRON_BRANCH=master - # repo proto is https or (default) ssh. Leave commented for ssh # CONTRAIL_REPO_PROTO=https diff --git a/contrail/localrc-single b/contrail/localrc-single index 18636bc90d..8384f9c7e3 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -43,14 +43,9 @@ SERVICE_TOKEN=contrail123 SERVICE_PASSWORD=contrail123 ADMIN_PASSWORD=contrail123 -ENABLE_CONTRAIL=yes Q_PLUGIN=contrail PHYSICAL_INTERFACE=eth0 -# use contrail forked neutron repo -NEUTRON_REPO=https://github.com/dsetia/neutron.git -NEUTRON_BRANCH=master - # repo proto is https or (default) ssh. Leave commented for ssh # CONTRAIL_REPO_PROTO=https diff --git a/contrail/neutron_v3.patch b/contrail/neutron_v3.patch deleted file mode 100644 index 8f74cdb552..0000000000 --- a/contrail/neutron_v3.patch +++ /dev/null @@ -1,4706 +0,0 @@ -diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py -new file mode 100644 -index 0000000..5d610b3 ---- /dev/null -+++ neutron/extensions/ipam.py -@@ -0,0 +1,140 @@ -+from abc import abstractmethod -+ -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron.api import extensions -+from neutron import manager -+from oslo.config import cfg -+ -+ -+# Ipam Exceptions -+class IpamNotFound(qexception.NotFound): -+ message = _("IPAM %(id)s could not be found") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'ipams': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:regex': attr.UUID_PATTERN}, -+ 'is_visible': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'fq_name': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ 'mgmt': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': None}, -+ 'nets_using': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True, 'default': ''} -+ }, -+} -+ -+# TODO should this be tied to ipam extension? -+EXTENDED_ATTRIBUTES_2_0 = { -+ 'networks': { -+ 'contrail:fq_name': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:policys': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ 'contrail:subnet_ipam': {'allow_post': False, -+ 'allow_put': False, -+ 'default': '', -+ 'is_visible': True}, -+ }, -+ 'subnets': { -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:ipam_fq_name': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ } -+} -+ -+ -+class Ipam(object): -+ -+ @classmethod -+ def get_name(cls): -+ return "Network IP Address Management" -+ -+ @classmethod -+ def get_alias(cls): -+ return "ipam" -+ -+ @classmethod -+ def get_description(cls): -+ return ("Configuration object for holding common to a set of" -+ " IP address blocks") -+ -+ @classmethod -+ def get_namespace(cls): -+ return "http://docs.openstack.org/TODO" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2012-07-20T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ exts = [] -+ plugin = manager.QuantumManager.get_plugin() -+ for resource_name in ['ipam']: -+ collection_name = resource_name + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) -+ -+ member_actions = {} -+ -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, -+ member_actions=member_actions) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ member_actions=member_actions) -+ exts.append(ex) -+ -+ return exts -+ -+ def get_extended_resources(self, version): -+ if version == "2.0": -+ return EXTENDED_ATTRIBUTES_2_0 -+ else: -+ return {} -+#end class Ipam -+ -+ -+class IpamPluginBase(object): -+ -+ @abstractmethod -+ def create_ipam(self, context, ipam): -+ pass -+ -+ @abstractmethod -+ def update_ipam(self, context, id, ipam): -+ pass -+ -+ @abstractmethod -+ def get_ipam(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def delete_ipam(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_ipams(self, context, filters=None, fields=None): -+ pass -+#end class IpamPluginBase -diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py -index dbef592..f6b2144 100644 ---- neutron/extensions/portbindings.py -+++ neutron/extensions/portbindings.py -@@ -45,11 +45,12 @@ VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_HYPERV = 'hyperv' - VIF_TYPE_MIDONET = 'midonet' -+VIF_TYPE_CONTRAIL = 'contrail' - VIF_TYPE_OTHER = 'other' - VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, - VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, - VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_MIDONET, -- VIF_TYPE_OTHER] -+ VIF_TYPE_CONTRAIL, VIF_TYPE_OTHER] - - - EXTENDED_ATTRIBUTES_2_0 = { -diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py -new file mode 100644 -index 0000000..8028b32 ---- /dev/null -+++ neutron/plugins/juniper/contrail/contrailplugin.py -@@ -0,0 +1,1187 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+ -+import ConfigParser -+import logging -+from pprint import pformat -+ -+#from neutron.manager import NeutronManager -+from neutron.common import exceptions as exc -+from neutron.db import db_base_plugin_v2 -+from neutron.db import portbindings_base -+from neutron.extensions import l3 -+from neutron.extensions import securitygroup -+from neutron.extensions import portbindings -+#from neutron.extensions import vpcroutetable -+ -+import cgitb -+from httplib2 import Http -+from oslo.config import cfg -+import re -+import string -+import sys -+ -+import ctdb.config_db -+ -+LOG = logging.getLogger(__name__) -+ -+vnc_opts = [ -+ cfg.StrOpt('api_server_ip', default='127.0.0.1'), -+ cfg.StrOpt('api_server_port', default='8082'), -+] -+ -+ -+def _read_cfg(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.get(section, option) -+ except (AttributeError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+def _read_cfg_boolean(cfg_parser, section, option, default): -+ try: -+ val = cfg_parser.getboolean(section, option) -+ except (AttributeError, ValueError, -+ ConfigParser.NoOptionError, -+ ConfigParser.NoSectionError): -+ val = default -+ -+ return val -+ -+ -+class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, -+ l3.RouterPluginBase, -+ securitygroup.SecurityGroupPluginBase, -+ portbindings_base.PortBindingBaseMixin): -+#vpcroutetable.RouteTablePluginBase): -+ -+ supported_extension_aliases = ["ipam", "policy", "security-group", -+ "router", "route-table", "port-security", -+ "binding",] -+ __native_bulk_support = False -+ _cfgdb = None -+ _args = None -+ _tenant_id_dict = {} -+ _tenant_name_dict = {} -+ -+ @classmethod -+ def _parse_class_args(cls, cfg_parser): -+ cfg_parser.read("/etc/neutron/plugins/juniper/" -+ "contrail/ContrailPlugin.ini" -+ ) -+ cls._multi_tenancy = _read_cfg_boolean(cfg_parser, 'APISERVER', -+ 'multi_tenancy', False) -+ cls._admin_token = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_token', '') -+ cls._auth_url = _read_cfg(cfg_parser, 'KEYSTONE', 'auth_url', '') -+ cls._admin_user = _read_cfg(cfg_parser, 'KEYSTONE', 'admin_user', -+ 'user1') -+ cls._admin_password = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_password', 'password1') -+ cls._admin_tenant_name = _read_cfg(cfg_parser, 'KEYSTONE', -+ 'admin_tenant_name', -+ 'default-domain') -+ cls._tenants_api = '%s/tenants' % (cls._auth_url) -+ pass -+ -+ @classmethod -+ def _connect_to_db(cls): -+ """ -+ Many instantiations of plugin (base + extensions) but need to have -+ only one config db conn (else error from ifmap-server) -+ """ -+ cls._cfgdb_map = {} -+ if cls._cfgdb is None: -+ sip = cfg.CONF.APISERVER.api_server_ip -+ sport = cfg.CONF.APISERVER.api_server_port -+ # Initialize connection to DB and add default entries -+ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, -+ cls._admin_password, -+ cls._admin_tenant_name, -+ sip, sport) -+ cls._cfgdb.manager = cls -+ -+ @classmethod -+ def _get_user_cfgdb(cls, context): -+ if not cls._multi_tenancy: -+ return cls._cfgdb -+ user_id = context.user_id -+ role = string.join(context.roles, ",") -+ if user_id not in cls._cfgdb_map: -+ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( -+ cls._admin_user, cls._admin_password, cls._admin_tenant_name, -+ cfg.CONF.APISERVER.api_server_ip, -+ cfg.CONF.APISERVER.api_server_port, -+ user_info={'user_id': user_id, 'role': role}) -+ cls._cfgdb_map[user_id].manager = cls -+ -+ return cls._cfgdb_map[user_id] -+ -+ @classmethod -+ def _tenant_list_from_keystone(cls): -+ # get all tenants -+ hdrs = {'X-Auth-Token': cls._admin_token, -+ 'Content-Type': 'application/json'} -+ try: -+ rsp, content = Http().request(cls._tenants_api, -+ method="GET", headers=hdrs) -+ if rsp.status != 200: -+ return -+ except Exception: -+ return -+ -+ # transform needed for python compatibility -+ content = re.sub('true', 'True', content) -+ content = re.sub('null', 'None', content) -+ content = eval(content) -+ -+ # bail if response is unexpected -+ if 'tenants' not in content: -+ return -+ -+ # create a dictionary for id->name and name->id mapping -+ for tenant in content['tenants']: -+ print 'Adding tenant %s:%s to cache' % (tenant['name'], -+ tenant['id']) -+ cls._tenant_id_dict[tenant['id']] = tenant['name'] -+ cls._tenant_name_dict[tenant['name']] = tenant['id'] -+ -+ def update_security_group(self, context, id, security_group): -+ pass -+ -+ def __init__(self): -+ cfg.CONF.register_opts(vnc_opts, 'APISERVER') -+ -+ cfg_parser = ConfigParser.ConfigParser() -+ ContrailPlugin._parse_class_args(cfg_parser) -+ -+ ContrailPlugin._connect_to_db() -+ self._cfgdb = ContrailPlugin._cfgdb -+ -+ ContrailPlugin._tenant_list_from_keystone() -+ self.base_binding_dict = self._get_base_binding_dict() -+ portbindings_base.register_port_dict_function() -+ -+ def _get_base_binding_dict(self): -+ binding = { -+ portbindings.VIF_TYPE: portbindings.VIF_TYPE_CONTRAIL, -+ portbindings.CAPABILITIES: { -+ portbindings.CAP_PORT_FILTER: -+ 'security-group' in self.supported_extension_aliases}} -+ return binding -+ -+ @classmethod -+ def tenant_id_to_name(cls, id): -+ # bail if we never built the list successfully -+ if len(cls._tenant_id_dict) == 0: -+ return id -+ # check cache -+ if id in cls._tenant_id_dict: -+ return cls._tenant_id_dict[id] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ return cls._tenant_id_dict[id] if id in cls._tenant_id_dict else id -+ -+ @classmethod -+ def tenant_name_to_id(cls, name): -+ # bail if we never built the list successfully -+ if len(cls._tenant_name_dict) == 0: -+ return name -+ # check cache -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ # otherwise refresh -+ cls._tenant_list_from_keystone() -+ # second time's a charm? -+ if name in cls._tenant_name_dict: -+ return cls._tenant_name_dict[name] -+ else: -+ return name -+ -+ # Network API handlers -+ def create_network(self, context, network): -+ """ -+ Creates a new Virtual Network, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_create(network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("create_network(): " + pformat(net_dict) + "\n") -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_network(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_read(id, fields) -+ -+ # verify transformation is conforming to api -+ if not fields: -+ # should return all fields -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ fields, False) -+ net_dict.update(net_info['q_extra_data']) -+ else: -+ net_dict = net_info['q_api_data'] -+ -+ LOG.debug("get_network(): " + pformat(net_dict)) -+ return self._fields(net_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_network(self, context, net_id, network): -+ """ -+ Updates the attributes of a particular Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ net_info = cfgdb.network_update(net_id, network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ net_dict.update(net_info['q_extra_data']) -+ -+ LOG.debug("update_network(): " + pformat(net_dict)) -+ return net_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_network(self, context, net_id): -+ """ -+ Deletes the network with the specified network identifier -+ belonging to the specified tenant. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.network_delete(net_id) -+ LOG.debug("delete_network(): " + pformat(net_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_info = cfgdb.network_list(filters) -+ -+ nets_dicts = [] -+ for n_info in nets_info: -+ # verify transformation is conforming to api -+ n_dict = self._make_network_dict(n_info['q_api_data'], fields, -+ False) -+ -+ n_dict.update(n_info['q_extra_data']) -+ nets_dicts.append(n_dict) -+ -+ LOG.debug( -+ "get_networks(): filters: " + pformat(filters) + " data: " -+ + pformat(nets_dicts)) -+ return nets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_networks_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ nets_count = cfgdb.network_count(filters) -+ LOG.debug("get_networks_count(): " + str(nets_count)) -+ return nets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Subnet API handlers -+ def create_subnet(self, context, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_create(subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("create_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnet(self, context, subnet_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_read(subnet_id) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], -+ fields) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("get_subnet(): " + pformat(subnet_dict)) -+ return self._fields(subnet_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_subnet(self, context, subnet_id, subnet): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ subnet_dict.update(subnet_info['q_extra_data']) -+ -+ LOG.debug("update_subnet(): " + pformat(subnet_dict)) -+ return subnet_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_subnet(self, context, subnet_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.subnet_delete(subnet_id) -+ -+ LOG.debug("delete_subnet(): " + pformat(subnet_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets(self, context, filters=None, fields=None): -+ """ -+ Called from Neutron API -> get_ -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_info = cfgdb.subnets_list(filters) -+ -+ subnets_dicts = [] -+ for sn_info in subnets_info: -+ # verify transformation is conforming to api -+ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) -+ -+ sn_dict.update(sn_info['q_extra_data']) -+ subnets_dicts.append(sn_dict) -+ -+ LOG.debug( -+ "get_subnets(): filters: " + pformat(filters) + " data: " -+ + pformat(subnets_dicts)) -+ return subnets_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_subnets_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ subnets_count = cfgdb.subnets_count(filters) -+ LOG.debug("get_subnets_count(): " + str(subnets_count)) -+ return subnets_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Ipam API handlers -+ def create_ipam(self, context, ipam): -+ """ -+ Creates a new IPAM, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_create(ipam['ipam']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("create_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipam(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("get_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_ipam(self, context, id, ipam): -+ """ -+ Updates the attributes of a particular IPAM. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipam_info = cfgdb.ipam_update(id, ipam) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ -+ LOG.debug("update_ipam(): " + pformat(ipam_dict)) -+ return ipam_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_ipam(self, context, ipam_id): -+ """ -+ Deletes the ipam with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.ipam_delete(ipam_id) -+ -+ LOG.debug("delete_ipam(): " + pformat(ipam_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_info = cfgdb.ipam_list(filters) -+ -+ ipams_dicts = [] -+ for ipam_info in ipams_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ ipam_dict = ipam_info['q_api_data'] -+ ipam_dict.update(ipam_info['q_extra_data']) -+ ipams_dicts.append(ipam_dict) -+ -+ LOG.debug("get_ipams(): " + pformat(ipams_dicts)) -+ return ipams_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ipams_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ipams_count = cfgdb.ipams_count(filters) -+ LOG.debug("get_ipams_count(): " + str(ipams_count)) -+ return ipams_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Policy API handlers -+ def create_policy(self, context, policy): -+ """ -+ Creates a new Policy, and assigns it -+ a symbolic name. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_create(policy['policy']) -+ -+ ##verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("create_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_read(id) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("get_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_policy(self, context, id, policy): -+ """ -+ Updates the attributes of a particular Policy. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_info = cfgdb.policy_update(id, policy) -+ -+ ## verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ -+ LOG.debug("update_policy(): " + pformat(policy_dict)) -+ return policy_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_policy(self, context, policy_id): -+ """ -+ Deletes the Policy with the specified identifier -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.policy_delete(policy_id) -+ -+ LOG.debug("delete_policy(): " + pformat(policy_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policys(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policys_info = cfgdb.policy_list(filters) -+ -+ policys_dicts = [] -+ for policy_info in policys_info: -+ # verify transformation is conforming to api -+ #ipam_dict = self._make_ipam_dict(ipam_info) -+ policy_dict = policy_info['q_api_data'] -+ policy_dict.update(policy_info['q_extra_data']) -+ policys_dicts.append(policy_dict) -+ -+ LOG.debug("get_policys(): " + pformat(policys_dicts)) -+ return policys_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_policy_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ policy_count = cfgdb.policy_count(filters) -+ LOG.debug("get_policy_count(): " + str(policy_count)) -+ return policy_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Floating IP API handlers -+ def _make_floatingip_dict(self, floatingip, fields=None): -+ res = {'id': floatingip['id'], -+ 'tenant_id': floatingip['tenant_id'], -+ 'floating_ip_address': floatingip['floating_ip_address'], -+ 'floating_network_id': floatingip['floating_network_id'], -+ 'router_id': floatingip['router_id'], -+ 'port_id': floatingip['fixed_port_id'], -+ 'fixed_ip_address': floatingip['fixed_ip_address']} -+ return self._fields(res, fields) -+ -+ def create_floatingip(self, context, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("create_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_floatingip(self, context, fip_id, floatingip): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_update(fip_id, -+ floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("update_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingip(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_read(id) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ -+ LOG.debug("get_floatingip(): " + pformat(fip_dict)) -+ return fip_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_floatingip(self, context, fip_id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.floatingip_delete(fip_id) -+ LOG.debug("delete_floating(): " + pformat(fip_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips(self, context, filters=None, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ fips_info = cfgdb.floatingip_list(filters) -+ -+ fips_dicts = [] -+ for fip_info in fips_info: -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fip_dict.update(fip_info['q_extra_data']) -+ fips_dicts.append(fip_dict) -+ -+ LOG.debug("get_floatingips(): " + pformat(fips_dicts)) -+ return fips_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_floatingips_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ floatingips_count = cfgdb.floatingip_count(filters) -+ LOG.debug("get_floatingips_count(): " + str(floatingips_count)) -+ return floatingips_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Port API handlers -+ def create_port(self, context, port): -+ """ -+ Creates a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_create(port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ -+ LOG.debug("create_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_port(self, context, port_id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_read(port_id) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ port_info, -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("get_port(): " + pformat(port_dict)) -+ return self._fields(port_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_port(self, context, port_id, port): -+ """ -+ Updates the attributes of a port on the specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ port_info = cfgdb.port_update(port_id, port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_dict) -+ -+ port_dict.update(port_info['q_extra_data']) -+ -+ LOG.debug("update_port(): " + pformat(port_dict)) -+ return port_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_port(self, context, port_id): -+ """ -+ Deletes a port on a specified Virtual Network, -+ if the port contains a remote interface attachment, -+ the remote interface is first un-plugged and then the port -+ is deleted. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.port_delete(port_id) -+ LOG.debug("delete_port(): " + pformat(port_id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports(self, context, filters=None, fields=None): -+ """ -+ Retrieves all port identifiers belonging to the -+ specified Virtual Network. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_info = cfgdb.port_list(filters) -+ -+ ports_dicts = [] -+ for p_info in ports_info: -+ # verify transformation is conforming to api -+ p_dict = self._make_port_dict(p_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ p_info, -+ p_dict) -+ -+ p_dict.update(p_info['q_extra_data']) -+ ports_dicts.append(p_dict) -+ -+ LOG.debug( -+ "get_ports(): filter: " + pformat(filters) + 'data: ' -+ + pformat(ports_dicts)) -+ return ports_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_ports_count(self, context, filters=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ ports_count = cfgdb.port_count(filters) -+ LOG.debug("get_ports_count(): " + str(ports_count)) -+ return ports_count -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): -+ """ -+ Attaches a remote interface to the specified port on the -+ specified Virtual Network. -+ """ -+ port = self._get_port(tenant_id, net_id, port_id) -+ # Validate attachment -+ self._validate_attachment(tenant_id, net_id, port_id, -+ remote_interface_id) -+ if port['interface_id']: -+ raise exc.PortInUse(net_id=net_id, port_id=port_id, -+ att_id=port['interface_id']) -+ -+ def unplug_interface(self, tenant_id, net_id, port_id): -+ """ -+ Detaches a remote interface from the specified port on the -+ specified Virtual Network. -+ """ -+ self._get_port(tenant_id, net_id, port_id) -+ -+ # VPC route table handlers -+ def _make_route_table_routes_dict(self, route_table_route, fields=None): -+ res = {'prefix': route_table_route['prefix'], -+ 'next_hop': route_table_route['next_hop']} -+ -+ return self._fields(res, fields) -+ -+ def _make_route_table_dict(self, route_table, fields=None): -+ res = {'id': route_table['id'], -+ 'name': route_table['name'], -+ 'fq_name': route_table['fq_name'], -+ 'tenant_id': route_table['tenant_id']} -+ if route_table['routes']: -+ res['routes'] = [self._make_route_table_routes_dict(r) -+ for r in route_table['routes']['route']] -+ return self._fields(res, fields) -+ -+ def create_route_table(self, context, route_table): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_create( -+ route_table['route_table']) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def update_route_table(self, context, id, route_table): -+ """ -+ Updates the attributes of a particular route table. -+ """ -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_update(id, route_table['route_table']) -+ -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data']) -+ rt_dict.update(rt_info['q_extra_data']) -+ LOG.debug("create_route_table(): " + pformat(rt_dict)) -+ return rt_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_route_table(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.route_table_delete(id) -+ LOG.debug("delete_route_table(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_tables(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ route_tables_info = cfgdb.route_table_list(context, filters) -+ -+ route_tables_dicts = [] -+ for rt_info in route_tables_info: -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ route_tables_dicts.append(rt_dict) -+ -+ LOG.debug( -+ "get_route_tables(): filter: " + pformat(filters) -+ + 'data: ' + pformat(route_tables_dicts)) -+ return route_tables_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_route_table(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ rt_info = cfgdb.route_table_read(id) -+ -+ # verify transformation is conforming to api -+ rt_dict = self._make_route_table_dict(rt_info['q_api_data'], -+ fields) -+ -+ rt_dict.update(rt_info['q_extra_data']) -+ -+ LOG.debug("get_route_table(): " + pformat(rt_dict)) -+ return self._fields(rt_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # VPC route table svc instance handlers -+ def _make_svc_instance_dict(self, svc_instance, fields=None): -+ res = {'id': svc_instance['id'], -+ 'name': svc_instance['name'], -+ 'tenant_id': svc_instance['tenant_id']} -+ if svc_instance['internal_net']: -+ res['internal_net'] = svc_instance['internal_net'] -+ if svc_instance['external_net']: -+ res['external_net'] = svc_instance['external_net'] -+ return self._fields(res, fields) -+ -+ def create_nat_instance(self, context, nat_instance): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_create( -+ nat_instance['nat_instance']) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data']) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("create_nat_instance(): " + pformat(si_dict)) -+ return si_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_nat_instance(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.svc_instance_delete(id) -+ LOG.debug("delete_nat_instance(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instances(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ svc_instances_info = cfgdb.svc_instance_list(context, filters) -+ -+ svc_instances_dicts = [] -+ for si_info in svc_instances_info: -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ svc_instances_dicts.append(si_dict) -+ -+ LOG.debug( -+ "get_nat_instances(): filter: " + pformat(filters) -+ + 'data: ' + pformat(svc_instances_dicts)) -+ return svc_instances_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_nat_instance(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ si_info = cfgdb.svc_instance_read(id) -+ -+ # verify transformation is conforming to api -+ si_dict = self._make_svc_instance_dict(si_info['q_api_data'], -+ fields) -+ -+ si_dict.update(si_info['q_extra_data']) -+ -+ LOG.debug("get_nat_instance(): " + pformat(si_dict)) -+ return self._fields(si_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ # Security Group handlers -+ def _make_security_group_rule_dict(self, security_group_rule, fields=None): -+ res = {'id': security_group_rule['id'], -+ 'tenant_id': security_group_rule['tenant_id'], -+ 'security_group_id': security_group_rule['security_group_id'], -+ 'ethertype': security_group_rule['ethertype'], -+ 'direction': security_group_rule['direction'], -+ 'protocol': security_group_rule['protocol'], -+ 'port_range_min': security_group_rule['port_range_min'], -+ 'port_range_max': security_group_rule['port_range_max'], -+ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], -+ 'remote_group_id': security_group_rule['remote_group_id']} -+ -+ return self._fields(res, fields) -+ -+ def _make_security_group_dict(self, security_group, fields=None): -+ res = {'id': security_group['id'], -+ 'name': security_group['name'], -+ 'tenant_id': security_group['tenant_id'], -+ 'description': security_group['description']} -+ res['security_group_rules'] = [self._make_security_group_rule_dict(r) -+ for r in security_group['rules']] -+ return self._fields(res, fields) -+ -+ def create_security_group(self, context, security_group): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_create( -+ security_group['security_group']) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("create_security_group(): " + pformat(sg_dict)) -+ return sg_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_delete(id) -+ LOG.debug("delete_security_group(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_groups(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_groups_info = cfgdb.security_group_list(context, filters) -+ -+ security_groups_dicts = [] -+ for sg_info in security_groups_info: -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ security_groups_dicts.append(sg_dict) -+ -+ LOG.debug( -+ "get_security_groups(): filter: " + pformat(filters) -+ + 'data: ' + pformat(security_groups_dicts)) -+ return security_groups_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_read(id) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ sg_dict.update(sg_info['q_extra_data']) -+ -+ LOG.debug("get_security_group(): " + pformat(sg_dict)) -+ return self._fields(sg_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def create_security_group_rule(self, context, security_group_rule): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_create( -+ security_group_rule['security_group_rule']) -+ -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data']) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("create_security_group_rule(): " + pformat(sgr_dict)) -+ return sgr_dict -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def delete_security_group_rule(self, context, id): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ cfgdb.security_group_rule_delete(id) -+ LOG.debug("delete_security_group_rule(): " + pformat(id)) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rules(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ security_group_rules_info = cfgdb.security_group_rule_list(filters) -+ -+ security_group_rules_dicts = [] -+ for sgr_info in security_group_rules_info: -+ for sgr in sgr_info: -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr['q_api_data'], fields) -+ sgr_dict.update(sgr['q_extra_data']) -+ security_group_rules_dicts.append(sgr_dict) -+ -+ LOG.debug( -+ "get_security_group_rules(): filter: " + pformat(filters) + -+ 'data: ' + pformat(security_group_rules_dicts)) -+ return security_group_rules_dicts -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -+ -+ def get_security_group_rule(self, context, id, fields=None): -+ try: -+ cfgdb = ContrailPlugin._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_read(id) -+ -+ # verify transformation is conforming to api -+ sgr_dict = {} -+ if sgr_info != {}: -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data'], fields) -+ sgr_dict.update(sgr_info['q_extra_data']) -+ -+ LOG.debug("get_security_group_rule(): " + pformat(sgr_dict)) -+ return self._fields(sgr_dict, fields) -+ except Exception as e: -+ cgitb.Hook(format="text").handle(sys.exc_info()) -+ raise e -diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py -new file mode 100644 -index 0000000..4a87a41 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/config_db.py -@@ -0,0 +1,2238 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+import json -+import re -+import requests -+import socket -+import time -+import uuid -+from netaddr import IPNetwork, IPSet, IPAddress -+ -+from neutron.api.v2 import attributes as attr -+from neutron.common import constants -+from neutron.common import exceptions -+from neutron.extensions import portbindings -+from vnc_api.common import exceptions as vnc_exc -+from vnc_api import vnc_api -+ -+_DEFAULT_HEADERS = { -+ 'Content-type': 'application/json; charset="UTF-8"', } -+ -+CREATE = 1 -+READ = 2 -+UPDATE = 3 -+DELETE = 4 -+ -+ -+class DBInterface(object): -+ """ -+ An instance of this class forwards requests to vnc cfg api (web)server -+ """ -+ Q_URL_PREFIX = '/extensions/ct' -+ -+ def __init__(self, admin_name, admin_password, admin_tenant_name, -+ api_srvr_ip, api_srvr_port, user_info=None): -+ self._api_srvr_ip = api_srvr_ip -+ self._api_srvr_port = api_srvr_port -+ -+ self._db_cache = {} -+ self._db_cache['q_networks'] = {} -+ self._db_cache['q_subnets'] = {} -+ self._db_cache['q_subnet_maps'] = {} -+ self._db_cache['q_policies'] = {} -+ self._db_cache['q_ipams'] = {} -+ self._db_cache['q_floatingips'] = {} -+ self._db_cache['q_ports'] = {} -+ self._db_cache['q_fixed_ip_to_subnet'] = {} -+ #obj-uuid to tenant-uuid mapping -+ self._db_cache['q_obj_to_tenant'] = {} -+ #port count per tenant-id -+ self._db_cache['q_tenant_port_count'] = {} -+ self._db_cache['vnc_networks'] = {} -+ self._db_cache['vnc_ports'] = {} -+ self._db_cache['vnc_projects'] = {} -+ self._db_cache['vnc_instance_ips'] = {} -+ -+ # Retry till a api-server is up -+ connected = False -+ while not connected: -+ try: -+ self._vnc_lib = vnc_api.VncApi( -+ admin_name, admin_password, -+ admin_tenant_name, api_srvr_ip, -+ api_srvr_port, '/', user_info=user_info) -+ connected = True -+ except requests.exceptions.RequestException: -+ time.sleep(3) -+ -+ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key -+ subnet_map = self._vnc_lib.kv_retrieve(key=None) -+ for kv_dict in subnet_map: -+ key = kv_dict['key'] -+ if len(key.split()) == 1: -+ subnet_id = key -+ # uuid key, fixup value portion to 'net_id pfx/len' format -+ # if not already so -+ if len(kv_dict['value'].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ net_fq_name = kv_dict['value'].split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ self._vnc_lib.kv_delete(subnet_id) -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, -+ kv_dict['value'].split()[1]) -+ self._vnc_lib.kv_store(subnet_id, new_subnet_key) -+ else: # subnet key -+ if len(key.split()[0].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ # delete old key, convert to new key format and save -+ old_subnet_key = key -+ self._vnc_lib.kv_delete(old_subnet_key) -+ -+ subnet_id = kv_dict['value'] -+ net_fq_name = key.split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) -+ self._vnc_lib.kv_store(new_subnet_key, subnet_id) -+ -+ # Helper routines -+ def _request_api_server(self, url, method, data=None, headers=None): -+ if method == 'GET': -+ return requests.get(url) -+ if method == 'POST': -+ return requests.post(url, data=data, headers=headers) -+ if method == 'DELETE': -+ return requests.delete(url) -+ -+ def _relay_request(self, request): -+ """ -+ Send received request to api server -+ """ -+ # chop neutron parts of url and add api server address -+ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) -+ url = "http://%s:%s%s" % (self._api_srvr_ip, self._api_srvr_port, -+ url_path) -+ -+ return self._request_api_server( -+ url, request.environ['REQUEST_METHOD'], -+ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) -+ -+ def _obj_to_json(self, obj): -+ return dict((k, v) for k, v in obj.__dict__.iteritems()) -+ -+ def _ensure_instance_exists(self, instance_id): -+ instance_name = instance_id -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ try: -+ id = self._vnc_lib.obj_to_id(instance_obj) -+ instance_obj = self._vnc_lib.virtual_machine_read(id=id) -+ except Exception as e: -+ #except vnc_exc.NoIdError: # instance doesn't exist, create it -+ instance_obj.uuid = instance_id -+ self._vnc_lib.virtual_machine_create(instance_obj) -+ -+ return instance_obj -+ -+ def _ensure_default_security_group_exists(self, proj_id): -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ sg_groups = proj_obj.get_security_groups() -+ for sg_group in sg_groups or []: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) -+ if sg_obj.name == 'default': -+ return -+ -+ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) -+ self._vnc_lib.security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ #allow ingress traffic from within default security group -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'ingress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ def _get_obj_tenant_id(self, q_type, obj_uuid): -+ # Get the mapping from cache, else seed cache and return -+ try: -+ return self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except KeyError: -+ # Seed the cache and return -+ if q_type == 'port': -+ port_obj = self._virtual_machine_interface_read(obj_uuid) -+ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] -+ # recurse up type-hierarchy -+ tenant_id = self._get_obj_tenant_id('network', net_id) -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ if q_type == 'network': -+ net_obj = self._virtual_network_read(net_id=obj_uuid) -+ tenant_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ return None -+ -+ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): -+ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid -+ -+ def _del_obj_tenant_id(self, obj_uuid): -+ try: -+ del self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except Exception: -+ pass -+ -+ def _project_read(self, proj_id=None, fq_name=None): -+ if proj_id: -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][proj_id] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ fq_name_str = json.dumps(proj_obj.get_fq_name()) -+ self._db_cache['vnc_projects'][proj_id] = proj_obj -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ return proj_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # disable cache for now as fip pool might be put without -+ # neutron knowing it -+ raise KeyError -+ #return self._db_cache['vnc_projects'][fq_name_str] -+ except KeyError: -+ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj -+ return proj_obj -+ -+ def _security_group_rule_create(self, sg_id, sg_rule): -+ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) -+ rules = sg_vnc.get_security_group_entries() -+ if rules is None: -+ rules = vnc_api.PolicyEntriesType([sg_rule]) -+ else: -+ rules.add_policy_rule(sg_rule) -+ -+ sg_vnc.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_vnc) -+ return -+ -+ def _security_group_rule_find(self, sgr_id): -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ -+ for sg in project_sgs: -+ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) -+ sgr_entries = sg_obj.get_security_group_entries() -+ if sgr_entries is None: -+ continue -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ if sg_rule.get_rule_uuid() == sgr_id: -+ return sg_obj, sg_rule -+ -+ return None, None -+ -+ def _security_group_rule_delete(self, sg_obj, sg_rule): -+ rules = sg_obj.get_security_group_entries() -+ rules.get_policy_rule().remove(sg_rule) -+ sg_obj.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_obj) -+ return -+ -+ def _security_group_create(self, sg_obj): -+ sg_uuid = self._vnc_lib.security_group_create(sg_obj) -+ return sg_uuid -+ -+ def _security_group_delete(self, sg_id): -+ self._vnc_lib.security_group_delete(id=sg_id) -+ -+ def _svc_instance_create(self, si_obj): -+ si_uuid = self._vnc_lib.service_instance_create(si_obj) -+ st_fq_name = ['default-domain', 'nat-template'] -+ st_obj = self._vnc_lib.service_template_read(fq_name=st_fq_name) -+ si_obj.set_service_template(st_obj) -+ self._vnc_lib.service_instance_update(si_obj) -+ -+ return si_uuid -+ -+ def _svc_instance_delete(self, si_id): -+ self._vnc_lib.service_instance_delete(id=si_id) -+ -+ def _route_table_create(self, rt_obj): -+ rt_uuid = self._vnc_lib.route_table_create(rt_obj) -+ return rt_uuid -+ -+ def _route_table_delete(self, rt_id): -+ self._vnc_lib.route_table_delete(id=rt_id) -+ -+ def _virtual_network_create(self, net_obj): -+ net_uuid = self._vnc_lib.virtual_network_create(net_obj) -+ -+ return net_uuid -+ -+ def _virtual_network_read(self, net_id=None, fq_name=None): -+ if net_id: -+ try: -+ # return self._db_cache['vnc_networks'][net_id] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(id=net_id) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ self._db_cache['vnc_networks'][net_id] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ return net_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_networks'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ return net_obj -+ -+ def _virtual_network_update(self, net_obj): -+ self._vnc_lib.virtual_network_update(net_obj) -+ # read back to get subnet gw allocated by api-server -+ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ -+ def _virtual_network_delete(self, net_id): -+ fq_name_str = None -+ try: -+ net_obj = self._db_cache['vnc_networks'][net_id] -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_network_delete(id=net_id) -+ -+ try: -+ del self._db_cache['vnc_networks'][net_id] -+ if fq_name_str: -+ del self._db_cache['vnc_networks'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _virtual_machine_interface_create(self, port_obj): -+ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) -+ -+ return port_uuid -+ -+ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): -+ if port_id: -+ try: -+ # return self._db_cache['vnc_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ id=port_id) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ self._db_cache['vnc_ports'][port_id] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ return port_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_ports'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ fq_name=fq_name) -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ return port_obj -+ -+ def _virtual_machine_interface_update(self, port_obj): -+ self._vnc_lib.virtual_machine_interface_update(port_obj) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ -+ def _virtual_machine_interface_delete(self, port_id): -+ fq_name_str = None -+ try: -+ port_obj = self._db_cache['vnc_ports'][port_id] -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_machine_interface_delete(id=port_id) -+ -+ try: -+ del self._db_cache['vnc_ports'][port_id] -+ if fq_name_str: -+ del self._db_cache['vnc_ports'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _instance_ip_create(self, iip_obj): -+ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) -+ -+ return iip_uuid -+ -+ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): -+ if instance_ip_id: -+ try: -+ # return self._db_cache['vnc_instance_ips'][instance_ip_id] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ return iip_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ try: -+ # return self._db_cache['vnc_instance_ips'][fq_name_str] -+ raise KeyError -+ except KeyError: -+ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ return iip_obj -+ -+ def _instance_ip_update(self, iip_obj): -+ self._vnc_lib.instance_ip_update(iip_obj) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ -+ def _instance_ip_delete(self, instance_ip_id): -+ fq_name_str = None -+ try: -+ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.instance_ip_delete(id=instance_ip_id) -+ -+ try: -+ del self._db_cache['vnc_instance_ips'][instance_ip_id] -+ if fq_name_str: -+ del self._db_cache['vnc_instance_ips'][fq_name_str] -+ except KeyError: -+ pass -+ -+ # find projects on a given domain -+ def _project_list_domain(self, domain_id): -+ fq_name = ['default-domain'] -+ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) -+ -+ return resp_dict['projects'] -+ -+ # find network ids on a given project -+ def _network_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) -+ -+ return resp_dict['virtual-networks'] -+ -+ def _ipam_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_ipams_list(parent_id=project_uuid) -+ -+ return resp_dict['network-ipams'] -+ -+ def _security_group_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ self._ensure_default_security_group_exists(project_uuid) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _security_group_entries_list_sg(self, sg_id): -+ try: -+ sg_uuid = str(uuid.UUID(sg_id)) -+ except Exception: -+ print "Error in converting SG uuid %s" % (sg_id) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _route_table_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.route_tables_list(parent_id=project_uuid) -+ -+ return resp_dict['route-tables'] -+ -+ def _svc_instance_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.service_instances_list(parent_id=project_uuid) -+ -+ return resp_dict['service-instances'] -+ -+ def _policy_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ print "Error in converting uuid %s" % (project_id) -+ -+ resp_dict = self._vnc_lib.network_policys_list(parent_id=project_uuid) -+ -+ return resp_dict['network-policys'] -+ -+ # find floating ip pools a project has access to -+ def _fip_pool_refs_project(self, project_id): -+ project_uuid = str(uuid.UUID(project_id)) -+ project_obj = self._project_read(proj_id=project_uuid) -+ -+ return project_obj.get_floating_ip_pool_refs() -+ -+ # find networks of floating ip pools project has access to -+ def _fip_pool_ref_networks(self, project_id): -+ ret_nets = [] -+ -+ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) -+ if not proj_fip_pool_refs: -+ return ret_nets -+ -+ for fip_pool_ref in proj_fip_pool_refs: -+ fip_uuid = fip_pool_ref['uuid'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) -+ net_uuid = fip_pool_obj.parent_uuid -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ ret_nets.append({'uuid': net_obj.uuid, -+ 'fq_name': net_obj.get_fq_name()}) -+ -+ return ret_nets -+ -+ # find floating ip pools defined by network -+ def _fip_pool_list_network(self, net_id): -+ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) -+ -+ return resp_dict['floating-ip-pools'] -+ -+ # find port ids on a given network -+ def _port_list_network(self, network_id): -+ ret_list = [] -+ -+ try: -+ net_obj = self._virtual_network_read(net_id=network_id) -+ except vnc_exc.NoIdError: -+ return ret_list -+ -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ for port_back_ref in port_back_refs: -+ ret_list.append({'id': port_back_ref['uuid']}) -+ -+ return ret_list -+ -+ # find port ids on a given project -+ def _port_list_project(self, project_id): -+ ret_list = [] -+ project_nets = self._network_list_project(project_id) -+ for net in project_nets: -+ net_ports = self._port_list_network(net['uuid']) -+ ret_list.extend(net_ports) -+ -+ return ret_list -+ -+ # Returns True if -+ # * no filter is specified -+ # OR -+ # * search-param is not present in filters -+ # OR -+ # * 1. search-param is present in filters AND -+ # 2. resource matches param-list AND -+ # 3. shared parameter in filters is False -+ def _filters_is_present(self, filters, key_name, match_value): -+ if filters: -+ if key_name in filters: -+ try: -+ if ('shared' in filters and -+ filters['shared'][0] is True): -+ # yuck, q-api has shared as list always of 1 elem -+ return False # no shared-resource support -+ except ValueError: # not in requested list -+ return False -+ elif len(filters.keys()) == 1: -+ shared_val = filters.get('shared', None) -+ if shared_val and shared_val[0] is True: -+ return False -+ -+ return True -+ -+ def _network_read(self, net_uuid): -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ return net_obj -+ -+ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): -+ #import pdb; pdb.set_trace() -+ self._vnc_lib.kv_store(subnet_id, subnet_key) -+ self._vnc_lib.kv_store(subnet_key, subnet_id) -+ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key -+ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id -+ -+ def _subnet_vnc_read_mapping(self, id=None, key=None): -+ if id: -+ try: -+ return self._db_cache['q_subnet_maps'][id] -+ #raise KeyError -+ except KeyError: -+ subnet_key = self._vnc_lib.kv_retrieve(id) -+ self._db_cache['q_subnet_maps'][id] = subnet_key -+ return subnet_key -+ if key: -+ try: -+ return self._db_cache['q_subnet_maps'][key] -+ #raise KeyError -+ except KeyError: -+ subnet_id = self._vnc_lib.kv_retrieve(key) -+ self._db_cache['q_subnet_maps'][key] = subnet_id -+ return subnet_id -+ -+ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): -+ if id: -+ return self._subnet_vnc_read_mapping(id=id) -+ -+ # if subnet was created outside of neutron handle it and create -+ # neutron representation now (lazily) -+ try: -+ return self._subnet_vnc_read_mapping(key=key) -+ except vnc_exc.NoIdError: -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, key) -+ return self._subnet_vnc_read_mapping(key=key) -+ -+ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): -+ self._vnc_lib.kv_delete(subnet_id) -+ self._vnc_lib.kv_delete(subnet_key) -+ try: -+ del self._db_cache['q_subnet_maps'][subnet_id] -+ del self._db_cache['q_subnet_maps'][subnet_key] -+ except KeyError: -+ pass -+ -+ def _subnet_vnc_get_key(self, subnet_vnc, net_id): -+ pfx = subnet_vnc.subnet.get_ip_prefix() -+ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() -+ -+ return '%s %s/%s' % (net_id, pfx, pfx_len) -+ -+ def _subnet_read(self, net_uuid, subnet_key): -+ try: -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ except vnc_exc.NoIdError: -+ return None -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if not ipam_refs: -+ return None -+ -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_uuid) == subnet_key: -+ return subnet_vnc -+ -+ return None -+ -+ def _ip_address_to_subnet_id(self, ip_addr, net_obj): -+ # find subnet-id for ip-addr, called when instance-ip created -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ if IPAddress(ip_addr) in IPSet([cidr]): -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, -+ net_obj.uuid) -+ subnet_id = self._subnet_vnc_read_mapping( -+ key=subnet_key) -+ return subnet_id -+ -+ return None -+ -+ # Conversion routines between VNC and Quantum objects -+ def _svc_instance_neutron_to_vnc(self, si_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(si_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ net_id = si_q['internal_net'] -+ int_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ net_id = si_q['external_net'] -+ ext_vn = self._vnc_lib.virtual_network_read(id=net_id) -+ scale_out = vnc_api.ServiceScaleOutType(max_instances=1, -+ auto_scale=False) -+ si_prop = vnc_api.ServiceInstanceType( -+ auto_policy=True, left_virtual_network=int_vn.name, -+ right_virtual_network=ext_vn.name, scale_out=scale_out) -+ si_prop.set_scale_out(scale_out) -+ si_vnc = vnc_api.ServiceInstance( -+ name=si_q['name'], -+ parent_obj=project_obj, -+ service_instance_properties=si_prop) -+ -+ return si_vnc -+ -+ def _svc_instance_vnc_to_neutron(self, si_obj): -+ si_q_dict = json.loads(json.dumps(si_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ si_q_dict['id'] = si_obj.uuid -+ si_q_dict['tenant_id'] = si_obj.parent_uuid.replace('-', '') -+ si_q_dict['name'] = si_obj.name -+ si_props = si_obj.get_service_instance_properties() -+ if si_props: -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_left_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['internal_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ vn_fq_name = si_obj.get_parent_fq_name() -+ vn_name = si_props.get_right_virtual_network() -+ vn_fq_name.extend([vn_name]) -+ vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) -+ si_q_dict['external_net'] = str(vn_obj.uuid) + ' ' + vn_name -+ -+ return {'q_api_data': si_q_dict, -+ 'q_extra_data': {}} -+ -+ def _route_table_neutron_to_vnc(self, rt_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(rt_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ rt_vnc = vnc_api.RouteTable(name=rt_q['name'], -+ parent_obj=project_obj) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ else: -+ rt_vnc = self._vnc_lib.route_table_read(id=rt_q['id']) -+ rt_vnc.set_routes(vnc_api.RouteTableType.factory(**rt_q['routes'])) -+ -+ return rt_vnc -+ -+ def _route_table_vnc_to_neutron(self, rt_obj): -+ rt_q_dict = json.loads(json.dumps(rt_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ rt_q_dict['id'] = rt_obj.uuid -+ rt_q_dict['tenant_id'] = rt_obj.parent_uuid.replace('-', '') -+ rt_q_dict['name'] = rt_obj.name -+ rt_q_dict['fq_name'] = rt_obj.fq_name -+ -+ # get route table routes -+ rt_q_dict['routes'] = rt_q_dict.pop('routes', None) -+ return {'q_api_data': rt_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_vnc_to_neutron(self, sg_obj): -+ sg_q_dict = json.loads(json.dumps(sg_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ sg_q_dict['id'] = sg_obj.uuid -+ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sg_q_dict['name'] = sg_obj.name -+ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() -+ -+ # get security group rules -+ sg_q_dict['rules'] = [] -+ rule_list = self.security_group_rules_read(sg_obj.uuid) -+ if rule_list: -+ for rule in rule_list: -+ sg_q_dict['rules'].append(rule['q_api_data']) -+ -+ return {'q_api_data': sg_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_neutron_to_vnc(self, sg_q, oper): -+ if oper == CREATE: -+ project_id = str(uuid.UUID(sg_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType( -+ enable=True, description=sg_q['description']) -+ sg_vnc = vnc_api.SecurityGroup( -+ name=sg_q['name'], parent_obj=project_obj, -+ id_perms=id_perms) -+ -+ return sg_vnc -+ -+ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): -+ sgr_q_dict = {} -+ if sg_id is None: -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ direction = 'egress' -+ if sg_rule.get_direction() == '<': -+ direction = 'ingress' -+ -+ remote_cidr = '' -+ remote_sg_uuid = '' -+ if direction == 'ingress': -+ addr = sg_rule.get_src_addresses()[0] -+ else: -+ addr = sg_rule.get_dst_addresses()[0] -+ -+ if addr.get_subnet(): -+ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), -+ addr.get_subnet().get_ip_prefix_len()) -+ elif addr.get_security_group(): -+ if (addr.get_security_group() != 'any') and \ -+ (addr.get_security_group() != 'local'): -+ remote_sg = addr.get_security_group() -+ try: -+ remote_sg_obj = self._vnc_lib.security_group_read( -+ fq_name_str=remote_sg) -+ remote_sg_uuid = remote_sg_obj.uuid -+ except vnc_exc.NoIdError: -+ pass -+ -+ sgr_q_dict['id'] = sg_rule.get_rule_uuid() -+ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sgr_q_dict['security_group_id'] = sg_obj.uuid -+ sgr_q_dict['ethertype'] = 'IPv4' -+ sgr_q_dict['direction'] = direction -+ sgr_q_dict['protocol'] = sg_rule.get_protocol() -+ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ -+ get_start_port() -+ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ -+ get_end_port() -+ sgr_q_dict['remote_ip_prefix'] = remote_cidr -+ sgr_q_dict['remote_group_id'] = remote_sg_uuid -+ -+ return {'q_api_data': sgr_q_dict, -+ 'q_extra_data': {}} -+ -+ def _security_group_rule_neutron_to_vnc(self, sgr_q, oper): -+ if oper == CREATE: -+ port_min = 0 -+ port_max = 65535 -+ if sgr_q['port_range_min']: -+ port_min = sgr_q['port_range_min'] -+ if sgr_q['port_range_max']: -+ port_max = sgr_q['port_range_max'] -+ -+ endpt = [vnc_api.AddressType(security_group='any')] -+ if sgr_q['remote_ip_prefix']: -+ cidr = sgr_q['remote_ip_prefix'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ endpt = [vnc_api.AddressType( -+ subnet=vnc_api.SubnetType(pfx, pfx_len))] -+ elif sgr_q['remote_group_id']: -+ sg_obj = self._vnc_lib.security_group_read( -+ id=sgr_q['remote_group_id']) -+ endpt = [vnc_api.AddressType( -+ security_group=sg_obj.get_fq_name_str())] -+ -+ if sgr_q['direction'] == 'ingress': -+ dir = '<' -+ local = endpt -+ remote = [vnc_api.AddressType(security_group='local')] -+ else: -+ dir = '>' -+ remote = endpt -+ local = [vnc_api.AddressType(security_group='local')] -+ -+ if not sgr_q['protocol']: -+ sgr_q['protocol'] = 'any' -+ -+ sgr_uuid = str(uuid.uuid4()) -+ -+ rule = vnc_api.PolicyRuleType( -+ rule_uuid=sgr_uuid, -+ direction=dir, -+ protocol=sgr_q['protocol'], -+ src_addresses=local, -+ src_ports=[vnc_api.PortType(0, 65535)], -+ dst_addresses=remote, -+ dst_ports=[vnc_api.PortType(port_min, port_max)]) -+ return rule -+ -+ def _network_neutron_to_vnc(self, network_q, oper): -+ net_name = network_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(network_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType(enable=True) -+ net_obj = vnc_api.VirtualNetwork( -+ net_name, project_obj, id_perms=id_perms) -+ else: # READ/UPDATE/DELETE -+ net_obj = self._virtual_network_read(net_id=network_q['id']) -+ -+ id_perms = net_obj.get_id_perms() -+ if 'admin_state_up' in network_q: -+ id_perms.enable = network_q['admin_state_up'] -+ net_obj.set_id_perms(id_perms) -+ -+ if 'contrail:policys' in network_q: -+ policy_fq_names = network_q['contrail:policys'] -+ # reset and add with newly specified list -+ net_obj.set_network_policy_list([], []) -+ seq = 0 -+ for p_fq_name in policy_fq_names: -+ domain_name, project_name, policy_name = p_fq_name -+ -+ domain_obj = vnc_api.Domain(domain_name) -+ project_obj = vnc_api.Project(project_name, domain_obj) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ -+ net_obj.add_network_policy( -+ policy_obj, -+ vnc_api.VirtualNetworkPolicyType( -+ sequence=vnc_api.SequenceType(seq, 0))) -+ seq = seq + 1 -+ -+ if 'vpc:route_table' in network_q: -+ rt_fq_name = network_q['vpc:route_table'] -+ if rt_fq_name: -+ try: -+ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) -+ net_obj.set_route_table(rt_obj) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) -+ -+ return net_obj -+ -+ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): -+ net_q_dict = {} -+ extra_dict = {} -+ -+ net_q_dict['id'] = net_obj.uuid -+ net_q_dict['name'] = net_obj.name -+ extra_dict['contrail:fq_name'] = net_obj.get_fq_name() -+ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable -+ net_q_dict['shared'] = False -+ net_q_dict['status'] = constants.NET_STATUS_ACTIVE -+ -+ if net_repr == 'SHOW': -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ #if port_back_refs: -+ # net_q_dict['ports'] = [] -+ # for port_back_ref in port_back_refs: -+ # fq_name = port_back_ref['to'] -+ # try: -+ # port_obj = self._virtual_machine_interface_read( -+ # port_id = fq_name[-1]) -+ # except NoIdError: -+ # continue -+ # -+ # port_info = self._port_vnc_to_neutron(port_obj, net_obj) -+ # port_dict = port_info['q_api_data'] -+ # port_dict.update(port_info['q_extra_data']) -+ # -+ # net_q_dict['ports'].append(port_dict) -+ -+ extra_dict['contrail:instance_count'] = 0 -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ net_policy_refs = net_obj.get_network_policy_refs() -+ if net_policy_refs: -+ extra_dict['contrail:policys'] = \ -+ [np_ref['to'] for np_ref in net_policy_refs] -+ -+ elif net_repr == 'LIST': -+ extra_dict['contrail:instance_count'] = 0 -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ extra_dict['contrail:instance_count'] = len(port_back_refs) -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ net_q_dict['subnets'] = [] -+ if ipam_refs: -+ extra_dict['contrail:subnet_ipam'] = [] -+ for ipam_ref in ipam_refs: -+ subnets = ipam_ref['attr'].get_ipam_subnets() -+ for subnet in subnets: -+ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, -+ ipam_ref['to']) -+ sn_dict = sn_info['q_api_data'] -+ sn_dict.update(sn_info['q_extra_data']) -+ net_q_dict['subnets'].append(sn_dict) -+ sn_ipam = {} -+ sn_ipam['subnet_cidr'] = sn_dict['cidr'] -+ sn_ipam['ipam_fq_name'] = ipam_ref['to'] -+ extra_dict['contrail:subnet_ipam'].append(sn_ipam) -+ -+ return {'q_api_data': net_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _subnet_neutron_to_vnc(self, subnet_q): -+ cidr = subnet_q['cidr'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: -+ default_gw = subnet_q['gateway_ip'] -+ else: -+ # Assigned by address manager -+ default_gw = None -+ sub_net = vnc_api.SubnetType(ip_prefix=pfx, -+ ip_prefix_len=pfx_len) -+ #subnet_vnc = vnc_api.IpamSubnetType( -+ #subnet=vnc_api.SubnetType(pfx, pfx_len), -+ #default_gateway=default_gw) -+ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, -+ default_gateway=default_gw) -+ return subnet_vnc -+ -+ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): -+ sn_q_dict = {} -+ sn_q_dict['name'] = '' -+ sn_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ sn_q_dict['network_id'] = net_obj.uuid -+ sn_q_dict['ip_version'] = 4 -+ -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ sn_q_dict['cidr'] = cidr -+ -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) -+ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) -+ -+ sn_q_dict['id'] = sn_id -+ -+ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway -+ -+ first_ip = str(IPNetwork(cidr).network + 1) -+ last_ip = str(IPNetwork(cidr).broadcast - 2) -+ sn_q_dict['allocation_pools'] = \ -+ [{'id': 'TODO-allocation_pools-id', -+ 'subnet_id': sn_id, -+ 'first_ip': first_ip, -+ 'last_ip': last_ip, -+ 'available_ranges': {}}] -+ -+ sn_q_dict['enable_dhcp'] = False -+ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['routes'] = [{'destination': 'TODO-destination', -+ 'nexthop': 'TODO-nexthop', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['shared'] = False -+ -+ extra_dict = {} -+ extra_dict['contrail:instance_count'] = 0 -+ extra_dict['contrail:ipam_fq_name'] = ipam_fq_name -+ -+ return {'q_api_data': sn_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _ipam_neutron_to_vnc(self, ipam_q, oper): -+ ipam_name = ipam_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(ipam_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ ipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_q['id']) -+ -+ if ipam_q['mgmt']: -+ ipam_obj.set_network_ipam_mgmt( -+ vnc_api.IpamType.factory(**ipam_q['mgmt'])) -+ -+ return ipam_obj -+ -+ def _ipam_vnc_to_neutron(self, ipam_obj): -+ ipam_q_dict = json.loads(json.dumps(ipam_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ ipam_q_dict['id'] = ipam_q_dict.pop('uuid') -+ ipam_q_dict['tenant_id'] = ipam_obj.parent_uuid.replace('-', '') -+ ipam_q_dict['mgmt'] = ipam_q_dict.pop('network_ipam_mgmt', None) -+ net_back_refs = ipam_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ ipam_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ ipam_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': ipam_q_dict, -+ 'q_extra_data': {}} -+ -+ def _policy_neutron_to_vnc(self, policy_q, oper): -+ policy_name = policy_q.get('name', None) -+ if oper == CREATE: -+ project_id = str(uuid.UUID(policy_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ else: # READ/UPDATE/DELETE -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_q['id']) -+ -+ policy_obj.set_network_policy_entries( -+ vnc_api.PolicyEntriesType.factory(**policy_q['entries'])) -+ -+ return policy_obj -+ -+ def _policy_vnc_to_neutron(self, policy_obj): -+ policy_q_dict = json.loads(json.dumps(policy_obj, -+ default=self._obj_to_json)) -+ -+ # replace field names -+ policy_q_dict['id'] = policy_q_dict.pop('uuid') -+ policy_q_dict['tenant_id'] = policy_obj.uuid.replace('-', '') -+ policy_q_dict['entries'] = policy_q_dict.pop('network_policy_entries', -+ None) -+ net_back_refs = policy_q_dict.pop('virtual_network_back_refs', None) -+ if net_back_refs: -+ policy_q_dict['nets_using'] = [] -+ for net_back_ref in net_back_refs: -+ net_fq_name = net_back_ref['to'] -+ policy_q_dict['nets_using'].append(net_fq_name) -+ -+ return {'q_api_data': policy_q_dict, -+ 'q_extra_data': {}} -+ -+ def _floatingip_neutron_to_vnc(self, fip_q, oper): -+ if oper == CREATE: -+ # use first available pool on net -+ net_id = fip_q['floating_network_id'] -+ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) -+ fip_name = str(uuid.uuid4()) -+ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) -+ fip_obj.uuid = fip_name -+ -+ proj_id = str(uuid.UUID(fip_q['tenant_id'])) -+ proj_obj = self._project_read(proj_id=proj_id) -+ fip_obj.set_project(proj_obj) -+ else: # READ/UPDATE/DELETE -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) -+ -+ if fip_q['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=fip_q['port_id']) -+ fip_obj.set_virtual_machine_interface(port_obj) -+ else: -+ fip_obj.set_virtual_machine_interface_list([]) -+ -+ return fip_obj -+ -+ def _floatingip_vnc_to_neutron(self, fip_obj): -+ fip_q_dict = {} -+ extra_dict = {} -+ -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( -+ id=fip_obj.parent_uuid) -+ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) -+ -+ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') -+ -+ port_id = None -+ port_refs = fip_obj.get_virtual_machine_interface_refs() -+ if port_refs: -+ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] -+ -+ fip_q_dict['id'] = fip_obj.uuid -+ fip_q_dict['tenant_id'] = tenant_id -+ fip_q_dict['floating_ip_address'] = fip_obj.get_floating_ip_address() -+ fip_q_dict['floating_network_id'] = net_obj.uuid -+ fip_q_dict['router_id'] = None -+ fip_q_dict['fixed_port_id'] = port_id -+ fip_q_dict['fixed_ip_address'] = None -+ -+ return {'q_api_data': fip_q_dict, -+ 'q_extra_data': extra_dict} -+ -+ def _port_neutron_to_vnc(self, port_q, net_obj, oper): -+ if oper == CREATE: -+ port_name = str(uuid.uuid4()) -+ instance_name = port_q['device_id'] -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ -+ id_perms = vnc_api.IdPermsType(enable=True) -+ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, -+ id_perms=id_perms) -+ port_obj.uuid = port_name -+ port_obj.set_virtual_network(net_obj) -+ -+ else: # READ/UPDATE/DELETE -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_q['id']) -+ -+ port_obj.set_security_group_list([]) -+ if ('security_groups' in port_q and -+ port_q['security_groups'].__class__ is not object): -+ for sg_id in port_q['security_groups']: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ port_obj.add_security_group(sg_obj) -+ -+ id_perms = port_obj.get_id_perms() -+ if 'admin_state_up' in port_q: -+ id_perms.enable = port_q['admin_state_up'] -+ port_obj.set_id_perms(id_perms) -+ -+ return port_obj -+ -+ def _port_vnc_to_neutron(self, port_obj, net_obj=None): -+ port_q_dict = {} -+ port_q_dict['name'] = port_obj.uuid -+ port_q_dict['id'] = port_obj.uuid -+ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_CONTRAIL -+ -+ if not net_obj: -+ net_refs = port_obj.get_virtual_network_refs() -+ if net_refs: -+ net_id = net_refs[0]['uuid'] -+ else: -+ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) -+ -+ #proj_id = self._get_obj_tenant_id('port', port_obj.uuid) -+ proj_id = None -+ if not proj_id: -+ # not in cache, get by reading VN obj, and populate cache -+ net_obj = self._virtual_network_read(net_id=net_id) -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(port_obj.uuid, proj_id) -+ else: -+ net_id = net_obj.uuid -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ -+ port_q_dict['tenant_id'] = proj_id -+ port_q_dict['network_id'] = net_id -+ -+ port_q_dict['mac_address'] = '' -+ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() -+ if mac_refs: -+ port_q_dict['mac_address'] = mac_refs.mac_address[0] -+ -+ port_q_dict['fixed_ips'] = [] -+ ip_back_refs = port_obj.get_instance_ip_back_refs() -+ if ip_back_refs: -+ for ip_back_ref in ip_back_refs: -+ try: -+ ip_obj = self._instance_ip_read( -+ instance_ip_id=ip_back_ref['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ -+ ip_addr = ip_obj.get_instance_ip_address() -+ -+ ip_q_dict = {} -+ ip_q_dict['port_id'] = port_obj.uuid -+ ip_q_dict['ip_address'] = ip_addr -+ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, -+ net_obj) -+ ip_q_dict['net_id'] = net_id -+ -+ port_q_dict['fixed_ips'].append(ip_q_dict) -+ -+ sg_dict = {'port_security_enabled': True} -+ sg_dict['security_groups'] = [] -+ sg_refs = port_obj.get_security_group_refs() -+ for sg_ref in sg_refs or []: -+ sg_dict['security_groups'].append(sg_ref['uuid']) -+ -+ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable -+ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE -+ port_q_dict['device_id'] = port_obj.parent_name -+ port_q_dict['device_owner'] = 'TODO-device-owner' -+ -+ return {'q_api_data': port_q_dict, -+ 'q_extra_data': sg_dict} -+ -+ # public methods -+ # network api handlers -+ def network_create(self, network_q): -+ #self._ensure_project_exists(network_q['tenant_id']) -+ -+ net_obj = self._network_neutron_to_vnc(network_q, CREATE) -+ net_uuid = self._virtual_network_create(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_uuid] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_read(self, net_uuid, fields=None): -+ # see if we can return fast... -+ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': -+ tenant_id = self._get_obj_tenant_id('network', net_uuid) -+ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} -+ -+ try: -+ # return self._db_cache['q_networks']['net_uuid'] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ try: -+ net_obj = self._network_read(net_uuid) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_uuid) -+ -+ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ -+ def network_update(self, net_id, network_q): -+ network_q['id'] = net_id -+ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) -+ self._virtual_network_update(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_id] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_delete(self, net_id): -+ self._virtual_network_delete(net_id=net_id) -+ try: -+ del self._db_cache['q_networks'][net_id] -+ except KeyError: -+ pass -+ -+ def network_list(self, filters=None): -+ ret_list = [] -+ -+ if filters and 'shared' in filters: -+ if filters['shared'][0] is True: -+ # no support for shared networks -+ return ret_list -+ -+ # collect phase -+ all_nets = [] # all n/ws in all projects -+ if filters and 'tenant_id' in filters: -+ # project-id is present -+ if 'id' in filters: -+ # required networks are also specified, -+ # just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in project, and prune below -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ if 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(p_id)) -+ else: -+ project_nets = self._network_list_project(p_id) -+ all_nets.append(project_nets) -+ elif filters and 'id' in filters: -+ # required networks are specified, just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in all projects -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ if filters and 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(proj_id)) -+ else: -+ project_nets = self._network_list_project(proj_id) -+ all_nets.append(project_nets) -+ -+ # prune phase -+ for project_nets in all_nets: -+ for proj_net in project_nets: -+ proj_net_id = proj_net['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_net_id): -+ continue -+ -+ proj_net_fq_name = unicode(proj_net['fq_name']) -+ if not self._filters_is_present(filters, 'contrail:fq_name', -+ proj_net_fq_name): -+ continue -+ -+ try: -+ net_obj = self._network_read(proj_net['uuid']) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ except vnc_exc.NoIdError: -+ continue -+ ret_list.append(net_info) -+ -+ return ret_list -+ -+ def network_count(self, filters=None): -+ nets_info = self.network_list(filters) -+ return len(nets_info) -+ -+ # subnet api handlers -+ def subnet_create(self, subnet_q): -+ net_id = subnet_q['network_id'] -+ net_obj = self._virtual_network_read(net_id=net_id) -+ -+ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] -+ if ipam_fq_name != '': -+ domain_name, project_name, ipam_name = ipam_fq_name -+ -+ project_obj = vnc_api.Project(project_name) -+ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # link subnet with default ipam -+ project_obj = vnc_api.Project(net_obj.parent_name) -+ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) -+ ipam_fq_name = netipam_obj.get_fq_name() -+ -+ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) -+ -+ # Locate list of subnets to which this subnet has to be appended -+ net_ipam_ref = None -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ if ipam_ref['to'] == ipam_fq_name: -+ net_ipam_ref = ipam_ref -+ break -+ -+ if not net_ipam_ref: -+ # First link from net to this ipam -+ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) -+ net_obj.add_network_ipam(netipam_obj, vnsn_data) -+ else: # virtual-network already linked to this ipam -+ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): -+ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): -+ # duplicate !! -+ subnet_info = self._subnet_vnc_to_neutron(subnet, -+ net_obj, -+ ipam_fq_name) -+ return subnet_info -+ vnsn_data = net_ipam_ref['attr'] -+ vnsn_data.ipam_subnets.append(subnet_vnc) -+ -+ self._virtual_network_update(net_obj) -+ -+ # allocate an id to the subnet and store mapping with -+ # api-server -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, subnet_key) -+ -+ # Read in subnet from server to get updated values for gw etc. -+ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) -+ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, -+ ipam_fq_name) -+ -+ #self._db_cache['q_subnets'][subnet_id] = subnet_info -+ -+ return subnet_info -+ -+ def subnet_read(self, subnet_id): -+ try: -+ # return self._db_cache['q_subnets'][subnet_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_id) == subnet_key: -+ ret_subnet_q = self._subnet_vnc_to_neutron( -+ subnet_vnc, net_obj, ipam_ref['to']) -+ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q -+ return ret_subnet_q -+ -+ return {} -+ -+ def subnet_delete(self, subnet_id): -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ orig_subnets = ipam_ref['attr'].get_ipam_subnets() -+ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets -+ if self._subnet_vnc_get_key(subnet_vnc, net_id) -+ != subnet_key] -+ if len(orig_subnets) != len(new_subnets): -+ # matched subnet to be deleted -+ ipam_ref['attr'].set_ipam_subnets(new_subnets) -+ self._virtual_network_update(net_obj) -+ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) -+ try: -+ del self._db_cache['q_subnets'][subnet_id] -+ except KeyError: -+ pass -+ -+ return -+ -+ def subnets_list(self, filters=None): -+ ret_subnets = [] -+ -+ if filters and 'id' in filters: -+ # required subnets are specified, -+ # just read in corresponding net_ids -+ net_ids = set([]) -+ for subnet_id in filters['id']: -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ net_ids.add(net_id) -+ else: -+ nets_info = self.network_list() -+ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] -+ -+ for net_id in net_ids: -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, -+ net_obj, -+ ipam_ref['to']) -+ sn_id = sn_info['q_api_data']['id'] -+ sn_proj_id = sn_info['q_api_data']['tenant_id'] -+ sn_net_id = sn_info['q_api_data']['network_id'] -+ -+ if filters: -+ if not self._filters_is_present(filters, 'id', -+ sn_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'tenant_id', -+ sn_proj_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'network_id', -+ sn_net_id): -+ continue -+ -+ ret_subnets.append(sn_info) -+ -+ return ret_subnets -+ -+ def subnets_count(self, filters=None): -+ subnets_info = self.subnets_list(filters) -+ return len(subnets_info) -+ -+ # ipam api handlers -+ def ipam_create(self, ipam_q): -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, CREATE) -+ self._vnc_lib.network_ipam_create(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_read(self, ipam_id): -+ try: -+ ipam_obj = self._vnc_lib.network_ipam_read(id=ipam_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=ipam_id) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_update(self, ipam_id, ipam): -+ ipam_q = ipam['ipam'] -+ ipam_q['id'] = ipam_id -+ ipam_obj = self._ipam_neutron_to_vnc(ipam_q, UPDATE) -+ self._vnc_lib.network_ipam_update(ipam_obj) -+ -+ return self._ipam_vnc_to_neutron(ipam_obj) -+ -+ def ipam_delete(self, ipam_id): -+ self._vnc_lib.network_ipam_delete(id=ipam_id) -+ -+ def ipam_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_ipams = [] # all ipams in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_ipams = self._ipam_list_project(p_id) -+ all_ipams.append(project_ipams) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_ipams = self._ipam_list_project(proj_id) -+ all_ipams.append(project_ipams) -+ -+ # prune phase -+ for project_ipams in all_ipams: -+ for proj_ipam in project_ipams: -+ proj_ipam_id = proj_ipam['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_ipam_id): -+ continue -+ ipam_info = self.ipam_read(proj_ipam['uuid']) -+ ret_list.append(ipam_info) -+ -+ return ret_list -+ -+ def ipam_count(self, filters=None): -+ ipam_info = self.ipam_list(filters) -+ return len(ipam_info) -+ -+ # policy api handlers -+ def policy_create(self, policy_q): -+ -+ policy_obj = self._policy_neutron_to_vnc(policy_q, CREATE) -+ self._vnc_lib.network_policy_create(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_read(self, policy_id): -+ policy_obj = self._vnc_lib.network_policy_read(id=policy_id) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_update(self, policy_id, policy): -+ policy_q = policy['policy'] -+ policy_q['id'] = policy_id -+ policy_obj = self._policy_neutron_to_vnc(policy_q, UPDATE) -+ self._vnc_lib.network_policy_update(policy_obj) -+ -+ return self._policy_vnc_to_neutron(policy_obj) -+ -+ def policy_delete(self, policy_id): -+ self._vnc_lib.network_policy_delete(id=policy_id) -+ -+ def policy_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_policys = [] # all policys in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_policys = self._policy_list_project(p_id) -+ all_policys.append(project_policys) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_policys = self._policy_list_project(proj_id) -+ all_policys.append(project_policys) -+ -+ # prune phase -+ for project_policys in all_policys: -+ for proj_policy in project_policys: -+ proj_policy_id = proj_policy['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_policy_id): -+ continue -+ policy_info = self.policy_read(proj_policy['uuid']) -+ ret_list.append(policy_info) -+ -+ return ret_list -+ -+ def policy_count(self, filters=None): -+ policy_info = self.policy_list(filters) -+ return len(policy_info) -+ -+ # floatingip api handlers -+ def floatingip_create(self, fip_q): -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) -+ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_read(self, fip_uuid): -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_update(self, fip_id, fip_q): -+ fip_q['id'] = fip_id -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, UPDATE) -+ self._vnc_lib.floating_ip_update(fip_obj) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_delete(self, fip_id): -+ self._vnc_lib.floating_ip_delete(id=fip_id) -+ -+ def floatingip_list(self, filters=None): -+ # Find networks, get floatingip backrefs and return -+ ret_list = [] -+ -+ if filters: -+ if 'tenant_id' in filters: -+ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] -+ elif 'port_id' in filters: -+ # required ports are specified, just read and populate ret_list -+ # prune is skipped because proj_objs is empty -+ proj_ids = [] -+ for port_id in filters['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_id) -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron( -+ fip_obj)) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ proj_ids = [proj['uuid'] for proj in dom_projects] -+ -+ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] -+ -+ for proj_obj in proj_objs: -+ fip_back_refs = proj_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) -+ -+ return ret_list -+ -+ def floatingip_count(self, filters=None): -+ floatingip_info = self.floatingip_list(filters) -+ return len(floatingip_info) -+ -+ # port api handlers -+ def port_create(self, port_q): -+ net_id = port_q['network_id'] -+ net_obj = self._network_read(net_id) -+ proj_id = net_obj.parent_uuid -+ -+ self._ensure_instance_exists(port_q['device_id']) -+ -+ # initialize port object -+ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) -+ -+ # if ip address passed then use it -+ ip_addr = None -+ ip_obj = None -+ if port_q['fixed_ips'].__class__ is not object: -+ ip_addr = port_q['fixed_ips'][0]['ip_address'] -+ ip_name = '%s %s' % (net_id, ip_addr) -+ try: -+ ip_obj = self._instance_ip_read(fq_name=[ip_name]) -+ #ip_id = ip_obj.uuid -+ except Exception as e: -+ ip_obj = None -+ -+ # create the object -+ port_id = self._virtual_machine_interface_create(port_obj) -+ -+ # initialize ip object -+ if ip_obj is None: -+ ip_name = str(uuid.uuid4()) -+ ip_obj = vnc_api.InstanceIp(name=ip_name) -+ ip_obj.uuid = ip_name -+ ip_obj.set_virtual_machine_interface(port_obj) -+ ip_obj.set_virtual_network(net_obj) -+ if ip_addr: -+ ip_obj.set_instance_ip_address(ip_addr) -+ try: -+ self._instance_ip_create(ip_obj) -+ except Exception as e: -+ # ResourceExhaustionError, resources are not available -+ self._virtual_machine_interface_delete(port_id=port_id) -+ raise e -+ # shared ip address -+ else: -+ if ip_addr == ip_obj.get_instance_ip_address(): -+ ip_obj.add_virtual_machine_interface(port_obj) -+ self._instance_ip_update(ip_obj) -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) -+ #self._db_cache['q_ports'][port_id] = ret_port_q -+ self._set_obj_tenant_id(port_id, proj_id) -+ -+ # update cache on successful creation -+ tenant_id = proj_id.replace('-', '') -+ if tenant_id not in self._db_cache['q_tenant_port_count']: -+ ncurports = self.port_count({'tenant_id': tenant_id}) -+ else: -+ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] -+ -+ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 -+ -+ return ret_port_q -+ -+ def port_read(self, port_id): -+ try: -+ # return self._db_cache['q_ports'][port_id] -+ raise KeyError -+ except KeyError: -+ pass -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_update(self, port_id, port_q): -+ port_q['id'] = port_id -+ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) -+ self._virtual_machine_interface_update(port_obj) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_delete(self, port_id): -+ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) -+ instance_id = port_obj.parent_uuid -+ -+ # release instance IP address -+ iip_back_refs = port_obj.get_instance_ip_back_refs() -+ if iip_back_refs: -+ for iip_back_ref in iip_back_refs: -+ # if name contains IP address then this is shared ip -+ iip_obj = self._vnc_lib.instance_ip_read( -+ id=iip_back_ref['uuid']) -+ name = iip_obj.name -+ if len(name.split(' ')) > 1: -+ name = name.split(' ')[1] -+ -+ # in case of shared ip only delete the link to the VMI -+ try: -+ socket.inet_aton(name) -+ iip_obj.del_virtual_machine_interface(port_obj) -+ self._instance_ip_update(iip_obj) -+ except socket.error: -+ self._instance_ip_delete( -+ instance_ip_id=iip_back_ref['uuid']) -+ -+ # disassociate any floating IP used by instance -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if fip_back_refs: -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ self.floatingip_update(fip_obj.uuid, {'port_id': None}) -+ -+ self._virtual_machine_interface_delete(port_id=port_id) -+ -+ # delete instance if this was the last port -+ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) -+ inst_intfs = inst_obj.get_virtual_machine_interfaces() -+ if not inst_intfs: -+ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) -+ -+ try: -+ del self._db_cache['q_ports'][port_id] -+ except KeyError: -+ pass -+ -+ # update cache on successful deletion -+ try: -+ tenant_id = self._get_obj_tenant_id('port', port_id) -+ self._db_cache['q_tenant_port_count'][tenant_id] = \ -+ self._db_cache['q_tenant_port_count'][tenant_id] - 1 -+ except KeyError: -+ pass -+ -+ self._del_obj_tenant_id(port_id) -+ -+ def port_list(self, filters=None): -+ ret_q_ports = [] -+ all_project_ids = [] -+ -+ if 'device_owner' in filters: -+ return ret_q_ports -+ -+ if 'device_id' not in filters: -+ # Listing from back references -+ if not filters: -+ # no filters => return all ports! -+ all_projects = self._project_list_domain(None) -+ all_project_ids = [project['uuid'] for project in all_projects] -+ elif 'tenant_id' in filters: -+ all_project_ids = filters.get('tenant_id') -+ -+ for proj_id in all_project_ids: -+ proj_ports = self._port_list_project(proj_id) -+ for port in proj_ports: -+ try: -+ port_info = self.port_read(port['id']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ for net_id in filters.get('network_id', []): -+ net_ports = self._port_list_network(net_id) -+ for port in net_ports: -+ port_info = self.port_read(port['id']) -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ # Listing from parent to children -+ virtual_machine_ids = filters['device_id'] -+ for vm_id in virtual_machine_ids: -+ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( -+ parent_id=vm_id) -+ vm_intf_ids = resp_dict['virtual-machine-interfaces'] -+ for vm_intf in vm_intf_ids: -+ try: -+ port_info = self.port_read(vm_intf['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ def port_count(self, filters=None): -+ if 'device_owner' in filters: -+ return 0 -+ -+ if 'tenant_id' in filters: -+ project_id = filters['tenant_id'][0] -+ try: -+ return self._db_cache['q_tenant_port_count'][project_id] -+ except KeyError: -+ # do it the hard way but remember for next time -+ nports = len(self._port_list_project(project_id)) -+ self._db_cache['q_tenant_port_count'][project_id] = nports -+ else: -+ # across all projects -+ # get only a count from api-server! -+ nports = len(self.port_list(filters)) -+ -+ return nports -+ -+ # security group api handlers -+ def security_group_create(self, sg_q): -+ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) -+ sg_uuid = self._security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = {} -+ def_rule['port_range_min'] = 0 -+ def_rule['port_range_max'] = 65535 -+ def_rule['direction'] = 'egress' -+ def_rule['remote_ip_prefix'] = None -+ def_rule['remote_group_id'] = None -+ def_rule['protocol'] = 'any' -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_uuid, rule) -+ -+ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) -+ return ret_sg_q -+ -+ def security_group_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return self._security_group_vnc_to_neutron(sg_obj) -+ -+ def security_group_delete(self, sg_id): -+ self._security_group_delete(sg_id) -+ -+ def security_group_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] # all sgs in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sg_info = self.security_group_read(proj_sg_id) -+ if not self._filters_is_present(filters, 'name', -+ sg_info['q_api_data']['name']): -+ continue -+ ret_list.append(sg_info) -+ -+ return ret_list -+ -+ def security_group_rule_create(self, sgr_q): -+ sg_id = sgr_q['security_group_id'] -+ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) -+ self._security_group_rule_create(sg_id, sg_rule) -+ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, -+ sg_rule) -+ -+ return ret_sg_rule_q -+ -+ def security_group_rule_read(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ -+ return {} -+ -+ def security_group_rule_delete(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_delete(sg_obj, sg_rule) -+ -+ def security_group_rules_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ sgr_entries = sg_obj.get_security_group_entries() -+ sg_rules = [] -+ if sgr_entries is None: -+ return -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ sg_info = self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ sg_rules.append(sg_info) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return sg_rules -+ -+ def security_group_rule_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sgs = [] -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sgs = self._security_group_list_project(p_id) -+ all_sgs.append(project_sgs) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ all_sgs.append(project_sgs) -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sgr_info = self.security_group_rules_read(proj_sg_id) -+ if sgr_info: -+ ret_list.append(sgr_info) -+ -+ return ret_list -+ -+ #route table api handlers -+ def route_table_create(self, rt_q): -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, CREATE) -+ self._route_table_create(rt_obj) -+ ret_rt_q = self._route_table_vnc_to_neutron(rt_obj) -+ return ret_rt_q -+ -+ def route_table_read(self, rt_id): -+ try: -+ rt_obj = self._vnc_lib.route_table_read(id=rt_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=rt_id) -+ -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_update(self, rt_id, rt_q): -+ rt_q['id'] = rt_id -+ rt_obj = self._route_table_neutron_to_vnc(rt_q, UPDATE) -+ self._vnc_lib.route_table_update(rt_obj) -+ return self._route_table_vnc_to_neutron(rt_obj) -+ -+ def route_table_delete(self, rt_id): -+ self._route_table_delete(rt_id) -+ -+ def route_table_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_rts = [] # all rts in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_rts = self._route_table_list_project(p_id) -+ all_rts.append(project_rts) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_rts = self._route_table_list_project(proj_id) -+ all_rts.append(project_rts) -+ -+ # prune phase -+ for project_rts in all_rts: -+ for proj_rt in project_rts: -+ proj_rt_id = proj_rt['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_rt_id): -+ continue -+ rt_info = self.route_table_read(proj_rt_id) -+ if not self._filters_is_present(filters, 'name', -+ rt_info['q_api_data']['name']): -+ continue -+ ret_list.append(rt_info) -+ -+ return ret_list -+ -+ #service instance api handlers -+ def svc_instance_create(self, si_q): -+ si_obj = self._svc_instance_neutron_to_vnc(si_q, CREATE) -+ self._svc_instance_create(si_obj) -+ ret_si_q = self._svc_instance_vnc_to_neutron(si_obj) -+ return ret_si_q -+ -+ def svc_instance_read(self, si_id): -+ try: -+ si_obj = self._vnc_lib.service_instance_read(id=si_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=si_id) -+ -+ return self._svc_instance_vnc_to_neutron(si_obj) -+ -+ def svc_instance_delete(self, si_id): -+ self._svc_instance_delete(si_id) -+ -+ def svc_instance_list(self, context, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ all_sis = [] # all sis in all projects -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ elif filters and 'name' in filters: -+ p_id = str(uuid.UUID(context.tenant)) -+ project_sis = self._svc_instance_list_project(p_id) -+ all_sis.append(project_sis) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sis = self._svc_instance_list_project(proj_id) -+ all_sis.append(project_sis) -+ -+ # prune phase -+ for project_sis in all_sis: -+ for proj_si in project_sis: -+ proj_si_id = proj_si['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_si_id): -+ continue -+ si_info = self.svc_instance_read(proj_si_id) -+ if not self._filters_is_present(filters, 'name', -+ si_info['q_api_data']['name']): -+ continue -+ ret_list.append(si_info) -+ -+ return ret_list -diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py -new file mode 100644 -index 0000000..72bebec ---- /dev/null -+++ neutron/tests/unit/juniper/__init__.py -@@ -0,0 +1,14 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py -new file mode 100644 -index 0000000..decf79e ---- /dev/null -+++ neutron/tests/unit/juniper/test_contrail_plugin.py -@@ -0,0 +1,998 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -+ -+import datetime -+import mock -+import neutron.db.api -+from neutron.manager import NeutronManager -+from neutron.tests.unit import test_db_plugin as test_plugin -+import sys -+import uuid -+ -+subnet_obj = {u'subnet': -+ {'name': '', 'enable_dhcp': True, -+ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', -+ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', -+ 'dns_nameservers': '', -+ u'contrail:ipam_fq_name': -+ [u'default-domain', u'admin', u'default-network-ipam'], -+ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, -+ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} -+ -+vn_list = [] -+GlobalProjects = [] -+ -+ -+class MockVncApi(mock.MagicMock): -+ def __init__(self, *args, **kwargs): -+ pass -+ -+ def kv_retrieve(self, *args, **kwargs): -+ return [] -+ -+ def kv_store(self, *args, **kwargs): -+ return -+ -+ def kv_delete(self, *args, **kwargs): -+ return -+ -+ def project_read(self, *args, **kwargs): -+ #return MockProject('dummy-proj') -+ return GlobalProjects[0] -+ -+ def virtual_network_create(self, net_obj): -+ net_id = unicode(str(uuid.uuid4())) -+ net_obj.set_uuid(net_id) -+ vn_list.append(net_obj) -+ return net_id -+ -+ def virtual_network_read(self, id, *args, **kwargs): -+ if len(vn_list): -+ for index in range(len(vn_list)): -+ if ((vn_list[index].get_uuid()) == id): -+ return vn_list[index] -+ -+ #return a mock object if it is not created so far -+ return MockVirtualNetwork('dummy-net', MockProject()) -+ -+ def virtual_network_delete(self, *args, **kwargs): -+ return -+ -+ def virtual_network_update(self, *args, **kwargs): -+ return -+ -+ def virtual_networks_list(self, *args, **kwargs): -+ return vn_list -+ -+ -+class MockVncObject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ if not parent_obj: -+ self._fq_name = [name] -+ else: -+ self._fq_name = parent_obj.get_fq_name() + [name] -+ -+ self._ipam_refs = [{'to': [u'default-domain', u'admin', -+ u'default-network-ipam']}] -+ self.uuid = None -+ self.name = name -+ self.network_ipam_refs = [] -+ -+ def set_uuid(self, uuid): -+ self.uuid = uuid -+ -+ def get_uuid(self): -+ return self.uuid -+ -+ def get_fq_name(self): -+ return self._fq_name -+ -+ def get_network_ipam_refs(self): -+ return getattr(self, 'network_ipam_refs', None) -+ -+ def add_network_ipam(self, ref_obj, ref_data): -+ refs = getattr(self, 'network_ipam_refs', []) -+ if not refs: -+ self.network_ipam_refs = [] -+ -+ # if ref already exists, update any attr with it -+ for ref in refs: -+ if ref['to'] == ref_obj.get_fq_name(): -+ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref['uuid'] = ref_obj.uuid -+ return -+ -+ # ref didn't exist before -+ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref_info['uuid'] = ref_obj.uuid -+ -+ self.network_ipam_refs.append(ref_info) -+ -+ -+class MockVirtualNetwork(MockVncObject): -+ pass -+ -+ -+class MockSubnetType(mock.MagicMock): -+ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ip_prefix = ip_prefix -+ self.ip_prefix_len = ip_prefix_len -+ -+ def get_ip_prefix(self): -+ return self.ip_prefix -+ -+ def set_ip_prefix(self, ip_prefix): -+ self.ip_prefix = ip_prefix -+ -+ def get_ip_prefix_len(self): -+ return self.ip_prefix_len -+ -+ def set_ip_prefix_len(self, ip_prefix_len): -+ self.ip_prefix_len = ip_prefix_len -+ -+ -+class MockIpamSubnetType(mock.MagicMock): -+ def __init__(self, name=None, subnet=None, default_gateway=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.subnet = subnet -+ self.default_gateway = default_gateway -+ -+ def get_subnet(self): -+ return self.subnet -+ -+ def set_subnet(self, subnet): -+ self.subnet = subnet -+ -+ def get_default_gateway(self): -+ return self.default_gateway -+ -+ def set_default_gateway(self, default_gateway): -+ self.default_gateway = default_gateway -+ -+ def validate_IpAddressType(self, value): -+ pass -+ -+ -+class MockVnSubnetsType(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ipam_subnets = [] -+ if ipam_subnets: -+ #self.ipam_subnets = copy.deepcopy(ipam_subnets) -+ self.ipam_subnets = ipam_subnets -+ -+ def get_ipam_subnets(self): -+ return self.ipam_subnets -+ -+ def set_ipam_subnets(self, ipam_subnets): -+ self.ipam_subnets = ipam_subnets -+ -+ def add_ipam_subnets(self, value): -+ self.ipam_subnets.append(value) -+ -+ def insert_ipam_subnets(self, index, value): -+ self.ipam_subnets[index] = value -+ -+ def delete_ipam_subnets(self, value): -+ self.ipam_subnets.remove(value) -+ -+ -+class MockNetworkIpam(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, -+ network_ipam_mgmt=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'default-network-ipam' -+ self.name = name -+ self.uuid = None -+ if parent_obj: -+ self.parent_type = parent_obj._type -+ # copy parent's fq_name -+ self.fq_name = list(parent_obj.fq_name) -+ self.fq_name.append(name) -+ if not parent_obj.get_network_ipams(): -+ parent_obj.network_ipams = [] -+ parent_obj.network_ipams.append(self) -+ else: # No parent obj specified -+ self.parent_type = 'project' -+ self.fq_name = [u'default-domain', u'default-project'] -+ self.fq_name.append(name) -+ -+ # property fields -+ if network_ipam_mgmt: -+ self.network_ipam_mgmt = network_ipam_mgmt -+ if id_perms: -+ self.id_perms = id_perms -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+class MockProject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'project' -+ self.uuid = None -+ self.parent_type = 'domain' -+ self.fq_name = [u'default-domain'] -+ self.fq_name.append(name) -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+def GlobalProjectApi(project_name): -+ if not GlobalProjects: -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ return GlobalProjects[0] -+ -+ -+# Mock definations for different pkgs, modules and VncApi -+mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) -+mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') -+mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork -+mock_vnc_api_mod.SubnetType = MockSubnetType -+mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType -+mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType -+mock_vnc_api_mod.NetworkIpam = MockNetworkIpam -+mock_vnc_api_mod.Project = GlobalProjectApi -+ -+mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') -+mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') -+mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ -+ mock_vnc_api_pkg -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ -+ mock_vnc_api_mod -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ -+ mock_vnc_common_mod -+sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' -+ 'exceptions')] = \ -+ mock_vnc_exception_mod -+ -+CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" -+ -+ -+class RouterInstance(object): -+ def __init__(self): -+ self._name = 'rounter_instance' -+ -+ -+class Context(object): -+ def __init__(self, tenant_id=''): -+ self.read_only = False -+ self.show_deleted = False -+ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] -+ self._read_deleted = 'no' -+ self.timestamp = datetime.datetime.now() -+ self.auth_token = None -+ self._session = None -+ self._is_admin = True -+ self.admin = uuid.uuid4().hex.decode() -+ self.request_id = 'req-' + str(uuid.uuid4()) -+ self.tenant = tenant_id -+ -+ -+class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): -+ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) -+ -+ def setUp(self): -+ -+ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod -+ -+ mock_vnc_api_mod.common = mock_vnc_common_mod -+ mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+ -+ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+ -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ neutron.db.api._ENGINE = mock.MagicMock() -+ -+ def teardown(self): -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ -+ -+class TestContrailNetworks(test_plugin.TestNetworksV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ if 'contrail:fq_name' not in net.keys(): -+ assert False -+ else: -+ assert True -+ -+ def test_delete_network(self): -+ # First create the network and request to delete the same -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ -+ plugin_obj.delete_network(context_obj, net_id) -+ mock_vnc_api_cls.virtual_network_delete.assert_called_once() -+ -+ def test_update_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ # change one of the attribute and update the network -+ network['admin_state_up'] = 'False' -+ new_dict = plugin_obj.update_network(context_obj, net_id, -+ networks_req) -+ if (net_dict.get('admin_state_up') == new_dict.get('admin_state_up')): -+ assert False -+ else: -+ assert True -+ -+ # Not supported test cases in the this TestClass -+ def test_create_networks_bulk_emulated(self): -+ pass -+ -+ def test_create_networks_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_public_network(self): -+ pass -+ -+ def test_create_networks_bulk_wrong_input(self): -+ pass -+ -+ def test_update_shared_network_noadmin_returns_403(self): -+ pass -+ -+ def test_update_network_set_shared(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_single_tenant(self): -+ pass -+ -+ def test_update_network_set_not_shared_other_tenant_returns_409(self): -+ pass -+ -+ def test_update_network_with_subnet_set_shared(self): -+ pass -+ -+ def test_show_network(self): -+ pass -+ -+ def test_show_network_with_subnet(self): -+ pass -+ -+ def test_list_networks(self): -+ pass -+ -+ def test_list_shared_networks_with_non_admin_user(self): -+ pass -+ -+ def test_list_networks_with_parameters(self): -+ pass -+ -+ def test_list_networks_with_fields(self): -+ pass -+ -+ def test_list_networks_with_parameters_invalid_values(self): -+ pass -+ -+ def test_list_networks_with_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_without_pk_in_fields_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_with_sort_emulated(self): -+ pass -+ -+ def test_list_networks_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_invalid_admin_status(self): -+ pass -+ -+ -+class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ if subnet_dict['cidr'] != subnet_obj['subnet']['cidr']: -+ assert False -+ else: -+ assert True -+ -+ def test_delete_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ network = {} -+ router_inst = RouterInstance() -+ network['router:external'] = router_inst -+ network[u'name'] = u'network1' -+ network['admin_state_up'] = 'True' -+ network['tenant_id'] = uuid.uuid4().hex.decode() -+ network['vpc:route_table'] = '' -+ network['shared'] = False -+ network['port_security_enabled'] = True -+ network[u'contrail:policys'] = [] -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ subnet_id = subnet_dict['id'] -+ plugin_obj.delete_subnet(context_obj, subnet_id) -+ -+ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_delete_network(self): -+ pass -+ -+ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet_adding_additional_host_routes_and_dns(self): -+ pass -+ -+ def test_update_subnet_no_gateway(self): -+ pass -+ -+ def test_create_subnet_bad_cidr(self): -+ pass -+ -+ def test_create_subnet_gw_of_network_force_on_returns_400(self): -+ pass -+ -+ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_create_two_subnets(self): -+ pass -+ -+ def test_create_two_subnets_same_cidr_returns_400(self): -+ pass -+ -+ def test_create_subnet_bad_V4_cidr(self): -+ pass -+ -+ def test_create_subnet_bad_V6_cidr(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): -+ pass -+ -+ def test_create_subnets_bulk_native(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_subnets_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_network(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_other(self): -+ pass -+ -+ def test_create_subnet_bad_tenant(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version_null(self): -+ pass -+ -+ def test_create_subnet_bad_uuid(self): -+ pass -+ -+ def test_create_subnet_bad_boolean(self): -+ pass -+ -+ def test_create_subnet_bad_pools(self): -+ pass -+ -+ def test_create_subnet_bad_nameserver(self): -+ pass -+ -+ def test_create_subnet_bad_hostroutes(self): -+ pass -+ -+ def test_create_subnet_defaults(self): -+ pass -+ -+ def test_create_subnet_gw_values(self): -+ pass -+ -+ def test_create_force_subnet_gw_values(self): -+ pass -+ -+ def test_create_subnet_with_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_fully_allocated(self): -+ pass -+ -+ def test_subnet_with_allocation_range(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_v6_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_large_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_multiple_allocation_pools(self): -+ pass -+ -+ def test_create_subnet_with_dhcp_disabled(self): -+ pass -+ -+ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( -+ self): -+ pass -+ -+ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_create_subnet_overlapping_allocation_pools_returns_409(self): -+ pass -+ -+ def test_create_subnet_invalid_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_shared_returns_400(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_cidrv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_cidrv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_dns_v4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): -+ pass -+ -+ def test_create_subnet_gw_bcast_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet(self): -+ pass -+ -+ def test_update_subnet_shared_returns_400(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_dns_v6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): -+ pass -+ -+ def test_show_subnet(self): -+ pass -+ -+ def test_list_subnets(self): -+ pass -+ -+ def test_list_subnets_shared(self): -+ pass -+ -+ def test_list_subnets_with_parameter(self): -+ pass -+ -+ def test_invalid_ip_version(self): -+ pass -+ -+ def test_invalid_subnet(self): -+ pass -+ -+ def test_invalid_ip_address(self): -+ pass -+ -+ def test_invalid_uuid(self): -+ pass -+ -+ def test_create_subnet_with_one_dns(self): -+ pass -+ -+ def test_create_subnet_with_two_dns(self): -+ pass -+ -+ def test_create_subnet_with_too_many_dns(self): -+ pass -+ -+ def test_create_subnet_with_one_host_route(self): -+ pass -+ -+ def test_create_subnet_with_two_host_routes(self): -+ pass -+ -+ def test_create_subnet_with_too_many_routes(self): -+ pass -+ -+ def test_update_subnet_dns(self): -+ pass -+ -+ def test_update_subnet_dns_to_None(self): -+ pass -+ -+ def test_update_subnet_dns_with_too_many_entries(self): -+ pass -+ -+ def test_update_subnet_route(self): -+ pass -+ -+ def test_update_subnet_route_to_None(self): -+ pass -+ -+ def test_update_subnet_route_with_too_many_entries(self): -+ pass -+ -+ def test_delete_subnet_with_dns(self): -+ pass -+ -+ def test_delete_subnet_with_route(self): -+ pass -+ -+ def test_delete_subnet_with_dns_and_route(self): -+ pass -+ -+ def test_list_subnets_with_pagination_emulated(self): -+ pass -+ -+ def test_list_subnets_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_subnets_with_sort_emulated(self): -+ pass -+ -+ def test_validate_subnet_host_routes_exhausted(self): -+ pass -+ -+ def test_validate_subnet_dns_nameservers_exhausted(self): -+ pass -+ -+ -+class TestContrailPortsV2(test_plugin.TestPortsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_port_json(self): -+ pass -+ -+ def test_create_port_bad_tenant(self): -+ pass -+ -+ def test_create_port_public_network(self): -+ pass -+ -+ def test_create_port_public_network_with_ip(self): -+ pass -+ -+ def test_create_ports_bulk_native(self): -+ pass -+ -+ def test_create_ports_bulk_emulated(self): -+ pass -+ -+ def test_create_ports_bulk_wrong_input(self): -+ pass -+ -+ def test_create_ports_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_ports_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_list_ports(self): -+ pass -+ -+ def test_list_ports_filtered_by_fixed_ip(self): -+ pass -+ -+ def test_list_ports_public_network(self): -+ pass -+ -+ def test_show_port(self): -+ pass -+ -+ def test_delete_port(self): -+ pass -+ -+ def test_delete_port_public_network(self): -+ pass -+ -+ def test_update_port(self): -+ pass -+ -+ def test_update_device_id_null(self): -+ pass -+ -+ def test_delete_network_if_port_exists(self): -+ pass -+ -+ def test_delete_network_port_exists_owned_by_network(self): -+ pass -+ -+ def test_update_port_delete_ip(self): -+ pass -+ -+ def test_no_more_port_exception(self): -+ pass -+ -+ def test_update_port_update_ip(self): -+ pass -+ -+ def test_update_port_update_ip_address_only(self): -+ pass -+ -+ def test_update_port_update_ips(self): -+ pass -+ -+ def test_update_port_add_additional_ip(self): -+ pass -+ -+ def test_requested_duplicate_mac(self): -+ pass -+ -+ def test_mac_generation(self): -+ pass -+ -+ def test_mac_generation_4octet(self): -+ pass -+ -+ def test_bad_mac_format(self): -+ pass -+ -+ def test_mac_exhaustion(self): -+ pass -+ -+ def test_requested_duplicate_ip(self): -+ pass -+ -+ def test_requested_subnet_delete(self): -+ pass -+ -+ def test_requested_subnet_id(self): -+ pass -+ -+ def test_requested_subnet_id_not_on_network(self): -+ pass -+ -+ def test_overlapping_subnets(self): -+ pass -+ -+ def test_requested_subnet_id_v4_and_v6(self): -+ pass -+ -+ def test_range_allocation(self): -+ pass -+ -+ def test_requested_invalid_fixed_ips(self): -+ pass -+ -+ def test_invalid_ip(self): -+ pass -+ -+ def test_requested_split(self): -+ pass -+ -+ def test_duplicate_ips(self): -+ pass -+ -+ def test_fixed_ip_invalid_subnet_id(self): -+ pass -+ -+ def test_fixed_ip_invalid_ip(self): -+ pass -+ -+ def test_requested_ips_only(self): -+ pass -+ -+ def test_recycling(self): -+ pass -+ -+ def test_invalid_admin_state(self): -+ pass -+ -+ def test_invalid_mac_address(self): -+ pass -+ -+ def test_default_allocation_expiration(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration(self): -+ pass -+ -+ def test_port_delete_holds_ip(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration_invalid_address(self): -+ pass -+ -+ def test_hold_ip_address(self): -+ pass -+ -+ def test_recycle_held_ip_address(self): -+ pass -+ -+ def test_recycle_expired_previously_run_within_context(self): -+ pass -+ -+ def test_update_port_not_admin(self): -+ pass -+ -+ def test_list_ports_with_pagination_emulated(self): -+ pass -+ -+ def test_list_ports_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_ports_with_sort_emulated(self): -+ pass -+ -+ def test_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_update_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_recycle_ip_address_without_allocation_pool(self): -+ pass -diff --git setup.cfg setup.cfg -index af52a4d..27ef0ce 100644 ---- setup.cfg -+++ setup.cfg -@@ -61,6 +61,7 @@ data_files = - etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini - etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini - etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini -+ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini - scripts = - bin/quantum-rootwrap - bin/neutron-rootwrap diff --git a/contrail/neutron_v4.patch b/contrail/neutron_v4.patch deleted file mode 100644 index 50bdbc8eba..0000000000 --- a/contrail/neutron_v4.patch +++ /dev/null @@ -1,3931 +0,0 @@ -diff --git etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini -new file mode 100644 -index 0000000..ab1cee6 ---- /dev/null -+++ etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini -@@ -0,0 +1,10 @@ -+ -+[APISERVER] -+api_server_ip=10.84.13.34 -+api_server_port=8082 -+multi_tenancy=False -+ -+[KEYSTONE] -+admin_user=admin -+admin_password=contrail123 -+admin_tenant_name=admin -diff --git neutron/extensions/ipam.py neutron/extensions/ipam.py -new file mode 100644 -index 0000000..5d610b3 ---- /dev/null -+++ neutron/extensions/ipam.py -@@ -0,0 +1,140 @@ -+from abc import abstractmethod -+ -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron.api import extensions -+from neutron import manager -+from oslo.config import cfg -+ -+ -+# Ipam Exceptions -+class IpamNotFound(qexception.NotFound): -+ message = _("IPAM %(id)s could not be found") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'ipams': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:regex': attr.UUID_PATTERN}, -+ 'is_visible': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'fq_name': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ 'mgmt': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': None}, -+ 'nets_using': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True, 'default': ''} -+ }, -+} -+ -+# TODO should this be tied to ipam extension? -+EXTENDED_ATTRIBUTES_2_0 = { -+ 'networks': { -+ 'contrail:fq_name': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:policys': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ 'contrail:subnet_ipam': {'allow_post': False, -+ 'allow_put': False, -+ 'default': '', -+ 'is_visible': True}, -+ }, -+ 'subnets': { -+ 'contrail:instance_count': {'allow_post': False, -+ 'allow_put': False, -+ 'is_visible': True}, -+ 'contrail:ipam_fq_name': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ } -+} -+ -+ -+class Ipam(object): -+ -+ @classmethod -+ def get_name(cls): -+ return "Network IP Address Management" -+ -+ @classmethod -+ def get_alias(cls): -+ return "ipam" -+ -+ @classmethod -+ def get_description(cls): -+ return ("Configuration object for holding common to a set of" -+ " IP address blocks") -+ -+ @classmethod -+ def get_namespace(cls): -+ return "http://docs.openstack.org/TODO" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2012-07-20T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ exts = [] -+ plugin = manager.NeutronManager.get_plugin() -+ for resource_name in ['ipam']: -+ collection_name = resource_name + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) -+ -+ member_actions = {} -+ -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, -+ member_actions=member_actions) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ member_actions=member_actions) -+ exts.append(ex) -+ -+ return exts -+ -+ def get_extended_resources(self, version): -+ if version == "2.0": -+ return EXTENDED_ATTRIBUTES_2_0 -+ else: -+ return {} -+#end class Ipam -+ -+ -+class IpamPluginBase(object): -+ -+ @abstractmethod -+ def create_ipam(self, context, ipam): -+ pass -+ -+ @abstractmethod -+ def update_ipam(self, context, id, ipam): -+ pass -+ -+ @abstractmethod -+ def get_ipam(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def delete_ipam(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_ipams(self, context, filters=None, fields=None): -+ pass -+#end class IpamPluginBase -diff --git neutron/extensions/policy.py neutron/extensions/policy.py -new file mode 100644 -index 0000000..59418e4 ---- /dev/null -+++ neutron/extensions/policy.py -@@ -0,0 +1,105 @@ -+from abc import abstractmethod -+ -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron.api import extensions -+from neutron import manager -+from oslo.config import cfg -+ -+ -+# Policy Exceptions -+class PolicyNotFound(qexception.NotFound): -+ message = _("Policy %(id)s could not be found") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'policys': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:regex': attr.UUID_PATTERN}, -+ 'is_visible': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'fq_name': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ 'entries': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': ''}, -+ 'nets_using': {'allow_post': False, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ }, -+} -+ -+ -+class Policy(object): -+ -+ @classmethod -+ def get_name(cls): -+ return "Network Policy" -+ -+ @classmethod -+ def get_alias(cls): -+ return "policy" -+ -+ @classmethod -+ def get_description(cls): -+ return ("Configuration object for Network Policies") -+ -+ @classmethod -+ def get_namespace(cls): -+ return "http://docs.openstack.org/TODO" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2012-07-20T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ exts = [] -+ plugin = manager.NeutronManager.get_plugin() -+ for resource_name in ['policy']: -+ collection_name = resource_name + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(collection_name, dict()) -+ -+ member_actions = {} -+ -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, -+ member_actions=member_actions) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ member_actions=member_actions) -+ exts.append(ex) -+ -+ return exts -+ -+#end class Policy -+ -+ -+class PolicyPluginBase(object): -+ -+ @abstractmethod -+ def create_policy(self, context, policy): -+ pass -+ -+ @abstractmethod -+ def update_policy(self, context, id, policy): -+ pass -+ -+ @abstractmethod -+ def get_policy(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def delete_policy(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_policys(self, context, filters=None, fields=None): -+ pass -+#end class PolicyPluginBase -diff --git neutron/extensions/portbindings.py neutron/extensions/portbindings.py -index dbef592..bbed97b 100644 ---- neutron/extensions/portbindings.py -+++ neutron/extensions/portbindings.py -@@ -45,11 +45,12 @@ VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_HYPERV = 'hyperv' - VIF_TYPE_MIDONET = 'midonet' -+VIF_TYPE_VROUTER = 'vrouter' - VIF_TYPE_OTHER = 'other' - VIF_TYPES = [VIF_TYPE_UNBOUND, VIF_TYPE_BINDING_FAILED, VIF_TYPE_OVS, - VIF_TYPE_IVS, VIF_TYPE_BRIDGE, VIF_TYPE_802_QBG, - VIF_TYPE_802_QBH, VIF_TYPE_HYPERV, VIF_TYPE_MIDONET, -- VIF_TYPE_OTHER] -+ VIF_TYPE_VROUTER, VIF_TYPE_OTHER] - - - EXTENDED_ATTRIBUTES_2_0 = { -diff --git neutron/extensions/vpcroutetable.py neutron/extensions/vpcroutetable.py -new file mode 100644 -index 0000000..ec1f720 ---- /dev/null -+++ neutron/extensions/vpcroutetable.py -@@ -0,0 +1,186 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+ -+# Copyright (c) 2012 OpenStack Foundation. -+# 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. -+ -+from abc import ABCMeta -+from abc import abstractmethod -+ -+from oslo.config import cfg -+ -+from neutron.api import extensions -+from neutron.api.v2 import attributes as attr -+from neutron.api.v2 import base -+from neutron.common import exceptions as qexception -+from neutron import manager -+from neutron.openstack.common import uuidutils -+from neutron import quota -+ -+ -+# Route table Exceptions -+class RouteTableNotFound(qexception.NotFound): -+ message = _("Route table %(id)s does not exist") -+ -+# Attribute Map -+RESOURCE_ATTRIBUTE_MAP = { -+ 'route_tables': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:uuid': None}, -+ 'is_visible': True, -+ 'primary_key': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': '', -+ 'validate': {'type:name_not_default': None}}, -+ 'fq_name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': '', -+ 'validate': {'type:name_not_default': None}}, -+ 'routes': {'allow_post': True, 'allow_put': True, -+ 'is_visible': True, 'default': ''}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ }, -+ 'nat_instances': { -+ 'id': {'allow_post': False, 'allow_put': False, -+ 'validate': {'type:uuid': None}, -+ 'is_visible': True, -+ 'primary_key': True}, -+ 'name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': '', -+ 'validate': {'type:name_not_default': None}}, -+ 'fq_name': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': '', -+ 'validate': {'type:name_not_default': None}}, -+ 'internal_net': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'internal_ip': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'external_net': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'external_ip': {'allow_post': True, 'allow_put': False, -+ 'is_visible': True, 'default': ''}, -+ 'tenant_id': {'allow_post': True, 'allow_put': False, -+ 'required_by_policy': True, -+ 'is_visible': True}, -+ }, -+} -+ -+EXTENDED_ATTRIBUTES_2_0 = { -+ 'networks': { -+ 'vpc:route_table': {'allow_post': True, -+ 'allow_put': True, -+ 'default': '', -+ 'is_visible': True}, -+ } -+} -+ -+ -+class Vpcroutetable(extensions.ExtensionDescriptor): -+ """ Route table extension""" -+ -+ @classmethod -+ def get_name(cls): -+ return "route-table" -+ -+ @classmethod -+ def get_alias(cls): -+ return "route-table" -+ -+ @classmethod -+ def get_description(cls): -+ return "VPC route tables extension." -+ -+ @classmethod -+ def get_namespace(cls): -+ # todo -+ return "http://docs.openstack.org/ext/routetables/api/v2.0" -+ -+ @classmethod -+ def get_updated(cls): -+ return "2013-07-24T10:00:00-00:00" -+ -+ @classmethod -+ def get_resources(cls): -+ """ Returns Ext Resources """ -+ my_plurals = [(key, key[:-1]) for key in RESOURCE_ATTRIBUTE_MAP.keys()] -+ attr.PLURALS.update(dict(my_plurals)) -+ exts = [] -+ plugin = manager.NeutronManager.get_plugin() -+ for resource_name in ['route_table', 'nat_instance']: -+ collection_name = resource_name.replace('_', '-') + "s" -+ params = RESOURCE_ATTRIBUTE_MAP.get(resource_name + "s", dict()) -+ quota.QUOTAS.register_resource_by_name(resource_name) -+ controller = base.create_resource(collection_name, -+ resource_name, -+ plugin, params, allow_bulk=True, -+ allow_pagination=True, -+ allow_sorting=True) -+ -+ ex = extensions.ResourceExtension(collection_name, -+ controller, -+ attr_map=params) -+ exts.append(ex) -+ -+ return exts -+ -+ def get_extended_resources(self, version): -+ if version == "2.0": -+ return EXTENDED_ATTRIBUTES_2_0 -+ else: -+ return {} -+ -+ -+class RouteTablePluginBase(object): -+ __metaclass__ = ABCMeta -+ -+ @abstractmethod -+ def create_route_table(self, context, route_table): -+ pass -+ -+ @abstractmethod -+ def delete_route_table(self, context, id): -+ pass -+ -+ @abstractmethod -+ def update_route_table(self, context, id, route_table): -+ pass -+ -+ @abstractmethod -+ def get_route_tables(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ pass -+ -+ @abstractmethod -+ def get_route_table(self, context, id, fields=None): -+ pass -+ -+ @abstractmethod -+ def create_nat_instance(self, context, nat_instance): -+ pass -+ -+ @abstractmethod -+ def delete_nat_instance(self, context, id): -+ pass -+ -+ @abstractmethod -+ def get_nat_instances(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ pass -+ -+ @abstractmethod -+ def get_nat_instance(self, context, id, fields=None): -+ pass -diff --git neutron/plugins/juniper/__init__.py neutron/plugins/juniper/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/__init__.py neutron/plugins/juniper/contrail/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/contrailplugin.py neutron/plugins/juniper/contrail/contrailplugin.py -new file mode 100644 -index 0000000..01f37e2 ---- /dev/null -+++ neutron/plugins/juniper/contrail/contrailplugin.py -@@ -0,0 +1,600 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+import ctdb.config_db -+import httplib2 -+from oslo.config import cfg -+import re -+import string -+ -+from neutron.common import exceptions as exc -+from neutron.db import db_base_plugin_v2 -+from neutron.db import portbindings_base -+from neutron.extensions import l3 -+from neutron.extensions import securitygroup -+from neutron.extensions import portbindings -+from neutron.openstack.common import log as logging -+ -+ -+LOG = logging.getLogger(__name__) -+ -+vnc_opts = [ -+ cfg.StrOpt('api_server_ip', default='127.0.0.1'), -+ cfg.StrOpt('api_server_port', default='8082'), -+] -+ -+ -+def _read_cfg(multi_parser, section, option, default): -+ name_tuple = (section, option) -+ cfg_names = [] -+ cfg_names.append(name_tuple) -+ try: -+ val = multi_parser.get(names=cfg_names, multi=False) -+ except KeyError: -+ val = default -+ -+ return val -+ -+ -+class ContrailPlugin(db_base_plugin_v2.NeutronDbPluginV2, -+ l3.RouterPluginBase, -+ securitygroup.SecurityGroupPluginBase, -+ portbindings_base.PortBindingBaseMixin): -+ -+ # only floatingip part of router extension is supported. -+ supported_extension_aliases = ["ipam", "policy", "security-group", -+ "router", "route-table", "port-security", -+ "binding",] -+ __native_bulk_support = False -+ _cfgdb = None -+ _args = None -+ _tenant_id_dict = {} -+ _tenant_name_dict = {} -+ -+ @classmethod -+ def _parse_class_args(cls, multi_parser): -+ read_ok = multi_parser.read(cfg.CONF.config_file) -+ -+ if len(read_ok) != len(cfg.CONF.config_file): -+ raise cfg.Error("Some config files were not parsed properly") -+ -+ cls._multi_tenancy = _read_cfg(multi_parser, 'APISERVER', -+ 'multi_tenancy', False) -+ cls._max_retries = _read_cfg(multi_parser, 'APISERVER', -+ 'max_retries', -1) -+ cls._retry_interval = _read_cfg(multi_parser, 'APISERVER', -+ 'retry_interval', 3) -+ cls._admin_token = _read_cfg(multi_parser, 'KEYSTONE', -+ 'admin_token', '') -+ cls._auth_url = _read_cfg(multi_parser, 'KEYSTONE', 'auth_url', '') -+ cls._admin_user = _read_cfg(multi_parser, 'KEYSTONE', 'admin_user', -+ 'user1') -+ cls._admin_password = _read_cfg(multi_parser, 'KEYSTONE', -+ 'admin_password', 'password1') -+ cls._admin_tenant_name = _read_cfg(multi_parser, 'KEYSTONE', -+ 'admin_tenant_name', -+ 'default-domain') -+ cls._tenants_api = '%s/tenants' % (cls._auth_url) -+ -+ @classmethod -+ def _connect_to_db(cls): -+ """Connection to config db. -+ -+ Many instantiations of plugin (base + extensions) but need to have -+ only one config db conn (else error from ifmap-server) -+ """ -+ cls._cfgdb_map = {} -+ if cls._cfgdb is None: -+ sip = cfg.CONF.APISERVER.api_server_ip -+ sport = cfg.CONF.APISERVER.api_server_port -+ # Initialize connection to DB and add default entries -+ cls._cfgdb = ctdb.config_db.DBInterface(cls._admin_user, -+ cls._admin_password, -+ cls._admin_tenant_name, -+ sip, sport, -+ cls._max_retries, -+ cls._retry_interval) -+ cls._cfgdb.manager = cls -+ -+ @classmethod -+ def _get_user_cfgdb(cls, context): -+ if not cls._multi_tenancy: -+ return cls._cfgdb -+ user_id = context.user_id -+ role = string.join(context.roles, ",") -+ if user_id not in cls._cfgdb_map: -+ cls._cfgdb_map[user_id] = ctdb.config_db.DBInterface( -+ cls._admin_user, cls._admin_password, cls._admin_tenant_name, -+ cfg.CONF.APISERVER.api_server_ip, -+ cfg.CONF.APISERVER.api_server_port, -+ cls._max_retries, cls._retry_interval, -+ user_info={'user_id': user_id, 'role': role}) -+ cls._cfgdb_map[user_id].manager = cls -+ -+ return cls._cfgdb_map[user_id] -+ -+ @classmethod -+ def _tenant_list_from_keystone(cls): -+ # get all tenants -+ hdrs = {'X-Auth-Token': cls._admin_token, -+ 'Content-Type': 'application/json'} -+ try: -+ rsp, content = httplib2.Http().request(cls._tenants_api, -+ method="GET", headers=hdrs) -+ if rsp.status != 200: -+ return -+ except Exception: -+ return -+ -+ # transform needed for python compatibility -+ content = re.sub('true', 'True', content) -+ content = re.sub('null', 'None', content) -+ content = eval(content) -+ -+ # bail if response is unexpected -+ if 'tenants' not in content: -+ return -+ -+ # create a dictionary for id->name and name->id mapping -+ for tenant in content['tenants']: -+ print 'Adding tenant %s:%s to cache' % (tenant['name'], -+ tenant['id']) -+ cls._tenant_id_dict[tenant['id']] = tenant['name'] -+ cls._tenant_name_dict[tenant['name']] = tenant['id'] -+ -+ def update_security_group(self, context, id, security_group): -+ pass -+ -+ def __init__(self): -+ cfg.CONF.register_opts(vnc_opts, 'APISERVER') -+ -+ multi_parser = cfg.MultiConfigParser() -+ ContrailPlugin._parse_class_args(multi_parser) -+ -+ ContrailPlugin._connect_to_db() -+ self._cfgdb = ContrailPlugin._cfgdb -+ -+ ContrailPlugin._tenant_list_from_keystone() -+ self.base_binding_dict = self._get_base_binding_dict() -+ portbindings_base.register_port_dict_function() -+ -+ def _get_base_binding_dict(self): -+ binding = { -+ portbindings.VIF_TYPE: portbindings.VIF_TYPE_VROUTER, -+ portbindings.CAPABILITIES: { -+ portbindings.CAP_PORT_FILTER: -+ 'security-group' in self.supported_extension_aliases}} -+ return binding -+ -+ # Network API handlers -+ def create_network(self, context, network): -+ """Creates a new Virtual Network, and assigns it a symbolic name.""" -+ cfgdb = self._get_user_cfgdb(context) -+ net_info = cfgdb.network_create(network['network']) -+ -+ # verify transformation is conforming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ LOG.debug(_("create_network(): %r"), net_dict) -+ return net_dict -+ -+ def get_network(self, context, id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ net_info = cfgdb.network_read(id, fields) -+ -+ # verify transformation is conforming to api -+ if not fields: -+ # should return all fields -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ fields, False) -+ else: -+ net_dict = net_info['q_api_data'] -+ -+ LOG.debug(_("get_network(): %r"), net_dict) -+ return self._fields(net_dict, fields) -+ -+ def update_network(self, context, net_id, network): -+ """Updates the attributes of a particular Virtual Network.""" -+ cfgdb = self._get_user_cfgdb(context) -+ net_info = cfgdb.network_update(net_id, network['network']) -+ -+ # verify transformation is confirming to api -+ net_dict = self._make_network_dict(net_info['q_api_data'], -+ None, False) -+ -+ LOG.debug(_("update_network(): %r"), net_dict) -+ return net_dict -+ -+ def delete_network(self, context, net_id): -+ """Network delete operation. -+ -+ Deletes the network with the specified network identifier -+ belonging to the specified tenant. -+ """ -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.network_delete(net_id) -+ LOG.debug(_("delete_network(): %r"), net_id) -+ -+ def get_networks(self, context, filters=None, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ nets_info = cfgdb.network_list(filters) -+ -+ nets_dicts = [] -+ for n_info in nets_info: -+ # verify transformation is conforming to api -+ n_dict = self._make_network_dict(n_info['q_api_data'], fields, -+ False) -+ -+ nets_dicts.append(n_dict) -+ -+ LOG.debug( -+ "get_networks(): filters: %r data: %r", filters, nets_dicts) -+ return nets_dicts -+ -+ def get_networks_count(self, context, filters=None): -+ cfgdb = self._get_user_cfgdb(context) -+ nets_count = cfgdb.network_count(filters) -+ LOG.debug(_("get_networks_count(): %r"), str(nets_count)) -+ return nets_count -+ -+ def create_subnet(self, context, subnet): -+ cfgdb = self._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_create(subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ LOG.debug(_("create_subnet(): %r"), subnet_dict) -+ return subnet_dict -+ -+ def get_subnet(self, context, subnet_id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_read(subnet_id) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data'], -+ fields) -+ -+ LOG.debug(_("get_subnet(): %r"), subnet_dict) -+ return self._fields(subnet_dict, fields) -+ -+ def update_subnet(self, context, subnet_id, subnet): -+ cfgdb = self._get_user_cfgdb(context) -+ subnet_info = cfgdb.subnet_update(subnet_id, subnet['subnet']) -+ -+ # verify transformation is conforming to api -+ subnet_dict = self._make_subnet_dict(subnet_info['q_api_data']) -+ -+ LOG.debug(_("update_subnet(): %r"), subnet_dict) -+ return subnet_dict -+ -+ def delete_subnet(self, context, subnet_id): -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.subnet_delete(subnet_id) -+ -+ LOG.debug(_("delete_subnet(): %r"), subnet_id) -+ -+ def get_subnets(self, context, filters=None, fields=None): -+ """Called from Neutron API -> get_.""" -+ cfgdb = self._get_user_cfgdb(context) -+ subnets_info = cfgdb.subnets_list(filters) -+ -+ subnets_dicts = [] -+ for sn_info in subnets_info: -+ # verify transformation is conforming to api -+ sn_dict = self._make_subnet_dict(sn_info['q_api_data'], fields) -+ -+ subnets_dicts.append(sn_dict) -+ -+ LOG.debug( -+ "get_subnets(): filters: %r data: %r", filters, subnets_dicts) -+ return subnets_dicts -+ -+ def get_subnets_count(self, context, filters=None): -+ cfgdb = self._get_user_cfgdb(context) -+ subnets_count = cfgdb.subnets_count(filters) -+ LOG.debug(_("get_subnets_count(): %r"), str(subnets_count)) -+ return subnets_count -+ -+ def _make_floatingip_dict(self, floatingip, fields=None): -+ res = {'id': floatingip['id'], -+ 'tenant_id': floatingip['tenant_id'], -+ 'floating_ip_address': floatingip['floating_ip_address'], -+ 'floating_network_id': floatingip['floating_network_id'], -+ 'router_id': floatingip['router_id'], -+ 'port_id': floatingip['fixed_port_id'], -+ 'fixed_ip_address': floatingip['fixed_ip_address']} -+ return self._fields(res, fields) -+ -+ def create_floatingip(self, context, floatingip): -+ cfgdb = self._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_create(floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ LOG.debug(_("create_floatingip(): %r"), fip_dict) -+ return fip_dict -+ -+ def update_floatingip(self, context, fip_id, floatingip): -+ cfgdb = self._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_update(fip_id, -+ floatingip['floatingip']) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ LOG.debug(_("update_floatingip(): %r"), fip_dict) -+ return fip_dict -+ -+ def get_floatingip(self, context, id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ fip_info = cfgdb.floatingip_read(id) -+ -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ LOG.debug(_("get_floatingip(): %r"), fip_dict) -+ return fip_dict -+ -+ def delete_floatingip(self, context, fip_id): -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.floatingip_delete(fip_id) -+ LOG.debug(_("delete_floating(): %r"), fip_id) -+ -+ def get_floatingips(self, context, filters=None, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ fips_info = cfgdb.floatingip_list(filters) -+ -+ fips_dicts = [] -+ for fip_info in fips_info: -+ # verify transformation is conforming to api -+ fip_dict = self._make_floatingip_dict(fip_info['q_api_data']) -+ -+ fips_dicts.append(fip_dict) -+ -+ LOG.debug(_("get_floatingips(): %r"), fips_dicts) -+ return fips_dicts -+ -+ def get_floatingips_count(self, context, filters=None): -+ cfgdb = self._get_user_cfgdb(context) -+ floatingips_count = cfgdb.floatingip_count(filters) -+ LOG.debug(_("get_floatingips_count(): %r"), str(floatingips_count)) -+ return floatingips_count -+ -+ def create_port(self, context, port): -+ """Creates a port on the specified Virtual Network.""" -+ cfgdb = self._get_user_cfgdb(context) -+ port_info = cfgdb.port_create(port['port']) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_dict) -+ -+ LOG.debug(_("create_port(): %r"), port_dict) -+ return port_dict -+ -+ def get_port(self, context, port_id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ port_info = cfgdb.port_read(port_id) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ port_info, -+ port_dict) -+ -+ LOG.debug(_("get_port(): %r"), port_dict) -+ return self._fields(port_dict, fields) -+ -+ def update_port(self, context, port_id, port): -+ """Port update on a virtual network. -+ -+ Updates the attributes of a port on the specified Virtual Network. -+ """ -+ cfgdb = self._get_user_cfgdb(context) -+ port_info = cfgdb.port_update(port_id, port['port']) -+ self._process_portbindings_create_and_update(context, -+ port['port'], -+ port_info) -+ -+ # verify transformation is conforming to api -+ port_dict = self._make_port_dict(port_info['q_api_data']) -+ -+ LOG.debug(_("update_port(): %r"), port_dict) -+ return port_dict -+ -+ def delete_port(self, context, port_id): -+ """port delete on a virtual network. -+ -+ Deletes a port on a specified Virtual Network, -+ if the port contains a remote interface attachment, -+ the remote interface is first un-plugged and then the port -+ is deleted. -+ """ -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.port_delete(port_id) -+ LOG.debug(_("delete_port(): %r"), port_id) -+ -+ def get_ports(self, context, filters=None, fields=None): -+ """Get all port identifiers in the specified Virtual Network.""" -+ cfgdb = self._get_user_cfgdb(context) -+ ports_info = cfgdb.port_list(filters) -+ -+ ports_dicts = [] -+ for p_info in ports_info: -+ # verify transformation is conforming to api -+ p_dict = self._make_port_dict(p_info['q_api_data'], fields) -+ self._process_portbindings_create_and_update(context, -+ p_info, -+ p_dict) -+ -+ ports_dicts.append(p_dict) -+ -+ LOG.debug( -+ "get_ports(): filter: %r data: %r", filters, ports_dicts) -+ return ports_dicts -+ -+ def get_ports_count(self, context, filters=None): -+ cfgdb = self._get_user_cfgdb(context) -+ ports_count = cfgdb.port_count(filters) -+ LOG.debug(_("get_ports_count(): %r"), str(ports_count)) -+ return ports_count -+ -+ def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): -+ """Plug in a remote interface. -+ -+ Attaches a remote interface to the specified port on the -+ specified Virtual Network. -+ """ -+ port = self._get_port(tenant_id, net_id, port_id) -+ # Validate attachment -+ self._validate_attachment(tenant_id, net_id, port_id, -+ remote_interface_id) -+ if port['interface_id']: -+ raise exc.PortInUse(net_id=net_id, port_id=port_id, -+ att_id=port['interface_id']) -+ -+ def unplug_interface(self, tenant_id, net_id, port_id): -+ """Unplug a remote interface. -+ -+ Detaches a remote interface from the specified port on the -+ specified Virtual Network. -+ """ -+ self._get_port(tenant_id, net_id, port_id) -+ -+ # Security Group handlers -+ def _make_security_group_rule_dict(self, security_group_rule, fields=None): -+ res = {'id': security_group_rule['id'], -+ 'tenant_id': security_group_rule['tenant_id'], -+ 'security_group_id': security_group_rule['security_group_id'], -+ 'ethertype': security_group_rule['ethertype'], -+ 'direction': security_group_rule['direction'], -+ 'protocol': security_group_rule['protocol'], -+ 'port_range_min': security_group_rule['port_range_min'], -+ 'port_range_max': security_group_rule['port_range_max'], -+ 'remote_ip_prefix': security_group_rule['remote_ip_prefix'], -+ 'remote_group_id': security_group_rule['remote_group_id']} -+ -+ return self._fields(res, fields) -+ -+ def _make_security_group_dict(self, security_group, fields=None): -+ res = {'id': security_group['id'], -+ 'name': security_group['name'], -+ 'tenant_id': security_group['tenant_id'], -+ 'description': security_group['description']} -+ res['security_group_rules'] = [self._make_security_group_rule_dict(r) -+ for r in security_group['rules']] -+ return self._fields(res, fields) -+ -+ def create_security_group(self, context, security_group): -+ cfgdb = self._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_create( -+ security_group['security_group']) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data']) -+ -+ LOG.debug(_("create_security_group(): %r"), sg_dict) -+ return sg_dict -+ -+ def delete_security_group(self, context, id): -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.security_group_delete(id) -+ LOG.debug(_("delete_security_group(): %r"), id) -+ -+ def get_security_groups(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ cfgdb = self._get_user_cfgdb(context) -+ security_groups_info = cfgdb.security_group_list(context, filters) -+ -+ security_groups_dicts = [] -+ for sg_info in security_groups_info: -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ security_groups_dicts.append(sg_dict) -+ -+ LOG.debug( -+ "get_security_groups(): filter: %r data: %r", -+ filters, security_groups_dicts) -+ return security_groups_dicts -+ -+ def get_security_group(self, context, id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ sg_info = cfgdb.security_group_read(id) -+ -+ # verify transformation is conforming to api -+ sg_dict = self._make_security_group_dict(sg_info['q_api_data'], -+ fields) -+ -+ LOG.debug(_("get_security_group(): %r"), sg_dict) -+ return self._fields(sg_dict, fields) -+ -+ def create_security_group_rule(self, context, security_group_rule): -+ cfgdb = self._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_create( -+ security_group_rule['security_group_rule']) -+ -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict(sgr_info['q_api_data']) -+ -+ LOG.debug(_("create_security_group_rule(): %r"), sgr_dict) -+ return sgr_dict -+ -+ def delete_security_group_rule(self, context, id): -+ cfgdb = self._get_user_cfgdb(context) -+ cfgdb.security_group_rule_delete(id) -+ LOG.debug(_("delete_security_group_rule(): %r"), id) -+ -+ def get_security_group_rules(self, context, filters=None, fields=None, -+ sorts=None, limit=None, marker=None, -+ page_reverse=False): -+ cfgdb = self._get_user_cfgdb(context) -+ security_group_rules_info = cfgdb.security_group_rule_list(filters) -+ -+ security_group_rules_dicts = [] -+ for sgr_info in security_group_rules_info: -+ for sgr in sgr_info: -+ # verify transformation is conforming to api -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr['q_api_data'], fields) -+ security_group_rules_dicts.append(sgr_dict) -+ -+ LOG.debug( -+ "get_security_group_rules(): filter: %r data: %r ", -+ filters, security_group_rules_dicts) -+ return security_group_rules_dicts -+ -+ def get_security_group_rule(self, context, id, fields=None): -+ cfgdb = self._get_user_cfgdb(context) -+ sgr_info = cfgdb.security_group_rule_read(id) -+ -+ # verify transformation is conforming to api -+ sgr_dict = {} -+ if sgr_info != {}: -+ sgr_dict = self._make_security_group_rule_dict( -+ sgr_info['q_api_data'], fields) -+ -+ LOG.debug(_("get_security_group_rule(): %r"), sgr_dict) -+ return self._fields(sgr_dict, fields) -diff --git neutron/plugins/juniper/contrail/ctdb/__init__.py neutron/plugins/juniper/contrail/ctdb/__init__.py -new file mode 100644 -index 0000000..7bc8217 ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/__init__.py -@@ -0,0 +1,17 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay Juniper Networks. -diff --git neutron/plugins/juniper/contrail/ctdb/config_db.py neutron/plugins/juniper/contrail/ctdb/config_db.py -new file mode 100644 -index 0000000..efe281c ---- /dev/null -+++ neutron/plugins/juniper/contrail/ctdb/config_db.py -@@ -0,0 +1,1708 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+# -+# Copyright 2013 Juniper Networks. 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: Hampapur Ajay, Rudra Rugge, Atul Moghe Juniper Networks. -+ -+import json -+import netaddr -+import re -+import requests -+import socket -+import time -+import uuid -+ -+from cfgm_common import exceptions as vnc_exc -+from vnc_api import vnc_api -+ -+from neutron.api.v2 import attributes as attr -+from neutron.common import constants -+from neutron.common import exceptions -+from neutron.extensions import portbindings -+from neutron.openstack.common import log as logging -+ -+ -+LOG = logging.getLogger(__name__) -+ -+_DEFAULT_HEADERS = { -+ 'Content-type': 'application/json; charset="UTF-8"', } -+ -+CREATE = 1 -+READ = 2 -+UPDATE = 3 -+DELETE = 4 -+ -+ -+class DBInterface(object): -+ """An instance of this class forwards requests to vnc cfg api server""" -+ Q_URL_PREFIX = '/extensions/ct' -+ -+ def __init__(self, admin_name, admin_password, admin_tenant_name, -+ api_server_ip, api_server_port, max_retries, retry_interval, -+ user_info=None): -+ self._api_server_ip = api_server_ip -+ self._api_server_port = api_server_port -+ self._max_retries = max_retries -+ self._retry_interval = retry_interval -+ -+ self._db_cache = { -+ 'q_networks': {}, -+ 'q_subnets': {}, -+ 'q_subnet_maps': {}, -+ 'q_policies': {}, -+ 'q_ipams': {}, -+ 'q_floatingips': {}, -+ 'q_ports': {}, -+ 'q_fixed_ip_to_subnet': {}, -+ # obj-uuid to tenant-uuid mapping -+ 'q_obj_to_tenant': {}, -+ # port count per tenant-id -+ 'q_tenant_port_count': {}, -+ 'vnc_networks': {}, -+ 'vnc_ports': {}, -+ 'vnc_projects': {}, -+ 'vnc_instance_ips': {}, -+ } -+ -+ # Retry till a api-server is up or up to max_retries -+ connected = False -+ remaining = self._max_retries -+ if remaining == -1: -+ remaining = 'infinite' -+ msg = _('api-server connection failed. %s attempts left.') -+ -+ while not connected: -+ try: -+ self._vnc_lib = vnc_api.VncApi( -+ admin_name, admin_password, -+ admin_tenant_name, api_server_ip, -+ api_server_port, '/', user_info=user_info) -+ connected = True -+ except requests.exceptions.RequestException: -+ LOG.warn(msg % remaining) -+ if (remaining != 'infinite' and remaining == 0): -+ raise -+ if (remaining != 'infinite'): -+ remaining -= 1 -+ -+ time.sleep(self._retry_interval) -+ -+ # changes 'net_fq_name_str pfx/len' key to 'net_id pfx/len' key -+ # eg. domain1:project1:net1 1.1.1.0/24 becomes 1.1.1.0/24 -+ subnet_map = self._vnc_lib.kv_retrieve(key=None) -+ for kv_dict in subnet_map: -+ key = kv_dict['key'] -+ if len(key.split()) == 1: -+ subnet_id = key -+ # uuid key, fixup value portion to 'net_id pfx/len' format -+ # if not already so -+ if len(kv_dict['value'].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ net_fq_name = kv_dict['value'].split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ LOG.warning(_("No network: %r"), net_fq_name) -+ self._vnc_lib.kv_delete(subnet_id) -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, -+ kv_dict['value'].split()[1]) -+ self._vnc_lib.kv_store(subnet_id, new_subnet_key) -+ else: # subnet key -+ if len(key.split()[0].split(':')) == 1: -+ # new format already, skip -+ continue -+ -+ # delete old key, convert to new key format and save -+ old_subnet_key = key -+ self._vnc_lib.kv_delete(old_subnet_key) -+ -+ subnet_id = kv_dict['value'] -+ net_fq_name = key.split()[0].split(':') -+ try: -+ net_obj = self._virtual_network_read(fq_name=net_fq_name) -+ except vnc_exc.NoIdError: -+ LOG.warning(_("No network: %r"), net_fq_name) -+ continue -+ -+ new_subnet_key = '%s %s' % (net_obj.uuid, key.split()[1]) -+ self._vnc_lib.kv_store(new_subnet_key, subnet_id) -+ -+ def _request_api_server(self, url, method, data=None, headers=None): -+ return requests.request(method, url=url, data=data, headers=headers) -+ -+ def _relay_request(self, request): -+ """Send received request to api server""" -+ # chop neutron parts of url and add api server address -+ url_path = re.sub(self.Q_URL_PREFIX, '', request.environ['PATH_INFO']) -+ url = "http://%s:%s%s" % (self._api_server_ip, self._api_server_port, -+ url_path) -+ -+ return self._request_api_server( -+ url, request.environ['REQUEST_METHOD'], -+ request.body, {'Content-type': request.environ['CONTENT_TYPE']}) -+ -+ def _obj_to_dict(self, obj): -+ return self._vnc_lib.obj_to_dict(obj) -+ #end _obj_to_dict -+ -+ def _ensure_instance_exists(self, instance_id): -+ instance_name = instance_id -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ try: -+ id = self._vnc_lib.obj_to_id(instance_obj) -+ instance_obj = self._vnc_lib.virtual_machine_read(id=id) -+ except vnc_exc.NoIdError: # instance doesn't exist, create it -+ instance_obj.uuid = instance_id -+ self._vnc_lib.virtual_machine_create(instance_obj) -+ -+ return instance_obj -+ -+ def _ensure_default_security_group_exists(self, proj_id): -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ sg_groups = proj_obj.get_security_groups() -+ for sg_group in sg_groups or []: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_group['uuid']) -+ if sg_obj.name == 'default': -+ return -+ -+ sg_obj = vnc_api.SecurityGroup(name='default', parent_obj=proj_obj) -+ self._vnc_lib.security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = { -+ 'port_range_min': 0, -+ 'port_range_max': 65535, -+ 'direction': 'egress', -+ 'remote_ip_prefix': None, -+ 'remote_group_id': None, -+ 'protocol': 'any', -+ } -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ #allow ingress traffic from within default security group -+ def_rule = { -+ 'port_range_min': 0, -+ 'port_range_max': 65535, -+ 'direction': 'ingress', -+ 'remote_ip_prefix': None, -+ 'remote_group_id': None, -+ 'protocol': 'any', -+ } -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_obj.uuid, rule) -+ -+ def _get_obj_tenant_id(self, q_type, obj_uuid): -+ # Get the mapping from cache, else seed cache and return -+ try: -+ return self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except KeyError: -+ # Seed the cache and return -+ if q_type == 'port': -+ port_obj = self._virtual_machine_interface_read(obj_uuid) -+ net_id = port_obj.get_virtual_network_refs()[0]['uuid'] -+ # recurse up type-hierarchy -+ tenant_id = self._get_obj_tenant_id('network', net_id) -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ if q_type == 'network': -+ net_obj = self._virtual_network_read(net_id=obj_uuid) -+ tenant_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(obj_uuid, tenant_id) -+ return tenant_id -+ -+ def _set_obj_tenant_id(self, obj_uuid, tenant_uuid): -+ self._db_cache['q_obj_to_tenant'][obj_uuid] = tenant_uuid -+ -+ def _del_obj_tenant_id(self, obj_uuid): -+ try: -+ del self._db_cache['q_obj_to_tenant'][obj_uuid] -+ except Exception: -+ pass -+ -+ def _project_read(self, proj_id=None, fq_name=None): -+ if proj_id: -+ proj_obj = self._vnc_lib.project_read(id=proj_id) -+ fq_name_str = json.dumps(proj_obj.get_fq_name()) -+ self._db_cache['vnc_projects'][proj_id] = proj_obj -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ return proj_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ proj_obj = self._vnc_lib.project_read(fq_name=fq_name) -+ self._db_cache['vnc_projects'][fq_name_str] = proj_obj -+ self._db_cache['vnc_projects'][proj_obj.uuid] = proj_obj -+ return proj_obj -+ -+ def _security_group_rule_create(self, sg_id, sg_rule): -+ sg_vnc = self._vnc_lib.security_group_read(id=sg_id) -+ rules = sg_vnc.get_security_group_entries() -+ if rules is None: -+ rules = vnc_api.PolicyEntriesType([sg_rule]) -+ else: -+ rules.add_policy_rule(sg_rule) -+ -+ sg_vnc.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_vnc) -+ -+ def _security_group_rule_find(self, sgr_id): -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ project_sgs = self._security_group_list_project(proj_id) -+ -+ for sg in project_sgs: -+ sg_obj = self._vnc_lib.security_group_read(id=sg['uuid']) -+ sgr_entries = sg_obj.get_security_group_entries() -+ if sgr_entries is None: -+ continue -+ -+ for sg_rule in sgr_entries.get_policy_rule(): -+ if sg_rule.get_rule_uuid() == sgr_id: -+ return sg_obj, sg_rule -+ -+ return None, None -+ -+ def _security_group_rule_delete(self, sg_obj, sg_rule): -+ rules = sg_obj.get_security_group_entries() -+ rules.get_policy_rule().remove(sg_rule) -+ sg_obj.set_security_group_entries(rules) -+ self._vnc_lib.security_group_update(sg_obj) -+ -+ def _security_group_create(self, sg_obj): -+ sg_uuid = self._vnc_lib.security_group_create(sg_obj) -+ return sg_uuid -+ -+ def _security_group_delete(self, sg_id): -+ self._vnc_lib.security_group_delete(id=sg_id) -+ -+ def _virtual_network_create(self, net_obj): -+ net_uuid = self._vnc_lib.virtual_network_create(net_obj) -+ -+ return net_uuid -+ -+ def _virtual_network_read(self, net_id=None, fq_name=None): -+ if net_id: -+ net_obj = self._vnc_lib.virtual_network_read(id=net_id) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ self._db_cache['vnc_networks'][net_id] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ return net_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ net_obj = self._vnc_lib.virtual_network_read(fq_name=fq_name) -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ return net_obj -+ -+ def _virtual_network_update(self, net_obj): -+ self._vnc_lib.virtual_network_update(net_obj) -+ # read back to get subnet gw allocated by api-server -+ net_obj = self._vnc_lib.virtual_network_read(id=net_obj.uuid) -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ -+ self._db_cache['vnc_networks'][net_obj.uuid] = net_obj -+ self._db_cache['vnc_networks'][fq_name_str] = net_obj -+ -+ def _virtual_network_delete(self, net_id): -+ fq_name_str = None -+ try: -+ net_obj = self._db_cache['vnc_networks'][net_id] -+ fq_name_str = json.dumps(net_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_network_delete(id=net_id) -+ -+ try: -+ del self._db_cache['vnc_networks'][net_id] -+ if fq_name_str: -+ del self._db_cache['vnc_networks'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _virtual_machine_interface_create(self, port_obj): -+ port_uuid = self._vnc_lib.virtual_machine_interface_create(port_obj) -+ -+ return port_uuid -+ -+ def _virtual_machine_interface_read(self, port_id=None, fq_name=None): -+ if port_id: -+ port_obj = self._vnc_lib.virtual_machine_interface_read(id=port_id) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ self._db_cache['vnc_ports'][port_id] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ return port_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ port_obj = self._vnc_lib.virtual_machine_interface_read( -+ fq_name=fq_name) -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ return port_obj -+ -+ def _virtual_machine_interface_update(self, port_obj): -+ self._vnc_lib.virtual_machine_interface_update(port_obj) -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ -+ self._db_cache['vnc_ports'][port_obj.uuid] = port_obj -+ self._db_cache['vnc_ports'][fq_name_str] = port_obj -+ -+ def _virtual_machine_interface_delete(self, port_id): -+ fq_name_str = None -+ try: -+ port_obj = self._db_cache['vnc_ports'][port_id] -+ fq_name_str = json.dumps(port_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.virtual_machine_interface_delete(id=port_id) -+ -+ try: -+ del self._db_cache['vnc_ports'][port_id] -+ if fq_name_str: -+ del self._db_cache['vnc_ports'][fq_name_str] -+ except KeyError: -+ pass -+ -+ def _instance_ip_create(self, iip_obj): -+ iip_uuid = self._vnc_lib.instance_ip_create(iip_obj) -+ -+ return iip_uuid -+ -+ def _instance_ip_read(self, instance_ip_id=None, fq_name=None): -+ if instance_ip_id: -+ iip_obj = self._vnc_lib.instance_ip_read(id=instance_ip_id) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ self._db_cache['vnc_instance_ips'][instance_ip_id] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ return iip_obj -+ -+ if fq_name: -+ fq_name_str = json.dumps(fq_name) -+ iip_obj = self._vnc_lib.instance_ip_read(fq_name=fq_name) -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ return iip_obj -+ -+ def _instance_ip_update(self, iip_obj): -+ self._vnc_lib.instance_ip_update(iip_obj) -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ -+ self._db_cache['vnc_instance_ips'][iip_obj.uuid] = iip_obj -+ self._db_cache['vnc_instance_ips'][fq_name_str] = iip_obj -+ -+ def _instance_ip_delete(self, instance_ip_id): -+ fq_name_str = None -+ try: -+ iip_obj = self._db_cache['vnc_instance_ips'][instance_ip_id] -+ fq_name_str = json.dumps(iip_obj.get_fq_name()) -+ except KeyError: -+ pass -+ -+ self._vnc_lib.instance_ip_delete(id=instance_ip_id) -+ -+ try: -+ del self._db_cache['vnc_instance_ips'][instance_ip_id] -+ if fq_name_str: -+ del self._db_cache['vnc_instance_ips'][fq_name_str] -+ except KeyError: -+ pass -+ -+ # find projects on a given domain -+ def _project_list_domain(self, domain_id): -+ fq_name = ['default-domain'] -+ resp_dict = self._vnc_lib.projects_list(parent_fq_name=fq_name) -+ -+ return resp_dict['projects'] -+ -+ # find network ids on a given project -+ def _network_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ LOG.warning(_("Error in converting uuid: %r"), project_id) -+ -+ resp_dict = self._vnc_lib.virtual_networks_list(parent_id=project_uuid) -+ -+ return resp_dict['virtual-networks'] -+ -+ def _security_group_list_project(self, project_id): -+ try: -+ project_uuid = str(uuid.UUID(project_id)) -+ except Exception: -+ LOG.warning(_("Error in converting uuid: %r"), project_id) -+ -+ self._ensure_default_security_group_exists(project_uuid) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=project_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ def _security_group_entries_list_sg(self, sg_id): -+ try: -+ sg_uuid = str(uuid.UUID(sg_id)) -+ except Exception: -+ LOG.warning(_("Error in converting SG uuid: %r"), sg_id) -+ -+ resp_dict = self._vnc_lib.security_groups_list(parent_id=sg_uuid) -+ -+ return resp_dict['security-groups'] -+ -+ # find floating ip pools a project has access to -+ def _fip_pool_refs_project(self, project_id): -+ project_uuid = str(uuid.UUID(project_id)) -+ project_obj = self._project_read(proj_id=project_uuid) -+ -+ return project_obj.get_floating_ip_pool_refs() -+ -+ # find networks of floating ip pools project has access to -+ def _fip_pool_ref_networks(self, project_id): -+ ret_nets = [] -+ -+ proj_fip_pool_refs = self._fip_pool_refs_project(project_id) -+ if not proj_fip_pool_refs: -+ return ret_nets -+ -+ for fip_pool_ref in proj_fip_pool_refs: -+ fip_uuid = fip_pool_ref['uuid'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(id=fip_uuid) -+ net_uuid = fip_pool_obj.parent_uuid -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ ret_nets.append({'uuid': net_obj.uuid, -+ 'fq_name': net_obj.get_fq_name()}) -+ -+ return ret_nets -+ -+ # find floating ip pools defined by network -+ def _fip_pool_list_network(self, net_id): -+ resp_dict = self._vnc_lib.floating_ip_pools_list(parent_id=net_id) -+ -+ return resp_dict['floating-ip-pools'] -+ -+ # find port ids on a given network -+ def _port_list_network(self, network_id): -+ ret_list = [] -+ -+ try: -+ net_obj = self._virtual_network_read(net_id=network_id) -+ except vnc_exc.NoIdError: -+ return ret_list -+ -+ port_back_refs = net_obj.get_virtual_machine_interface_back_refs() -+ if port_back_refs: -+ ret_list = [{'id': port_back_ref['uuid']} -+ for port_back_ref in port_back_refs] -+ -+ return ret_list -+ -+ # find port ids on a given project -+ def _port_list_project(self, project_id): -+ ret_list = [] -+ project_nets = self._network_list_project(project_id) -+ for net in project_nets: -+ net_ports = self._port_list_network(net['uuid']) -+ ret_list.extend(net_ports) -+ -+ return ret_list -+ -+ def _filters_is_present(self, filters, key_name, match_value): -+ """Check if filters present or not. -+ -+ Returns True if no filter is specified -+ OR search-param is not present in filters -+ OR (search-param is present in filters AND -+ resource matches param-list AND -+ shared parameter in filters is False) -+ """ -+ if filters: -+ if key_name in filters: -+ try: -+ filters[key_name].index(match_value) -+ if ('shared' in filters and filters['shared'][0]): -+ # yuck, q-api has shared as list always of 1 elem -+ return False # no shared-resource support -+ except ValueError: # not in requested list -+ return False -+ elif len(filters.keys()) == 1: -+ shared_val = filters.get('shared') -+ if shared_val and shared_val[0]: -+ return False -+ -+ return True -+ -+ def _network_read(self, net_uuid): -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ return net_obj -+ -+ def _subnet_vnc_create_mapping(self, subnet_id, subnet_key): -+ self._vnc_lib.kv_store(subnet_id, subnet_key) -+ self._vnc_lib.kv_store(subnet_key, subnet_id) -+ self._db_cache['q_subnet_maps'][subnet_id] = subnet_key -+ self._db_cache['q_subnet_maps'][subnet_key] = subnet_id -+ -+ def _subnet_vnc_read_mapping(self, id=None, key=None): -+ if id: -+ try: -+ return self._db_cache['q_subnet_maps'][id] -+ except KeyError: -+ subnet_key = self._vnc_lib.kv_retrieve(id) -+ self._db_cache['q_subnet_maps'][id] = subnet_key -+ return subnet_key -+ if key: -+ try: -+ return self._db_cache['q_subnet_maps'][key] -+ except KeyError: -+ subnet_id = self._vnc_lib.kv_retrieve(key) -+ self._db_cache['q_subnet_maps'][key] = subnet_id -+ return subnet_id -+ -+ def _subnet_vnc_read_or_create_mapping(self, id=None, key=None): -+ if id: -+ return self._subnet_vnc_read_mapping(id=id) -+ -+ # if subnet was created outside of neutron handle it and create -+ # neutron representation now (lazily) -+ try: -+ return self._subnet_vnc_read_mapping(key=key) -+ except vnc_exc.NoIdError: -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, key) -+ return self._subnet_vnc_read_mapping(key=key) -+ -+ def _subnet_vnc_delete_mapping(self, subnet_id, subnet_key): -+ self._vnc_lib.kv_delete(subnet_id) -+ self._vnc_lib.kv_delete(subnet_key) -+ try: -+ del self._db_cache['q_subnet_maps'][subnet_id] -+ except KeyError: -+ pass -+ try: -+ del self._db_cache['q_subnet_maps'][subnet_key] -+ except KeyError: -+ pass -+ -+ def _subnet_vnc_get_key(self, subnet_vnc, net_id): -+ pfx = subnet_vnc.subnet.get_ip_prefix() -+ pfx_len = subnet_vnc.subnet.get_ip_prefix_len() -+ -+ return '%s %s/%s' % (net_id, pfx, pfx_len) -+ -+ def _subnet_read(self, net_uuid, subnet_key): -+ try: -+ net_obj = self._virtual_network_read(net_id=net_uuid) -+ except vnc_exc.NoIdError: -+ return -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if not ipam_refs: -+ return -+ -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_uuid) == subnet_key: -+ return subnet_vnc -+ -+ return -+ -+ def _ip_address_to_subnet_id(self, ip_addr, net_obj): -+ # find subnet-id for ip-addr, called when instance-ip created -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ if netaddr.IPAddress(ip_addr) in netaddr.IPSet([cidr]): -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, -+ net_obj.uuid) -+ subnet_id = self._subnet_vnc_read_mapping( -+ key=subnet_key) -+ return subnet_id -+ -+ def _security_group_vnc_to_neutron(self, sg_obj): -+ sg_q_dict = self._obj_to_dict(sg_obj) -+ -+ # replace field names -+ sg_q_dict['id'] = sg_obj.uuid -+ sg_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sg_q_dict['name'] = sg_obj.name -+ sg_q_dict['description'] = sg_obj.get_id_perms().get_description() -+ -+ # get security group rules -+ sg_q_dict['rules'] = [] -+ rule_list = self.security_group_rules_read(sg_obj.uuid) -+ if rule_list: -+ sg_q_dict['rules'] = [rule['q_api_data'] -+ for rule in rule_list] -+ -+ return {'q_api_data': sg_q_dict} -+ -+ def _security_group_neutron_to_vnc(self, sg_q, operator): -+ if operator == CREATE: -+ project_id = str(uuid.UUID(sg_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType( -+ enable=True, description=sg_q['description']) -+ sg_vnc = vnc_api.SecurityGroup( -+ name=sg_q['name'], parent_obj=project_obj, -+ id_perms=id_perms) -+ -+ return sg_vnc -+ -+ def _security_group_rule_vnc_to_neutron(self, sg_id, sg_rule): -+ sgr_q_dict = {} -+ if sg_id is None: -+ return {'q_api_data': sgr_q_dict} -+ -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ direction = 'egress' -+ if sg_rule.get_direction() == '<': -+ direction = 'ingress' -+ -+ remote_cidr = '' -+ remote_sg_uuid = '' -+ if direction == 'ingress': -+ addr = sg_rule.get_src_addresses()[0] -+ else: -+ addr = sg_rule.get_dst_addresses()[0] -+ -+ if addr.get_subnet(): -+ remote_cidr = '%s/%s' % (addr.get_subnet().get_ip_prefix(), -+ addr.get_subnet().get_ip_prefix_len()) -+ elif addr.get_security_group(): -+ if (addr.get_security_group() != 'any') and \ -+ (addr.get_security_group() != 'local'): -+ remote_sg = addr.get_security_group() -+ try: -+ remote_sg_obj = self._vnc_lib.security_group_read( -+ fq_name_str=remote_sg) -+ remote_sg_uuid = remote_sg_obj.uuid -+ except vnc_exc.NoIdError: -+ pass -+ -+ sgr_q_dict['id'] = sg_rule.get_rule_uuid() -+ sgr_q_dict['tenant_id'] = sg_obj.parent_uuid.replace('-', '') -+ sgr_q_dict['security_group_id'] = sg_obj.uuid -+ sgr_q_dict['ethertype'] = 'IPv4' -+ sgr_q_dict['direction'] = direction -+ sgr_q_dict['protocol'] = sg_rule.get_protocol() -+ sgr_q_dict['port_range_min'] = sg_rule.get_dst_ports()[0].\ -+ get_start_port() -+ sgr_q_dict['port_range_max'] = sg_rule.get_dst_ports()[0].\ -+ get_end_port() -+ sgr_q_dict['remote_ip_prefix'] = remote_cidr -+ sgr_q_dict['remote_group_id'] = remote_sg_uuid -+ -+ return {'q_api_data': sgr_q_dict} -+ -+ def _security_group_rule_neutron_to_vnc(self, sgr_q, operator): -+ if operator == CREATE: -+ port_min = 0 -+ port_max = 65535 -+ if sgr_q['port_range_min']: -+ port_min = sgr_q['port_range_min'] -+ if sgr_q['port_range_max']: -+ port_max = sgr_q['port_range_max'] -+ -+ endpt = [vnc_api.AddressType(security_group='any')] -+ if sgr_q['remote_ip_prefix']: -+ cidr = sgr_q['remote_ip_prefix'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ endpt = [vnc_api.AddressType( -+ subnet=vnc_api.SubnetType(pfx, pfx_len))] -+ elif sgr_q['remote_group_id']: -+ sg_obj = self._vnc_lib.security_group_read( -+ id=sgr_q['remote_group_id']) -+ endpt = [vnc_api.AddressType( -+ security_group=sg_obj.get_fq_name_str())] -+ -+ if sgr_q['direction'] == 'ingress': -+ dir = '<' -+ local = endpt -+ remote = [vnc_api.AddressType(security_group='local')] -+ else: -+ dir = '>' -+ remote = endpt -+ local = [vnc_api.AddressType(security_group='local')] -+ -+ if not sgr_q['protocol']: -+ sgr_q['protocol'] = 'any' -+ -+ sgr_uuid = str(uuid.uuid4()) -+ -+ rule = vnc_api.PolicyRuleType( -+ rule_uuid=sgr_uuid, -+ direction=dir, -+ protocol=sgr_q['protocol'], -+ src_addresses=local, -+ src_ports=[vnc_api.PortType(0, 65535)], -+ dst_addresses=remote, -+ dst_ports=[vnc_api.PortType(port_min, port_max)]) -+ return rule -+ -+ def _network_neutron_to_vnc(self, network_q, operator): -+ net_name = network_q.get('name', None) -+ if operator == CREATE: -+ project_id = str(uuid.UUID(network_q['tenant_id'])) -+ project_obj = self._project_read(proj_id=project_id) -+ id_perms = vnc_api.IdPermsType(enable=True) -+ net_obj = vnc_api.VirtualNetwork( -+ net_name, project_obj, id_perms=id_perms) -+ else: # READ/UPDATE/DELETE -+ net_obj = self._virtual_network_read(net_id=network_q['id']) -+ -+ id_perms = net_obj.get_id_perms() -+ if 'admin_state_up' in network_q: -+ id_perms.enable = network_q['admin_state_up'] -+ net_obj.set_id_perms(id_perms) -+ -+ if 'contrail:policys' in network_q: -+ policy_fq_names = network_q['contrail:policys'] -+ # reset and add with newly specified list -+ net_obj.set_network_policy_list([], []) -+ seq = 0 -+ for p_fq_name in policy_fq_names: -+ domain_name, project_name, policy_name = p_fq_name -+ -+ domain_obj = vnc_api.Domain(domain_name) -+ project_obj = vnc_api.Project(project_name, domain_obj) -+ policy_obj = vnc_api.NetworkPolicy(policy_name, project_obj) -+ -+ net_obj.add_network_policy( -+ policy_obj, -+ vnc_api.VirtualNetworkPolicyType( -+ sequence=vnc_api.SequenceType(seq, 0))) -+ seq = seq + 1 -+ -+ if 'vpc:route_table' in network_q: -+ rt_fq_name = network_q['vpc:route_table'] -+ if rt_fq_name: -+ try: -+ rt_obj = self._vnc_lib.route_table_read(fq_name=rt_fq_name) -+ net_obj.set_route_table(rt_obj) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_obj.uuid) -+ -+ return net_obj -+ -+ def _network_vnc_to_neutron(self, net_obj, net_repr='SHOW'): -+ net_q_dict = {} -+ -+ net_q_dict['id'] = net_obj.uuid -+ net_q_dict['name'] = net_obj.name -+ net_q_dict['tenant_id'] = net_obj.parent_uuid.replace('-', '') -+ net_q_dict['admin_state_up'] = net_obj.get_id_perms().enable -+ net_q_dict['shared'] = False -+ net_q_dict['status'] = constants.NET_STATUS_ACTIVE -+ -+ ipam_refs = net_obj.get_network_ipam_refs() -+ net_q_dict['subnets'] = [] -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnets = ipam_ref['attr'].get_ipam_subnets() -+ for subnet in subnets: -+ sn_info = self._subnet_vnc_to_neutron(subnet, net_obj, -+ ipam_ref['to']) -+ sn_dict = sn_info['q_api_data'] -+ net_q_dict['subnets'].append(sn_dict) -+ sn_ipam = {} -+ sn_ipam['subnet_cidr'] = sn_dict['cidr'] -+ sn_ipam['ipam_fq_name'] = ipam_ref['to'] -+ -+ return {'q_api_data': net_q_dict} -+ -+ def _subnet_neutron_to_vnc(self, subnet_q): -+ cidr = subnet_q['cidr'].split('/') -+ pfx = cidr[0] -+ pfx_len = int(cidr[1]) -+ if subnet_q['gateway_ip'] != attr.ATTR_NOT_SPECIFIED: -+ default_gw = subnet_q['gateway_ip'] -+ else: -+ # Assigned by address manager -+ default_gw = None -+ sub_net = vnc_api.SubnetType(ip_prefix=pfx, -+ ip_prefix_len=pfx_len) -+ subnet_vnc = vnc_api.IpamSubnetType(subnet=sub_net, -+ default_gateway=default_gw) -+ return subnet_vnc -+ -+ def _subnet_vnc_to_neutron(self, subnet_vnc, net_obj, ipam_fq_name): -+ sn_q_dict = { -+ 'name': '', -+ 'tenant_id': net_obj.parent_uuid.replace('-', ''), -+ 'network_id': net_obj.uuid, -+ 'ip_version': 4, -+ } -+ -+ cidr = '%s/%s' % (subnet_vnc.subnet.get_ip_prefix(), -+ subnet_vnc.subnet.get_ip_prefix_len()) -+ sn_q_dict['cidr'] = cidr -+ -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_obj.uuid) -+ sn_id = self._subnet_vnc_read_or_create_mapping(key=subnet_key) -+ -+ sn_q_dict['id'] = sn_id -+ -+ sn_q_dict['gateway_ip'] = subnet_vnc.default_gateway -+ -+ first_ip = str(netaddr.IPNetwork(cidr).network + 1) -+ last_ip = str(netaddr.IPNetwork(cidr).broadcast - 2) -+ sn_q_dict['allocation_pools'] = [{'id': 'TODO-allocation_pools-id', -+ 'subnet_id': sn_id, -+ 'first_ip': first_ip, -+ 'last_ip': last_ip, -+ 'available_ranges': {}}] -+ -+ sn_q_dict['enable_dhcp'] = False -+ sn_q_dict['dns_nameservers'] = [{'address': '169.254.169.254', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['routes'] = [{'destination': 'TODO-destination', -+ 'nexthop': 'TODO-nexthop', -+ 'subnet_id': sn_id}] -+ -+ sn_q_dict['shared'] = False -+ -+ return {'q_api_data': sn_q_dict} -+ -+ def _floatingip_neutron_to_vnc(self, fip_q, operator): -+ if operator == CREATE: -+ # use first available pool on net -+ net_id = fip_q['floating_network_id'] -+ fq_name = self._fip_pool_list_network(net_id)[0]['fq_name'] -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read(fq_name=fq_name) -+ fip_name = str(uuid.uuid4()) -+ fip_obj = vnc_api.FloatingIp(fip_name, fip_pool_obj) -+ fip_obj.uuid = fip_name -+ -+ proj_id = str(uuid.UUID(fip_q['tenant_id'])) -+ proj_obj = self._project_read(proj_id=proj_id) -+ fip_obj.set_project(proj_obj) -+ else: # READ/UPDATE/DELETE -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_q['id']) -+ -+ if fip_q['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=fip_q['port_id']) -+ fip_obj.set_virtual_machine_interface(port_obj) -+ else: -+ fip_obj.set_virtual_machine_interface_list([]) -+ -+ return fip_obj -+ -+ def _floatingip_vnc_to_neutron(self, fip_obj): -+ fip_pool_obj = self._vnc_lib.floating_ip_pool_read( -+ id=fip_obj.parent_uuid) -+ net_obj = self._virtual_network_read(net_id=fip_pool_obj.parent_uuid) -+ -+ tenant_id = fip_obj.get_project_refs()[0]['uuid'].replace('-', '') -+ -+ port_id = None -+ port_refs = fip_obj.get_virtual_machine_interface_refs() -+ if port_refs: -+ port_id = fip_obj.get_virtual_machine_interface_refs()[0]['uuid'] -+ -+ fip_q_dict = { -+ 'id': fip_obj.uuid, -+ 'tenant_id': tenant_id, -+ 'floating_ip_address': fip_obj.get_floating_ip_address(), -+ 'floating_network_id': net_obj.uuid, -+ 'router_id': None, -+ 'fixed_port_id': port_id, -+ 'fixed_ip_address': None, -+ } -+ -+ return {'q_api_data': fip_q_dict} -+ -+ def _port_neutron_to_vnc(self, port_q, net_obj, operator): -+ # if name not passed in use name = uuid = -+ if 'name' in port_q and port_q['name'] != '': -+ port_name = port_q['name'] -+ port_uuid = None -+ else: -+ port_name = str(uuid.uuid4()) -+ port_uuid = port_name -+ -+ if operator == CREATE: -+ instance_name = port_q['device_id'] -+ instance_obj = vnc_api.VirtualMachine(instance_name) -+ -+ id_perms = vnc_api.IdPermsType(enable=True) -+ port_obj = vnc_api.VirtualMachineInterface(port_name, instance_obj, -+ id_perms=id_perms) -+ port_obj.uuid = port_uuid -+ port_obj.set_virtual_network(net_obj) -+ -+ else: # READ/UPDATE/DELETE -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_q['id']) -+ -+ port_obj.set_security_group_list([]) -+ if ('security_groups' in port_q and -+ port_q['security_groups'].__class__ is not object): -+ for sg_id in port_q['security_groups']: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ port_obj.add_security_group(sg_obj) -+ -+ id_perms = port_obj.get_id_perms() -+ if 'admin_state_up' in port_q: -+ id_perms.enable = port_q['admin_state_up'] -+ port_obj.set_id_perms(id_perms) -+ -+ return port_obj -+ -+ def _port_vnc_to_neutron(self, port_obj, net_obj=None): -+ port_q_dict = {} -+ port_q_dict['name'] = port_obj.name -+ port_q_dict['id'] = port_obj.uuid -+ port_q_dict[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_VROUTER -+ -+ if not net_obj: -+ net_refs = port_obj.get_virtual_network_refs() -+ if net_refs: -+ net_id = net_refs[0]['uuid'] -+ else: -+ net_id = self._vnc_lib.obj_to_id(vnc_api.VirtualNetwork()) -+ -+ proj_id = None -+ # not in cache, get by reading VN obj, and populate cache -+ net_obj = self._virtual_network_read(net_id=net_id) -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ self._set_obj_tenant_id(port_obj.uuid, proj_id) -+ else: -+ net_id = net_obj.uuid -+ proj_id = net_obj.parent_uuid.replace('-', '') -+ -+ port_q_dict['tenant_id'] = proj_id -+ port_q_dict['network_id'] = net_id -+ -+ port_q_dict['mac_address'] = '' -+ mac_refs = port_obj.get_virtual_machine_interface_mac_addresses() -+ if mac_refs: -+ port_q_dict['mac_address'] = mac_refs.mac_address[0] -+ -+ port_q_dict['fixed_ips'] = [] -+ ip_back_refs = port_obj.get_instance_ip_back_refs() -+ if ip_back_refs: -+ for ip_back_ref in ip_back_refs: -+ try: -+ ip_obj = self._instance_ip_read( -+ instance_ip_id=ip_back_ref['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ -+ ip_addr = ip_obj.get_instance_ip_address() -+ -+ ip_q_dict = {} -+ ip_q_dict['port_id'] = port_obj.uuid -+ ip_q_dict['ip_address'] = ip_addr -+ ip_q_dict['subnet_id'] = self._ip_address_to_subnet_id(ip_addr, -+ net_obj) -+ ip_q_dict['net_id'] = net_id -+ -+ port_q_dict['fixed_ips'].append(ip_q_dict) -+ -+ sg_dict = {'port_security_enabled': True} -+ sg_dict['security_groups'] = [] -+ sg_refs = port_obj.get_security_group_refs() -+ for sg_ref in sg_refs or []: -+ sg_dict['security_groups'].append(sg_ref['uuid']) -+ -+ port_q_dict['admin_state_up'] = port_obj.get_id_perms().enable -+ port_q_dict['status'] = constants.PORT_STATUS_ACTIVE -+ port_q_dict['device_id'] = port_obj.parent_name -+ port_q_dict['device_owner'] = 'TODO-device-owner' -+ -+ return {'q_api_data': port_q_dict} -+ -+ def network_create(self, network_q): -+ net_obj = self._network_neutron_to_vnc(network_q, CREATE) -+ net_uuid = self._virtual_network_create(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_uuid] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_read(self, net_uuid, fields=None): -+ # see if we can return fast... -+ if fields and (len(fields) == 1) and fields[0] == 'tenant_id': -+ tenant_id = self._get_obj_tenant_id('network', net_uuid) -+ return {'q_api_data': {'id': net_uuid, 'tenant_id': tenant_id}} -+ -+ try: -+ net_obj = self._network_read(net_uuid) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=net_uuid) -+ -+ return self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ -+ def network_update(self, net_id, network_q): -+ network_q['id'] = net_id -+ net_obj = self._network_neutron_to_vnc(network_q, UPDATE) -+ self._virtual_network_update(net_obj) -+ -+ ret_network_q = self._network_vnc_to_neutron(net_obj, net_repr='SHOW') -+ self._db_cache['q_networks'][net_id] = ret_network_q -+ -+ return ret_network_q -+ -+ def network_delete(self, net_id): -+ self._virtual_network_delete(net_id=net_id) -+ try: -+ del self._db_cache['q_networks'][net_id] -+ except KeyError: -+ pass -+ -+ def network_list(self, filters=None): -+ ret_list = [] -+ -+ if filters and 'shared' in filters: -+ if filters['shared'][0]: -+ # no support for shared networks -+ return ret_list -+ -+ # collect phase -+ all_nets = [] # all networks in all projects -+ if filters and 'tenant_id' in filters: -+ # project-id is present -+ if 'id' in filters: -+ # required networks are also specified, -+ # just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in project, and prune below -+ project_ids = filters['tenant_id'] -+ for p_id in project_ids: -+ if 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(p_id)) -+ else: -+ project_nets = self._network_list_project(p_id) -+ all_nets.append(project_nets) -+ elif filters and 'id' in filters: -+ # required networks are specified, just read and populate ret_list -+ # prune is skipped because all_nets is empty -+ for net_id in filters['id']: -+ net_obj = self._network_read(net_id) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ ret_list.append(net_info) -+ else: -+ # read all networks in all projects -+ dom_projects = self._project_list_domain(None) -+ for project in dom_projects: -+ proj_id = project['uuid'] -+ if filters and 'router:external' in filters: -+ all_nets.append(self._fip_pool_ref_networks(proj_id)) -+ else: -+ project_nets = self._network_list_project(proj_id) -+ all_nets.append(project_nets) -+ -+ # prune phase -+ for project_nets in all_nets: -+ for proj_net in project_nets: -+ proj_net_id = proj_net['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_net_id): -+ continue -+ -+ proj_net_fq_name = unicode(proj_net['fq_name']) -+ if not self._filters_is_present(filters, 'contrail:fq_name', -+ proj_net_fq_name): -+ continue -+ -+ try: -+ net_obj = self._network_read(proj_net['uuid']) -+ net_info = self._network_vnc_to_neutron(net_obj, -+ net_repr='LIST') -+ except vnc_exc.NoIdError: -+ continue -+ ret_list.append(net_info) -+ -+ return ret_list -+ -+ def network_count(self, filters=None): -+ nets_info = self.network_list(filters) -+ return len(nets_info) -+ -+ def subnet_create(self, subnet_q): -+ net_id = subnet_q['network_id'] -+ net_obj = self._virtual_network_read(net_id=net_id) -+ -+ ipam_fq_name = subnet_q['contrail:ipam_fq_name'] -+ if ipam_fq_name != '': -+ domain_name, project_name, ipam_name = ipam_fq_name -+ -+ project_obj = vnc_api.Project(project_name) -+ netipam_obj = vnc_api.NetworkIpam(ipam_name, project_obj) -+ else: # link subnet with default ipam -+ project_obj = vnc_api.Project(net_obj.parent_name) -+ netipam_obj = vnc_api.NetworkIpam(project_obj=project_obj) -+ ipam_fq_name = netipam_obj.get_fq_name() -+ -+ subnet_vnc = self._subnet_neutron_to_vnc(subnet_q) -+ subnet_key = self._subnet_vnc_get_key(subnet_vnc, net_id) -+ -+ # Locate list of subnets to which this subnet has to be appended -+ net_ipam_ref = None -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ if ipam_ref['to'] == ipam_fq_name: -+ net_ipam_ref = ipam_ref -+ break -+ -+ if not net_ipam_ref: -+ # First link from net to this ipam -+ vnsn_data = vnc_api.VnSubnetsType(ipam_subnets=[subnet_vnc]) -+ net_obj.add_network_ipam(netipam_obj, vnsn_data) -+ else: # virtual-network already linked to this ipam -+ for subnet in net_ipam_ref['attr'].get_ipam_subnets(): -+ if subnet_key == self._subnet_vnc_get_key(subnet, net_id): -+ # duplicate !! -+ subnet_info = self._subnet_vnc_to_neutron(subnet, -+ net_obj, -+ ipam_fq_name) -+ return subnet_info -+ vnsn_data = net_ipam_ref['attr'] -+ vnsn_data.ipam_subnets.append(subnet_vnc) -+ -+ self._virtual_network_update(net_obj) -+ -+ # allocate an id to the subnet and store mapping with -+ # api-server -+ subnet_id = str(uuid.uuid4()) -+ self._subnet_vnc_create_mapping(subnet_id, subnet_key) -+ -+ # Read in subnet from server to get updated values for gw etc. -+ subnet_vnc = self._subnet_read(net_obj.uuid, subnet_key) -+ subnet_info = self._subnet_vnc_to_neutron(subnet_vnc, net_obj, -+ ipam_fq_name) -+ -+ #self._db_cache['q_subnets'][subnet_id] = subnet_info -+ -+ return subnet_info -+ -+ def subnet_read(self, subnet_id): -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ if self._subnet_vnc_get_key(subnet_vnc, -+ net_id) == subnet_key: -+ ret_subnet_q = self._subnet_vnc_to_neutron( -+ subnet_vnc, net_obj, ipam_ref['to']) -+ self._db_cache['q_subnets'][subnet_id] = ret_subnet_q -+ return ret_subnet_q -+ -+ return {} -+ -+ def subnet_update(self, subnet_id, subnet_q): -+ ret_subnet_q = self.subnet_read(subnet_id) -+ if 'name' in subnet_q: -+ ret_subnet_q['q_api_data']['name'] = subnet_q['name'] -+ return ret_subnet_q -+ -+ def subnet_delete(self, subnet_id): -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ orig_subnets = ipam_ref['attr'].get_ipam_subnets() -+ new_subnets = [subnet_vnc for subnet_vnc in orig_subnets -+ if self._subnet_vnc_get_key(subnet_vnc, net_id) -+ != subnet_key] -+ if len(orig_subnets) != len(new_subnets): -+ # matched subnet to be deleted -+ ipam_ref['attr'].set_ipam_subnets(new_subnets) -+ self._virtual_network_update(net_obj) -+ self._subnet_vnc_delete_mapping(subnet_id, subnet_key) -+ try: -+ del self._db_cache['q_subnets'][subnet_id] -+ except KeyError: -+ pass -+ -+ def subnets_list(self, filters=None): -+ ret_subnets = [] -+ -+ if filters and 'id' in filters: -+ # required subnets are specified, -+ # just read in corresponding net_ids -+ net_ids = set([]) -+ for subnet_id in filters['id']: -+ subnet_key = self._subnet_vnc_read_mapping(id=subnet_id) -+ net_id = subnet_key.split()[0] -+ net_ids.add(net_id) -+ else: -+ nets_info = self.network_list() -+ net_ids = [n_info['q_api_data']['id'] for n_info in nets_info] -+ -+ for net_id in net_ids: -+ net_obj = self._network_read(net_id) -+ ipam_refs = net_obj.get_network_ipam_refs() -+ if ipam_refs: -+ for ipam_ref in ipam_refs: -+ subnet_vncs = ipam_ref['attr'].get_ipam_subnets() -+ for subnet_vnc in subnet_vncs: -+ sn_info = self._subnet_vnc_to_neutron(subnet_vnc, -+ net_obj, -+ ipam_ref['to']) -+ sn_id = sn_info['q_api_data']['id'] -+ sn_proj_id = sn_info['q_api_data']['tenant_id'] -+ sn_net_id = sn_info['q_api_data']['network_id'] -+ -+ if filters: -+ if not self._filters_is_present(filters, 'id', -+ sn_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'tenant_id', -+ sn_proj_id): -+ continue -+ if not self._filters_is_present(filters, -+ 'network_id', -+ sn_net_id): -+ continue -+ -+ ret_subnets.append(sn_info) -+ -+ return ret_subnets -+ -+ def subnets_count(self, filters=None): -+ subnets_info = self.subnets_list(filters) -+ return len(subnets_info) -+ -+ # floatingip api handlers -+ def floatingip_create(self, fip_q): -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, CREATE) -+ fip_uuid = self._vnc_lib.floating_ip_create(fip_obj) -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_read(self, fip_uuid): -+ fip_obj = self._vnc_lib.floating_ip_read(id=fip_uuid) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_update(self, fip_id, fip_q): -+ fip_q['id'] = fip_id -+ fip_obj = self._floatingip_neutron_to_vnc(fip_q, UPDATE) -+ self._vnc_lib.floating_ip_update(fip_obj) -+ -+ return self._floatingip_vnc_to_neutron(fip_obj) -+ -+ def floatingip_delete(self, fip_id): -+ self._vnc_lib.floating_ip_delete(id=fip_id) -+ -+ def floatingip_list(self, filters=None): -+ # Find networks, get floatingip backrefs and return -+ ret_list = [] -+ -+ if filters: -+ if 'tenant_id' in filters: -+ proj_ids = [str(uuid.UUID(id)) for id in filters['tenant_id']] -+ elif 'port_id' in filters: -+ # required ports are specified, just read and populate ret_list -+ # prune is skipped because proj_objs is empty -+ proj_ids = [] -+ for port_id in filters['port_id']: -+ port_obj = self._virtual_machine_interface_read( -+ port_id=port_id) -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron( -+ fip_obj)) -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ proj_ids = [proj['uuid'] for proj in dom_projects] -+ -+ proj_objs = [self._project_read(proj_id=id) for id in proj_ids] -+ -+ for proj_obj in proj_objs: -+ fip_back_refs = proj_obj.get_floating_ip_back_refs() -+ if not fip_back_refs: -+ continue -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ ret_list.append(self._floatingip_vnc_to_neutron(fip_obj)) -+ -+ return ret_list -+ -+ def floatingip_count(self, filters=None): -+ floatingip_info = self.floatingip_list(filters) -+ return len(floatingip_info) -+ -+ # port api handlers -+ def port_create(self, port_q): -+ net_id = port_q['network_id'] -+ net_obj = self._network_read(net_id) -+ proj_id = net_obj.parent_uuid -+ -+ self._ensure_instance_exists(port_q['device_id']) -+ -+ # initialize port object -+ port_obj = self._port_neutron_to_vnc(port_q, net_obj, CREATE) -+ -+ # if ip address passed then use it -+ ip_addr = None -+ ip_obj = None -+ if port_q['fixed_ips'].__class__ is not object: -+ ip_addr = port_q['fixed_ips'][0]['ip_address'] -+ ip_name = '%s %s' % (net_id, ip_addr) -+ try: -+ ip_obj = self._instance_ip_read(fq_name=[ip_name]) -+ #ip_id = ip_obj.uuid -+ except Exception as e: -+ ip_obj = None -+ -+ # create the object -+ port_id = self._virtual_machine_interface_create(port_obj) -+ -+ # initialize ip object -+ if ip_obj is None: -+ # Allocate an IP address only if there is a defined subnet -+ if net_obj.get_network_ipam_refs(): -+ ip_name = str(uuid.uuid4()) -+ ip_obj = vnc_api.InstanceIp(name=ip_name) -+ ip_obj.uuid = ip_name -+ ip_obj.set_virtual_machine_interface(port_obj) -+ ip_obj.set_virtual_network(net_obj) -+ if ip_addr: -+ ip_obj.set_instance_ip_address(ip_addr) -+ try: -+ self._instance_ip_create(ip_obj) -+ except Exception as e: -+ # ResourceExhaustionError, resources are not available -+ self._virtual_machine_interface_delete(port_id=port_id) -+ raise e -+ # shared ip address -+ else: -+ if ip_addr == ip_obj.get_instance_ip_address(): -+ ip_obj.add_virtual_machine_interface(port_obj) -+ self._instance_ip_update(ip_obj) -+ -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj, net_obj) -+ #self._db_cache['q_ports'][port_id] = ret_port_q -+ self._set_obj_tenant_id(port_id, proj_id) -+ -+ # update cache on successful creation -+ tenant_id = proj_id.replace('-', '') -+ if tenant_id not in self._db_cache['q_tenant_port_count']: -+ ncurports = self.port_count({'tenant_id': tenant_id}) -+ else: -+ ncurports = self._db_cache['q_tenant_port_count'][tenant_id] -+ -+ self._db_cache['q_tenant_port_count'][tenant_id] = ncurports + 1 -+ -+ return ret_port_q -+ -+ def port_read(self, port_id): -+ port_obj = self._virtual_machine_interface_read(port_id=port_id) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_update(self, port_id, port_q): -+ port_q['id'] = port_id -+ port_obj = self._port_neutron_to_vnc(port_q, None, UPDATE) -+ self._virtual_machine_interface_update(port_obj) -+ -+ ret_port_q = self._port_vnc_to_neutron(port_obj) -+ self._db_cache['q_ports'][port_id] = ret_port_q -+ -+ return ret_port_q -+ -+ def port_delete(self, port_id): -+ port_obj = self._port_neutron_to_vnc({'id': port_id}, None, READ) -+ instance_id = port_obj.parent_uuid -+ -+ # release instance IP address -+ iip_back_refs = port_obj.get_instance_ip_back_refs() -+ if iip_back_refs: -+ for iip_back_ref in iip_back_refs: -+ # if name contains IP address then this is shared ip -+ iip_obj = self._vnc_lib.instance_ip_read( -+ id=iip_back_ref['uuid']) -+ name = iip_obj.name -+ if len(name.split(' ')) > 1: -+ name = name.split(' ')[1] -+ -+ # in case of shared ip only delete the link to the VMI -+ try: -+ socket.inet_aton(name) -+ iip_obj.del_virtual_machine_interface(port_obj) -+ self._instance_ip_update(iip_obj) -+ except socket.error: -+ self._instance_ip_delete( -+ instance_ip_id=iip_back_ref['uuid']) -+ -+ # disassociate any floating IP used by instance -+ fip_back_refs = port_obj.get_floating_ip_back_refs() -+ if fip_back_refs: -+ for fip_back_ref in fip_back_refs: -+ fip_obj = self._vnc_lib.floating_ip_read( -+ id=fip_back_ref['uuid']) -+ self.floatingip_update(fip_obj.uuid, {'port_id': None}) -+ -+ self._virtual_machine_interface_delete(port_id=port_id) -+ -+ # delete instance if this was the last port -+ inst_obj = self._vnc_lib.virtual_machine_read(id=instance_id) -+ inst_intfs = inst_obj.get_virtual_machine_interfaces() -+ if not inst_intfs: -+ self._vnc_lib.virtual_machine_delete(id=inst_obj.uuid) -+ -+ try: -+ del self._db_cache['q_ports'][port_id] -+ except KeyError: -+ pass -+ -+ # update cache on successful deletion -+ try: -+ tenant_id = self._get_obj_tenant_id('port', port_id) -+ self._db_cache['q_tenant_port_count'][tenant_id] = \ -+ self._db_cache['q_tenant_port_count'][tenant_id] - 1 -+ except KeyError: -+ pass -+ -+ self._del_obj_tenant_id(port_id) -+ -+ def port_list(self, filters=None): -+ ret_q_ports = [] -+ all_project_ids = [] -+ -+ if 'device_owner' in filters: -+ return ret_q_ports -+ -+ if 'device_id' not in filters: -+ # Listing from back references -+ if not filters: -+ # no filters => return all ports! -+ all_projects = self._project_list_domain(None) -+ all_project_ids = [project['uuid'] for project in all_projects] -+ elif 'tenant_id' in filters: -+ all_project_ids = filters.get('tenant_id') -+ -+ for proj_id in all_project_ids: -+ proj_ports = self._port_list_project(proj_id) -+ for port in proj_ports: -+ try: -+ port_info = self.port_read(port['id']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ for net_id in filters.get('network_id', []): -+ net_ports = self._port_list_network(net_id) -+ for port in net_ports: -+ port_info = self.port_read(port['id']) -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ # Listing from parent to children -+ virtual_machine_ids = filters['device_id'] -+ for vm_id in virtual_machine_ids: -+ resp_dict = self._vnc_lib.virtual_machine_interfaces_list( -+ parent_id=vm_id) -+ vm_intf_ids = resp_dict['virtual-machine-interfaces'] -+ for vm_intf in vm_intf_ids: -+ try: -+ port_info = self.port_read(vm_intf['uuid']) -+ except vnc_exc.NoIdError: -+ continue -+ ret_q_ports.append(port_info) -+ -+ return ret_q_ports -+ -+ def port_count(self, filters=None): -+ if 'device_owner' in filters: -+ return 0 -+ -+ if 'tenant_id' in filters: -+ project_id = filters['tenant_id'][0] -+ try: -+ return self._db_cache['q_tenant_port_count'][project_id] -+ except KeyError: -+ # do it the hard way but remember for next time -+ nports = len(self._port_list_project(project_id)) -+ self._db_cache['q_tenant_port_count'][project_id] = nports -+ else: -+ # across all projects -+ # get only a count from api-server! -+ nports = len(self.port_list(filters)) -+ -+ return nports -+ -+ # security group api handlers -+ def security_group_create(self, sg_q): -+ sg_obj = self._security_group_neutron_to_vnc(sg_q, CREATE) -+ sg_uuid = self._security_group_create(sg_obj) -+ -+ #allow all egress traffic -+ def_rule = { -+ 'port_range_min': 0, -+ 'port_range_max': 65535, -+ 'direction': 'egress', -+ 'remote_ip_prefix': None, -+ 'remote_group_id': None, -+ 'protocol': 'any', -+ } -+ rule = self._security_group_rule_neutron_to_vnc(def_rule, CREATE) -+ self._security_group_rule_create(sg_uuid, rule) -+ -+ ret_sg_q = self._security_group_vnc_to_neutron(sg_obj) -+ return ret_sg_q -+ -+ def security_group_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return self._security_group_vnc_to_neutron(sg_obj) -+ -+ def security_group_delete(self, sg_id): -+ self._security_group_delete(sg_id) -+ -+ def security_group_list(self, context, filters=None): -+ ret_list = [] -+ -+ # all_sgs[] all sgs in all projects -+ # collect phase -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ all_sgs = [self._security_group_list_project(p_id) for -+ p_id in project_ids] -+ elif filters and 'name' in filters: -+ all_sgs = [self._security_group_list_project( -+ str(uuid.UUID(context.tenant)))] -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ all_sgs = [self._security_group_list_project(project['uuid']) for -+ project in dom_projects] -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ for proj_sg in project_sgs: -+ proj_sg_id = proj_sg['uuid'] -+ if not self._filters_is_present(filters, 'id', proj_sg_id): -+ continue -+ sg_info = self.security_group_read(proj_sg_id) -+ if not self._filters_is_present(filters, 'name', -+ sg_info['q_api_data']['name']): -+ continue -+ ret_list.append(sg_info) -+ -+ return ret_list -+ -+ def security_group_rule_create(self, sgr_q): -+ sg_id = sgr_q['security_group_id'] -+ sg_rule = self._security_group_rule_neutron_to_vnc(sgr_q, CREATE) -+ self._security_group_rule_create(sg_id, sg_rule) -+ ret_sg_rule_q = self._security_group_rule_vnc_to_neutron(sg_id, -+ sg_rule) -+ -+ return ret_sg_rule_q -+ -+ def security_group_rule_read(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_vnc_to_neutron(sg_obj.uuid, -+ sg_rule) -+ -+ return {} -+ -+ def security_group_rule_delete(self, sgr_id): -+ sg_obj, sg_rule = self._security_group_rule_find(sgr_id) -+ if sg_obj and sg_rule: -+ return self._security_group_rule_delete(sg_obj, sg_rule) -+ -+ def security_group_rules_read(self, sg_id): -+ try: -+ sg_obj = self._vnc_lib.security_group_read(id=sg_id) -+ sgr_entries = sg_obj.get_security_group_entries() -+ if sgr_entries is None: -+ return -+ -+ sg_rules = [self._security_group_rule_vnc_to_neutron( -+ sg_obj.uuid, sg_rule) for -+ sg_rule in sgr_entries.get_policy_rule()] -+ except vnc_exc.NoIdError: -+ raise exceptions.NetworkNotFound(net_id=sg_id) -+ -+ return sg_rules -+ -+ def security_group_rule_list(self, filters=None): -+ ret_list = [] -+ -+ # collect phase -+ if filters and 'tenant_id' in filters: -+ project_ids = filters['tenant_id'] -+ all_sgs = [self._security_group_list_project(p_id) for -+ p_id in project_ids] -+ else: # no filters -+ dom_projects = self._project_list_domain(None) -+ all_sgs = [self._security_group_list_project(project['uuid']) -+ for project in dom_projects] -+ -+ # prune phase -+ for project_sgs in all_sgs: -+ ret_list.extend( -+ self.security_group_rules_read(proj_sg['uuid']) -+ for proj_sg in project_sgs -+ if self._filters_is_present(filters, 'id', proj_sg['uuid']) -+ ) -+ -+ return ret_list -diff --git neutron/tests/unit/juniper/__init__.py neutron/tests/unit/juniper/__init__.py -new file mode 100644 -index 0000000..72bebec ---- /dev/null -+++ neutron/tests/unit/juniper/__init__.py -@@ -0,0 +1,14 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -diff --git neutron/tests/unit/juniper/test_contrail_plugin.py neutron/tests/unit/juniper/test_contrail_plugin.py -new file mode 100644 -index 0000000..3984971 ---- /dev/null -+++ neutron/tests/unit/juniper/test_contrail_plugin.py -@@ -0,0 +1,1021 @@ -+# Copyright (c) 2012 OpenStack Foundation. -+# -+# 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. -+ -+import datetime -+import mock -+import sys -+import uuid -+ -+import neutron.db.api -+from neutron.manager import NeutronManager -+from neutron.tests.unit import test_db_plugin as test_plugin -+ -+ -+subnet_obj = {u'subnet': -+ {'name': '', 'enable_dhcp': True, -+ u'network_id': u'b11ffca3-3dfc-435e-ae0e-8f44da7188b7', -+ 'tenant_id': u'8162e75da480419a8b2ae7088dbc14f5', -+ 'dns_nameservers': '', -+ u'contrail:ipam_fq_name': -+ [u'default-domain', u'admin', u'default-network-ipam'], -+ 'allocation_pools': '', 'host_routes': '', u'ip_version': 4, -+ 'gateway_ip': '', u'cidr': u'20.20.1.0/29'}} -+ -+vn_list = [] -+GlobalProjects = [] -+ -+ -+class MockVncApi(mock.MagicMock): -+ def __init__(self, *args, **kwargs): -+ pass -+ -+ def kv_retrieve(self, *args, **kwargs): -+ return [] -+ -+ def kv_store(self, *args, **kwargs): -+ return -+ -+ def kv_delete(self, *args, **kwargs): -+ return -+ -+ def project_read(self, *args, **kwargs): -+ return GlobalProjects[0] -+ -+ def virtual_network_create(self, net_obj): -+ net_id = unicode(str(uuid.uuid4())) -+ net_obj.set_uuid(net_id) -+ vn_list.append(net_obj) -+ return net_id -+ -+ def virtual_network_read(self, id, *args, **kwargs): -+ if len(vn_list): -+ for index in range(len(vn_list)): -+ if ((vn_list[index].get_uuid()) == id): -+ return vn_list[index] -+ -+ #return a mock object if it is not created so far -+ return MockVirtualNetwork('dummy-net', MockProject()) -+ -+ def virtual_network_delete(self, *args, **kwargs): -+ return -+ -+ def virtual_network_update(self, *args, **kwargs): -+ return -+ -+ def virtual_networks_list(self, *args, **kwargs): -+ return vn_list -+ -+ -+class MockVncObject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ if not parent_obj: -+ self._fq_name = [name] -+ else: -+ self._fq_name = parent_obj.get_fq_name() + [name] -+ -+ self._ipam_refs = [{'to': [u'default-domain', u'admin', -+ u'default-network-ipam']}] -+ self.uuid = None -+ self.name = name -+ self.network_ipam_refs = [] -+ -+ def set_uuid(self, uuid): -+ self.uuid = uuid -+ -+ def get_uuid(self): -+ return self.uuid -+ -+ def get_fq_name(self): -+ return self._fq_name -+ -+ def get_network_ipam_refs(self): -+ return getattr(self, 'network_ipam_refs', None) -+ -+ def add_network_ipam(self, ref_obj, ref_data): -+ refs = getattr(self, 'network_ipam_refs', []) -+ if not refs: -+ self.network_ipam_refs = [] -+ -+ # if ref already exists, update any attr with it -+ for ref in refs: -+ if ref['to'] == ref_obj.get_fq_name(): -+ ref = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref['uuid'] = ref_obj.uuid -+ return -+ -+ # ref didn't exist before -+ ref_info = {'to': ref_obj.get_fq_name(), 'attr': ref_data} -+ if ref_obj.uuid: -+ ref_info['uuid'] = ref_obj.uuid -+ -+ self.network_ipam_refs.append(ref_info) -+ -+ -+class MockVirtualNetwork(MockVncObject): -+ pass -+ -+ -+class MockSubnetType(mock.MagicMock): -+ def __init__(self, name=None, ip_prefix=None, ip_prefix_len=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ip_prefix = ip_prefix -+ self.ip_prefix_len = ip_prefix_len -+ -+ def get_ip_prefix(self): -+ return self.ip_prefix -+ -+ def set_ip_prefix(self, ip_prefix): -+ self.ip_prefix = ip_prefix -+ -+ def get_ip_prefix_len(self): -+ return self.ip_prefix_len -+ -+ def set_ip_prefix_len(self, ip_prefix_len): -+ self.ip_prefix_len = ip_prefix_len -+ -+ -+class MockIpamSubnetType(mock.MagicMock): -+ def __init__(self, name=None, subnet=None, default_gateway=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.subnet = subnet -+ self.default_gateway = default_gateway -+ -+ def get_subnet(self): -+ return self.subnet -+ -+ def set_subnet(self, subnet): -+ self.subnet = subnet -+ -+ def get_default_gateway(self): -+ return self.default_gateway -+ -+ def set_default_gateway(self, default_gateway): -+ self.default_gateway = default_gateway -+ -+ def validate_IpAddressType(self, value): -+ pass -+ -+ -+class MockVnSubnetsType(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, ipam_subnets=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self.ipam_subnets = [] -+ if ipam_subnets: -+ #self.ipam_subnets = copy.deepcopy(ipam_subnets) -+ self.ipam_subnets = ipam_subnets -+ -+ def get_ipam_subnets(self): -+ return self.ipam_subnets -+ -+ def set_ipam_subnets(self, ipam_subnets): -+ self.ipam_subnets = ipam_subnets -+ -+ def add_ipam_subnets(self, value): -+ self.ipam_subnets.append(value) -+ -+ def insert_ipam_subnets(self, index, value): -+ self.ipam_subnets[index] = value -+ -+ def delete_ipam_subnets(self, value): -+ self.ipam_subnets.remove(value) -+ -+ -+class MockNetworkIpam(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, -+ network_ipam_mgmt=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'default-network-ipam' -+ self.name = name -+ self.uuid = None -+ if parent_obj: -+ self.parent_type = parent_obj._type -+ # copy parent's fq_name -+ self.fq_name = list(parent_obj.fq_name) -+ self.fq_name.append(name) -+ if not parent_obj.get_network_ipams(): -+ parent_obj.network_ipams = [] -+ parent_obj.network_ipams.append(self) -+ else: # No parent obj specified -+ self.parent_type = 'project' -+ self.fq_name = [u'default-domain', u'default-project'] -+ self.fq_name.append(name) -+ -+ # property fields -+ if network_ipam_mgmt: -+ self.network_ipam_mgmt = network_ipam_mgmt -+ if id_perms: -+ self.id_perms = id_perms -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+class MockProject(mock.MagicMock): -+ def __init__(self, name=None, parent_obj=None, id_perms=None, -+ *args, **kwargs): -+ super(mock.MagicMock, self).__init__() -+ self._type = 'project' -+ self.uuid = None -+ self.parent_type = 'domain' -+ self.fq_name = [u'default-domain'] -+ self.fq_name.append(name) -+ -+ def get_fq_name(self): -+ return self.fq_name -+ -+ -+def GlobalProjectApi(project_name): -+ if not GlobalProjects: -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ return GlobalProjects[0] -+ -+ -+# Mock definations for different pkgs, modules and VncApi -+mock_vnc_api_cls = mock.MagicMock(name='MockVncApi', side_effect=MockVncApi) -+mock_vnc_api_mod = mock.MagicMock(name='vnc_api_mock_mod') -+mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+mock_vnc_api_mod.VirtualNetwork = MockVirtualNetwork -+mock_vnc_api_mod.SubnetType = MockSubnetType -+mock_vnc_api_mod.IpamSubnetType = MockIpamSubnetType -+mock_vnc_api_mod.VnSubnetsType = MockVnSubnetsType -+mock_vnc_api_mod.NetworkIpam = MockNetworkIpam -+mock_vnc_api_mod.Project = GlobalProjectApi -+ -+mock_vnc_api_pkg = mock.MagicMock(name='vnc_api_mock_pkg') -+mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+mock_vnc_common_mod = mock.MagicMock(name='vnc_common_mock_mod') -+mock_vnc_exception_mod = mock.MagicMock(name='vnc_exception_mock_mod') -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api'] = \ -+ mock_vnc_api_pkg -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.vnc_api'] = \ -+ mock_vnc_api_mod -+sys.modules['neutron.plugins.juniper.contrail.ctdb.vnc_api.common'] = \ -+ mock_vnc_common_mod -+sys.modules[('neutron.plugins.juniper.contrail.ctdb.vnc_api.common.' -+ 'exceptions')] = \ -+ mock_vnc_exception_mod -+ -+CONTRAIL_PKG_PATH = "neutron.plugins.juniper.contrail.contrailplugin" -+ -+ -+class RouterInstance(object): -+ def __init__(self): -+ self._name = 'rounter_instance' -+ -+ -+class Context(object): -+ def __init__(self, tenant_id=''): -+ self.read_only = False -+ self.show_deleted = False -+ self.roles = [u'admin', u'KeystoneServiceAdmin', u'KeystoneAdmin'] -+ self._read_deleted = 'no' -+ self.timestamp = datetime.datetime.now() -+ self.auth_token = None -+ self._session = None -+ self._is_admin = True -+ self.admin = uuid.uuid4().hex.decode() -+ self.request_id = 'req-' + str(uuid.uuid4()) -+ self.tenant = tenant_id -+ -+ -+class JVContrailPluginTestCase(test_plugin.NeutronDbPluginV2TestCase): -+ _plugin_name = ('%s.ContrailPlugin' % CONTRAIL_PKG_PATH) -+ -+ def setUp(self): -+ -+ mock_vnc_common_mod.exceptions = mock_vnc_exception_mod -+ -+ mock_vnc_api_mod.common = mock_vnc_common_mod -+ mock_vnc_api_mod.VncApi = mock_vnc_api_cls -+ -+ mock_vnc_api_pkg.vnc_api = mock_vnc_api_mod -+ -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ neutron.db.api._ENGINE = mock.MagicMock() -+ -+ def teardown(self): -+ super(JVContrailPluginTestCase, self).setUp(self._plugin_name) -+ -+ -+class TestContrailNetworks(test_plugin.TestNetworksV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ router_inst = RouterInstance() -+ network = { -+ 'router:external': router_inst, -+ u'name': u'network1', -+ 'admin_state_up': 'True', -+ 'tenant_id': uuid.uuid4().hex.decode(), -+ 'vpc:route_table': '', -+ 'shared': False, -+ 'port_security_enabled': True, -+ u'contrail:policys': [], -+ } -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ if 'contrail:fq_name' not in net.keys(): -+ assert False -+ else: -+ assert True -+ -+ def test_delete_network(self): -+ # First create the network and request to delete the same -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ router_inst = RouterInstance() -+ network = { -+ 'router:external': router_inst, -+ u'name': u'network1', -+ 'admin_state_up': 'True', -+ 'tenant_id': uuid.uuid4().hex.decode(), -+ 'vpc:route_table': '', -+ 'shared': False, -+ 'port_security_enabled': True, -+ u'contrail:policys': [], -+ } -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ -+ plugin_obj.delete_network(context_obj, net_id) -+ mock_vnc_api_cls.virtual_network_delete.assert_called_once() -+ -+ def test_update_network(self): -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ router_inst = RouterInstance() -+ network = { -+ 'router:external': router_inst, -+ u'name': u'network1', -+ 'admin_state_up': 'True', -+ 'tenant_id': uuid.uuid4().hex.decode(), -+ 'vpc:route_table': '', -+ 'shared': False, -+ 'port_security_enabled': True, -+ u'contrail:policys': [], -+ } -+ -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ networks_req[u'network'] = network -+ net_dict = plugin_obj.create_network(context_obj, networks_req) -+ net_id = net_dict.get('id') -+ # change one of the attribute and update the network -+ network['admin_state_up'] = 'False' -+ new_dict = plugin_obj.update_network(context_obj, net_id, -+ networks_req) -+ self.assertNotEqual(net_dict.get('admin_state_up'), -+ new_dict.get('admin_state_up')) -+ -+ # Not supported test cases in the this TestClass -+ def test_create_networks_bulk_emulated(self): -+ pass -+ -+ def test_create_networks_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_public_network(self): -+ pass -+ -+ def test_create_networks_bulk_wrong_input(self): -+ pass -+ -+ def test_update_shared_network_noadmin_returns_403(self): -+ pass -+ -+ def test_update_network_set_shared(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_multi_tenants2_returns_409(self): -+ pass -+ -+ def test_update_network_set_not_shared_single_tenant(self): -+ pass -+ -+ def test_update_network_set_not_shared_other_tenant_returns_409(self): -+ pass -+ -+ def test_update_network_with_subnet_set_shared(self): -+ pass -+ -+ def test_show_network(self): -+ pass -+ -+ def test_show_network_with_subnet(self): -+ pass -+ -+ def test_list_networks(self): -+ pass -+ -+ def test_list_shared_networks_with_non_admin_user(self): -+ pass -+ -+ def test_list_networks_with_parameters(self): -+ pass -+ -+ def test_list_networks_with_fields(self): -+ pass -+ -+ def test_list_networks_with_parameters_invalid_values(self): -+ pass -+ -+ def test_list_networks_with_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_without_pk_in_fields_pagination_emulated(self): -+ pass -+ -+ def test_list_networks_with_sort_emulated(self): -+ pass -+ -+ def test_list_networks_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_invalid_admin_status(self): -+ pass -+ -+ -+class TestContrailSubnetsV2(test_plugin.TestSubnetsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ router_inst = RouterInstance() -+ network = { -+ 'router:external': router_inst, -+ u'name': u'network1', -+ 'admin_state_up': 'True', -+ 'tenant_id': uuid.uuid4().hex.decode(), -+ 'vpc:route_table': '', -+ 'shared': False, -+ 'port_security_enabled': True, -+ u'contrail:policys': [], -+ } -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ self.assertEqual(subnet_dict['cidr'], -+ subnet_obj['subnet']['cidr']) -+ -+ def test_delete_subnet(self): -+ #First create virtual network without subnet and then -+ #create subnet to update given network. -+ plugin_obj = NeutronManager.get_plugin() -+ networks_req = {} -+ router_inst = RouterInstance() -+ network = { -+ 'router:external': router_inst, -+ u'name': u'network1', -+ 'admin_state_up': 'True', -+ 'tenant_id': uuid.uuid4().hex.decode(), -+ 'vpc:route_table': '', -+ 'shared': False, -+ 'port_security_enabled': True, -+ u'contrail:policys': [], -+ } -+ -+ networks_req[u'network'] = network -+ context_obj = Context(network['tenant_id']) -+ #create project -+ if not GlobalProjects: -+ project_name = 'admin' -+ GlobalProjects.append(MockProject(name=project_name)) -+ -+ net = plugin_obj.create_network(context_obj, networks_req) -+ -+ subnet_obj[u'subnet']['network_id'] = net['id'] -+ subnet_dict = plugin_obj.create_subnet(context_obj, subnet_obj) -+ subnet_id = subnet_dict['id'] -+ plugin_obj.delete_subnet(context_obj, subnet_id) -+ -+ def test_update_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_delete_network(self): -+ pass -+ -+ def test_update_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet_adding_additional_host_routes_and_dns(self): -+ pass -+ -+ def test_update_subnet_no_gateway(self): -+ pass -+ -+ def test_create_subnet_bad_cidr(self): -+ pass -+ -+ def test_create_subnet_gw_of_network_force_on_returns_400(self): -+ pass -+ -+ def test_create_subnet_gw_outside_cidr_force_on_returns_400(self): -+ pass -+ -+ def test_create_two_subnets(self): -+ pass -+ -+ def test_create_two_subnets_same_cidr_returns_400(self): -+ pass -+ -+ def test_create_subnet_bad_V4_cidr(self): -+ pass -+ -+ def test_create_subnet_bad_V6_cidr(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self): -+ pass -+ -+ def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self): -+ pass -+ -+ def test_create_subnets_bulk_native(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated(self): -+ pass -+ -+ def test_create_subnets_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_subnets_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_network(self): -+ pass -+ -+ def test_delete_subnet_port_exists_owned_by_other(self): -+ pass -+ -+ def test_create_subnet_bad_tenant(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version(self): -+ pass -+ -+ def test_create_subnet_bad_ip_version_null(self): -+ pass -+ -+ def test_create_subnet_bad_uuid(self): -+ pass -+ -+ def test_create_subnet_bad_boolean(self): -+ pass -+ -+ def test_create_subnet_bad_pools(self): -+ pass -+ -+ def test_create_subnet_bad_nameserver(self): -+ pass -+ -+ def test_create_subnet_bad_hostroutes(self): -+ pass -+ -+ def test_create_subnet_defaults(self): -+ pass -+ -+ def test_create_subnet_gw_values(self): -+ pass -+ -+ def test_create_force_subnet_gw_values(self): -+ pass -+ -+ def test_create_subnet_with_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_fully_allocated(self): -+ pass -+ -+ def test_subnet_with_allocation_range(self): -+ pass -+ -+ def test_create_subnet_with_none_gateway_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_v6_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_with_large_allocation_pool(self): -+ pass -+ -+ def test_create_subnet_multiple_allocation_pools(self): -+ pass -+ -+ def test_create_subnet_with_dhcp_disabled(self): -+ pass -+ -+ def test_create_subnet_default_gw_conflict_allocation_pool_returns_409( -+ self): -+ pass -+ -+ def test_create_subnet_gateway_in_allocation_pool_returns_409(self): -+ pass -+ -+ def test_create_subnet_overlapping_allocation_pools_returns_409(self): -+ pass -+ -+ def test_create_subnet_invalid_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_out_of_range_allocation_pool_returns_400(self): -+ pass -+ -+ def test_create_subnet_shared_returns_400(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_cidrv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_cidrv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv6_dns_v4(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self): -+ pass -+ -+ def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self): -+ pass -+ -+ def test_create_subnet_gw_bcast_force_on_returns_400(self): -+ pass -+ -+ def test_update_subnet(self): -+ pass -+ -+ def test_update_subnet_shared_returns_400(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_gatewayv6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_gatewayv4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv4_dns_v6(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self): -+ pass -+ -+ def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self): -+ pass -+ -+ def test_show_subnet(self): -+ pass -+ -+ def test_list_subnets(self): -+ pass -+ -+ def test_list_subnets_shared(self): -+ pass -+ -+ def test_list_subnets_with_parameter(self): -+ pass -+ -+ def test_invalid_ip_version(self): -+ pass -+ -+ def test_invalid_subnet(self): -+ pass -+ -+ def test_invalid_ip_address(self): -+ pass -+ -+ def test_invalid_uuid(self): -+ pass -+ -+ def test_create_subnet_with_one_dns(self): -+ pass -+ -+ def test_create_subnet_with_two_dns(self): -+ pass -+ -+ def test_create_subnet_with_too_many_dns(self): -+ pass -+ -+ def test_create_subnet_with_one_host_route(self): -+ pass -+ -+ def test_create_subnet_with_two_host_routes(self): -+ pass -+ -+ def test_create_subnet_with_too_many_routes(self): -+ pass -+ -+ def test_create_subnet_as_admin(self): -+ pass -+ -+ def test_update_subnet_dns(self): -+ pass -+ -+ def test_update_subnet_dns_to_None(self): -+ pass -+ -+ def test_update_subnet_dns_with_too_many_entries(self): -+ pass -+ -+ def test_update_subnet_route(self): -+ pass -+ -+ def test_update_subnet_route_to_None(self): -+ pass -+ -+ def test_update_subnet_route_with_too_many_entries(self): -+ pass -+ -+ def test_delete_subnet_with_dns(self): -+ pass -+ -+ def test_delete_subnet_with_route(self): -+ pass -+ -+ def test_delete_subnet_with_dns_and_route(self): -+ pass -+ -+ def test_list_subnets_with_pagination_emulated(self): -+ pass -+ -+ def test_list_subnets_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_subnets_with_sort_emulated(self): -+ pass -+ -+ def test_validate_subnet_host_routes_exhausted(self): -+ pass -+ -+ def test_validate_subnet_dns_nameservers_exhausted(self): -+ pass -+ -+ def test_update_subnet_gw_ip_in_use_returns_409(self): -+ pass -+ -+ -+class TestContrailPortsV2(test_plugin.TestPortsV2, -+ JVContrailPluginTestCase): -+ -+ def test_create_port(self): -+ pass -+ -+ def test_create_port_json(self): -+ pass -+ -+ def test_create_port_bad_tenant(self): -+ pass -+ -+ def test_create_port_public_network(self): -+ pass -+ -+ def test_create_port_public_network_with_ip(self): -+ pass -+ -+ def test_create_ports_bulk_native(self): -+ pass -+ -+ def test_create_ports_bulk_emulated(self): -+ pass -+ -+ def test_create_ports_bulk_wrong_input(self): -+ pass -+ -+ def test_create_ports_bulk_emulated_plugin_failure(self): -+ pass -+ -+ def test_create_ports_bulk_native_plugin_failure(self): -+ pass -+ -+ def test_create_port_as_admin(self): -+ pass -+ -+ def test_list_ports(self): -+ pass -+ -+ def test_list_ports_filtered_by_fixed_ip(self): -+ pass -+ -+ def test_list_ports_public_network(self): -+ pass -+ -+ def test_show_port(self): -+ pass -+ -+ def test_delete_port(self): -+ pass -+ -+ def test_delete_port_public_network(self): -+ pass -+ -+ def test_update_port(self): -+ pass -+ -+ def test_update_device_id_null(self): -+ pass -+ -+ def test_delete_network_if_port_exists(self): -+ pass -+ -+ def test_delete_network_port_exists_owned_by_network(self): -+ pass -+ -+ def test_update_port_delete_ip(self): -+ pass -+ -+ def test_no_more_port_exception(self): -+ pass -+ -+ def test_update_port_update_ip(self): -+ pass -+ -+ def test_update_port_update_ip_address_only(self): -+ pass -+ -+ def test_update_port_update_ips(self): -+ pass -+ -+ def test_update_port_add_additional_ip(self): -+ pass -+ -+ def test_requested_duplicate_mac(self): -+ pass -+ -+ def test_mac_generation(self): -+ pass -+ -+ def test_mac_generation_4octet(self): -+ pass -+ -+ def test_bad_mac_format(self): -+ pass -+ -+ def test_mac_exhaustion(self): -+ pass -+ -+ def test_requested_duplicate_ip(self): -+ pass -+ -+ def test_requested_subnet_delete(self): -+ pass -+ -+ def test_requested_subnet_id(self): -+ pass -+ -+ def test_requested_subnet_id_not_on_network(self): -+ pass -+ -+ def test_overlapping_subnets(self): -+ pass -+ -+ def test_requested_subnet_id_v4_and_v6(self): -+ pass -+ -+ def test_range_allocation(self): -+ pass -+ -+ def test_requested_invalid_fixed_ips(self): -+ pass -+ -+ def test_invalid_ip(self): -+ pass -+ -+ def test_requested_split(self): -+ pass -+ -+ def test_duplicate_ips(self): -+ pass -+ -+ def test_fixed_ip_invalid_subnet_id(self): -+ pass -+ -+ def test_fixed_ip_invalid_ip(self): -+ pass -+ -+ def test_requested_ips_only(self): -+ pass -+ -+ def test_recycling(self): -+ pass -+ -+ def test_invalid_admin_state(self): -+ pass -+ -+ def test_invalid_mac_address(self): -+ pass -+ -+ def test_default_allocation_expiration(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration(self): -+ pass -+ -+ def test_port_delete_holds_ip(self): -+ pass -+ -+ def test_update_fixed_ip_lease_expiration_invalid_address(self): -+ pass -+ -+ def test_hold_ip_address(self): -+ pass -+ -+ def test_recycle_held_ip_address(self): -+ pass -+ -+ def test_recycle_expired_previously_run_within_context(self): -+ pass -+ -+ def test_update_port_not_admin(self): -+ pass -+ -+ def test_list_ports_with_pagination_emulated(self): -+ pass -+ -+ def test_list_ports_with_pagination_reverse_emulated(self): -+ pass -+ -+ def test_list_ports_with_sort_emulated(self): -+ pass -+ -+ def test_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_update_max_fixed_ips_exceeded(self): -+ pass -+ -+ def test_recycle_ip_address_without_allocation_pool(self): -+ pass -+ -+ def test_recycle_ip_address_on_exhausted_allocation_pool(self): -+ pass -+ -+ def test_recycle_ip_address_outside_allocation_pool(self): -+ pass -+ -+ def test_recycle_ip_address_in_allocation_pool(self): -+ pass -diff --git setup.cfg setup.cfg -index bae3ffd..6c2ea4f 100644 ---- setup.cfg -+++ setup.cfg -@@ -63,6 +63,7 @@ data_files = - etc/neutron/plugins/openvswitch = etc/neutron/plugins/openvswitch/ovs_neutron_plugin.ini - etc/neutron/plugins/plumgrid = etc/neutron/plugins/plumgrid/plumgrid.ini - etc/neutron/plugins/ryu = etc/neutron/plugins/ryu/ryu.ini -+ etc/neutron/plugins/juniper/contrail/ContrailPlugin = etc/neutron/plugins/juniper/contrail/ContrailPlugin.ini - scripts = - bin/quantum-rootwrap - bin/neutron-rootwrap diff --git a/contrail/nova_v3.patch b/contrail/nova_v3.patch deleted file mode 100644 index a766f0afd8..0000000000 --- a/contrail/nova_v3.patch +++ /dev/null @@ -1,3252 +0,0 @@ -diff --git nova/network/model.py nova/network/model.py -index e11bfeb..a004cb4 100644 ---- nova/network/model.py -+++ nova/network/model.py -@@ -38,6 +38,7 @@ VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' - VIF_TYPE_MIDONET = 'midonet' -+VIF_TYPE_CONTRAIL = 'contrail' - VIF_TYPE_OTHER = 'other' - - # Constant for max length of network interface names -diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py -index 0e38345..32ef4bb 100644 ---- nova/virt/libvirt/vif.py -+++ nova/virt/libvirt/vif.py -@@ -312,6 +312,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - - return conf - -+ def get_config_contrail(self, instance, vif, image_meta, -+ inst_type): -+ conf = super(LibvirtGenericVIFDriver, -+ self).get_config(instance, vif, -+ image_meta, inst_type) -+ -+ dev = self.get_vif_devname(vif) -+ designer.set_vif_host_backend_ethernet_config(conf, dev) -+ -+ return conf -+ - def get_config_mlnx_direct(self, instance, vif, image_meta, - inst_type): - conf = super(LibvirtGenericVIFDriver, -@@ -375,6 +386,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - vif, - image_meta, - inst_type) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ return self.get_config_contrail(instance, -+ vif, -+ image_meta, -+ inst_type) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -567,6 +583,31 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except processutils.ProcessExecutionError: - LOG.exception(_("Failed while plugging vif"), instance=instance) - -+ def plug_contrail(self, instance, vif): -+ """Plug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).plug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ iface_id = vif['id'] -+ from nova.virt import netutils -+ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) -+ try: -+ linux_net.create_tap_dev(dev) -+ utils.execute('config_parser', 'create', -+ '--port_id', vif['id'], -+ '--tap_name', dev, -+ '--ip_address', vif['network']['subnets'][0]['ips'][0]['address'], -+ '--instance_id', instance['uuid'], -+ '--vn_id', vif['network']['id'], -+ '--mac_address', vif['address'], -+ '--display_name', instance['display_name'], -+ '--hostname', instance['hostname'], -+ '--host', instance['host'], -+ '--prefix_len', prefix_len) -+ except processutils.ProcessExecutionError: -+ LOG.exception(_("Failed while plugging vif"), instance=instance) -+ - def plug(self, instance, vif): - vif_type = vif['type'] - -@@ -574,7 +615,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - 'vif=%(vif)s'), - {'vif_type': vif_type, 'instance': instance, - 'vif': vif}) -- - if vif_type is None: - raise exception.NovaException( - _("vif_type parameter must be present " -@@ -595,6 +635,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.plug_mlnx_direct(instance, vif) - elif vif_type == network_model.VIF_TYPE_MIDONET: - self.plug_midonet(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ self.plug_contrail(instance, vif) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -746,6 +788,19 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except processutils.ProcessExecutionError: - LOG.exception(_("Failed while unplugging vif"), instance=instance) - -+ def unplug_contrail(self, instance, vif): -+ """Unplug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).unplug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ try: -+ utils.execute('config_parser', 'delete', -+ '--port_id', vif['id']) -+ linux_net.delete_net_dev(dev) -+ except processutils.ProcessExecutionError: -+ LOG.exception(_("Failed while unplugging vif"), instance=instance) -+ - def unplug(self, instance, vif): - vif_type = vif['type'] - -@@ -770,6 +825,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.unplug_ivs(instance, vif) - elif vif_type == network_model.VIF_TYPE_IOVISOR: - self.unplug_iovisor(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_CONTRAIL: -+ self.unplug_contrail(instance, vif) - elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: - self.unplug_mlnx_direct(instance, vif) - elif vif_type == network_model.VIF_TYPE_MIDONET: -diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py -new file mode 100755 -index 0000000..acac9fb ---- /dev/null -+++ plugins/contrail/config_parser.py -@@ -0,0 +1,126 @@ -+#! /usr/bin/env python -+import os -+import sys -+import cgitb -+import argparse -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' -+ -+class ContrailVifDelete(object): -+ def __init__(self, port_id): -+ if os.path.exists(VIF_DIR+port_id): -+ os.remove(VIF_DIR+port_id) -+ #end __init__ -+# end ContrailVifDelete -+ -+class ContrailVifUpdate(object): -+ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, -+ hostname, host, prefix_len): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ self.__update_vif(port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, display_name, -+ hostname, host, prefix_len) -+ -+ # end __init__ -+ -+ def __update_vif(self, port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, -+ display_name, -+ hostname, -+ host, prefix_len): -+ if (port_id and tap_name and -+ ip_address and instance_id and -+ vn_id and mac_address and -+ host and prefix_len): -+ import ConfigParser -+ config = ConfigParser.RawConfigParser() -+ config.add_section('Vif') -+ config.set('Vif', 'port_id', port_id) -+ config.set('Vif', 'tap_name', tap_name) -+ config.set('Vif', 'ip_address', ip_address) -+ config.set('Vif', 'instance_id', instance_id) -+ config.set('Vif', 'vn_id', vn_id) -+ config.set('Vif', 'mac_address', mac_address) -+ config.set('Vif', 'display_name', display_name) -+ config.set('Vif', 'hostname', hostname) -+ config.set('Vif', 'host', host) -+ config.set('Vif', 'prefix_len', prefix_len) -+ with open(VIF_DIR + port_id, 'wb') as configfile: -+ config.write(configfile) -+ -+ # end __update_vif -+# end ContrailVifUpdate -+ -+def update_vif_file(args): -+ if args.which is 'create': -+ if (args.port_id and args.tap_name and -+ args.ip_address and args.instance_id and -+ args.vn_id and args.mac_address and -+ args.host and args.prefix_len): -+ ContrailVifUpdate(args.port_id, args.tap_name, -+ args.ip_address, args.instance_id, -+ args.vn_id, args.mac_address, args.display_name, -+ args.hostname, args.host, args.prefix_len) -+ elif args.which is 'delete': -+ if args.port_id is not None: -+ ContrailVifDelete(args.port_id) -+ -+# end update_vif_file -+ -+def parse_args(args_str): -+ ''' -+ ''' -+ # Source any specified config/ini file -+ # Turn off help, so we all options in response to -h -+ conf_parser = argparse.ArgumentParser(add_help=False) -+ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) -+ parser = argparse.ArgumentParser( -+ # Inherit options from config_parser -+ parents=[conf_parser], -+ # print script description with -h/--help -+ description=__doc__, -+ # Don't mess with format of description -+ formatter_class=argparse.RawDescriptionHelpFormatter, -+ ) -+ #defaults.update(secopts) -+ #defaults.update(ksopts) -+ #parser.set_defaults(**defaults) -+ -+ subparsers = parser.add_subparsers(help='commands') -+ create_parser = subparsers.add_parser('create', help='Create/Modify vif') -+ create_parser.set_defaults(which='create') -+ create_parser.add_argument("--port_id", help = "port id") -+ create_parser.add_argument("--tap_name", help = "tap_name") -+ create_parser.add_argument("--ip_address", help = "ip_address") -+ create_parser.add_argument("--instance_id", help = "instance_id") -+ create_parser.add_argument("--vn_id", help = "vn_id") -+ create_parser.add_argument("--mac_address", help = "mac_address") -+ create_parser.add_argument("--display_name", help = "display_name") -+ create_parser.add_argument("--hostname", help = "hostname") -+ create_parser.add_argument("--host", help = "host") -+ create_parser.add_argument("--prefix_len", help = "prefix_len") -+ delete_parser = subparsers.add_parser('delete', help='Delete vif') -+ delete_parser.set_defaults(which='delete') -+ delete_parser.add_argument("--port_id", help = "port id") -+ print parser.parse_args() -+ args = parser.parse_args(remaining_argv) -+ update_vif_file(args) -+# end parse_args -+ -+def main(args_str=None): -+ if not args_str: -+ args_str = ' '.join(sys.argv[1:]) -+ args = parse_args(args_str) -+# end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py -new file mode 100644 -index 0000000..7d004a0 ---- /dev/null -+++ plugins/contrail/contrail_vif.py -@@ -0,0 +1,298 @@ -+# -+# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. -+# -+ -+""" -+contril vif plug, communicate with contrail agent -+""" -+import os -+import pyinotify -+import sys -+import socket -+import cgitb -+from nova import utils -+from nova import exception -+from nova.openstack.common import log as logging -+from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent -+import gevent -+from gevent import monkey; monkey.patch_time() -+ -+LOG = logging.getLogger(__name__) -+ -+''' -+struct Port { -+ 1:required tuuid port_id, -+ 2:required tuuid instance_id, -+ 3:required string tap_name, -+ 4:required string ip_address, -+ 5:required tuuid vn_id, -+ 6:required string mac_address, -+ 7:optional string display_name, -+ 8:optional string hostname, -+ 9:optional string host; -+ 10: optional byte prefix_len; -+} -+''' -+ -+class ContrailVifPlug(object): -+ "" -+ "" -+ def __init__(self): -+ self._agent_alive = False -+ self._agent_connected = False -+ self._port_dict = {} -+ self._protocol = None -+ self._notifier = None -+ #end __init__ -+ -+ def _agent_connect(self, protocol): -+ # Agent connect for first time -+ if protocol != None: -+ from instance_service import InstanceService -+ service = InstanceService.Client(protocol) -+ return service.Connect() -+ else: -+ return False -+ #end __agent_connect -+ -+ def _keep_alive(self): -+ try: -+ if self._agent_alive == False: -+ self._protocol = self._agent_conn_open() -+ if self._protocol == None: -+ return -+ from instance_service import InstanceService -+ service = InstanceService.Client(self._protocol) -+ aa_latest = service.KeepAliveCheck() -+ if self._agent_alive == False and aa_latest == True: -+ port_l = [v for k, v in self._port_dict.iteritems()] -+ service.AddPort(port_l) -+ self._agent_alive = True -+ return -+ if self._agent_alive == True and aa_latest == False: -+ self._agent_alive = False -+ return -+ except: -+ self._agent_alive = False -+ #end _keep_alive -+ -+ def _agent_conn_open(self): -+ import socket -+ import sys -+ import uuid -+ from thrift.transport import TTransport, TSocket -+ from thrift.transport.TTransport import TTransportException -+ from thrift.protocol import TBinaryProtocol, TProtocol -+ from instance_service import InstanceService -+ from instance_service import ttypes -+ try: -+ socket = TSocket.TSocket("127.0.0.1", 9090) -+ transport = TTransport.TFramedTransport(socket) -+ transport.open() -+ protocol = TBinaryProtocol.TBinaryProtocol(transport) -+ self._agent_connected = self._agent_connect(protocol) -+ return protocol -+ except TTransportException: -+ return None -+ #end _agent_conn_open -+ -+ def get_dev_name(self, iface_id): -+ return "tap" + iface_id[0:11] -+ #end get_dev_name -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _agent_inform_port_add(self, port, port_id): -+ # First add to the port list -+ self._port_dict[port_id] = port -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.AddPort([port]) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_add -+ -+ def _agent_inform_port_delete(self, port_id): -+ # First add to the port list -+ if port_id in self._port_dict: -+ del_port_id = self._port_dict[port_id].port_id -+ del self._port_dict[port_id] -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.DeletePort(del_port_id) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_delete -+ -+ -+#end class ContrailVifPlug -+ -+def launch_interval_looping(contrail_vif_plug): -+ while True: -+ contrail_vif_plug._keep_alive() -+ gevent.sleep(2) -+#end launch_internal_looping -+ -+ -+class ContrailVifDir(ProcessEvent): -+ def __init__(self, contrail_vif, vif_dir): -+ self._create_port_list(contrail_vif, vif_dir) -+ self._contrail_vif_plug = contrail_vif -+ #end __init__ -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _create_port_list(self, contrail_vif, vif_dir): -+ import os -+ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] -+ for f in files: -+ print f -+ file_name = os.path.join(vif_dir, f) -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ contrail_vif._agent_inform_port_add(port, port_id) -+ #end create_port_list -+ -+ def _get_port_info(self, config): -+ import ConfigParser -+ #import pdb; pdb.set_trace() -+ from instance_service import ttypes -+ try: -+ vif = 'Vif' -+ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), -+ self._convert_to_bl(config.get(vif, 'instance_id')), -+ config.get(vif, 'tap_name'), -+ config.get(vif, 'ip_address'), -+ self._convert_to_bl(config.get(vif, 'vn_id')), -+ config.get(vif, 'mac_address'), -+ config.get(vif, 'display_name'), -+ config.get(vif, 'hostname'), -+ config.get(vif, 'host')) -+ #print config.get(vif, 'prefix_len') -+ return port -+ except: -+ return None -+ -+ def _print_port_info(self, config): -+ import ConfigParser -+ try: -+ vif = 'Vif' -+ print config.get(vif, 'port_id') -+ print config.get(vif, 'instance_id') -+ print config.get(vif, 'tap_name') -+ print config.get(vif, 'ip_address') -+ print config.get(vif, 'vn_id') -+ print config.get(vif, 'mac_address') -+ print config.get(vif, 'display_name') -+ print config.get(vif, 'hostname') -+ print config.get(vif, 'host') -+ print config.get(vif, 'prefix_len') -+ except: -+ return -+ #end __print_port_into -+ -+ def _read_port_info_from_file(self, file_name): -+ import ConfigParser -+ config = ConfigParser.ConfigParser() -+ config.read(file_name) -+ self._print_port_info(config) -+ port = self._get_port_info(config) -+ if port is not None: -+ return port, config.get('Vif', 'port_id') -+ else: -+ return None, None -+ #end _read_port_info_from_file -+ -+ def _is_allowed(self, file_name): -+ ret = True -+ if (file_name[0] == '.' or file_name[-1] == '~'): -+ ret = False -+ return ret -+ #end _is_allowed -+ -+ def process_IN_CREATE(self, event): -+ file_name = os.path.join(event.path, event.name) -+ if not self._is_allowed(event.name): -+ return -+ print "Create: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In create: %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ -+ #end process_IN_CREATE -+ -+ def process_IN_DELETE(self, event): -+ if not self._is_allowed(event.name): -+ return -+ print "Remove: %s" % os.path.join(event.path, event.name) -+ file_name = os.path.join(event.path, event.name) -+ #import pdb; pdb.set_trace() -+ if self._is_allowed(event.name): -+ self._contrail_vif_plug._agent_inform_port_delete(event.name) -+ return -+ -+ #end process_IN_DELETE -+ -+ def process_IN_MODIFY(self, event): -+ if not self._is_allowed(event.name): -+ return -+ file_name = os.path.join(event.path, event.name) -+ print "Modify: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In modify %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ #end process_IN_MODIFY -+#end ContrilVifDir -+ -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' -+def contrail_vif_dir_monitor(contrail_vif_plug): -+ #import pdb; pdb.set_trace() -+ wm = WatchManager() -+ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) -+ contrail_vif_plug._notifier = notifier -+ # watched events -+ mask = pyinotify.IN_DELETE | \ -+ pyinotify.IN_CREATE | \ -+ pyinotify.IN_MODIFY | \ -+ pyinotify.IN_ISDIR -+ wm.add_watch(VIF_DIR, mask, quiet=False) -+ notifier.start() -+#end contrail_vif_dir_monitor -+ -+def main(args_str = None): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ contrail_vif_plug = ContrailVifPlug() -+ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) -+ #import pdb; pdb.set_trace() -+ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) -+ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) -+#end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote -new file mode 100644 -index 0000000..76626d4 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService-remote -@@ -0,0 +1,165 @@ -+#!/usr/bin/env python -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+import sys -+import pprint -+from urlparse import urlparse -+from thrift.transport import TTransport -+from thrift.transport import TSocket -+from thrift.transport import THttpClient -+from thrift.protocol import TBinaryProtocol -+ -+import InstanceService -+from ttypes import * -+ -+if len(sys.argv) <= 1 or sys.argv[1] == '--help': -+ print '' -+ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' -+ print '' -+ print 'Functions:' -+ print ' bool AddPort(PortList port_list)' -+ print ' bool KeepAliveCheck()' -+ print ' bool Connect()' -+ print ' bool DeletePort(tuuid port_id)' -+ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' -+ print ' bool AddHostRoute(string ip_address, string vrf_name)' -+ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' -+ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool CreateVrf(string vrf_name)' -+ print '' -+ sys.exit(0) -+ -+pp = pprint.PrettyPrinter(indent = 2) -+host = 'localhost' -+port = 9090 -+uri = '' -+framed = False -+http = False -+argi = 1 -+ -+if sys.argv[argi] == '-h': -+ parts = sys.argv[argi+1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ argi += 2 -+ -+if sys.argv[argi] == '-u': -+ url = urlparse(sys.argv[argi+1]) -+ parts = url[1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ else: -+ port = 80 -+ uri = url[2] -+ if url[4]: -+ uri += '?%s' % url[4] -+ http = True -+ argi += 2 -+ -+if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': -+ framed = True -+ argi += 1 -+ -+cmd = sys.argv[argi] -+args = sys.argv[argi+1:] -+ -+if http: -+ transport = THttpClient.THttpClient(host, port, uri) -+else: -+ socket = TSocket.TSocket(host, port) -+ if framed: -+ transport = TTransport.TFramedTransport(socket) -+ else: -+ transport = TTransport.TBufferedTransport(socket) -+protocol = TBinaryProtocol.TBinaryProtocol(transport) -+client = InstanceService.Client(protocol) -+transport.open() -+ -+if cmd == 'AddPort': -+ if len(args) != 1: -+ print 'AddPort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.AddPort(eval(args[0]),)) -+ -+elif cmd == 'KeepAliveCheck': -+ if len(args) != 0: -+ print 'KeepAliveCheck requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.KeepAliveCheck()) -+ -+elif cmd == 'Connect': -+ if len(args) != 0: -+ print 'Connect requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.Connect()) -+ -+elif cmd == 'DeletePort': -+ if len(args) != 1: -+ print 'DeletePort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.DeletePort(eval(args[0]),)) -+ -+elif cmd == 'TunnelNHEntryAdd': -+ if len(args) != 3: -+ print 'TunnelNHEntryAdd requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) -+ -+elif cmd == 'TunnelNHEntryDelete': -+ if len(args) != 3: -+ print 'TunnelNHEntryDelete requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) -+ -+elif cmd == 'RouteEntryAdd': -+ if len(args) != 4: -+ print 'RouteEntryAdd requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'RouteEntryDelete': -+ if len(args) != 2: -+ print 'RouteEntryDelete requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) -+ -+elif cmd == 'AddHostRoute': -+ if len(args) != 2: -+ print 'AddHostRoute requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.AddHostRoute(args[0],args[1],)) -+ -+elif cmd == 'AddLocalVmRoute': -+ if len(args) != 4: -+ print 'AddLocalVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'AddRemoteVmRoute': -+ if len(args) != 4: -+ print 'AddRemoteVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'CreateVrf': -+ if len(args) != 1: -+ print 'CreateVrf requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.CreateVrf(args[0],)) -+ -+else: -+ print 'Unrecognized method %s' % cmd -+ sys.exit(1) -+ -+transport.close() -diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py -new file mode 100644 -index 0000000..2219045 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService.py -@@ -0,0 +1,2275 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+from thrift.Thrift import TProcessor -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+class Iface: -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ pass -+ -+ def KeepAliveCheck(self, ): -+ pass -+ -+ def Connect(self, ): -+ pass -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ pass -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ pass -+ -+ -+class Client(Iface): -+ def __init__(self, iprot, oprot=None): -+ self._iprot = self._oprot = iprot -+ if oprot is not None: -+ self._oprot = oprot -+ self._seqid = 0 -+ -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ self.send_AddPort(port_list) -+ return self.recv_AddPort() -+ -+ def send_AddPort(self, port_list): -+ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) -+ args = AddPort_args() -+ args.port_list = port_list -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddPort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddPort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); -+ -+ def KeepAliveCheck(self, ): -+ self.send_KeepAliveCheck() -+ return self.recv_KeepAliveCheck() -+ -+ def send_KeepAliveCheck(self, ): -+ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) -+ args = KeepAliveCheck_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_KeepAliveCheck(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = KeepAliveCheck_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); -+ -+ def Connect(self, ): -+ self.send_Connect() -+ return self.recv_Connect() -+ -+ def send_Connect(self, ): -+ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) -+ args = Connect_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_Connect(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = Connect_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ self.send_DeletePort(port_id) -+ return self.recv_DeletePort() -+ -+ def send_DeletePort(self, port_id): -+ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) -+ args = DeletePort_args() -+ args.port_id = port_id -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_DeletePort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = DeletePort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryAdd() -+ -+ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryAdd_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryDelete() -+ -+ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryDelete_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) -+ return self.recv_RouteEntryAdd() -+ -+ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) -+ args = RouteEntryAdd_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_RouteEntryDelete(ip_address, vrf_name) -+ return self.recv_RouteEntryDelete() -+ -+ def send_RouteEntryDelete(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) -+ args = RouteEntryDelete_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_AddHostRoute(ip_address, vrf_name) -+ return self.recv_AddHostRoute() -+ -+ def send_AddHostRoute(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) -+ args = AddHostRoute_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddHostRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddHostRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) -+ return self.recv_AddLocalVmRoute() -+ -+ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) -+ args = AddLocalVmRoute_args() -+ args.ip_address = ip_address -+ args.intf_uuid = intf_uuid -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddLocalVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddLocalVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) -+ return self.recv_AddRemoteVmRoute() -+ -+ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) -+ args = AddRemoteVmRoute_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddRemoteVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddRemoteVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ self.send_CreateVrf(vrf_name) -+ return self.recv_CreateVrf() -+ -+ def send_CreateVrf(self, vrf_name): -+ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) -+ args = CreateVrf_args() -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_CreateVrf(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = CreateVrf_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); -+ -+ -+class Processor(Iface, TProcessor): -+ def __init__(self, handler): -+ self._handler = handler -+ self._processMap = {} -+ self._processMap["AddPort"] = Processor.process_AddPort -+ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck -+ self._processMap["Connect"] = Processor.process_Connect -+ self._processMap["DeletePort"] = Processor.process_DeletePort -+ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd -+ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete -+ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd -+ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete -+ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute -+ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute -+ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute -+ self._processMap["CreateVrf"] = Processor.process_CreateVrf -+ -+ def process(self, iprot, oprot): -+ (name, type, seqid) = iprot.readMessageBegin() -+ if name not in self._processMap: -+ iprot.skip(TType.STRUCT) -+ iprot.readMessageEnd() -+ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) -+ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) -+ x.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ return -+ else: -+ self._processMap[name](self, seqid, iprot, oprot) -+ return True -+ -+ def process_AddPort(self, seqid, iprot, oprot): -+ args = AddPort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddPort_result() -+ result.success = self._handler.AddPort(args.port_list) -+ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_KeepAliveCheck(self, seqid, iprot, oprot): -+ args = KeepAliveCheck_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = KeepAliveCheck_result() -+ result.success = self._handler.KeepAliveCheck() -+ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_Connect(self, seqid, iprot, oprot): -+ args = Connect_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = Connect_result() -+ result.success = self._handler.Connect() -+ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_DeletePort(self, seqid, iprot, oprot): -+ args = DeletePort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = DeletePort_result() -+ result.success = self._handler.DeletePort(args.port_id) -+ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): -+ args = TunnelNHEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryAdd_result() -+ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): -+ args = TunnelNHEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryDelete_result() -+ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryAdd(self, seqid, iprot, oprot): -+ args = RouteEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryAdd_result() -+ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryDelete(self, seqid, iprot, oprot): -+ args = RouteEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryDelete_result() -+ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddHostRoute(self, seqid, iprot, oprot): -+ args = AddHostRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddHostRoute_result() -+ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddLocalVmRoute(self, seqid, iprot, oprot): -+ args = AddLocalVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddLocalVmRoute_result() -+ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): -+ args = AddRemoteVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddRemoteVmRoute_result() -+ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_CreateVrf(self, seqid, iprot, oprot): -+ args = CreateVrf_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = CreateVrf_result() -+ result.success = self._handler.CreateVrf(args.vrf_name) -+ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ -+# HELPER FUNCTIONS AND STRUCTURES -+ -+class AddPort_args: -+ """ -+ Attributes: -+ - port_list -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_list=None,): -+ self.port_list = port_list -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_list = [] -+ (_etype24, _size21) = iprot.readListBegin() -+ for _i25 in xrange(_size21): -+ _elem26 = Port() -+ _elem26.read(iprot) -+ self.port_list.append(_elem26) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_args') -+ if self.port_list is not None: -+ oprot.writeFieldBegin('port_list', TType.LIST, -1) -+ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) -+ for iter27 in self.port_list: -+ iter27.write(oprot) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddPort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_args: -+ """ -+ Attributes: -+ - port_id -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_id=None,): -+ self.port_id = port_id -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype31, _size28) = iprot.readListBegin() -+ for _i32 in xrange(_size28): -+ _elem33 = iprot.readI16(); -+ self.port_id.append(_elem33) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_args') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, -1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter34 in self.port_id: -+ oprot.writeI16(iter34) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.intf_uuid = intf_uuid -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.intf_uuid = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.intf_uuid is not None: -+ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) -+ oprot.writeString(self.intf_uuid) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.intf_uuid is None: -+ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_args: -+ """ -+ Attributes: -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'vrf_name', None, None, ), # 1 -+ ) -+ -+ def __init__(self, vrf_name=None,): -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_args') -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py -new file mode 100644 -index 0000000..f34ead4 ---- /dev/null -+++ plugins/contrail/instance_service/__init__.py -@@ -0,0 +1 @@ -+__all__ = ['ttypes', 'constants', 'InstanceService'] -diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py -new file mode 100644 -index 0000000..73f07fe ---- /dev/null -+++ plugins/contrail/instance_service/constants.py -@@ -0,0 +1,11 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+ -diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py -new file mode 100644 -index 0000000..564f82e ---- /dev/null -+++ plugins/contrail/instance_service/ttypes.py -@@ -0,0 +1,210 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+ -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+ -+class Port: -+ """ -+ Attributes: -+ - port_id -+ - instance_id -+ - tap_name -+ - ip_address -+ - vn_id -+ - mac_address -+ - display_name -+ - hostname -+ - host -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 -+ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 -+ (3, TType.STRING, 'tap_name', None, None, ), # 3 -+ (4, TType.STRING, 'ip_address', None, None, ), # 4 -+ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 -+ (6, TType.STRING, 'mac_address', None, None, ), # 6 -+ (7, TType.STRING, 'display_name', None, None, ), # 7 -+ (8, TType.STRING, 'hostname', None, None, ), # 8 -+ (9, TType.STRING, 'host', None, None, ), # 9 -+ ) -+ -+ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): -+ self.port_id = port_id -+ self.instance_id = instance_id -+ self.tap_name = tap_name -+ self.ip_address = ip_address -+ self.vn_id = vn_id -+ self.mac_address = mac_address -+ self.display_name = display_name -+ self.hostname = hostname -+ self.host = host -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype3, _size0) = iprot.readListBegin() -+ for _i4 in xrange(_size0): -+ _elem5 = iprot.readI16(); -+ self.port_id.append(_elem5) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.LIST: -+ self.instance_id = [] -+ (_etype9, _size6) = iprot.readListBegin() -+ for _i10 in xrange(_size6): -+ _elem11 = iprot.readI16(); -+ self.instance_id.append(_elem11) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.tap_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 5: -+ if ftype == TType.LIST: -+ self.vn_id = [] -+ (_etype15, _size12) = iprot.readListBegin() -+ for _i16 in xrange(_size12): -+ _elem17 = iprot.readI16(); -+ self.vn_id.append(_elem17) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 6: -+ if ftype == TType.STRING: -+ self.mac_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 7: -+ if ftype == TType.STRING: -+ self.display_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 8: -+ if ftype == TType.STRING: -+ self.hostname = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 9: -+ if ftype == TType.STRING: -+ self.host = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Port') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, 1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter18 in self.port_id: -+ oprot.writeI16(iter18) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.instance_id is not None: -+ oprot.writeFieldBegin('instance_id', TType.LIST, 2) -+ oprot.writeListBegin(TType.I16, len(self.instance_id)) -+ for iter19 in self.instance_id: -+ oprot.writeI16(iter19) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.tap_name is not None: -+ oprot.writeFieldBegin('tap_name', TType.STRING, 3) -+ oprot.writeString(self.tap_name) -+ oprot.writeFieldEnd() -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 4) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vn_id is not None: -+ oprot.writeFieldBegin('vn_id', TType.LIST, 5) -+ oprot.writeListBegin(TType.I16, len(self.vn_id)) -+ for iter20 in self.vn_id: -+ oprot.writeI16(iter20) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.mac_address is not None: -+ oprot.writeFieldBegin('mac_address', TType.STRING, 6) -+ oprot.writeString(self.mac_address) -+ oprot.writeFieldEnd() -+ if self.display_name is not None: -+ oprot.writeFieldBegin('display_name', TType.STRING, 7) -+ oprot.writeString(self.display_name) -+ oprot.writeFieldEnd() -+ if self.hostname is not None: -+ oprot.writeFieldBegin('hostname', TType.STRING, 8) -+ oprot.writeString(self.hostname) -+ oprot.writeFieldEnd() -+ if self.host is not None: -+ oprot.writeFieldBegin('host', TType.STRING, 9) -+ oprot.writeString(self.host) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.port_id is None: -+ raise TProtocol.TProtocolException(message='Required field port_id is unset!') -+ if self.instance_id is None: -+ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') -+ if self.tap_name is None: -+ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vn_id is None: -+ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') -+ if self.mac_address is None: -+ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) diff --git a/contrail/nova_v4.patch b/contrail/nova_v4.patch deleted file mode 100644 index 93716cb3a7..0000000000 --- a/contrail/nova_v4.patch +++ /dev/null @@ -1,3252 +0,0 @@ -diff --git nova/network/model.py nova/network/model.py -index 9a543a3..cf5f56d 100644 ---- nova/network/model.py -+++ nova/network/model.py -@@ -39,6 +39,7 @@ VIF_TYPE_802_QBG = '802.1qbg' - VIF_TYPE_802_QBH = '802.1qbh' - VIF_TYPE_MLNX_DIRECT = 'mlnx_direct' - VIF_TYPE_MIDONET = 'midonet' -+VIF_TYPE_VROUTER = 'vrouter' - VIF_TYPE_OTHER = 'other' - - # Constant for max length of network interface names -diff --git nova/virt/libvirt/vif.py nova/virt/libvirt/vif.py -index cfff8dd..0a51783 100644 ---- nova/virt/libvirt/vif.py -+++ nova/virt/libvirt/vif.py -@@ -309,6 +309,17 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - - return conf - -+ def get_config_contrail(self, instance, vif, image_meta, -+ inst_type): -+ conf = super(LibvirtGenericVIFDriver, -+ self).get_config(instance, vif, -+ image_meta, inst_type) -+ -+ dev = self.get_vif_devname(vif) -+ designer.set_vif_host_backend_ethernet_config(conf, dev) -+ -+ return conf -+ - def get_config_mlnx_direct(self, instance, vif, image_meta, - inst_type): - conf = super(LibvirtGenericVIFDriver, -@@ -372,6 +383,11 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - vif, - image_meta, - inst_type) -+ elif vif_type == network_model.VIF_TYPE_VROUTER: -+ return self.get_config_contrail(instance, -+ vif, -+ image_meta, -+ inst_type) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -564,6 +580,31 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except processutils.ProcessExecutionError: - LOG.exception(_("Failed while plugging vif"), instance=instance) - -+ def plug_contrail(self, instance, vif): -+ """Plug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).plug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ iface_id = vif['id'] -+ from nova.virt import netutils -+ net, prefix_len=netutils.get_net_and_prefixlen(vif['network']['subnets'][0]['cidr']) -+ try: -+ linux_net.create_tap_dev(dev) -+ utils.execute('config_parser', 'create', -+ '--port_id', vif['id'], -+ '--tap_name', dev, -+ '--ip_address', vif['network']['subnets'][0]['ips'][0]['address'], -+ '--instance_id', instance['uuid'], -+ '--vn_id', vif['network']['id'], -+ '--mac_address', vif['address'], -+ '--display_name', instance['display_name'], -+ '--hostname', instance['hostname'], -+ '--host', instance['host'], -+ '--prefix_len', prefix_len) -+ except processutils.ProcessExecutionError: -+ LOG.exception(_("Failed while plugging vif"), instance=instance) -+ - def plug(self, instance, vif): - vif_type = vif['type'] - -@@ -571,7 +612,6 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - 'vif=%(vif)s'), - {'vif_type': vif_type, 'instance': instance, - 'vif': vif}) -- - if vif_type is None: - raise exception.NovaException( - _("vif_type parameter must be present " -@@ -592,6 +632,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.plug_mlnx_direct(instance, vif) - elif vif_type == network_model.VIF_TYPE_MIDONET: - self.plug_midonet(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_VROUTER: -+ self.plug_contrail(instance, vif) - else: - raise exception.NovaException( - _("Unexpected vif_type=%s") % vif_type) -@@ -746,6 +788,19 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - except processutils.ProcessExecutionError: - LOG.exception(_("Failed while unplugging vif"), instance=instance) - -+ def unplug_contrail(self, instance, vif): -+ """Unplug using Contrail Driver -+ """ -+ super(LibvirtGenericVIFDriver, -+ self).unplug(instance, vif) -+ dev = self.get_vif_devname(vif) -+ try: -+ utils.execute('config_parser', 'delete', -+ '--port_id', vif['id']) -+ linux_net.delete_net_dev(dev) -+ except processutils.ProcessExecutionError: -+ LOG.exception(_("Failed while unplugging vif"), instance=instance) -+ - def unplug(self, instance, vif): - vif_type = vif['type'] - -@@ -770,6 +825,8 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver): - self.unplug_ivs(instance, vif) - elif vif_type == network_model.VIF_TYPE_IOVISOR: - self.unplug_iovisor(instance, vif) -+ elif vif_type == network_model.VIF_TYPE_VROUTER: -+ self.unplug_contrail(instance, vif) - elif vif_type == network_model.VIF_TYPE_MLNX_DIRECT: - self.unplug_mlnx_direct(instance, vif) - elif vif_type == network_model.VIF_TYPE_MIDONET: -diff --git plugins/contrail/config_parser.py plugins/contrail/config_parser.py -new file mode 100755 -index 0000000..acac9fb ---- /dev/null -+++ plugins/contrail/config_parser.py -@@ -0,0 +1,126 @@ -+#! /usr/bin/env python -+import os -+import sys -+import cgitb -+import argparse -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif/' -+ -+class ContrailVifDelete(object): -+ def __init__(self, port_id): -+ if os.path.exists(VIF_DIR+port_id): -+ os.remove(VIF_DIR+port_id) -+ #end __init__ -+# end ContrailVifDelete -+ -+class ContrailVifUpdate(object): -+ def __init__(self, port_id, tap_name, ip_address, instance_id, vn_id, mac_address, display_name, -+ hostname, host, prefix_len): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ self.__update_vif(port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, display_name, -+ hostname, host, prefix_len) -+ -+ # end __init__ -+ -+ def __update_vif(self, port_id, tap_name, -+ ip_address, instance_id, -+ vn_id, mac_address, -+ display_name, -+ hostname, -+ host, prefix_len): -+ if (port_id and tap_name and -+ ip_address and instance_id and -+ vn_id and mac_address and -+ host and prefix_len): -+ import ConfigParser -+ config = ConfigParser.RawConfigParser() -+ config.add_section('Vif') -+ config.set('Vif', 'port_id', port_id) -+ config.set('Vif', 'tap_name', tap_name) -+ config.set('Vif', 'ip_address', ip_address) -+ config.set('Vif', 'instance_id', instance_id) -+ config.set('Vif', 'vn_id', vn_id) -+ config.set('Vif', 'mac_address', mac_address) -+ config.set('Vif', 'display_name', display_name) -+ config.set('Vif', 'hostname', hostname) -+ config.set('Vif', 'host', host) -+ config.set('Vif', 'prefix_len', prefix_len) -+ with open(VIF_DIR + port_id, 'wb') as configfile: -+ config.write(configfile) -+ -+ # end __update_vif -+# end ContrailVifUpdate -+ -+def update_vif_file(args): -+ if args.which is 'create': -+ if (args.port_id and args.tap_name and -+ args.ip_address and args.instance_id and -+ args.vn_id and args.mac_address and -+ args.host and args.prefix_len): -+ ContrailVifUpdate(args.port_id, args.tap_name, -+ args.ip_address, args.instance_id, -+ args.vn_id, args.mac_address, args.display_name, -+ args.hostname, args.host, args.prefix_len) -+ elif args.which is 'delete': -+ if args.port_id is not None: -+ ContrailVifDelete(args.port_id) -+ -+# end update_vif_file -+ -+def parse_args(args_str): -+ ''' -+ ''' -+ # Source any specified config/ini file -+ # Turn off help, so we all options in response to -h -+ conf_parser = argparse.ArgumentParser(add_help=False) -+ args, remaining_argv = conf_parser.parse_known_args(args_str.split()) -+ parser = argparse.ArgumentParser( -+ # Inherit options from config_parser -+ parents=[conf_parser], -+ # print script description with -h/--help -+ description=__doc__, -+ # Don't mess with format of description -+ formatter_class=argparse.RawDescriptionHelpFormatter, -+ ) -+ #defaults.update(secopts) -+ #defaults.update(ksopts) -+ #parser.set_defaults(**defaults) -+ -+ subparsers = parser.add_subparsers(help='commands') -+ create_parser = subparsers.add_parser('create', help='Create/Modify vif') -+ create_parser.set_defaults(which='create') -+ create_parser.add_argument("--port_id", help = "port id") -+ create_parser.add_argument("--tap_name", help = "tap_name") -+ create_parser.add_argument("--ip_address", help = "ip_address") -+ create_parser.add_argument("--instance_id", help = "instance_id") -+ create_parser.add_argument("--vn_id", help = "vn_id") -+ create_parser.add_argument("--mac_address", help = "mac_address") -+ create_parser.add_argument("--display_name", help = "display_name") -+ create_parser.add_argument("--hostname", help = "hostname") -+ create_parser.add_argument("--host", help = "host") -+ create_parser.add_argument("--prefix_len", help = "prefix_len") -+ delete_parser = subparsers.add_parser('delete', help='Delete vif') -+ delete_parser.set_defaults(which='delete') -+ delete_parser.add_argument("--port_id", help = "port id") -+ print parser.parse_args() -+ args = parser.parse_args(remaining_argv) -+ update_vif_file(args) -+# end parse_args -+ -+def main(args_str=None): -+ if not args_str: -+ args_str = ' '.join(sys.argv[1:]) -+ args = parse_args(args_str) -+# end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/contrail_vif.py plugins/contrail/contrail_vif.py -new file mode 100644 -index 0000000..7d004a0 ---- /dev/null -+++ plugins/contrail/contrail_vif.py -@@ -0,0 +1,298 @@ -+# -+# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. -+# -+ -+""" -+contril vif plug, communicate with contrail agent -+""" -+import os -+import pyinotify -+import sys -+import socket -+import cgitb -+from nova import utils -+from nova import exception -+from nova.openstack.common import log as logging -+from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent -+import gevent -+from gevent import monkey; monkey.patch_time() -+ -+LOG = logging.getLogger(__name__) -+ -+''' -+struct Port { -+ 1:required tuuid port_id, -+ 2:required tuuid instance_id, -+ 3:required string tap_name, -+ 4:required string ip_address, -+ 5:required tuuid vn_id, -+ 6:required string mac_address, -+ 7:optional string display_name, -+ 8:optional string hostname, -+ 9:optional string host; -+ 10: optional byte prefix_len; -+} -+''' -+ -+class ContrailVifPlug(object): -+ "" -+ "" -+ def __init__(self): -+ self._agent_alive = False -+ self._agent_connected = False -+ self._port_dict = {} -+ self._protocol = None -+ self._notifier = None -+ #end __init__ -+ -+ def _agent_connect(self, protocol): -+ # Agent connect for first time -+ if protocol != None: -+ from instance_service import InstanceService -+ service = InstanceService.Client(protocol) -+ return service.Connect() -+ else: -+ return False -+ #end __agent_connect -+ -+ def _keep_alive(self): -+ try: -+ if self._agent_alive == False: -+ self._protocol = self._agent_conn_open() -+ if self._protocol == None: -+ return -+ from instance_service import InstanceService -+ service = InstanceService.Client(self._protocol) -+ aa_latest = service.KeepAliveCheck() -+ if self._agent_alive == False and aa_latest == True: -+ port_l = [v for k, v in self._port_dict.iteritems()] -+ service.AddPort(port_l) -+ self._agent_alive = True -+ return -+ if self._agent_alive == True and aa_latest == False: -+ self._agent_alive = False -+ return -+ except: -+ self._agent_alive = False -+ #end _keep_alive -+ -+ def _agent_conn_open(self): -+ import socket -+ import sys -+ import uuid -+ from thrift.transport import TTransport, TSocket -+ from thrift.transport.TTransport import TTransportException -+ from thrift.protocol import TBinaryProtocol, TProtocol -+ from instance_service import InstanceService -+ from instance_service import ttypes -+ try: -+ socket = TSocket.TSocket("127.0.0.1", 9090) -+ transport = TTransport.TFramedTransport(socket) -+ transport.open() -+ protocol = TBinaryProtocol.TBinaryProtocol(transport) -+ self._agent_connected = self._agent_connect(protocol) -+ return protocol -+ except TTransportException: -+ return None -+ #end _agent_conn_open -+ -+ def get_dev_name(self, iface_id): -+ return "tap" + iface_id[0:11] -+ #end get_dev_name -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _agent_inform_port_add(self, port, port_id): -+ # First add to the port list -+ self._port_dict[port_id] = port -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.AddPort([port]) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_add -+ -+ def _agent_inform_port_delete(self, port_id): -+ # First add to the port list -+ if port_id in self._port_dict: -+ del_port_id = self._port_dict[port_id].port_id -+ del self._port_dict[port_id] -+ if not self._agent_alive: -+ return -+ from instance_service import InstanceService -+ import socket -+ try: -+ service = InstanceService.Client(self._protocol) -+ service.DeletePort(del_port_id) -+ except: -+ self._agent_alive = False -+ #end _agent_inform_port_delete -+ -+ -+#end class ContrailVifPlug -+ -+def launch_interval_looping(contrail_vif_plug): -+ while True: -+ contrail_vif_plug._keep_alive() -+ gevent.sleep(2) -+#end launch_internal_looping -+ -+ -+class ContrailVifDir(ProcessEvent): -+ def __init__(self, contrail_vif, vif_dir): -+ self._create_port_list(contrail_vif, vif_dir) -+ self._contrail_vif_plug = contrail_vif -+ #end __init__ -+ -+ def _convert_to_bl(self, id): -+ import uuid -+ hexstr = uuid.UUID(id).hex -+ return [int(hexstr[i:i+2], 16) for i in range(32) if i%2 == 0] -+ #end _convert_to_bl -+ -+ def _create_port_list(self, contrail_vif, vif_dir): -+ import os -+ files = [f for f in os.listdir(vif_dir) if os.path.isfile(os.path.join(vif_dir,f))] -+ for f in files: -+ print f -+ file_name = os.path.join(vif_dir, f) -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ contrail_vif._agent_inform_port_add(port, port_id) -+ #end create_port_list -+ -+ def _get_port_info(self, config): -+ import ConfigParser -+ #import pdb; pdb.set_trace() -+ from instance_service import ttypes -+ try: -+ vif = 'Vif' -+ port = ttypes.Port(self._convert_to_bl(config.get(vif, 'port_id')), -+ self._convert_to_bl(config.get(vif, 'instance_id')), -+ config.get(vif, 'tap_name'), -+ config.get(vif, 'ip_address'), -+ self._convert_to_bl(config.get(vif, 'vn_id')), -+ config.get(vif, 'mac_address'), -+ config.get(vif, 'display_name'), -+ config.get(vif, 'hostname'), -+ config.get(vif, 'host')) -+ #print config.get(vif, 'prefix_len') -+ return port -+ except: -+ return None -+ -+ def _print_port_info(self, config): -+ import ConfigParser -+ try: -+ vif = 'Vif' -+ print config.get(vif, 'port_id') -+ print config.get(vif, 'instance_id') -+ print config.get(vif, 'tap_name') -+ print config.get(vif, 'ip_address') -+ print config.get(vif, 'vn_id') -+ print config.get(vif, 'mac_address') -+ print config.get(vif, 'display_name') -+ print config.get(vif, 'hostname') -+ print config.get(vif, 'host') -+ print config.get(vif, 'prefix_len') -+ except: -+ return -+ #end __print_port_into -+ -+ def _read_port_info_from_file(self, file_name): -+ import ConfigParser -+ config = ConfigParser.ConfigParser() -+ config.read(file_name) -+ self._print_port_info(config) -+ port = self._get_port_info(config) -+ if port is not None: -+ return port, config.get('Vif', 'port_id') -+ else: -+ return None, None -+ #end _read_port_info_from_file -+ -+ def _is_allowed(self, file_name): -+ ret = True -+ if (file_name[0] == '.' or file_name[-1] == '~'): -+ ret = False -+ return ret -+ #end _is_allowed -+ -+ def process_IN_CREATE(self, event): -+ file_name = os.path.join(event.path, event.name) -+ if not self._is_allowed(event.name): -+ return -+ print "Create: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In create: %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ -+ #end process_IN_CREATE -+ -+ def process_IN_DELETE(self, event): -+ if not self._is_allowed(event.name): -+ return -+ print "Remove: %s" % os.path.join(event.path, event.name) -+ file_name = os.path.join(event.path, event.name) -+ #import pdb; pdb.set_trace() -+ if self._is_allowed(event.name): -+ self._contrail_vif_plug._agent_inform_port_delete(event.name) -+ return -+ -+ #end process_IN_DELETE -+ -+ def process_IN_MODIFY(self, event): -+ if not self._is_allowed(event.name): -+ return -+ file_name = os.path.join(event.path, event.name) -+ print "Modify: %s" % file_name -+ port, port_id = self._read_port_info_from_file(file_name) -+ if port is not None: -+ print "In modify %s" % port.tap_name -+ self._contrail_vif_plug._agent_inform_port_add(port, port_id) -+ #end process_IN_MODIFY -+#end ContrilVifDir -+ -+ -+VIF_DIR = '/opt/stack/nova/plugins/contrail/vif' -+def contrail_vif_dir_monitor(contrail_vif_plug): -+ #import pdb; pdb.set_trace() -+ wm = WatchManager() -+ notifier = pyinotify.ThreadedNotifier(wm, ContrailVifDir(contrail_vif_plug, VIF_DIR)) -+ contrail_vif_plug._notifier = notifier -+ # watched events -+ mask = pyinotify.IN_DELETE | \ -+ pyinotify.IN_CREATE | \ -+ pyinotify.IN_MODIFY | \ -+ pyinotify.IN_ISDIR -+ wm.add_watch(VIF_DIR, mask, quiet=False) -+ notifier.start() -+#end contrail_vif_dir_monitor -+ -+def main(args_str = None): -+ try: -+ os.makedirs(VIF_DIR) -+ except OSError: -+ if os.path.exists(VIF_DIR): -+ pass -+ else: -+ raise -+ contrail_vif_plug = ContrailVifPlug() -+ contrail_vif_dir_monitor_task = gevent.spawn(contrail_vif_dir_monitor, contrail_vif_plug) -+ #import pdb; pdb.set_trace() -+ contrail_timer_task = gevent.spawn(launch_interval_looping, contrail_vif_plug) -+ gevent.joinall([contrail_timer_task, contrail_vif_dir_monitor_task]) -+#end main -+ -+if __name__ == '__main__': -+ cgitb.enable(format='text') -+ main() -diff --git plugins/contrail/instance_service/InstanceService-remote plugins/contrail/instance_service/InstanceService-remote -new file mode 100644 -index 0000000..76626d4 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService-remote -@@ -0,0 +1,165 @@ -+#!/usr/bin/env python -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+import sys -+import pprint -+from urlparse import urlparse -+from thrift.transport import TTransport -+from thrift.transport import TSocket -+from thrift.transport import THttpClient -+from thrift.protocol import TBinaryProtocol -+ -+import InstanceService -+from ttypes import * -+ -+if len(sys.argv) <= 1 or sys.argv[1] == '--help': -+ print '' -+ print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]' -+ print '' -+ print 'Functions:' -+ print ' bool AddPort(PortList port_list)' -+ print ' bool KeepAliveCheck()' -+ print ' bool Connect()' -+ print ' bool DeletePort(tuuid port_id)' -+ print ' bool TunnelNHEntryAdd(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool TunnelNHEntryDelete(string src_ip, string dst_ip, string vrf_name)' -+ print ' bool RouteEntryAdd(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool RouteEntryDelete(string ip_address, string vrf_name)' -+ print ' bool AddHostRoute(string ip_address, string vrf_name)' -+ print ' bool AddLocalVmRoute(string ip_address, string intf_uuid, string vrf_name, string label)' -+ print ' bool AddRemoteVmRoute(string ip_address, string gw_ip, string vrf_name, string label)' -+ print ' bool CreateVrf(string vrf_name)' -+ print '' -+ sys.exit(0) -+ -+pp = pprint.PrettyPrinter(indent = 2) -+host = 'localhost' -+port = 9090 -+uri = '' -+framed = False -+http = False -+argi = 1 -+ -+if sys.argv[argi] == '-h': -+ parts = sys.argv[argi+1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ argi += 2 -+ -+if sys.argv[argi] == '-u': -+ url = urlparse(sys.argv[argi+1]) -+ parts = url[1].split(':') -+ host = parts[0] -+ if len(parts) > 1: -+ port = int(parts[1]) -+ else: -+ port = 80 -+ uri = url[2] -+ if url[4]: -+ uri += '?%s' % url[4] -+ http = True -+ argi += 2 -+ -+if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': -+ framed = True -+ argi += 1 -+ -+cmd = sys.argv[argi] -+args = sys.argv[argi+1:] -+ -+if http: -+ transport = THttpClient.THttpClient(host, port, uri) -+else: -+ socket = TSocket.TSocket(host, port) -+ if framed: -+ transport = TTransport.TFramedTransport(socket) -+ else: -+ transport = TTransport.TBufferedTransport(socket) -+protocol = TBinaryProtocol.TBinaryProtocol(transport) -+client = InstanceService.Client(protocol) -+transport.open() -+ -+if cmd == 'AddPort': -+ if len(args) != 1: -+ print 'AddPort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.AddPort(eval(args[0]),)) -+ -+elif cmd == 'KeepAliveCheck': -+ if len(args) != 0: -+ print 'KeepAliveCheck requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.KeepAliveCheck()) -+ -+elif cmd == 'Connect': -+ if len(args) != 0: -+ print 'Connect requires 0 args' -+ sys.exit(1) -+ pp.pprint(client.Connect()) -+ -+elif cmd == 'DeletePort': -+ if len(args) != 1: -+ print 'DeletePort requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.DeletePort(eval(args[0]),)) -+ -+elif cmd == 'TunnelNHEntryAdd': -+ if len(args) != 3: -+ print 'TunnelNHEntryAdd requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryAdd(args[0],args[1],args[2],)) -+ -+elif cmd == 'TunnelNHEntryDelete': -+ if len(args) != 3: -+ print 'TunnelNHEntryDelete requires 3 args' -+ sys.exit(1) -+ pp.pprint(client.TunnelNHEntryDelete(args[0],args[1],args[2],)) -+ -+elif cmd == 'RouteEntryAdd': -+ if len(args) != 4: -+ print 'RouteEntryAdd requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryAdd(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'RouteEntryDelete': -+ if len(args) != 2: -+ print 'RouteEntryDelete requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.RouteEntryDelete(args[0],args[1],)) -+ -+elif cmd == 'AddHostRoute': -+ if len(args) != 2: -+ print 'AddHostRoute requires 2 args' -+ sys.exit(1) -+ pp.pprint(client.AddHostRoute(args[0],args[1],)) -+ -+elif cmd == 'AddLocalVmRoute': -+ if len(args) != 4: -+ print 'AddLocalVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddLocalVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'AddRemoteVmRoute': -+ if len(args) != 4: -+ print 'AddRemoteVmRoute requires 4 args' -+ sys.exit(1) -+ pp.pprint(client.AddRemoteVmRoute(args[0],args[1],args[2],args[3],)) -+ -+elif cmd == 'CreateVrf': -+ if len(args) != 1: -+ print 'CreateVrf requires 1 args' -+ sys.exit(1) -+ pp.pprint(client.CreateVrf(args[0],)) -+ -+else: -+ print 'Unrecognized method %s' % cmd -+ sys.exit(1) -+ -+transport.close() -diff --git plugins/contrail/instance_service/InstanceService.py plugins/contrail/instance_service/InstanceService.py -new file mode 100644 -index 0000000..2219045 ---- /dev/null -+++ plugins/contrail/instance_service/InstanceService.py -@@ -0,0 +1,2275 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+from thrift.Thrift import TProcessor -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+class Iface: -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ pass -+ -+ def KeepAliveCheck(self, ): -+ pass -+ -+ def Connect(self, ): -+ pass -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ pass -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ pass -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ pass -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ pass -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ pass -+ -+ -+class Client(Iface): -+ def __init__(self, iprot, oprot=None): -+ self._iprot = self._oprot = iprot -+ if oprot is not None: -+ self._oprot = oprot -+ self._seqid = 0 -+ -+ def AddPort(self, port_list): -+ """ -+ Parameters: -+ - port_list -+ """ -+ self.send_AddPort(port_list) -+ return self.recv_AddPort() -+ -+ def send_AddPort(self, port_list): -+ self._oprot.writeMessageBegin('AddPort', TMessageType.CALL, self._seqid) -+ args = AddPort_args() -+ args.port_list = port_list -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddPort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddPort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddPort failed: unknown result"); -+ -+ def KeepAliveCheck(self, ): -+ self.send_KeepAliveCheck() -+ return self.recv_KeepAliveCheck() -+ -+ def send_KeepAliveCheck(self, ): -+ self._oprot.writeMessageBegin('KeepAliveCheck', TMessageType.CALL, self._seqid) -+ args = KeepAliveCheck_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_KeepAliveCheck(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = KeepAliveCheck_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "KeepAliveCheck failed: unknown result"); -+ -+ def Connect(self, ): -+ self.send_Connect() -+ return self.recv_Connect() -+ -+ def send_Connect(self, ): -+ self._oprot.writeMessageBegin('Connect', TMessageType.CALL, self._seqid) -+ args = Connect_args() -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_Connect(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = Connect_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "Connect failed: unknown result"); -+ -+ def DeletePort(self, port_id): -+ """ -+ Parameters: -+ - port_id -+ """ -+ self.send_DeletePort(port_id) -+ return self.recv_DeletePort() -+ -+ def send_DeletePort(self, port_id): -+ self._oprot.writeMessageBegin('DeletePort', TMessageType.CALL, self._seqid) -+ args = DeletePort_args() -+ args.port_id = port_id -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_DeletePort(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = DeletePort_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "DeletePort failed: unknown result"); -+ -+ def TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryAdd(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryAdd() -+ -+ def send_TunnelNHEntryAdd(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryAdd', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryAdd_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryAdd failed: unknown result"); -+ -+ def TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ """ -+ Parameters: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ self.send_TunnelNHEntryDelete(src_ip, dst_ip, vrf_name) -+ return self.recv_TunnelNHEntryDelete() -+ -+ def send_TunnelNHEntryDelete(self, src_ip, dst_ip, vrf_name): -+ self._oprot.writeMessageBegin('TunnelNHEntryDelete', TMessageType.CALL, self._seqid) -+ args = TunnelNHEntryDelete_args() -+ args.src_ip = src_ip -+ args.dst_ip = dst_ip -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_TunnelNHEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = TunnelNHEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "TunnelNHEntryDelete failed: unknown result"); -+ -+ def RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_RouteEntryAdd(ip_address, gw_ip, vrf_name, label) -+ return self.recv_RouteEntryAdd() -+ -+ def send_RouteEntryAdd(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('RouteEntryAdd', TMessageType.CALL, self._seqid) -+ args = RouteEntryAdd_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryAdd(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryAdd_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryAdd failed: unknown result"); -+ -+ def RouteEntryDelete(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_RouteEntryDelete(ip_address, vrf_name) -+ return self.recv_RouteEntryDelete() -+ -+ def send_RouteEntryDelete(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('RouteEntryDelete', TMessageType.CALL, self._seqid) -+ args = RouteEntryDelete_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_RouteEntryDelete(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = RouteEntryDelete_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "RouteEntryDelete failed: unknown result"); -+ -+ def AddHostRoute(self, ip_address, vrf_name): -+ """ -+ Parameters: -+ - ip_address -+ - vrf_name -+ """ -+ self.send_AddHostRoute(ip_address, vrf_name) -+ return self.recv_AddHostRoute() -+ -+ def send_AddHostRoute(self, ip_address, vrf_name): -+ self._oprot.writeMessageBegin('AddHostRoute', TMessageType.CALL, self._seqid) -+ args = AddHostRoute_args() -+ args.ip_address = ip_address -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddHostRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddHostRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddHostRoute failed: unknown result"); -+ -+ def AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ self.send_AddLocalVmRoute(ip_address, intf_uuid, vrf_name, label) -+ return self.recv_AddLocalVmRoute() -+ -+ def send_AddLocalVmRoute(self, ip_address, intf_uuid, vrf_name, label): -+ self._oprot.writeMessageBegin('AddLocalVmRoute', TMessageType.CALL, self._seqid) -+ args = AddLocalVmRoute_args() -+ args.ip_address = ip_address -+ args.intf_uuid = intf_uuid -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddLocalVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddLocalVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddLocalVmRoute failed: unknown result"); -+ -+ def AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ """ -+ Parameters: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ self.send_AddRemoteVmRoute(ip_address, gw_ip, vrf_name, label) -+ return self.recv_AddRemoteVmRoute() -+ -+ def send_AddRemoteVmRoute(self, ip_address, gw_ip, vrf_name, label): -+ self._oprot.writeMessageBegin('AddRemoteVmRoute', TMessageType.CALL, self._seqid) -+ args = AddRemoteVmRoute_args() -+ args.ip_address = ip_address -+ args.gw_ip = gw_ip -+ args.vrf_name = vrf_name -+ args.label = label -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_AddRemoteVmRoute(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = AddRemoteVmRoute_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "AddRemoteVmRoute failed: unknown result"); -+ -+ def CreateVrf(self, vrf_name): -+ """ -+ Parameters: -+ - vrf_name -+ """ -+ self.send_CreateVrf(vrf_name) -+ return self.recv_CreateVrf() -+ -+ def send_CreateVrf(self, vrf_name): -+ self._oprot.writeMessageBegin('CreateVrf', TMessageType.CALL, self._seqid) -+ args = CreateVrf_args() -+ args.vrf_name = vrf_name -+ args.write(self._oprot) -+ self._oprot.writeMessageEnd() -+ self._oprot.trans.flush() -+ -+ def recv_CreateVrf(self, ): -+ (fname, mtype, rseqid) = self._iprot.readMessageBegin() -+ if mtype == TMessageType.EXCEPTION: -+ x = TApplicationException() -+ x.read(self._iprot) -+ self._iprot.readMessageEnd() -+ raise x -+ result = CreateVrf_result() -+ result.read(self._iprot) -+ self._iprot.readMessageEnd() -+ if result.success is not None: -+ return result.success -+ raise TApplicationException(TApplicationException.MISSING_RESULT, "CreateVrf failed: unknown result"); -+ -+ -+class Processor(Iface, TProcessor): -+ def __init__(self, handler): -+ self._handler = handler -+ self._processMap = {} -+ self._processMap["AddPort"] = Processor.process_AddPort -+ self._processMap["KeepAliveCheck"] = Processor.process_KeepAliveCheck -+ self._processMap["Connect"] = Processor.process_Connect -+ self._processMap["DeletePort"] = Processor.process_DeletePort -+ self._processMap["TunnelNHEntryAdd"] = Processor.process_TunnelNHEntryAdd -+ self._processMap["TunnelNHEntryDelete"] = Processor.process_TunnelNHEntryDelete -+ self._processMap["RouteEntryAdd"] = Processor.process_RouteEntryAdd -+ self._processMap["RouteEntryDelete"] = Processor.process_RouteEntryDelete -+ self._processMap["AddHostRoute"] = Processor.process_AddHostRoute -+ self._processMap["AddLocalVmRoute"] = Processor.process_AddLocalVmRoute -+ self._processMap["AddRemoteVmRoute"] = Processor.process_AddRemoteVmRoute -+ self._processMap["CreateVrf"] = Processor.process_CreateVrf -+ -+ def process(self, iprot, oprot): -+ (name, type, seqid) = iprot.readMessageBegin() -+ if name not in self._processMap: -+ iprot.skip(TType.STRUCT) -+ iprot.readMessageEnd() -+ x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) -+ oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) -+ x.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ return -+ else: -+ self._processMap[name](self, seqid, iprot, oprot) -+ return True -+ -+ def process_AddPort(self, seqid, iprot, oprot): -+ args = AddPort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddPort_result() -+ result.success = self._handler.AddPort(args.port_list) -+ oprot.writeMessageBegin("AddPort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_KeepAliveCheck(self, seqid, iprot, oprot): -+ args = KeepAliveCheck_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = KeepAliveCheck_result() -+ result.success = self._handler.KeepAliveCheck() -+ oprot.writeMessageBegin("KeepAliveCheck", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_Connect(self, seqid, iprot, oprot): -+ args = Connect_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = Connect_result() -+ result.success = self._handler.Connect() -+ oprot.writeMessageBegin("Connect", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_DeletePort(self, seqid, iprot, oprot): -+ args = DeletePort_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = DeletePort_result() -+ result.success = self._handler.DeletePort(args.port_id) -+ oprot.writeMessageBegin("DeletePort", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryAdd(self, seqid, iprot, oprot): -+ args = TunnelNHEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryAdd_result() -+ result.success = self._handler.TunnelNHEntryAdd(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_TunnelNHEntryDelete(self, seqid, iprot, oprot): -+ args = TunnelNHEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = TunnelNHEntryDelete_result() -+ result.success = self._handler.TunnelNHEntryDelete(args.src_ip, args.dst_ip, args.vrf_name) -+ oprot.writeMessageBegin("TunnelNHEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryAdd(self, seqid, iprot, oprot): -+ args = RouteEntryAdd_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryAdd_result() -+ result.success = self._handler.RouteEntryAdd(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("RouteEntryAdd", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_RouteEntryDelete(self, seqid, iprot, oprot): -+ args = RouteEntryDelete_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = RouteEntryDelete_result() -+ result.success = self._handler.RouteEntryDelete(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("RouteEntryDelete", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddHostRoute(self, seqid, iprot, oprot): -+ args = AddHostRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddHostRoute_result() -+ result.success = self._handler.AddHostRoute(args.ip_address, args.vrf_name) -+ oprot.writeMessageBegin("AddHostRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddLocalVmRoute(self, seqid, iprot, oprot): -+ args = AddLocalVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddLocalVmRoute_result() -+ result.success = self._handler.AddLocalVmRoute(args.ip_address, args.intf_uuid, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddLocalVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_AddRemoteVmRoute(self, seqid, iprot, oprot): -+ args = AddRemoteVmRoute_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = AddRemoteVmRoute_result() -+ result.success = self._handler.AddRemoteVmRoute(args.ip_address, args.gw_ip, args.vrf_name, args.label) -+ oprot.writeMessageBegin("AddRemoteVmRoute", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ def process_CreateVrf(self, seqid, iprot, oprot): -+ args = CreateVrf_args() -+ args.read(iprot) -+ iprot.readMessageEnd() -+ result = CreateVrf_result() -+ result.success = self._handler.CreateVrf(args.vrf_name) -+ oprot.writeMessageBegin("CreateVrf", TMessageType.REPLY, seqid) -+ result.write(oprot) -+ oprot.writeMessageEnd() -+ oprot.trans.flush() -+ -+ -+# HELPER FUNCTIONS AND STRUCTURES -+ -+class AddPort_args: -+ """ -+ Attributes: -+ - port_list -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_list=None,): -+ self.port_list = port_list -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_list = [] -+ (_etype24, _size21) = iprot.readListBegin() -+ for _i25 in xrange(_size21): -+ _elem26 = Port() -+ _elem26.read(iprot) -+ self.port_list.append(_elem26) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_args') -+ if self.port_list is not None: -+ oprot.writeFieldBegin('port_list', TType.LIST, -1) -+ oprot.writeListBegin(TType.STRUCT, len(self.port_list)) -+ for iter27 in self.port_list: -+ iter27.write(oprot) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddPort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddPort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class KeepAliveCheck_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('KeepAliveCheck_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_args: -+ -+ thrift_spec = ( -+ ) -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_args') -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class Connect_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Connect_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_args: -+ """ -+ Attributes: -+ - port_id -+ """ -+ -+ thrift_spec = None -+ def __init__(self, port_id=None,): -+ self.port_id = port_id -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == -1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype31, _size28) = iprot.readListBegin() -+ for _i32 in xrange(_size28): -+ _elem33 = iprot.readI16(); -+ self.port_id.append(_elem33) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_args') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, -1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter34 in self.port_id: -+ oprot.writeI16(iter34) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class DeletePort_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('DeletePort_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_args: -+ """ -+ Attributes: -+ - src_ip -+ - dst_ip -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'src_ip', None, None, ), # 1 -+ (2, TType.STRING, 'dst_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ ) -+ -+ def __init__(self, src_ip=None, dst_ip=None, vrf_name=None,): -+ self.src_ip = src_ip -+ self.dst_ip = dst_ip -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.src_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.dst_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_args') -+ if self.src_ip is not None: -+ oprot.writeFieldBegin('src_ip', TType.STRING, 1) -+ oprot.writeString(self.src_ip) -+ oprot.writeFieldEnd() -+ if self.dst_ip is not None: -+ oprot.writeFieldBegin('dst_ip', TType.STRING, 2) -+ oprot.writeString(self.dst_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.src_ip is None: -+ raise TProtocol.TProtocolException(message='Required field src_ip is unset!') -+ if self.dst_ip is None: -+ raise TProtocol.TProtocolException(message='Required field dst_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class TunnelNHEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('TunnelNHEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryAdd_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryAdd_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class RouteEntryDelete_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('RouteEntryDelete_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'vrf_name', None, None, ), # 2 -+ ) -+ -+ def __init__(self, ip_address=None, vrf_name=None,): -+ self.ip_address = ip_address -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 2) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddHostRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddHostRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - intf_uuid -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'intf_uuid', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, intf_uuid=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.intf_uuid = intf_uuid -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.intf_uuid = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.intf_uuid is not None: -+ oprot.writeFieldBegin('intf_uuid', TType.STRING, 2) -+ oprot.writeString(self.intf_uuid) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.intf_uuid is None: -+ raise TProtocol.TProtocolException(message='Required field intf_uuid is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddLocalVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddLocalVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_args: -+ """ -+ Attributes: -+ - ip_address -+ - gw_ip -+ - vrf_name -+ - label -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'ip_address', None, None, ), # 1 -+ (2, TType.STRING, 'gw_ip', None, None, ), # 2 -+ (3, TType.STRING, 'vrf_name', None, None, ), # 3 -+ (4, TType.STRING, 'label', None, None, ), # 4 -+ ) -+ -+ def __init__(self, ip_address=None, gw_ip=None, vrf_name=None, label=None,): -+ self.ip_address = ip_address -+ self.gw_ip = gw_ip -+ self.vrf_name = vrf_name -+ self.label = label -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.STRING: -+ self.gw_ip = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.label = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_args') -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 1) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.gw_ip is not None: -+ oprot.writeFieldBegin('gw_ip', TType.STRING, 2) -+ oprot.writeString(self.gw_ip) -+ oprot.writeFieldEnd() -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 3) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ if self.label is not None: -+ oprot.writeFieldBegin('label', TType.STRING, 4) -+ oprot.writeString(self.label) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.gw_ip is None: -+ raise TProtocol.TProtocolException(message='Required field gw_ip is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class AddRemoteVmRoute_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('AddRemoteVmRoute_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_args: -+ """ -+ Attributes: -+ - vrf_name -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.STRING, 'vrf_name', None, None, ), # 1 -+ ) -+ -+ def __init__(self, vrf_name=None,): -+ self.vrf_name = vrf_name -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.STRING: -+ self.vrf_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_args') -+ if self.vrf_name is not None: -+ oprot.writeFieldBegin('vrf_name', TType.STRING, 1) -+ oprot.writeString(self.vrf_name) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.vrf_name is None: -+ raise TProtocol.TProtocolException(message='Required field vrf_name is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -+ -+class CreateVrf_result: -+ """ -+ Attributes: -+ - success -+ """ -+ -+ thrift_spec = ( -+ (0, TType.BOOL, 'success', None, None, ), # 0 -+ ) -+ -+ def __init__(self, success=None,): -+ self.success = success -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 0: -+ if ftype == TType.BOOL: -+ self.success = iprot.readBool(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('CreateVrf_result') -+ if self.success is not None: -+ oprot.writeFieldBegin('success', TType.BOOL, 0) -+ oprot.writeBool(self.success) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) -diff --git plugins/contrail/instance_service/__init__.py plugins/contrail/instance_service/__init__.py -new file mode 100644 -index 0000000..f34ead4 ---- /dev/null -+++ plugins/contrail/instance_service/__init__.py -@@ -0,0 +1 @@ -+__all__ = ['ttypes', 'constants', 'InstanceService'] -diff --git plugins/contrail/instance_service/constants.py plugins/contrail/instance_service/constants.py -new file mode 100644 -index 0000000..73f07fe ---- /dev/null -+++ plugins/contrail/instance_service/constants.py -@@ -0,0 +1,11 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+from ttypes import * -+ -diff --git plugins/contrail/instance_service/ttypes.py plugins/contrail/instance_service/ttypes.py -new file mode 100644 -index 0000000..564f82e ---- /dev/null -+++ plugins/contrail/instance_service/ttypes.py -@@ -0,0 +1,210 @@ -+# -+# Autogenerated by Thrift Compiler (0.8.0) -+# -+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING -+# -+# options string: py -+# -+ -+from thrift.Thrift import TType, TMessageType, TException -+ -+from thrift.transport import TTransport -+from thrift.protocol import TBinaryProtocol, TProtocol -+try: -+ from thrift.protocol import fastbinary -+except: -+ fastbinary = None -+ -+ -+ -+class Port: -+ """ -+ Attributes: -+ - port_id -+ - instance_id -+ - tap_name -+ - ip_address -+ - vn_id -+ - mac_address -+ - display_name -+ - hostname -+ - host -+ """ -+ -+ thrift_spec = ( -+ None, # 0 -+ (1, TType.LIST, 'port_id', (TType.I16,None), None, ), # 1 -+ (2, TType.LIST, 'instance_id', (TType.I16,None), None, ), # 2 -+ (3, TType.STRING, 'tap_name', None, None, ), # 3 -+ (4, TType.STRING, 'ip_address', None, None, ), # 4 -+ (5, TType.LIST, 'vn_id', (TType.I16,None), None, ), # 5 -+ (6, TType.STRING, 'mac_address', None, None, ), # 6 -+ (7, TType.STRING, 'display_name', None, None, ), # 7 -+ (8, TType.STRING, 'hostname', None, None, ), # 8 -+ (9, TType.STRING, 'host', None, None, ), # 9 -+ ) -+ -+ def __init__(self, port_id=None, instance_id=None, tap_name=None, ip_address=None, vn_id=None, mac_address=None, display_name=None, hostname=None, host=None,): -+ self.port_id = port_id -+ self.instance_id = instance_id -+ self.tap_name = tap_name -+ self.ip_address = ip_address -+ self.vn_id = vn_id -+ self.mac_address = mac_address -+ self.display_name = display_name -+ self.hostname = hostname -+ self.host = host -+ -+ def read(self, iprot): -+ if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: -+ fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) -+ return -+ iprot.readStructBegin() -+ while True: -+ (fname, ftype, fid) = iprot.readFieldBegin() -+ if ftype == TType.STOP: -+ break -+ if fid == 1: -+ if ftype == TType.LIST: -+ self.port_id = [] -+ (_etype3, _size0) = iprot.readListBegin() -+ for _i4 in xrange(_size0): -+ _elem5 = iprot.readI16(); -+ self.port_id.append(_elem5) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 2: -+ if ftype == TType.LIST: -+ self.instance_id = [] -+ (_etype9, _size6) = iprot.readListBegin() -+ for _i10 in xrange(_size6): -+ _elem11 = iprot.readI16(); -+ self.instance_id.append(_elem11) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 3: -+ if ftype == TType.STRING: -+ self.tap_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 4: -+ if ftype == TType.STRING: -+ self.ip_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 5: -+ if ftype == TType.LIST: -+ self.vn_id = [] -+ (_etype15, _size12) = iprot.readListBegin() -+ for _i16 in xrange(_size12): -+ _elem17 = iprot.readI16(); -+ self.vn_id.append(_elem17) -+ iprot.readListEnd() -+ else: -+ iprot.skip(ftype) -+ elif fid == 6: -+ if ftype == TType.STRING: -+ self.mac_address = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 7: -+ if ftype == TType.STRING: -+ self.display_name = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 8: -+ if ftype == TType.STRING: -+ self.hostname = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ elif fid == 9: -+ if ftype == TType.STRING: -+ self.host = iprot.readString(); -+ else: -+ iprot.skip(ftype) -+ else: -+ iprot.skip(ftype) -+ iprot.readFieldEnd() -+ iprot.readStructEnd() -+ -+ def write(self, oprot): -+ if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: -+ oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) -+ return -+ oprot.writeStructBegin('Port') -+ if self.port_id is not None: -+ oprot.writeFieldBegin('port_id', TType.LIST, 1) -+ oprot.writeListBegin(TType.I16, len(self.port_id)) -+ for iter18 in self.port_id: -+ oprot.writeI16(iter18) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.instance_id is not None: -+ oprot.writeFieldBegin('instance_id', TType.LIST, 2) -+ oprot.writeListBegin(TType.I16, len(self.instance_id)) -+ for iter19 in self.instance_id: -+ oprot.writeI16(iter19) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.tap_name is not None: -+ oprot.writeFieldBegin('tap_name', TType.STRING, 3) -+ oprot.writeString(self.tap_name) -+ oprot.writeFieldEnd() -+ if self.ip_address is not None: -+ oprot.writeFieldBegin('ip_address', TType.STRING, 4) -+ oprot.writeString(self.ip_address) -+ oprot.writeFieldEnd() -+ if self.vn_id is not None: -+ oprot.writeFieldBegin('vn_id', TType.LIST, 5) -+ oprot.writeListBegin(TType.I16, len(self.vn_id)) -+ for iter20 in self.vn_id: -+ oprot.writeI16(iter20) -+ oprot.writeListEnd() -+ oprot.writeFieldEnd() -+ if self.mac_address is not None: -+ oprot.writeFieldBegin('mac_address', TType.STRING, 6) -+ oprot.writeString(self.mac_address) -+ oprot.writeFieldEnd() -+ if self.display_name is not None: -+ oprot.writeFieldBegin('display_name', TType.STRING, 7) -+ oprot.writeString(self.display_name) -+ oprot.writeFieldEnd() -+ if self.hostname is not None: -+ oprot.writeFieldBegin('hostname', TType.STRING, 8) -+ oprot.writeString(self.hostname) -+ oprot.writeFieldEnd() -+ if self.host is not None: -+ oprot.writeFieldBegin('host', TType.STRING, 9) -+ oprot.writeString(self.host) -+ oprot.writeFieldEnd() -+ oprot.writeFieldStop() -+ oprot.writeStructEnd() -+ -+ def validate(self): -+ if self.port_id is None: -+ raise TProtocol.TProtocolException(message='Required field port_id is unset!') -+ if self.instance_id is None: -+ raise TProtocol.TProtocolException(message='Required field instance_id is unset!') -+ if self.tap_name is None: -+ raise TProtocol.TProtocolException(message='Required field tap_name is unset!') -+ if self.ip_address is None: -+ raise TProtocol.TProtocolException(message='Required field ip_address is unset!') -+ if self.vn_id is None: -+ raise TProtocol.TProtocolException(message='Required field vn_id is unset!') -+ if self.mac_address is None: -+ raise TProtocol.TProtocolException(message='Required field mac_address is unset!') -+ return -+ -+ -+ def __repr__(self): -+ L = ['%s=%r' % (key, value) -+ for key, value in self.__dict__.iteritems()] -+ return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) -+ -+ def __eq__(self, other): -+ return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ -+ -+ def __ne__(self, other): -+ return not (self == other) diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index 8c97520e4b..ac51d06599 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -18,10 +18,11 @@ function neutron_plugin_configure_common() { Q_PLUGIN_CONF_PATH=etc/neutron/plugins/juniper/contrail Q_PLUGIN_CONF_FILENAME=ContrailPlugin.ini Q_DB_NAME="contrail_neutron" - Q_PLUGIN_CLASS="neutron.plugins.juniper.contrail.contrailplugin.ContrailPlugin" + Q_PLUGIN_CLASS="neutron_plugin_contrail.plugins.opencontrail.contrailplugin.ContrailPlugin" } function neutron_plugin_configure_service() { + iniset $NEUTRON_CONF DEFAULT api_extensions_path $DEST/contrail/openstack/neutron_plugin/neutron_plugin_contrail/extensions/ iniset $NEUTRON_CONF quotas quota_driver neutron.quota.ConfDriver } diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index fbe4e87474..ddcbec3c94 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -102,9 +102,8 @@ function install_contrail() { # install VIF driver sudo pip install $CONTRAIL_SRC/build/noarch/nova_contrail_vif/dist/nova_contrail_vif*.tar.gz - - # install neutron patch after VNC api is built and installed - # test_install_neutron_patch + # install Neutron OpenContrail plugin + sudo pip install -e $CONTRAIL_SRC/openstack/neutron_plugin/ # get cassandra if ! which cassandra > /dev/null 2>&1 ; then @@ -235,18 +234,6 @@ function apply_patch() { fi } -function test_install_neutron_patch() { - apply_patch $TOP_DIR/contrail/neutron_v4.patch $DEST/neutron -} - -function test_install_nova_patch() { - apply_patch $TOP_DIR/contrail/nova_v4.patch $DEST/nova - if [ -e $DEST/nova/plugins/contrail/config_parser.py ]; then - sudo cp $DEST/nova/plugins/contrail/config_parser.py /usr/bin/config_parser - sudo chmod +x /usr/bin/config_parser - fi -} - # take over physical interface function insert_vrouter() { source /etc/contrail/agent_param From c16de55de5cfaa38020e5cfbbb789fd482e89ec9 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 5 Jun 2014 21:15:45 +0000 Subject: [PATCH 159/179] Update neutron config based on modular plugin --- contrail/contrail_config_templates.py | 1 + lib/neutron_plugins/contrail | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 845833a262..031091d4f5 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -40,6 +40,7 @@ api_server_ip = $__contrail_api_server_ip__ api_server_port = $__contrail_api_server_port__ multi_tenancy = $__contrail_multi_tenancy__ +contrail_extensions = ipam:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_ipam.NeutronPluginContrailIpam,policy:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_policy.NeutronPluginContrailPolicy,route-table:neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_vpc.NeutronPluginContrailVpc [KEYSTONE] ;auth_url = http://$__contrail_keystone_ip__:35357/v2.0 diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index ac51d06599..774e39e355 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -18,7 +18,7 @@ function neutron_plugin_configure_common() { Q_PLUGIN_CONF_PATH=etc/neutron/plugins/juniper/contrail Q_PLUGIN_CONF_FILENAME=ContrailPlugin.ini Q_DB_NAME="contrail_neutron" - Q_PLUGIN_CLASS="neutron_plugin_contrail.plugins.opencontrail.contrailplugin.ContrailPlugin" + Q_PLUGIN_CLASS="neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_core.NeutronPluginContrailCoreV2" } function neutron_plugin_configure_service() { From 32313078eea0070e71cd4e535200fd0575cffcfd Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 5 Jun 2014 22:03:50 +0000 Subject: [PATCH 160/179] VIF create now needs xconnect option --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index fe54c325b0..9a72a421c7 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -255,7 +255,7 @@ function insert_vrouter() { || echo "Error creating interface: $DEVICE" echo "Adding $DEVICE to vrouter" - sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --mode x --type vhost \ + sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --xconnect $dev --mode x --type vhost \ || echo "Error adding $DEVICE to vrouter" echo "Adding $dev to vrouter" From 05144ea07bfa1d47eedceb886e07b454f48e506b Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Sat, 7 Jun 2014 18:32:08 +0000 Subject: [PATCH 161/179] Add knob to skip sync/build --- contrail/localrc-single | 3 +++ lib/neutron_thirdparty/contrail | 9 ++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index 8384f9c7e3..d427886a6d 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -57,3 +57,6 @@ NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver CASS_MAX_HEAP_SIZE=1G CASS_HEAP_NEWSIZE=200M + +# set CONTRAIL_REPO_SKIP_SYNC to avoid sync and build +# CONTRAIL_REPO_SKIP_SYNC=yes diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 9a72a421c7..90cb29dbe2 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -86,14 +86,13 @@ function install_contrail() { fi fi - # If CONTRAIL_REPO_SETUP_SKIP is not set, sync the repo. - if [ -z $CONTRAIL_REPO_SYNC_SKIP ]; then + # If CONTRAIL_REPO_SKIP_SYNC is not set, sync the repo. + if [ -z $CONTRAIL_REPO_SKIP_SYNC ]; then repo sync python third_party/fetch_packages.py + (cd third_party/thrift-*; touch configure.ac README ChangeLog; autoreconf --force --install) + scons fi - - (cd third_party/thrift-*; touch configure.ac README ChangeLog; autoreconf --force --install) - scons cd ${contrail_cwd} # install contrail modules From c17d96fc05a75796069886e31d8659d9f460fa9d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 9 Jun 2014 16:57:19 +0000 Subject: [PATCH 162/179] Support using frozen contrail bits with devstack --- contrail/localrc-single | 3 +++ lib/neutron_thirdparty/contrail | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/contrail/localrc-single b/contrail/localrc-single index d427886a6d..16ccfd1cf9 100644 --- a/contrail/localrc-single +++ b/contrail/localrc-single @@ -60,3 +60,6 @@ CASS_HEAP_NEWSIZE=200M # set CONTRAIL_REPO_SKIP_SYNC to avoid sync and build # CONTRAIL_REPO_SKIP_SYNC=yes + +# uncomment to use specific contrail bits instead of t-o-t +# CONTRAIL_REPO=devstack.xml diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index c70086daee..bb30609473 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -70,6 +70,7 @@ function install_contrail() { sudo pip install kazoo pyinotify sudo pip install bottle + CONTRAIL_REPO=${CONTRAIL_REPO:-default.xml} CONTRAIL_REPO_PROTO=${CONTRAIL_REPO_PROTO:-ssh} CONTRAIL_SRC=${CONTRAIL_SRC:-/opt/stack/contrail} mkdir -p $CONTRAIL_SRC/third_party @@ -79,9 +80,9 @@ function install_contrail() { git config --global --get user.name || git config --global user.name "Anonymous" git config --global --get user.email || git config --global user.email "anonymous@nowhere.com" if [ "$CONTRAIL_REPO_PROTO" == "ssh" ]; then - repo init -u git@github.com:Juniper/contrail-vnc + repo init -u git@github.com:Juniper/contrail-vnc -m $CONTRAIL_REPO else - repo init -u https://github.com/Juniper/contrail-vnc + repo init -u https://github.com/Juniper/contrail-vnc -m $CONTRAIL_REPO sed -i 's/fetch=".."/fetch=\"https:\/\/github.com\/Juniper\/\"/' .repo/manifest.xml fi fi From 2cc1185b2974d0ac11574d08d81ad54967260295 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Mon, 9 Jun 2014 22:28:04 +0000 Subject: [PATCH 163/179] fix error in creating ifmap user + syntax error --- contrail/setup_contrail.py | 9 ++------- lib/neutron_thirdparty/contrail | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 888b9fa982..efd2a70f02 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -706,15 +706,10 @@ def fixup_config_files(self): self.run_shell("echo 'api-server:api-server' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'schema-transformer:schema-transformer' >> %s/basicauthusers.properties" % dir) self.run_shell("echo 'svc-monitor:svc-monitor' >> %s/basicauthusers.properties" % dir) - self.run_shell("sudo sed -e '/%s:/d' -e '/%s.dns:/d' %s/%s | sudo tee %s/%s.new > /dev/null" \ - %(control_ip, control_ip, dir, 'basicauthusers.properties', - dir, 'basicauthusers.properties')) - self.run_shell("echo '%s:%s' >> %s/%s.new" \ + self.run_shell("echo '%s:%s' >> %s/%s" \ %(control_ip, control_ip, dir, 'basicauthusers.properties')) - self.run_shell("echo '%s.dns:%s.dns' >> %s/%s.new" \ + self.run_shell("echo '%s.dns:%s.dns' >> %s/%s" \ %(control_ip, control_ip, dir, 'basicauthusers.properties')) - self.run_shell("sudo mv %s/%s.new %s/%s" \ - % (dir, 'basicauthusers.properties', dir, 'basicauthusers.properties')) self.run_shell("echo '%s=%s--0000000001-1' >> %s/%s" \ %(control_ip, control_ip, dir, 'publisher.properties')) if self._args.puppet_server: diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index bb30609473..ae0456f91e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -194,7 +194,7 @@ function install_contrail() { cd ${contrail_cwd} fi if ! which node > /dev/null 2>&1 ; then - if [ ! -f node-v0.8.15.tar.gz]; then + if [ ! -f node-v0.8.15.tar.gz ]; then wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz fi tar -xf node-v0.8.15.tar.gz From 0bbbb4425afcd3b71cd50a3a6f2fd9ce89ae5479 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 10 Jun 2014 02:09:09 +0000 Subject: [PATCH 164/179] Avoid downloading node-v0.8.15 again --- lib/neutron_thirdparty/contrail | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index ae0456f91e..f99c901275 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -194,16 +194,18 @@ function install_contrail() { cd ${contrail_cwd} fi if ! which node > /dev/null 2>&1 ; then - if [ ! -f node-v0.8.15.tar.gz ]; then + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC/third_party + if [ ! -d $CONTRAIL_SRC/third_party/node-v0.8.15 ]; then wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + tar -xf node-v0.8.15.tar.gz fi - tar -xf node-v0.8.15.tar.gz - contrail_cwd=$(pwd) cd node-v0.8.15 ./configure; make; sudo make install cd ${contrail_cwd} rm -rf node-v0.8.15.tar.gz rm -rf node-v0.8.15 + cd ${contrail_cwd} fi if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then contrail_cwd=$(pwd) From c66bb72f54576abd70547261839d984b6fd8c1f7 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 10 Jun 2014 20:14:32 +0000 Subject: [PATCH 165/179] Add dependenvy for npm -- some packeges via fetch_packages.py need it --- lib/neutron_thirdparty/contrail | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index f99c901275..e6a9c60c63 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -35,6 +35,7 @@ function install_contrail() { apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities apt_get install libvirt-bin + apt_get install npm if ! which redis-server > /dev/null 2>&1 ; then sudo apt-get install libjemalloc1 @@ -52,6 +53,7 @@ function install_contrail() { sudo yum -y install tunctl sudo yum -y install java-1.7.0-openjdk sudo yum -y install libvirt-bin + sudo yum -y install npm if ! which redis-server > /dev/null 2>&1 ; then wget http://mir01.syntis.net/atomic/fedora/17/x86_64/RPMS/redis-2.6.13-3.fc17.art.x86_64.rpm From 41a7ff539ab9abae0f5891ff42d42fd87659b280 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 11 Jun 2014 16:32:00 +0000 Subject: [PATCH 166/179] Fix npm build --- lib/neutron_thirdparty/contrail | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index e6a9c60c63..b2a2db6500 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -35,7 +35,6 @@ function install_contrail() { apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities apt_get install libvirt-bin - apt_get install npm if ! which redis-server > /dev/null 2>&1 ; then sudo apt-get install libjemalloc1 @@ -53,7 +52,6 @@ function install_contrail() { sudo yum -y install tunctl sudo yum -y install java-1.7.0-openjdk sudo yum -y install libvirt-bin - sudo yum -y install npm if ! which redis-server > /dev/null 2>&1 ; then wget http://mir01.syntis.net/atomic/fedora/17/x86_64/RPMS/redis-2.6.13-3.fc17.art.x86_64.rpm @@ -62,6 +60,18 @@ function install_contrail() { fi fi + # install node which brings npm that's used in fetch_packages.py + if ! which node > /dev/null 2>&1 || ! which npm > /dev/null 2>&1 ; then + wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + tar -xf node-v0.8.15.tar.gz + contrail_cwd=$(pwd) + cd node-v0.8.15 + ./configure; make; sudo make install + cd ${contrail_cwd} + rm -rf node-v0.8.15.tar.gz + rm -rf node-v0.8.15 + fi + # api server requirements # sudo pip install gevent==0.13.8 geventhttpclient==1.0a thrift==0.8.0 # sudo easy_install -U distribute @@ -195,20 +205,6 @@ function install_contrail() { sudo python setup.py install cd ${contrail_cwd} fi - if ! which node > /dev/null 2>&1 ; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/third_party - if [ ! -d $CONTRAIL_SRC/third_party/node-v0.8.15 ]; then - wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz - tar -xf node-v0.8.15.tar.gz - fi - cd node-v0.8.15 - ./configure; make; sudo make install - cd ${contrail_cwd} - rm -rf node-v0.8.15.tar.gz - rm -rf node-v0.8.15 - cd ${contrail_cwd} - fi if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC/contrail-web-core From 0a37c2ac67046fc22a29bf09455c19c39d7c5df1 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 12 Jun 2014 17:09:49 +0000 Subject: [PATCH 167/179] Add cassandra list for cassandra based discovery --- contrail/contrail_config_templates.py | 1 + contrail/setup_contrail.py | 1 + 2 files changed, 2 insertions(+) diff --git a/contrail/contrail_config_templates.py b/contrail/contrail_config_templates.py index 031091d4f5..9566782467 100644 --- a/contrail/contrail_config_templates.py +++ b/contrail/contrail_config_templates.py @@ -146,6 +146,7 @@ listen_port=$__contrail_listen_port__ log_local=$__contrail_log_local__ log_file=$__contrail_log_file__ +cassandra_server_list=$__contrail_cassandra_server_list__ # minimim time to allow client to cache service information (seconds) ttl_min=300 diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index efd2a70f02..753acc1f8c 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -628,6 +628,7 @@ def fixup_config_files(self): '__contrail_listen_port__': '5998', '__contrail_log_local__': 'True', '__contrail_log_file__': '/var/log/contrail/discovery.log', + '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), } self._template_substitute_write(discovery_conf_template, template_vals, temp_dir_name + '/discovery.conf') From 66e8c2531c36412e63f8b188a779255bcf537d8c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 12 Jun 2014 21:10:33 +0000 Subject: [PATCH 168/179] change the path to core path and feature path --- lib/neutron_thirdparty/contrail | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index b2a2db6500..47c22c1224 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -207,7 +207,11 @@ function install_contrail() { fi if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then contrail_cwd=$(pwd) - cd $CONTRAIL_SRC/contrail-web-core + cd $CONTRAIL_SRC + sed -ie "s/config\.discoveryService\.enable.*$/config\.discoveryService\.enable = false;/" contrail-web-core/config/config.global.js + sed -ie "s/config\.featurePkg\.webController\.path.*$/config\.featurePkg\.webController\.path = '\/opt\/stack\/contrail\/contrail-web-controller';/" contrail-web-core/config/config.global.js + sed -ie "s/config\.core_path.*$/config\.core_path = '\/opt\/stack\/contrail\/contrail-web-core';/" contrail-web-controller/webroot/common/js/controller.config.global.js + cd contrail-web-core make fetch-pkgs-prod make dev-env REPO=webController fi From ba75acc0735cb3a73f287de8690c8b0d0b907e3b Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 17 Jun 2014 14:11:36 -0700 Subject: [PATCH 169/179] Enable security groups for neutron --- lib/neutron_plugins/contrail | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index 774e39e355..f84749b6d5 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -36,8 +36,8 @@ function is_neutron_ovs_base_plugin() { } function has_neutron_plugin_security_group() { - # False - return 1 + # True + return 0 } function neutron_plugin_check_adv_test_requirements() { From 57093cf6793c5287a35f1d81e878b565a37c2f6d Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 17 Jun 2014 16:02:18 -0700 Subject: [PATCH 170/179] Add support for neutron plugin in CI environment --- contrail/localrc-ci | 70 ++++++++++++++++++++++++++++++++++++ lib/neutron_plugins/contrail | 6 ++-- 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 contrail/localrc-ci diff --git a/contrail/localrc-ci b/contrail/localrc-ci new file mode 100644 index 0000000000..8c2353ed09 --- /dev/null +++ b/contrail/localrc-ci @@ -0,0 +1,70 @@ +STACK_DIR=$(cd $(dirname $0) && pwd) + +SCREEN_LOGDIR=$STACK_DIR/log/screens +LOG=True +DEBUG=True +LOGFILE=$STACK_DIR/log/stack.log +LOGDAYS=1 + +# contrail services +enable_service cass +enable_service ifmap +enable_service apiSrv +enable_service schema +enable_service svc-mon +enable_service zk +enable_service control +enable_service agent +enable_service disco +enable_service redis +enable_service contrail +enable_service redis-u +enable_service redis-q +enable_service vizd +enable_service opserver +enable_service qed +enable_service redis-w +enable_service ui-jobs +enable_service ui-webs + +disable_service n-net +enable_service q-svc +enable_service q-meta +enable_service neutron + +# not used by contrail +disable_service q-agt +disable_service q-dhcp +disable_service q-l3 + +DATABASE_PASSWORD=contrail123 +RABBIT_PASSWORD=contrail123 +SERVICE_TOKEN=contrail123 +SERVICE_PASSWORD=contrail123 +ADMIN_PASSWORD=contrail123 + +Q_PLUGIN=contrail +PHYSICAL_INTERFACE=eth0 + +# repo proto is https or (default) ssh. Leave commented for ssh +# CONTRAIL_REPO_PROTO=https + +# proto for openstack bits. Use HTTPS if git is firewalled +GIT_BASE=https://git.openstack.org + +# use contrail VIF driver with NOVA +NOVA_VIF_DRIVER=nova_contrail_vif.contrailvif.VRouterVIFDriver + +CASS_MAX_HEAP_SIZE=1G +CASS_HEAP_NEWSIZE=200M + +# set CONTRAIL_REPO_SKIP_SYNC to avoid sync and build +# CONTRAIL_REPO_SKIP_SYNC=yes + +# uncomment to use specific contrail bits instead of t-o-t +CONTRAIL_REPO=devstack.xml + +# Set these to use neutron repo in openstack +Q_PLUGIN_CLASS=neutron.plugins.opencontrail.contrail_plugin_core.NeutronPluginContrailCoreV2 +Q_PLUGIN_CONF_PATH=etc/neutron/plugins/opencontrail +Q_PLUGIN_CONF_FILENAME=contrailplugin.ini diff --git a/lib/neutron_plugins/contrail b/lib/neutron_plugins/contrail index f84749b6d5..1810f4b99e 100644 --- a/lib/neutron_plugins/contrail +++ b/lib/neutron_plugins/contrail @@ -15,10 +15,10 @@ function neutron_plugin_setup_interface_driver() { } function neutron_plugin_configure_common() { - Q_PLUGIN_CONF_PATH=etc/neutron/plugins/juniper/contrail - Q_PLUGIN_CONF_FILENAME=ContrailPlugin.ini + Q_PLUGIN_CONF_PATH=${Q_PLUGIN_CONF_PATH:-etc/neutron/plugins/juniper/contrail} + Q_PLUGIN_CONF_FILENAME=${Q_PLUGIN_CONF_FILENAME:-ContrailPlugin.ini} Q_DB_NAME="contrail_neutron" - Q_PLUGIN_CLASS="neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_core.NeutronPluginContrailCoreV2" + Q_PLUGIN_CLASS=${Q_PLUGIN_CLASS:-"neutron_plugin_contrail.plugins.opencontrail.contrail_plugin_core.NeutronPluginContrailCoreV2"} } function neutron_plugin_configure_service() { From 226ca88d607678b8173adddfdeec61cb613bb3fe Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Tue, 17 Jun 2014 20:10:08 -0700 Subject: [PATCH 171/179] put HOST_IP= --- contrail/localrc-ci | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrail/localrc-ci b/contrail/localrc-ci index 8c2353ed09..ee697f9efd 100644 --- a/contrail/localrc-ci +++ b/contrail/localrc-ci @@ -1,3 +1,5 @@ +HOST_IP= + STACK_DIR=$(cd $(dirname $0) && pwd) SCREEN_LOGDIR=$STACK_DIR/log/screens From 4e29a7834d8e0e742c7a2a33d956454389412370 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 11 Jul 2014 07:48:35 -0700 Subject: [PATCH 172/179] devstack changes for webui and analytics redis changes --- contrail/setup_contrail.py | 25 ++----------------------- lib/neutron_thirdparty/contrail | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/contrail/setup_contrail.py b/contrail/setup_contrail.py index 753acc1f8c..fac84cd35b 100644 --- a/contrail/setup_contrail.py +++ b/contrail/setup_contrail.py @@ -473,27 +473,6 @@ def fixup_config_files(self): # collector in Phase 2 if 'collector' in self._args.role: - REDIS_UVE="/etc/contrail/redis-uve.conf" - REDIS_QUERY="/etc/contrail/redis-query.conf" - if os.path.isfile('/etc/redis/redis.conf'): - REDIS_CONF="/etc/redis/redis.conf" - else: - REDIS_CONF="/etc/redis.conf" - self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_UVE)) - self.run_shell("cp %s %s" %(REDIS_CONF, REDIS_QUERY)) - - self.replace_in_file(REDIS_UVE, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-uve.pid') - self.replace_in_file(REDIS_UVE, 'port 6379', 'port 6381') - self.replace_in_file(REDIS_UVE, 'bind 127.0.0.1', '#bind 127.0.0.1') - self.replace_in_file(REDIS_UVE, 'logfile /var/log/redis/redis-server.log', 'logfile /var/log/redis/redis-uve.log') - self.replace_in_file(REDIS_UVE, 'dbfilename dump.rdb', 'dbfilename dump-uve.rdb') - - self.replace_in_file(REDIS_QUERY, 'pidfile /var/run/redis/redis.pid', 'pidfile /var/run/redis/redis-query.pid') - self.replace_in_file(REDIS_QUERY, 'port 6379', 'port 6380') - self.replace_in_file(REDIS_QUERY, 'bind 127.0.0.1', '#bind 127.0.0.1') - self.replace_in_file(REDIS_QUERY, 'logfile /var/log/redis/redis-server.log', 'logfile /var/log/redis/redis-query.log') - self.replace_in_file(REDIS_QUERY, 'dbfilename dump.rdb', 'dbfilename dump-query.rdb') - template_vals = {'__contrail_discovery_ip__': self._args.discovery_ip, '__contrail_host_ip__': self._args.collector_ip, '__contrail_cassandra_server_list__' : ' '.join('%s:%s' % cassandra_server for cassandra_server in cassandra_server_list), @@ -510,8 +489,8 @@ def fixup_config_files(self): '__contrail_log_local__': '--log-local', '__contrail_log_file__': '--log-file=/var/log/contrail/qe.log', '__contrail_collectors__' : ' '.join('%s:%s' % collector_server for collector_server in collector_server_list), - '__contrail_redis_server__' : collector_ip, - '__contrail_redis_server_port__' : 6380, + '__contrail_redis_server__' : '127.0.0.1', + '__contrail_redis_server_port__' : 6379, } self._template_substitute_write(qe_param_template, template_vals, temp_dir_name + '/qed_param') diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 47c22c1224..0eaa960cf1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -62,14 +62,20 @@ function install_contrail() { # install node which brings npm that's used in fetch_packages.py if ! which node > /dev/null 2>&1 || ! which npm > /dev/null 2>&1 ; then - wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz - tar -xf node-v0.8.15.tar.gz - contrail_cwd=$(pwd) - cd node-v0.8.15 - ./configure; make; sudo make install - cd ${contrail_cwd} - rm -rf node-v0.8.15.tar.gz - rm -rf node-v0.8.15 + if is_ubuntu; then + wget https://launchpad.net/~opencontrail/+archive/ubuntu/ppa/+files/nodejs_0.8.15-1contrail1_amd64.deb + sudo dpkg -i nodejs_0.8.15-1contrail1_amd64.deb + rm -rf nodejs_0.8.15-1contrail1_amd64.deb + else + wget http://nodejs.org/dist/v0.8.15/node-v0.8.15.tar.gz -O node-v0.8.15.tar.gz + tar -xf node-v0.8.15.tar.gz + contrail_cwd=$(pwd) + cd node-v0.8.15 + ./configure; make; sudo make install + cd ${contrail_cwd} + rm -rf node-v0.8.15.tar.gz + rm -rf node-v0.8.15 + fi fi # api server requirements @@ -208,6 +214,7 @@ function install_contrail() { if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then contrail_cwd=$(pwd) cd $CONTRAIL_SRC + python contrail-webui-third-party/fetch_packages.py sed -ie "s/config\.discoveryService\.enable.*$/config\.discoveryService\.enable = false;/" contrail-web-core/config/config.global.js sed -ie "s/config\.featurePkg\.webController\.path.*$/config\.featurePkg\.webController\.path = '\/opt\/stack\/contrail\/contrail-web-controller';/" contrail-web-core/config/config.global.js sed -ie "s/config\.core_path.*$/config\.core_path = '\/opt\/stack\/contrail\/contrail-web-core';/" contrail-web-controller/webroot/common/js/controller.config.global.js @@ -370,13 +377,6 @@ function start_contrail() { screen_it control "sudo PATH=$PATH:$TOP_DIR/bin LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/control-node/control-node --IFMAP.server_url https://${IFMAP_SERVER}:${IFMAP_PORT} --IFMAP.user ${IFMAP_USER} --IFMAP.password ${IFMAP_PASWD} --DEFAULT.hostname ${HOSTNAME} --DEFAULT.hostip ${HOSTIP} --DEFAULT.bgp_port ${BGP_PORT} ${CERT_OPTS} ${LOG_LOCAL} --DEFAULT.collectors ${COLLECTOR}:${COLLECTOR_PORT}" # collector services - # redis-uve - screen_it redis-u "sudo redis-server /etc/contrail/redis-uve.conf" - sleep 2 - # redis-query - screen_it redis-q "sudo redis-server /etc/contrail/redis-query.conf" - sleep 2 - # collector/vizd source /etc/contrail/vizd_param screen_it vizd "sudo PATH=$PATH:$TOP_DIR/bin LD_LIBRARY_PATH=/opt/stack/contrail/build/lib $CONTRAIL_SRC/build/debug/analytics/vizd --DEFAULT.cassandra_server_list ${CASSANDRA_SERVER_LIST} --DEFAULT.hostip ${HOST_IP} --DEFAULT.log_file /var/log/contrail/collector.log" From e58742c9a3e91df6f2e72acf649d41969b86fc5f Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Tue, 15 Jul 2014 15:11:50 +0000 Subject: [PATCH 173/179] Fix the name of the agent executable --- lib/neutron_thirdparty/contrail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 47c22c1224..8cd1894302 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -432,7 +432,7 @@ EOF2 cat > $TOP_DIR/bin/vnsw.hlpr < Date: Mon, 21 Jul 2014 16:32:49 -0700 Subject: [PATCH 174/179] sometimes webui does not start up --- lib/neutron_thirdparty/contrail | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 0eaa960cf1..6a945caf3e 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -211,17 +211,17 @@ function install_contrail() { sudo python setup.py install cd ${contrail_cwd} fi - if [ ! -d $CONTRAIL_SRC/contrail-web-core/node_modules ]; then - contrail_cwd=$(pwd) - cd $CONTRAIL_SRC - python contrail-webui-third-party/fetch_packages.py - sed -ie "s/config\.discoveryService\.enable.*$/config\.discoveryService\.enable = false;/" contrail-web-core/config/config.global.js - sed -ie "s/config\.featurePkg\.webController\.path.*$/config\.featurePkg\.webController\.path = '\/opt\/stack\/contrail\/contrail-web-controller';/" contrail-web-core/config/config.global.js - sed -ie "s/config\.core_path.*$/config\.core_path = '\/opt\/stack\/contrail\/contrail-web-core';/" contrail-web-controller/webroot/common/js/controller.config.global.js - cd contrail-web-core - make fetch-pkgs-prod - make dev-env REPO=webController - fi + + contrail_cwd=$(pwd) + cd $CONTRAIL_SRC + python contrail-webui-third-party/fetch_packages.py + sed -ie "s/config\.discoveryService\.enable.*$/config\.discoveryService\.enable = false;/" contrail-web-core/config/config.global.js + sed -ie "s/config\.featurePkg\.webController\.path.*$/config\.featurePkg\.webController\.path = '\/opt\/stack\/contrail\/contrail-web-controller';/" contrail-web-core/config/config.global.js + sed -ie "s/config\.core_path.*$/config\.core_path = '\/opt\/stack\/contrail\/contrail-web-core';/" contrail-web-controller/webroot/common/js/controller.config.global.js + cd contrail-web-core + make fetch-pkgs-prod + make dev-env REPO=webController + cd ${contrail_cwd} } function apply_patch() { From bd3a38e803edb799178ed3a8244b01d07e0ef19f Mon Sep 17 00:00:00 2001 From: anandhk-juniper Date: Tue, 22 Jul 2014 12:17:39 +0530 Subject: [PATCH 175/179] - Arguments to vif command changed (the 'mode' argument is not supported anymore) --- lib/neutron_thirdparty/contrail | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 6a945caf3e..5214b72564 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -267,13 +267,14 @@ function insert_vrouter() { sudo $VIF --create $DEVICE --mac $DEV_MAC \ || echo "Error creating interface: $DEVICE" + echo "Adding $dev to vrouter" + sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --vhost-phys --type physical \ + || echo "Error adding $dev to vrouter" + echo "Adding $DEVICE to vrouter" - sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --xconnect $dev --mode x --type vhost \ + sudo $VIF --add $DEVICE --mac $DEV_MAC --vrf 0 --xconnect $dev --type vhost \ || echo "Error adding $DEVICE to vrouter" - echo "Adding $dev to vrouter" - sudo $VIF --add $dev --mac $DEV_MAC --vrf 0 --mode x --type physical \ - || echo "Error adding $dev to vrouter" if is_ubuntu; then From 4cfa2e75b909d36d09b83e5a082e5719d2105853 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 23 Jul 2014 18:29:42 +0000 Subject: [PATCH 176/179] Fix libvirt section; time to sync from openstack-dev/devstack --- lib/neutron | 2 +- lib/nova_plugins/hypervisor-libvirt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/neutron b/lib/neutron index 81db2a74d1..7770fcfcca 100644 --- a/lib/neutron +++ b/lib/neutron @@ -301,7 +301,7 @@ function create_nova_conf_neutron() { # set NOVA_VIF_DRIVER and optionally set options in nova_conf neutron_plugin_create_nova_conf - iniset $NOVA_CONF DEFAULT libvirt_vif_driver "$NOVA_VIF_DRIVER" + iniset $NOVA_CONF libvirt vif_driver "$NOVA_VIF_DRIVER" iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER" if is_service_enabled q-meta; then iniset $NOVA_CONF DEFAULT service_neutron_metadata_proxy "True" diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt index 6f90f4ac17..1f62eab721 100644 --- a/lib/nova_plugins/hypervisor-libvirt +++ b/lib/nova_plugins/hypervisor-libvirt @@ -105,8 +105,8 @@ EOF" # libvirt to detect those changes. restart_service $LIBVIRT_DAEMON - iniset $NOVA_CONF DEFAULT libvirt_type "$LIBVIRT_TYPE" - iniset $NOVA_CONF DEFAULT libvirt_cpu_mode "none" + iniset $NOVA_CONF libvirt virt_type "$LIBVIRT_TYPE" + iniset $NOVA_CONF libvirt virt_cpu_mode "none" iniset $NOVA_CONF DEFAULT use_usb_tablet "False" iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver" LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"} From 83ede5e99d1ff1e344e649d2d73d7439280dd2d0 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Thu, 24 Jul 2014 01:57:38 +0000 Subject: [PATCH 177/179] update localrc for ci to use its own manifest --- contrail/localrc-ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrail/localrc-ci b/contrail/localrc-ci index ee697f9efd..c0b0298d75 100644 --- a/contrail/localrc-ci +++ b/contrail/localrc-ci @@ -64,7 +64,7 @@ CASS_HEAP_NEWSIZE=200M # CONTRAIL_REPO_SKIP_SYNC=yes # uncomment to use specific contrail bits instead of t-o-t -CONTRAIL_REPO=devstack.xml +CONTRAIL_REPO=devstack-ci.xml # Set these to use neutron repo in openstack Q_PLUGIN_CLASS=neutron.plugins.opencontrail.contrail_plugin_core.NeutronPluginContrailCoreV2 From dc1860c3d96f16c93e26f651a9d42306072a1bb8 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Fri, 25 Jul 2014 17:37:40 +0000 Subject: [PATCH 178/179] Install kernel headers (needed for vrouter) --- lib/neutron_thirdparty/contrail | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/neutron_thirdparty/contrail b/lib/neutron_thirdparty/contrail index 75cd8e44e1..96c5c905c1 100644 --- a/lib/neutron_thirdparty/contrail +++ b/lib/neutron_thirdparty/contrail @@ -35,6 +35,7 @@ function install_contrail() { apt_get install libevent-dev libxml2-dev libxslt-dev apt_get install uml-utilities apt_get install libvirt-bin + apt_get install linux-headers-$(uname -r) if ! which redis-server > /dev/null 2>&1 ; then sudo apt-get install libjemalloc1 @@ -52,6 +53,7 @@ function install_contrail() { sudo yum -y install tunctl sudo yum -y install java-1.7.0-openjdk sudo yum -y install libvirt-bin + sudo yum -y install kernel-headers if ! which redis-server > /dev/null 2>&1 ; then wget http://mir01.syntis.net/atomic/fedora/17/x86_64/RPMS/redis-2.6.13-3.fc17.art.x86_64.rpm From b46bdfcc4e80d3469b4e264f408c4134ab4429c4 Mon Sep 17 00:00:00 2001 From: Deepinder Setia Date: Wed, 3 Sep 2014 15:59:14 -0700 Subject: [PATCH 179/179] deprecated in favor of juniper/contrail-installer --- README.md | 355 +------------ stack.sh | 1441 ---------------------------------------------------- unstack.sh | 185 ------- 3 files changed, 3 insertions(+), 1978 deletions(-) delete mode 100755 stack.sh delete mode 100755 unstack.sh diff --git a/README.md b/README.md index 9914b1ed69..1c6f8122fa 100644 --- a/README.md +++ b/README.md @@ -1,354 +1,5 @@ -DevStack is a set of scripts and utilities to quickly deploy an OpenStack cloud. +THIS REPOSITORY IS DEPRECATED +============================= -# Goals +This repository is deprecated in favor of http://github.com/juniper/contrail-installer -* To quickly build dev OpenStack environments in a clean Ubuntu or Fedora environment -* To describe working configurations of OpenStack (which code branches work together? what do config files look like for those branches?) -* To make it easier for developers to dive into OpenStack so that they can productively contribute without having to understand every part of the system at once -* To make it easy to prototype cross-project features -* To provide an environment for the OpenStack CI testing on every commit to the projects - -Read more at http://devstack.org. - -IMPORTANT: Be sure to carefully read `stack.sh` and any other scripts you -execute before you run them, as they install software and will alter your -networking configuration. We strongly recommend that you run `stack.sh` -in a clean and disposable vm when you are first getting started. - -# Versions - -The DevStack master branch generally points to trunk versions of OpenStack -components. For older, stable versions, look for branches named -stable/[release] in the DevStack repo. For example, you can do the -following to create a grizzly OpenStack cloud: - - git checkout stable/grizzly - ./stack.sh - -You can also pick specific OpenStack project releases by setting the appropriate -`*_BRANCH` variables in the ``localrc`` section of `local.conf` (look in -`stackrc` for the default set). Usually just before a release there will be -milestone-proposed branches that need to be tested:: - - GLANCE_REPO=git://git.openstack.org/openstack/glance.git - GLANCE_BRANCH=milestone-proposed - -# Start A Dev Cloud - -Installing in a dedicated disposable VM is safer than installing on your -dev machine! Plus you can pick one of the supported Linux distros for -your VM. To start a dev cloud run the following NOT AS ROOT (see -**DevStack Execution Environment** below for more on user accounts): - - ./stack.sh - -When the script finishes executing, you should be able to access OpenStack endpoints, like so: - -* Horizon: http://myhost/ -* Keystone: http://myhost:5000/v2.0/ - -We also provide an environment file that you can use to interact with your cloud via CLI: - - # source openrc file to load your environment with OpenStack CLI creds - . openrc - # list instances - nova list - -If the EC2 API is your cup-o-tea, you can create credentials and use euca2ools: - - # source eucarc to generate EC2 credentials and set up the environment - . eucarc - # list instances using ec2 api - euca-describe-instances - -# DevStack Execution Environment - -DevStack runs rampant over the system it runs on, installing things and uninstalling other things. Running this on a system you care about is a recipe for disappointment, or worse. Alas, we're all in the virtualization business here, so run it in a VM. And take advantage of the snapshot capabilities of your hypervisor of choice to reduce testing cycle times. You might even save enough time to write one more feature before the next feature freeze... - -``stack.sh`` needs to have root access for a lot of tasks, but uses ``sudo`` -for all of those tasks. However, it needs to be not-root for most of its -work and for all of the OpenStack services. ``stack.sh`` specifically -does not run if started as root. - -This is a recent change (Oct 2013) from the previous behaviour of -automatically creating a ``stack`` user. Automatically creating -user accounts is not the right response to running as root, so -that bit is now an explicit step using ``tools/create-stack-user.sh``. -Run that (as root!) or just check it out to see what DevStack's -expectations are for the account it runs under. Many people simply -use their usual login (the default 'ubuntu' login on a UEC image -for example). - -# Customizing - -You can override environment variables used in `stack.sh` by creating file -name `local.conf` with a ``localrc`` section as shown below. It is likely -that you will need to do this to tweak your networking configuration should -you need to access your cloud from a different host. - - [[local|localrc]] - VARIABLE=value - -See the **Local Configuration** section below for more details. - -# Database Backend - -Multiple database backends are available. The available databases are defined in the lib/databases directory. -`mysql` is the default database, choose a different one by putting the -following in the `localrc` section: - - disable_service mysql - enable_service postgresql - -`mysql` is the default database. - -# RPC Backend - -Multiple RPC backends are available. Currently, this -includes RabbitMQ (default), Qpid, and ZeroMQ. Your backend of -choice may be selected via the `localrc` section. - -Note that selecting more than one RPC backend will result in a failure. - -Example (ZeroMQ): - - ENABLED_SERVICES="$ENABLED_SERVICES,-rabbit,-qpid,zeromq" - -Example (Qpid): - - ENABLED_SERVICES="$ENABLED_SERVICES,-rabbit,-zeromq,qpid" - -# Apache Frontend - -Apache web server is enabled for wsgi services by setting -`APACHE_ENABLED_SERVICES` in your ``localrc`` section. Remember to -enable these services at first as above. - - APACHE_ENABLED_SERVICES+=keystone,swift - -# Swift - -Swift is disabled by default. When enabled, it is configured with -only one replica to avoid being IO/memory intensive on a small -vm. When running with only one replica the account, container and -object services will run directly in screen. The others services like -replicator, updaters or auditor runs in background. - -If you would like to enable Swift you can add this to your `localrc` section: - - enable_service s-proxy s-object s-container s-account - -If you want a minimal Swift install with only Swift and Keystone you -can have this instead in your `localrc` section: - - disable_all_services - enable_service key mysql s-proxy s-object s-container s-account - -If you only want to do some testing of a real normal swift cluster -with multiple replicas you can do so by customizing the variable -`SWIFT_REPLICAS` in your `localrc` section (usually to 3). - -# Swift S3 - -If you are enabling `swift3` in `ENABLED_SERVICES` DevStack will -install the swift3 middleware emulation. Swift will be configured to -act as a S3 endpoint for Keystone so effectively replacing the -`nova-objectstore`. - -Only Swift proxy server is launched in the screen session all other -services are started in background and managed by `swift-init` tool. - -# Neutron - -Basic Setup - -In order to enable Neutron a single node setup, you'll need the -following settings in your `localrc` section: - - disable_service n-net - enable_service q-svc - enable_service q-agt - enable_service q-dhcp - enable_service q-l3 - enable_service q-meta - enable_service q-metering - enable_service neutron - # Optional, to enable tempest configuration as part of DevStack - enable_service tempest - -Then run `stack.sh` as normal. - -DevStack supports setting specific Neutron configuration flags to the -service, Open vSwitch plugin and LinuxBridge plugin configuration files. -To make use of this feature, the following variables are defined and can -be configured in your `localrc` section: - - Variable Name Config File Section Modified - ------------------------------------------------------------------------------------- - Q_SRV_EXTRA_OPTS Plugin `OVS` (for Open Vswitch) or `LINUX_BRIDGE` (for LinuxBridge) - Q_AGENT_EXTRA_AGENT_OPTS Plugin AGENT - Q_AGENT_EXTRA_SRV_OPTS Plugin `OVS` (for Open Vswitch) or `LINUX_BRIDGE` (for LinuxBridge) - Q_SRV_EXTRA_DEFAULT_OPTS Service DEFAULT - -An example of using the variables in your `localrc` section is below: - - Q_AGENT_EXTRA_AGENT_OPTS=(tunnel_type=vxlan vxlan_udp_port=8472) - Q_SRV_EXTRA_OPTS=(tenant_network_type=vxlan) - -DevStack also supports configuring the Neutron ML2 plugin. The ML2 plugin -can run with the OVS, LinuxBridge, or Hyper-V agents on compute hosts. A -simple way to configure the ml2 plugin is shown below: - - # VLAN configuration - Q_PLUGIN=ml2 - ENABLE_TENANT_VLANS=True - - # GRE tunnel configuration - Q_PLUGIN=ml2 - ENABLE_TENANT_TUNNELS=True - - # VXLAN tunnel configuration - Q_PLUGIN=ml2 - Q_ML2_TENANT_NETWORK_TYPE=vxlan - -The above will default in DevStack to using the OVS on each compute host. -To change this, set the `Q_AGENT` variable to the agent you want to run -(e.g. linuxbridge). - - Variable Name Notes - ------------------------------------------------------------------------------------- - Q_AGENT This specifies which agent to run with the ML2 Plugin (either `openvswitch` or `linuxbridge`). - Q_ML2_PLUGIN_MECHANISM_DRIVERS The ML2 MechanismDrivers to load. The default is none. Note, ML2 will work with the OVS and LinuxBridge agents by default. - Q_ML2_PLUGIN_TYPE_DRIVERS The ML2 TypeDrivers to load. Defaults to all available TypeDrivers. - Q_ML2_PLUGIN_GRE_TYPE_OPTIONS GRE TypeDriver options. Defaults to none. - Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS VXLAN TypeDriver options. Defaults to none. - Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS VLAN TypeDriver options. Defaults to none. - Q_AGENT_EXTRA_AGENT_OPTS Extra configuration options to pass to the OVS or LinuxBridge Agent. - -# Heat - -Heat is disabled by default. To enable it you'll need the following settings -in your `localrc` section: - - enable_service heat h-api h-api-cfn h-api-cw h-eng - -Heat can also run in standalone mode, and be configured to orchestrate -on an external OpenStack cloud. To launch only Heat in standalone mode -you'll need the following settings in your `localrc` section: - - disable_all_services - enable_service rabbit mysql heat h-api h-api-cfn h-api-cw h-eng - HEAT_STANDALONE=True - KEYSTONE_SERVICE_HOST=... - KEYSTONE_AUTH_HOST=... - -# Tempest - -If tempest has been successfully configured, a basic set of smoke tests can be run as follows: - - $ cd /opt/stack/tempest - $ nosetests tempest/scenario/test_network_basic_ops.py - -# DevStack on Xenserver - -If you would like to use Xenserver as the hypervisor, please refer to the instructions in `./tools/xen/README.md`. - -# DevStack on Docker - -If you would like to use Docker as the hypervisor, please refer to the instructions in `./tools/docker/README.md`. - -# Additional Projects - -DevStack has a hook mechanism to call out to a dispatch script at specific -points in the execution of `stack.sh`, `unstack.sh` and `clean.sh`. This -allows upper-layer projects, especially those that the lower layer projects -have no dependency on, to be added to DevStack without modifying the core -scripts. Tempest is built this way as an example of how to structure the -dispatch script, see `extras.d/80-tempest.sh`. See `extras.d/README.md` -for more information. - -# Multi-Node Setup - -A more interesting setup involves running multiple compute nodes, with Neutron networks connecting VMs on different compute nodes. -You should run at least one "controller node", which should have a `stackrc` that includes at least: - - disable_service n-net - enable_service q-svc - enable_service q-agt - enable_service q-dhcp - enable_service q-l3 - enable_service q-meta - enable_service neutron - -You likely want to change your `localrc` section to run a scheduler that -will balance VMs across hosts: - - SCHEDULER=nova.scheduler.simple.SimpleScheduler - -You can then run many compute nodes, each of which should have a `stackrc` which includes the following, with the IP address of the above controller node: - - ENABLED_SERVICES=n-cpu,rabbit,g-api,neutron,q-agt - SERVICE_HOST=[IP of controller node] - MYSQL_HOST=$SERVICE_HOST - RABBIT_HOST=$SERVICE_HOST - Q_HOST=$SERVICE_HOST - MATCHMAKER_REDIS_HOST=$SERVICE_HOST - -# Cells - -Cells is a new scaling option with a full spec at http://wiki.openstack.org/blueprint-nova-compute-cells. - -To setup a cells environment add the following to your `localrc` section: - - enable_service n-cell - -Be aware that there are some features currently missing in cells, one notable one being security groups. The exercises have been patched to disable functionality not supported by cells. - - -# Local Configuration - -Historically DevStack has used ``localrc`` to contain all local configuration and customizations. More and more of the configuration variables available for DevStack are passed-through to the individual project configuration files. The old mechanism for this required specific code for each file and did not scale well. This is handled now by a master local configuration file. - -# local.conf - -The new config file ``local.conf`` is an extended-INI format that introduces a new meta-section header that provides some additional information such as a phase name and destination config filename: - - [[ | ]] - -where ```` is one of a set of phase names defined by ``stack.sh`` -and ```` is the configuration filename. The filename is -eval'ed in the ``stack.sh`` context so all environment variables are -available and may be used. Using the project config file variables in -the header is strongly suggested (see the ``NOVA_CONF`` example below). -If the path of the config file does not exist it is skipped. - -The defined phases are: - -* **local** - extracts ``localrc`` from ``local.conf`` before ``stackrc`` is sourced -* **post-config** - runs after the layer 2 services are configured and before they are started -* **extra** - runs after services are started and before any files in ``extra.d`` are executed -* **post-extra** - runs after files in ``extra.d`` are executed - -The file is processed strictly in sequence; meta-sections may be specified more than once but if any settings are duplicated the last to appear in the file will be used. - - [[post-config|$NOVA_CONF]] - [DEFAULT] - use_syslog = True - - [osapi_v3] - enabled = False - -A specific meta-section ``local|localrc`` is used to provide a default -``localrc`` file (actually ``.localrc.auto``). This allows all custom -settings for DevStack to be contained in a single file. If ``localrc`` -exists it will be used instead to preserve backward-compatibility. - - [[local|localrc]] - FIXED_RANGE=10.254.1.0/24 - ADMIN_PASSWORD=speciale - LOGFILE=$DEST/logs/stack.sh.log - -Note that ``Q_PLUGIN_CONF_FILE`` is unique in that it is assumed to *NOT* -start with a ``/`` (slash) character. A slash will need to be added: - - [[post-config|/$Q_PLUGIN_CONF_FILE]] diff --git a/stack.sh b/stack.sh deleted file mode 100755 index 45d47c819c..0000000000 --- a/stack.sh +++ /dev/null @@ -1,1441 +0,0 @@ -#!/usr/bin/env bash - -# ``stack.sh`` is an opinionated OpenStack developer installation. It -# installs and configures various combinations of **Ceilometer**, **Cinder**, -# **Glance**, **Heat**, **Horizon**, **Keystone**, **Nova**, **Neutron**, -# and **Swift** - -# This script allows you to specify configuration options of what git -# repositories to use, enabled services, network configuration and various -# passwords. If you are crafty you can run the script on multiple nodes using -# shared settings for common resources (mysql, rabbitmq) and build a multi-node -# developer install. - -# To keep this script simple we assume you are running on a recent **Ubuntu** -# (12.04 Precise or newer) or **Fedora** (F18 or newer) machine. (It may work -# on other platforms but support for those platforms is left to those who added -# them to DevStack.) It should work in a VM or physical server. Additionally -# we maintain a list of ``apt`` and ``rpm`` dependencies and other configuration -# files in this repo. - -# Learn more and get the most recent version at http://devstack.org - -# Make sure custom grep options don't get in the way -unset GREP_OPTIONS - -# Sanitize language settings to avoid commands bailing out -# with "unsupported locale setting" errors. -unset LANG -unset LANGUAGE -LC_ALL=C -export LC_ALL - -# Keep track of the devstack directory -TOP_DIR=$(cd $(dirname "$0") && pwd) - -# Import common functions -source $TOP_DIR/functions - -# Import config functions -source $TOP_DIR/lib/config - -# Determine what system we are running on. This provides ``os_VENDOR``, -# ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME`` -# and ``DISTRO`` -GetDistro - - -# Global Settings -# =============== - -# Check for a ``localrc`` section embedded in ``local.conf`` and extract if -# ``localrc`` does not already exist - -# Phase: local -rm -f $TOP_DIR/.localrc.auto -if [[ -r $TOP_DIR/local.conf ]]; then - LRC=$(get_meta_section_files $TOP_DIR/local.conf local) - for lfile in $LRC; do - if [[ "$lfile" == "localrc" ]]; then - if [[ -r $TOP_DIR/localrc ]]; then - warn $LINENO "localrc and local.conf:[[local]] both exist, using localrc" - else - echo "# Generated file, do not edit" >$TOP_DIR/.localrc.auto - get_meta_section $TOP_DIR/local.conf local $lfile >>$TOP_DIR/.localrc.auto - fi - fi - done -fi - -# ``stack.sh`` is customizable by setting environment variables. Override a -# default setting via export:: -# -# export DATABASE_PASSWORD=anothersecret -# ./stack.sh -# -# or by setting the variable on the command line:: -# -# DATABASE_PASSWORD=simple ./stack.sh -# -# Persistent variables can be placed in a ``localrc`` file:: -# -# DATABASE_PASSWORD=anothersecret -# DATABASE_USER=hellaroot -# -# We try to have sensible defaults, so you should be able to run ``./stack.sh`` -# in most cases. ``localrc`` is not distributed with DevStack and will never -# be overwritten by a DevStack update. -# -# DevStack distributes ``stackrc`` which contains locations for the OpenStack -# repositories, branches to configure, and other configuration defaults. -# ``stackrc`` sources ``localrc`` to allow you to safely override those settings. - -if [[ ! -r $TOP_DIR/stackrc ]]; then - log_error $LINENO "missing $TOP_DIR/stackrc - did you grab more than just stack.sh?" -fi -source $TOP_DIR/stackrc - - -# Local Settings -# -------------- - -# Make sure the proxy config is visible to sub-processes -export_proxy_variables - -# Destination path for installation ``DEST`` -DEST=${DEST:-/opt/stack} - - -# Sanity Check -# ------------ - -# Clean up last environment var cache -if [[ -r $TOP_DIR/.stackenv ]]; then - rm $TOP_DIR/.stackenv -fi - -# ``stack.sh`` keeps the list of ``apt`` and ``rpm`` dependencies and config -# templates and other useful files in the ``files`` subdirectory -FILES=$TOP_DIR/files -if [ ! -d $FILES ]; then - log_error $LINENO "missing devstack/files" -fi - -# ``stack.sh`` keeps function libraries here -# Make sure ``$TOP_DIR/lib`` directory is present -if [ ! -d $TOP_DIR/lib ]; then - log_error $LINENO "missing devstack/lib" -fi - -# Import common services (database, message queue) configuration -source $TOP_DIR/lib/database -source $TOP_DIR/lib/rpc_backend - -# Remove services which were negated in ENABLED_SERVICES -# using the "-" prefix (e.g., "-rabbit") instead of -# calling disable_service(). -disable_negated_services - -# Warn users who aren't on an explicitly supported distro, but allow them to -# override check and attempt installation with ``FORCE=yes ./stack`` -if [[ ! ${DISTRO} =~ (precise|raring|saucy|trusty|7.0|wheezy|sid|testing|jessie|f18|f19|f20|opensuse-12.2|rhel6) ]]; then - echo "WARNING: this script has not been tested on $DISTRO" - if [[ "$FORCE" != "yes" ]]; then - die $LINENO "If you wish to run this script anyway run with FORCE=yes" - fi -fi - -# Make sure we only have one rpc backend enabled, -# and the specified rpc backend is available on your platform. -check_rpc_backend - -# Check to see if we are already running DevStack -# Note that this may fail if USE_SCREEN=False -if type -p screen >/dev/null && screen -ls | egrep -q "[0-9].$SCREEN_NAME"; then - echo "You are already running a stack.sh session." - echo "To rejoin this session type 'screen -x stack'." - echo "To destroy this session, type './unstack.sh'." - exit 1 -fi - -# Set up logging level -VERBOSE=$(trueorfalse True $VERBOSE) - - -# Additional repos -# ================ - -# Some distros need to add repos beyond the defaults provided by the vendor -# to pick up required packages. - -# The Debian Wheezy official repositories do not contain all required packages, -# add gplhost repository. -if [[ "$os_VENDOR" =~ (Debian) ]]; then - echo 'deb http://archive.gplhost.com/debian grizzly main' | sudo tee /etc/apt/sources.list.d/gplhost_wheezy-backports.list - echo 'deb http://archive.gplhost.com/debian grizzly-backports main' | sudo tee -a /etc/apt/sources.list.d/gplhost_wheezy-backports.list - apt_get update - apt_get install --force-yes gplhost-archive-keyring -fi - -if [[ is_fedora && $DISTRO =~ (rhel6) ]]; then - # Installing Open vSwitch on RHEL6 requires enabling the RDO repo. - RHEL6_RDO_REPO_RPM=${RHEL6_RDO_REPO_RPM:-"http://rdo.fedorapeople.org/openstack-havana/rdo-release-havana.rpm"} - RHEL6_RDO_REPO_ID=${RHEL6_RDO_REPO_ID:-"openstack-havana"} - if ! yum repolist enabled $RHEL6_RDO_REPO_ID | grep -q $RHEL6_RDO_REPO_ID; then - echo "RDO repo not detected; installing" - yum_install $RHEL6_RDO_REPO_RPM || \ - die $LINENO "Error installing RDO repo, cannot continue" - fi - - # RHEL6 requires EPEL for many Open Stack dependencies - RHEL6_EPEL_RPM=${RHEL6_EPEL_RPM:-"http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm"} - if ! yum repolist enabled epel | grep -q 'epel'; then - echo "EPEL not detected; installing" - yum_install ${RHEL6_EPEL_RPM} || \ - die $LINENO "Error installing EPEL repo, cannot continue" - fi -fi - - -# root Access -# ----------- - -# OpenStack is designed to be run as a non-root user; Horizon will fail to run -# as **root** since Apache will not serve content from **root** user). -# ``stack.sh`` must not be run as **root**. It aborts and suggests one course of -# action to create a suitable user account. - -if [[ $EUID -eq 0 ]]; then - echo "You are running this script as root." - echo "Cut it out." - echo "Really." - echo "If you need an account to run DevStack, do this (as root, heh) to create $STACK_USER:" - echo "$TOP_DIR/tools/create-stack-user.sh" - exit 1 -fi - -# We're not **root**, make sure ``sudo`` is available -is_package_installed sudo || install_package sudo - -# UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one -sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers - -# Set up devstack sudoers -TEMPFILE=`mktemp` -echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE -# Some binaries might be under /sbin or /usr/sbin, so make sure sudo will -# see them by forcing PATH -echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE -chmod 0440 $TEMPFILE -sudo chown root:root $TEMPFILE -sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh - - -# Create the destination directory and ensure it is writable by the user -# and read/executable by everybody for daemons (e.g. apache run for horizon) -sudo mkdir -p $DEST -safe_chown -R $STACK_USER $DEST -safe_chmod 0755 $DEST - -# a basic test for $DEST path permissions (fatal on error unless skipped) -check_path_perm_sanity ${DEST} - -# Certain services such as rabbitmq require that the local hostname resolves -# correctly. Make sure it exists in /etc/hosts so that is always true. -LOCAL_HOSTNAME=`hostname -s` -if [ -z "`grep ^127.0.0.1 /etc/hosts | grep $LOCAL_HOSTNAME`" ]; then - sudo sed -i "s/\(^127.0.0.1.*\)/\1 $LOCAL_HOSTNAME/" /etc/hosts -fi - -# Set ``OFFLINE`` to ``True`` to configure ``stack.sh`` to run cleanly without -# Internet access. ``stack.sh`` must have been previously run with Internet -# access to install prerequisites and fetch repositories. -OFFLINE=`trueorfalse False $OFFLINE` - -# Set ``ERROR_ON_CLONE`` to ``True`` to configure ``stack.sh`` to exit if -# the destination git repository does not exist during the ``git_clone`` -# operation. -ERROR_ON_CLONE=`trueorfalse False $ERROR_ON_CLONE` - -# Whether to enable the debug log level in OpenStack services -ENABLE_DEBUG_LOG_LEVEL=`trueorfalse True $ENABLE_DEBUG_LOG_LEVEL` - -# Destination path for service data -DATA_DIR=${DATA_DIR:-${DEST}/data} -sudo mkdir -p $DATA_DIR -safe_chown -R $STACK_USER $DATA_DIR - - -# Common Configuration -# ==================== - -# Set fixed and floating range here so we can make sure not to use addresses -# from either range when attempting to guess the IP to use for the host. -# Note that setting FIXED_RANGE may be necessary when running DevStack -# in an OpenStack cloud that uses either of these address ranges internally. -FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.0/24} -FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24} -FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256} - -HOST_IP=$(get_default_host_ip $FIXED_RANGE $FLOATING_RANGE "$HOST_IP_IFACE" "$HOST_IP") -if [ "$HOST_IP" == "" ]; then - die $LINENO "Could not determine host ip address. Either localrc specified dhcp on ${HOST_IP_IFACE} or defaulted" -fi - -# Allow the use of an alternate hostname (such as localhost/127.0.0.1) for service endpoints. -SERVICE_HOST=${SERVICE_HOST:-$HOST_IP} - -# Allow the use of an alternate protocol (such as https) for service endpoints -SERVICE_PROTOCOL=${SERVICE_PROTOCOL:-http} - -# Configure services to use syslog instead of writing to individual log files -SYSLOG=`trueorfalse False $SYSLOG` -SYSLOG_HOST=${SYSLOG_HOST:-$HOST_IP} -SYSLOG_PORT=${SYSLOG_PORT:-516} - -# Enable sysstat logging -SYSSTAT_FILE=${SYSSTAT_FILE:-"sysstat.dat"} -SYSSTAT_INTERVAL=${SYSSTAT_INTERVAL:-"1"} - -PIDSTAT_FILE=${PIDSTAT_FILE:-"pidstat.txt"} -PIDSTAT_INTERVAL=${PIDSTAT_INTERVAL:-"5"} - -# Use color for logging output (only available if syslog is not used) -LOG_COLOR=`trueorfalse True $LOG_COLOR` - -# Service startup timeout -SERVICE_TIMEOUT=${SERVICE_TIMEOUT:-60} - -# Reset the bundle of CA certificates -SSL_BUNDLE_FILE="$DATA_DIR/ca-bundle.pem" -rm -f $SSL_BUNDLE_FILE - - -# Configure Projects -# ================== - -# Import apache functions -source $TOP_DIR/lib/apache - -# Import TLS functions -source $TOP_DIR/lib/tls - -# Source project function libraries -source $TOP_DIR/lib/infra -source $TOP_DIR/lib/oslo -source $TOP_DIR/lib/stackforge -source $TOP_DIR/lib/horizon -source $TOP_DIR/lib/keystone -source $TOP_DIR/lib/glance -source $TOP_DIR/lib/nova -source $TOP_DIR/lib/cinder -source $TOP_DIR/lib/swift -source $TOP_DIR/lib/ceilometer -source $TOP_DIR/lib/heat -source $TOP_DIR/lib/neutron -source $TOP_DIR/lib/baremetal -source $TOP_DIR/lib/ldap -source $TOP_DIR/lib/ironic - -# Extras Source -# -------------- - -# Phase: source -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i source - done -fi - -# Set the destination directories for other OpenStack projects -OPENSTACKCLIENT_DIR=$DEST/python-openstackclient - -# Interactive Configuration -# ------------------------- - -# Do all interactive config up front before the logging spew begins - -# Generic helper to configure passwords -function read_password { - XTRACE=$(set +o | grep xtrace) - set +o xtrace - var=$1; msg=$2 - pw=${!var} - - localrc=$TOP_DIR/localrc - - # If the password is not defined yet, proceed to prompt user for a password. - if [ ! $pw ]; then - # If there is no localrc file, create one - if [ ! -e $localrc ]; then - touch $localrc - fi - - # Presumably if we got this far it can only be that our localrc is missing - # the required password. Prompt user for a password and write to localrc. - echo '' - echo '################################################################################' - echo $msg - echo '################################################################################' - echo "This value will be written to your localrc file so you don't have to enter it " - echo "again. Use only alphanumeric characters." - echo "If you leave this blank, a random default value will be used." - pw=" " - while true; do - echo "Enter a password now:" - read -e $var - pw=${!var} - [[ "$pw" = "`echo $pw | tr -cd [:alnum:]`" ]] && break - echo "Invalid chars in password. Try again:" - done - if [ ! $pw ]; then - pw=`openssl rand -hex 10` - fi - eval "$var=$pw" - echo "$var=$pw" >> $localrc - fi - $XTRACE -} - - -# Database Configuration - -# To select between database backends, add the following to ``localrc``: -# -# disable_service mysql -# enable_service postgresql -# -# The available database backends are listed in ``DATABASE_BACKENDS`` after -# ``lib/database`` is sourced. ``mysql`` is the default. - -initialize_database_backends && echo "Using $DATABASE_TYPE database backend" || echo "No database enabled" - - -# Queue Configuration - -# Rabbit connection info -if is_service_enabled rabbit; then - RABBIT_HOST=${RABBIT_HOST:-localhost} - read_password RABBIT_PASSWORD "ENTER A PASSWORD TO USE FOR RABBIT." -fi - - -# Keystone - -if is_service_enabled key; then - # The ``SERVICE_TOKEN`` is used to bootstrap the Keystone database. It is - # just a string and is not a 'real' Keystone token. - read_password SERVICE_TOKEN "ENTER A SERVICE_TOKEN TO USE FOR THE SERVICE ADMIN TOKEN." - # Services authenticate to Identity with servicename/``SERVICE_PASSWORD`` - read_password SERVICE_PASSWORD "ENTER A SERVICE_PASSWORD TO USE FOR THE SERVICE AUTHENTICATION." - # Horizon currently truncates usernames and passwords at 20 characters - read_password ADMIN_PASSWORD "ENTER A PASSWORD TO USE FOR HORIZON AND KEYSTONE (20 CHARS OR LESS)." - - # Keystone can now optionally install OpenLDAP by enabling the ``ldap`` - # service in ``localrc`` (e.g. ``enable_service ldap``). - # To clean out the Keystone contents in OpenLDAP set ``KEYSTONE_CLEAR_LDAP`` - # to ``yes`` (e.g. ``KEYSTONE_CLEAR_LDAP=yes``) in ``localrc``. To enable the - # Keystone Identity Driver (``keystone.identity.backends.ldap.Identity``) - # set ``KEYSTONE_IDENTITY_BACKEND`` to ``ldap`` (e.g. - # ``KEYSTONE_IDENTITY_BACKEND=ldap``) in ``localrc``. - - # only request ldap password if the service is enabled - if is_service_enabled ldap; then - read_password LDAP_PASSWORD "ENTER A PASSWORD TO USE FOR LDAP" - fi -fi - - -# Swift - -if is_service_enabled s-proxy; then - # We only ask for Swift Hash if we have enabled swift service. - # ``SWIFT_HASH`` is a random unique string for a swift cluster that - # can never change. - read_password SWIFT_HASH "ENTER A RANDOM SWIFT HASH." -fi - - -# Configure logging -# ----------------- - -# Draw a spinner so the user knows something is happening -function spinner() { - local delay=0.75 - local spinstr='/-\|' - printf "..." >&3 - while [ true ]; do - local temp=${spinstr#?} - printf "[%c]" "$spinstr" >&3 - local spinstr=$temp${spinstr%"$temp"} - sleep $delay - printf "\b\b\b" >&3 - done -} - -# Echo text to the log file, summary log file and stdout -# echo_summary "something to say" -function echo_summary() { - if [[ -t 3 && "$VERBOSE" != "True" ]]; then - kill >/dev/null 2>&1 $LAST_SPINNER_PID - if [ ! -z "$LAST_SPINNER_PID" ]; then - printf "\b\b\bdone\n" >&3 - fi - echo -n -e $@ >&6 - spinner & - LAST_SPINNER_PID=$! - else - echo -e $@ >&6 - fi -} - -# Echo text only to stdout, no log files -# echo_nolog "something not for the logs" -function echo_nolog() { - echo $@ >&3 -} - -# Set up logging for ``stack.sh`` -# Set ``LOGFILE`` to turn on logging -# Append '.xxxxxxxx' to the given name to maintain history -# where 'xxxxxxxx' is a representation of the date the file was created -TIMESTAMP_FORMAT=${TIMESTAMP_FORMAT:-"%F-%H%M%S"} -if [[ -n "$LOGFILE" || -n "$SCREEN_LOGDIR" ]]; then - LOGDAYS=${LOGDAYS:-7} - CURRENT_LOG_TIME=$(date "+$TIMESTAMP_FORMAT") -fi - -if [[ -n "$LOGFILE" ]]; then - # First clean up old log files. Use the user-specified ``LOGFILE`` - # as the template to search for, appending '.*' to match the date - # we added on earlier runs. - LOGDIR=$(dirname "$LOGFILE") - LOGFILENAME=$(basename "$LOGFILE") - mkdir -p $LOGDIR - find $LOGDIR -maxdepth 1 -name $LOGFILENAME.\* -mtime +$LOGDAYS -exec rm {} \; - LOGFILE=$LOGFILE.${CURRENT_LOG_TIME} - SUMFILE=$LOGFILE.${CURRENT_LOG_TIME}.summary - - # Redirect output according to config - - # Copy stdout to fd 3 - exec 3>&1 - if [[ "$VERBOSE" == "True" ]]; then - # Redirect stdout/stderr to tee to write the log file - exec 1> >( awk ' - { - cmd ="date +\"%Y-%m-%d %H:%M:%S \"" - cmd | getline now - close("date +\"%Y-%m-%d %H:%M:%S \"") - sub(/^/, now) - print - fflush() - }' | tee "${LOGFILE}" ) 2>&1 - # Set up a second fd for output - exec 6> >( tee "${SUMFILE}" ) - else - # Set fd 1 and 2 to primary logfile - exec 1> "${LOGFILE}" 2>&1 - # Set fd 6 to summary logfile and stdout - exec 6> >( tee "${SUMFILE}" >&3 ) - fi - - echo_summary "stack.sh log $LOGFILE" - # Specified logfile name always links to the most recent log - ln -sf $LOGFILE $LOGDIR/$LOGFILENAME - ln -sf $SUMFILE $LOGDIR/$LOGFILENAME.summary -else - # Set up output redirection without log files - # Copy stdout to fd 3 - exec 3>&1 - if [[ "$VERBOSE" != "True" ]]; then - # Throw away stdout and stderr - exec 1>/dev/null 2>&1 - fi - # Always send summary fd to original stdout - exec 6>&3 -fi - -# Set up logging of screen windows -# Set ``SCREEN_LOGDIR`` to turn on logging of screen windows to the -# directory specified in ``SCREEN_LOGDIR``, we will log to the the file -# ``screen-$SERVICE_NAME-$TIMESTAMP.log`` in that dir and have a link -# ``screen-$SERVICE_NAME.log`` to the latest log file. -# Logs are kept for as long specified in ``LOGDAYS``. -if [[ -n "$SCREEN_LOGDIR" ]]; then - - # We make sure the directory is created. - if [[ -d "$SCREEN_LOGDIR" ]]; then - # We cleanup the old logs - find $SCREEN_LOGDIR -maxdepth 1 -name screen-\*.log -mtime +$LOGDAYS -exec rm {} \; - else - mkdir -p $SCREEN_LOGDIR - fi -fi - - -# Set Up Script Execution -# ----------------------- - -# Kill background processes on exit -trap clean EXIT -clean() { - local r=$? - kill >/dev/null 2>&1 $(jobs -p) - exit $r -} - - -# Exit on any errors so that errors don't compound -trap failed ERR -failed() { - local r=$? - kill >/dev/null 2>&1 $(jobs -p) - set +o xtrace - [ -n "$LOGFILE" ] && echo "${0##*/} failed: full log in $LOGFILE" - exit $r -} - -# Print the commands being run so that we can see the command that triggers -# an error. It is also useful for following along as the install occurs. -set -o xtrace - - -# Install Packages -# ================ - -# OpenStack uses a fair number of other projects. - -# Install package requirements -# Source it so the entire environment is available -echo_summary "Installing package prerequisites" -source $TOP_DIR/tools/install_prereqs.sh - -# Configure an appropriate python environment -if [[ "$OFFLINE" != "True" ]]; then - $TOP_DIR/tools/install_pip.sh -fi - -# Do the ugly hacks for borken packages and distros -$TOP_DIR/tools/fixup_stuff.sh - -install_rpc_backend - -if is_service_enabled $DATABASE_BACKENDS; then - install_database -fi - -if is_service_enabled neutron; then - install_neutron_agent_packages -fi - -TRACK_DEPENDS=${TRACK_DEPENDS:-False} - -# Install python packages into a virtualenv so that we can track them -if [[ $TRACK_DEPENDS = True ]]; then - echo_summary "Installing Python packages into a virtualenv $DEST/.venv" - pip_install -U virtualenv - - rm -rf $DEST/.venv - virtualenv --system-site-packages $DEST/.venv - source $DEST/.venv/bin/activate - $DEST/.venv/bin/pip freeze > $DEST/requires-pre-pip -fi - -# Check Out and Install Source -# ---------------------------- - -echo_summary "Installing OpenStack project source" - -# Install required infra support libraries -install_infra - -# Install oslo libraries that have graduated -install_oslo - -# Install stackforge libraries for testing -if is_service_enabled stackforge_libs; then - install_stackforge -fi - -# Install clients libraries -install_keystoneclient -install_glanceclient -install_cinderclient -install_novaclient -if is_service_enabled swift glance horizon; then - install_swiftclient -fi -if is_service_enabled neutron nova horizon; then - install_neutronclient -fi -if is_service_enabled heat horizon; then - install_heatclient -fi - -git_clone $OPENSTACKCLIENT_REPO $OPENSTACKCLIENT_DIR $OPENSTACKCLIENT_BRANCH -setup_develop $OPENSTACKCLIENT_DIR - -if is_service_enabled key; then - install_keystone - configure_keystone -fi - -if is_service_enabled s-proxy; then - install_swift - configure_swift - - # swift3 middleware to provide S3 emulation to Swift - if is_service_enabled swift3; then - # replace the nova-objectstore port by the swift port - S3_SERVICE_PORT=8080 - git_clone $SWIFT3_REPO $SWIFT3_DIR $SWIFT3_BRANCH - setup_develop $SWIFT3_DIR - fi -fi - -if is_service_enabled g-api n-api; then - # image catalog service - install_glance - configure_glance -fi - -if is_service_enabled cinder; then - install_cinder - configure_cinder -fi - -if is_service_enabled neutron; then - install_neutron - install_neutron_third_party -fi - -if is_service_enabled nova; then - # compute service - install_nova - cleanup_nova - configure_nova -fi - -if is_service_enabled horizon; then - # dashboard - install_horizon - configure_horizon -fi - -if is_service_enabled ceilometer; then - install_ceilometerclient - install_ceilometer - echo_summary "Configuring Ceilometer" - configure_ceilometer - configure_ceilometerclient -fi - -if is_service_enabled heat; then - install_heat - cleanup_heat - configure_heat -fi - -if is_service_enabled tls-proxy; then - configure_CA - init_CA - init_cert - # Add name to /etc/hosts - # don't be naive and add to existing line! -fi - -if is_service_enabled ir-api ir-cond; then - install_ironic - install_ironicclient - configure_ironic -fi - -# Extras Install -# -------------- - -# Phase: install -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i stack install - done -fi - -if [[ $TRACK_DEPENDS = True ]]; then - $DEST/.venv/bin/pip freeze > $DEST/requires-post-pip - if ! diff -Nru $DEST/requires-pre-pip $DEST/requires-post-pip > $DEST/requires.diff; then - echo "Detect some changes for installed packages of pip, in depend tracking mode" - cat $DEST/requires.diff - fi - echo "Ran stack.sh in depend tracking mode, bailing out now" - exit 0 -fi - - -# Syslog -# ------ - -if [[ $SYSLOG != "False" ]]; then - if [[ "$SYSLOG_HOST" = "$HOST_IP" ]]; then - # Configure the master host to receive - cat </tmp/90-stack-m.conf -\$ModLoad imrelp -\$InputRELPServerRun $SYSLOG_PORT -EOF - sudo mv /tmp/90-stack-m.conf /etc/rsyslog.d - else - # Set rsyslog to send to remote host - cat </tmp/90-stack-s.conf -*.* :omrelp:$SYSLOG_HOST:$SYSLOG_PORT -EOF - sudo mv /tmp/90-stack-s.conf /etc/rsyslog.d - fi - - RSYSLOGCONF="/etc/rsyslog.conf" - if [ -f $RSYSLOGCONF ]; then - sudo cp -b $RSYSLOGCONF $RSYSLOGCONF.bak - if [[ $(grep '$SystemLogRateLimitBurst' $RSYSLOGCONF) ]]; then - sudo sed -i 's/$SystemLogRateLimitBurst\ .*/$SystemLogRateLimitBurst\ 0/' $RSYSLOGCONF - else - sudo sed -i '$ i $SystemLogRateLimitBurst\ 0' $RSYSLOGCONF - fi - if [[ $(grep '$SystemLogRateLimitInterval' $RSYSLOGCONF) ]]; then - sudo sed -i 's/$SystemLogRateLimitInterval\ .*/$SystemLogRateLimitInterval\ 0/' $RSYSLOGCONF - else - sudo sed -i '$ i $SystemLogRateLimitInterval\ 0' $RSYSLOGCONF - fi - fi - - echo_summary "Starting rsyslog" - restart_service rsyslog -fi - - -# Finalize queue installation -# ---------------------------- -restart_rpc_backend - - -# Export Certicate Authority Bundle -# --------------------------------- - -# If certificates were used and written to the SSL bundle file then these -# should be exported so clients can validate their connections. - -if [ -f $SSL_BUNDLE_FILE ]; then - export OS_CACERT=$SSL_BUNDLE_FILE -fi - - -# Configure database -# ------------------ - -if is_service_enabled $DATABASE_BACKENDS; then - configure_database -fi - - -# Configure screen -# ---------------- - -USE_SCREEN=$(trueorfalse True $USE_SCREEN) -if [[ "$USE_SCREEN" == "True" ]]; then - # Create a new named screen to run processes in - screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash - sleep 1 - - # Set a reasonable status bar - if [ -z "$SCREEN_HARDSTATUS" ]; then - SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})' - fi - screen -r $SCREEN_NAME -X hardstatus alwayslastline "$SCREEN_HARDSTATUS" - screen -r $SCREEN_NAME -X setenv PROMPT_COMMAND /bin/true -fi - -# Clear screen rc file -SCREENRC=$TOP_DIR/$SCREEN_NAME-screenrc -if [[ -e $SCREENRC ]]; then - rm -f $SCREENRC -fi - -# Initialize the directory for service status check -init_service_check - - -# Sysstat -# ------- - -# If enabled, systat has to start early to track OpenStack service startup. -if is_service_enabled sysstat; then - # what we want to measure - # -u : cpu statitics - # -q : load - # -b : io load rates - # -w : process creation and context switch rates - SYSSTAT_OPTS="-u -q -b -w" - if [[ -n ${SCREEN_LOGDIR} ]]; then - screen_it sysstat "cd $TOP_DIR; ./tools/sar_filter.py $SYSSTAT_OPTS -o $SCREEN_LOGDIR/$SYSSTAT_FILE $SYSSTAT_INTERVAL" - else - screen_it sysstat "./tools/sar_filter.py $SYSSTAT_OPTS $SYSSTAT_INTERVAL" - fi -fi - -if is_service_enabled pidstat; then - # Per-process stats - PIDSTAT_OPTS="-l -p ALL -T ALL" - if [[ -n ${SCREEN_LOGDIR} ]]; then - screen_it pidstat "cd $TOP_DIR; pidstat $PIDSTAT_OPTS $PIDSTAT_INTERVAL > $SCREEN_LOGDIR/$PIDSTAT_FILE" - else - screen_it pidstat "pidstat $PIDSTAT_OPTS $PIDSTAT_INTERVAL" - fi -fi - - -# Start Services -# ============== - -# Keystone -# -------- - -if is_service_enabled key; then - echo_summary "Starting Keystone" - init_keystone - start_keystone - - # Set up a temporary admin URI for Keystone - SERVICE_ENDPOINT=$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v2.0 - - if is_service_enabled tls-proxy; then - export OS_CACERT=$INT_CA_DIR/ca-chain.pem - # Until the client support is fixed, just use the internal endpoint - SERVICE_ENDPOINT=http://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT_INT/v2.0 - fi - - # Do the keystone-specific bits from keystone_data.sh - export OS_SERVICE_TOKEN=$SERVICE_TOKEN - export OS_SERVICE_ENDPOINT=$SERVICE_ENDPOINT - create_keystone_accounts - create_nova_accounts - create_cinder_accounts - create_neutron_accounts - - if is_service_enabled ceilometer; then - create_ceilometer_accounts - fi - - if is_service_enabled swift || is_service_enabled s-proxy; then - create_swift_accounts - fi - - # ``keystone_data.sh`` creates services, admin and demo users, and roles. - ADMIN_PASSWORD=$ADMIN_PASSWORD SERVICE_TENANT_NAME=$SERVICE_TENANT_NAME SERVICE_PASSWORD=$SERVICE_PASSWORD \ - SERVICE_TOKEN=$SERVICE_TOKEN SERVICE_ENDPOINT=$SERVICE_ENDPOINT SERVICE_HOST=$SERVICE_HOST \ - S3_SERVICE_PORT=$S3_SERVICE_PORT KEYSTONE_CATALOG_BACKEND=$KEYSTONE_CATALOG_BACKEND \ - DEVSTACK_DIR=$TOP_DIR ENABLED_SERVICES=$ENABLED_SERVICES HEAT_API_CFN_PORT=$HEAT_API_CFN_PORT \ - HEAT_API_PORT=$HEAT_API_PORT \ - bash -x $FILES/keystone_data.sh - - # Set up auth creds now that keystone is bootstrapped - export OS_AUTH_URL=$SERVICE_ENDPOINT - export OS_TENANT_NAME=admin - export OS_USERNAME=admin - export OS_PASSWORD=$ADMIN_PASSWORD - unset OS_SERVICE_TOKEN OS_SERVICE_ENDPOINT -fi - - -# Horizon -# ------- - -# Set up the django horizon application to serve via apache/wsgi - -if is_service_enabled horizon; then - echo_summary "Configuring and starting Horizon" - init_horizon - start_horizon -fi - - -# Glance -# ------ - -if is_service_enabled g-reg; then - echo_summary "Configuring Glance" - init_glance -fi - - -# Ironic -# ------ - -if is_service_enabled ir-api ir-cond; then - echo_summary "Configuring Ironic" - init_ironic -fi - - -# Neutron -# ------- - -if is_service_enabled neutron; then - echo_summary "Configuring Neutron" - - configure_neutron - # Run init_neutron only on the node hosting the neutron API server - if is_service_enabled $DATABASE_BACKENDS && is_service_enabled q-svc; then - init_neutron - fi -fi - -# Some Neutron plugins require network controllers which are not -# a part of the OpenStack project. Configure and start them. -if is_service_enabled neutron; then - configure_neutron_third_party - init_neutron_third_party - start_neutron_third_party -fi - - -# Nova -# ---- - -if is_service_enabled n-net q-dhcp; then - # Delete traces of nova networks from prior runs - # Do not kill any dnsmasq instance spawned by NetworkManager - netman_pid=$(pidof NetworkManager || true) - if [ -z "$netman_pid" ]; then - sudo killall dnsmasq || true - else - sudo ps h -o pid,ppid -C dnsmasq | grep -v $netman_pid | awk '{print $1}' | sudo xargs kill || true - fi - - clean_iptables - rm -rf ${NOVA_STATE_PATH}/networks - sudo mkdir -p ${NOVA_STATE_PATH}/networks - safe_chown -R ${USER} ${NOVA_STATE_PATH}/networks - # Force IP forwarding on, just in case - sudo sysctl -w net.ipv4.ip_forward=1 -fi - - -# Storage Service -# --------------- - -if is_service_enabled s-proxy; then - echo_summary "Configuring Swift" - init_swift -fi - - -# Volume Service -# -------------- - -if is_service_enabled cinder; then - echo_summary "Configuring Cinder" - init_cinder -fi - - -# Compute Service -# --------------- - -if is_service_enabled nova; then - echo_summary "Configuring Nova" - init_nova - - # Additional Nova configuration that is dependent on other services - if is_service_enabled neutron; then - create_nova_conf_neutron - elif is_service_enabled n-net; then - create_nova_conf_nova_network - fi - - init_nova_cells -fi - -# Extra things to prepare nova for baremetal, before nova starts -if is_service_enabled nova && is_baremetal; then - echo_summary "Preparing for nova baremetal" - prepare_baremetal_toolchain - configure_baremetal_nova_dirs - if [[ "$BM_USE_FAKE_ENV" = "True" ]]; then - create_fake_baremetal_env - fi -fi - - -# Extras Configuration -# ==================== - -# Phase: post-config -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i stack post-config - done -fi - - -# Local Configuration -# =================== - -# Apply configuration from local.conf if it exists for layer 2 services -# Phase: post-config -merge_config_group $TOP_DIR/local.conf post-config - - -# Launch Services -# =============== - -# Only run the services specified in ``ENABLED_SERVICES`` - -# Launch Swift Services -if is_service_enabled s-proxy; then - echo_summary "Starting Swift" - start_swift -fi - -# Launch the Glance services -if is_service_enabled g-api g-reg; then - echo_summary "Starting Glance" - start_glance -fi - -# Launch the Ironic services -if is_service_enabled ir-api ir-cond; then - echo_summary "Starting Ironic" - start_ironic -fi - -# Create an access key and secret key for nova ec2 register image -if is_service_enabled key && is_service_enabled swift3 && is_service_enabled nova; then - NOVA_USER_ID=$(keystone user-list | grep ' nova ' | get_field 1) - die_if_not_set $LINENO NOVA_USER_ID "Failure retrieving NOVA_USER_ID for nova" - NOVA_TENANT_ID=$(keystone tenant-list | grep " $SERVICE_TENANT_NAME " | get_field 1) - die_if_not_set $LINENO NOVA_TENANT_ID "Failure retrieving NOVA_TENANT_ID for $SERVICE_TENANT_NAME" - CREDS=$(keystone ec2-credentials-create --user-id $NOVA_USER_ID --tenant-id $NOVA_TENANT_ID) - ACCESS_KEY=$(echo "$CREDS" | awk '/ access / { print $4 }') - SECRET_KEY=$(echo "$CREDS" | awk '/ secret / { print $4 }') - iniset $NOVA_CONF DEFAULT s3_access_key "$ACCESS_KEY" - iniset $NOVA_CONF DEFAULT s3_secret_key "$SECRET_KEY" - iniset $NOVA_CONF DEFAULT s3_affix_tenant "True" -fi - -# Create a randomized default value for the keymgr's fixed_key -if is_service_enabled nova; then - FIXED_KEY="" - for i in $(seq 1 64); - do FIXED_KEY+=$(echo "obase=16; $(($RANDOM % 16))" | bc); - done; - iniset $NOVA_CONF keymgr fixed_key "$FIXED_KEY" -fi - -if is_service_enabled zeromq; then - echo_summary "Starting zermomq receiver" - screen_it zeromq "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-rpc-zmq-receiver" -fi - -# Launch the nova-api and wait for it to answer before continuing -if is_service_enabled n-api; then - echo_summary "Starting Nova API" - start_nova_api -fi - -if is_service_enabled q-svc; then - echo_summary "Starting Neutron" - start_neutron_service_and_check - check_neutron_third_party_integration -elif is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-net; then - NM_CONF=${NOVA_CONF} - if is_service_enabled n-cell; then - NM_CONF=${NOVA_CELLS_CONF} - fi - - # Create a small network - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF network create "$PRIVATE_NETWORK_NAME" $FIXED_RANGE 1 $FIXED_NETWORK_SIZE $NETWORK_CREATE_ARGS - - # Create some floating ips - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create $FLOATING_RANGE --pool=$PUBLIC_NETWORK_NAME - - # Create a second pool - $NOVA_BIN_DIR/nova-manage --config-file $NM_CONF floating create --ip_range=$TEST_FLOATING_RANGE --pool=$TEST_FLOATING_POOL -fi - -if is_service_enabled neutron; then - start_neutron_agents -fi -# Once neutron agents are started setup initial network elements -if is_service_enabled q-svc; then - echo_summary "Creating initial neutron network elements" - create_neutron_initial_network - setup_neutron_debug -fi -if is_service_enabled nova; then - echo_summary "Starting Nova" - start_nova -fi -if is_service_enabled cinder; then - echo_summary "Starting Cinder" - start_cinder -fi -if is_service_enabled ceilometer; then - echo_summary "Starting Ceilometer" - init_ceilometer - start_ceilometer -fi - -# Configure and launch heat engine, api and metadata -if is_service_enabled heat; then - # Initialize heat, including replacing nova flavors - echo_summary "Configuring Heat" - init_heat - echo_summary "Starting Heat" - start_heat -fi - - -# Create account rc files -# ======================= - -# Creates source able script files for easier user switching. -# This step also creates certificates for tenants and users, -# which is helpful in image bundle steps. - -if is_service_enabled nova && is_service_enabled key; then - USERRC_PARAMS="-PA --target-dir $TOP_DIR/accrc" - - if [ -f $SSL_BUNDLE_FILE ]; then - USERRC_PARAMS="$USERRC_PARAMS --os-cacert $SSL_BUNDLE_FILE" - fi - - $TOP_DIR/tools/create_userrc.sh $USERRC_PARAMS -fi - - -# Install Images -# ============== - -# Upload an image to glance. -# -# The default image is cirros, a small testing image which lets you login as **root** -# cirros has a ``cloud-init`` analog supporting login via keypair and sending -# scripts as userdata. -# See https://help.ubuntu.com/community/CloudInit for more on cloud-init -# -# Override ``IMAGE_URLS`` with a comma-separated list of UEC images. -# * **precise**: http://uec-images.ubuntu.com/precise/current/precise-server-cloudimg-amd64.tar.gz - -if is_service_enabled g-reg; then - TOKEN=$(keystone token-get | grep ' id ' | get_field 2) - die_if_not_set $LINENO TOKEN "Keystone fail to get token" - - if is_baremetal; then - echo_summary "Creating and uploading baremetal images" - - # build and upload separate deploy kernel & ramdisk - upload_baremetal_deploy $TOKEN - - # upload images, separating out the kernel & ramdisk for PXE boot - for image_url in ${IMAGE_URLS//,/ }; do - upload_baremetal_image $image_url $TOKEN - done - else - echo_summary "Uploading images" - - # Option to upload legacy ami-tty, which works with xenserver - if [[ -n "$UPLOAD_LEGACY_TTY" ]]; then - IMAGE_URLS="${IMAGE_URLS:+${IMAGE_URLS},}https://github.com/downloads/citrix-openstack/warehouse/tty.tgz" - fi - - for image_url in ${IMAGE_URLS//,/ }; do - upload_image $image_url $TOKEN - done - fi -fi - -# If we are running nova with baremetal driver, there are a few -# last-mile configuration bits to attend to, which must happen -# after n-api and n-sch have started. -# Also, creating the baremetal flavor must happen after images -# are loaded into glance, though just knowing the IDs is sufficient here -if is_service_enabled nova && is_baremetal; then - # create special flavor for baremetal if we know what images to associate - [[ -n "$BM_DEPLOY_KERNEL_ID" ]] && [[ -n "$BM_DEPLOY_RAMDISK_ID" ]] && \ - create_baremetal_flavor $BM_DEPLOY_KERNEL_ID $BM_DEPLOY_RAMDISK_ID - - # otherwise user can manually add it later by calling nova-baremetal-manage - [[ -n "$BM_FIRST_MAC" ]] && add_baremetal_node - - if [[ "$BM_DNSMASQ_FROM_NOVA_NETWORK" = "False" ]]; then - # NOTE: we do this here to ensure that our copy of dnsmasq is running - sudo pkill dnsmasq || true - sudo dnsmasq --conf-file= --port=0 --enable-tftp --tftp-root=/tftpboot \ - --dhcp-boot=pxelinux.0 --bind-interfaces --pid-file=/var/run/dnsmasq.pid \ - --interface=$BM_DNSMASQ_IFACE --dhcp-range=$BM_DNSMASQ_RANGE \ - ${BM_DNSMASQ_DNS:+--dhcp-option=option:dns-server,$BM_DNSMASQ_DNS} - fi - # ensure callback daemon is running - sudo pkill nova-baremetal-deploy-helper || true - screen_it baremetal "cd ; nova-baremetal-deploy-helper" -fi - -# Save some values we generated for later use -CURRENT_RUN_TIME=$(date "+$TIMESTAMP_FORMAT") -echo "# $CURRENT_RUN_TIME" >$TOP_DIR/.stackenv -for i in BASE_SQL_CONN ENABLED_SERVICES HOST_IP LOGFILE \ - SERVICE_HOST SERVICE_PROTOCOL STACK_USER TLS_IP KEYSTONE_AUTH_PROTOCOL OS_CACERT; do - echo $i=${!i} >>$TOP_DIR/.stackenv -done - - -# Local Configuration -# =================== - -# Apply configuration from local.conf if it exists for layer 2 services -# Phase: extra -merge_config_group $TOP_DIR/local.conf extra - - -# Run extras -# ========== - -# Phase: extra -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i stack extra - done -fi - -# Local Configuration -# =================== - -# Apply configuration from local.conf if it exists for layer 2 services -# Phase: post-extra -merge_config_group $TOP_DIR/local.conf post-extra - - -# Run local script -# ================ - -# Run ``local.sh`` if it exists to perform user-managed tasks -if [[ -x $TOP_DIR/local.sh ]]; then - echo "Running user script $TOP_DIR/local.sh" - $TOP_DIR/local.sh -fi - -# Check the status of running services -service_check - - -# Fin -# === - -set +o xtrace - -if [[ -n "$LOGFILE" ]]; then - exec 1>&3 - # Force all output to stdout and logs now - exec 1> >( tee -a "${LOGFILE}" ) 2>&1 -else - # Force all output to stdout now - exec 1>&3 -fi - - -# Using the cloud -# --------------- - -echo "" -echo "" -echo "" - -# If you installed Horizon on this server you should be able -# to access the site using your browser. -if is_service_enabled horizon; then - echo "Horizon is now available at http://$SERVICE_HOST/" -fi - -# Warn that the default flavors have been changed by Heat -if is_service_enabled heat; then - echo "Heat has replaced the default flavors. View by running: nova flavor-list" -fi - -# If Keystone is present you can point ``nova`` cli to this server -if is_service_enabled key; then - echo "Keystone is serving at $KEYSTONE_AUTH_PROTOCOL://$SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/" - echo "Examples on using novaclient command line is in exercise.sh" - echo "The default users are: admin and demo" - echo "The password: $ADMIN_PASSWORD" -fi - -# Echo ``HOST_IP`` - useful for ``build_uec.sh``, which uses dhcp to give the instance an address -echo "This is your host ip: $HOST_IP" - -# Warn that a deprecated feature was used -if [[ -n "$DEPRECATED_TEXT" ]]; then - echo_summary "WARNING: $DEPRECATED_TEXT" -fi - -# Specific warning for deprecated configs -if [[ -n "$EXTRA_OPTS" ]]; then - echo "" - echo_summary "WARNING: EXTRA_OPTS is used" - echo "You are using EXTRA_OPTS to pass configuration into nova.conf." - echo "Please convert that configuration in localrc to a nova.conf section in local.conf:" - echo " -[[post-config|\$NOVA_CONF]] -[DEFAULT] -" - for I in "${EXTRA_OPTS[@]}"; do - # Replace the first '=' with ' ' for iniset syntax - echo ${I} - done -fi - -if [[ -n "$EXTRA_BAREMETAL_OPTS" ]]; then - echo "" - echo_summary "WARNING: EXTRA_OPTS is used" - echo "You are using EXTRA_OPTS to pass configuration into nova.conf." - echo "Please convert that configuration in localrc to a nova.conf section in local.conf:" - echo " -[[post-config|\$NOVA_CONF]] -[baremetal] -" - for I in "${EXTRA_BAREMETAL_OPTS[@]}"; do - # Replace the first '=' with ' ' for iniset syntax - echo ${I} - done -fi - -if [[ -n "$Q_DHCP_EXTRA_DEFAULT_OPTS" ]]; then - echo "" - echo_summary "WARNING: Q_DHCP_EXTRA_DEFAULT_OPTS is used" - echo "You are using Q_DHCP_EXTRA_DEFAULT_OPTS to pass configuration into $Q_DHCP_CONF_FILE." - echo "Please convert that configuration in localrc to a $Q_DHCP_CONF_FILE section in local.conf:" - echo " -[[post-config|\$Q_DHCP_CONF_FILE]] -[DEFAULT] -" - for I in "${Q_DHCP_EXTRA_DEFAULT_OPTS[@]}"; do - # Replace the first '=' with ' ' for iniset syntax - echo ${I} - done -fi - -if [[ -n "$Q_SRV_EXTRA_DEFAULT_OPTS" ]]; then - echo "" - echo_summary "WARNING: Q_SRV_EXTRA_DEFAULT_OPTS is used" - echo "You are using Q_SRV_EXTRA_DEFAULT_OPTS to pass configuration into $NEUTRON_CONF." - echo "Please convert that configuration in localrc to a $NEUTRON_CONF section in local.conf:" - echo " -[[post-config|\$NEUTRON_CONF]] -[DEFAULT] -" - for I in "${Q_SRV_EXTRA_DEFAULT_OPTS[@]}"; do - # Replace the first '=' with ' ' for iniset syntax - echo ${I} - done -fi - -# Indicate how long this took to run (bash maintained variable ``SECONDS``) -echo_summary "stack.sh completed in $SECONDS seconds." diff --git a/unstack.sh b/unstack.sh deleted file mode 100755 index 92d0642c38..0000000000 --- a/unstack.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env bash - -# **unstack.sh** - -# Stops that which is started by ``stack.sh`` (mostly) -# mysql and rabbit are left running as OpenStack code refreshes -# do not require them to be restarted. -# -# Stop all processes by setting ``UNSTACK_ALL`` or specifying ``--all`` -# on the command line - -# Keep track of the current devstack directory. -TOP_DIR=$(cd $(dirname "$0") && pwd) - -# Import common functions -source $TOP_DIR/functions - -# Import database library -source $TOP_DIR/lib/database - -# Load local configuration -source $TOP_DIR/stackrc - -# Destination path for service data -DATA_DIR=${DATA_DIR:-${DEST}/data} - -if [[ $EUID -eq 0 ]]; then - echo "You are running this script as root." - echo "It might work but you will have a better day running it as $STACK_USER" - exit 1 -fi - - -# Configure Projects -# ================== - -# Import apache functions -source $TOP_DIR/lib/apache - -# Import TLS functions -source $TOP_DIR/lib/tls - -# Source project function libraries -source $TOP_DIR/lib/infra -source $TOP_DIR/lib/oslo -source $TOP_DIR/lib/stackforge -source $TOP_DIR/lib/horizon -source $TOP_DIR/lib/keystone -source $TOP_DIR/lib/glance -source $TOP_DIR/lib/nova -source $TOP_DIR/lib/cinder -source $TOP_DIR/lib/swift -source $TOP_DIR/lib/ceilometer -source $TOP_DIR/lib/heat -source $TOP_DIR/lib/neutron -source $TOP_DIR/lib/baremetal -source $TOP_DIR/lib/ldap -source $TOP_DIR/lib/ironic - -# Extras Source -# -------------- - -# Phase: source -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i source - done -fi - -# Determine what system we are running on. This provides ``os_VENDOR``, -# ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME`` -GetOSVersion - -if [[ "$1" == "--all" ]]; then - UNSTACK_ALL=${UNSTACK_ALL:-1} -fi - -# Run extras -# ========== - -# Phase: unstack -if [[ -d $TOP_DIR/extras.d ]]; then - for i in $TOP_DIR/extras.d/*.sh; do - [[ -r $i ]] && source $i unstack - done -fi - -if [[ "$Q_USE_DEBUG_COMMAND" == "True" ]]; then - source $TOP_DIR/openrc - teardown_neutron_debug -fi - -# Call service stop - -if is_service_enabled heat; then - stop_heat -fi - -if is_service_enabled ceilometer; then - stop_ceilometer -fi - -if is_service_enabled nova; then - stop_nova -fi - -if is_service_enabled g-api g-reg; then - stop_glance -fi - -if is_service_enabled key; then - stop_keystone -fi - -# Swift runs daemons -if is_service_enabled s-proxy; then - stop_swift - cleanup_swift -fi - -# Ironic runs daemons -if is_service_enabled ir-api ir-cond; then - stop_ironic - cleanup_ironic -fi - -# Apache has the WSGI processes -if is_service_enabled horizon; then - stop_horizon -fi - -# Kill TLS proxies -if is_service_enabled tls-proxy; then - killall stud -fi - -# baremetal might have created a fake environment -if is_service_enabled baremetal && [[ "$BM_USE_FAKE_ENV" = "True" ]]; then - cleanup_fake_baremetal_env -fi - -SCSI_PERSIST_DIR=$CINDER_STATE_PATH/volumes/* - -# Get the iSCSI volumes -if is_service_enabled cinder; then - stop_cinder - cleanup_cinder -fi - -if [[ -n "$UNSTACK_ALL" ]]; then - # Stop MySQL server - if is_service_enabled mysql; then - stop_service mysql - fi - - if is_service_enabled postgresql; then - stop_service postgresql - fi - - # Stop rabbitmq-server - if is_service_enabled rabbit; then - stop_service rabbitmq-server - fi -fi - -if is_service_enabled neutron; then - stop_neutron - stop_neutron_third_party - cleanup_neutron -fi - -if is_service_enabled trove; then - cleanup_trove -fi - -# Clean up the remainder of the screen processes -SCREEN=$(which screen) -if [[ -n "$SCREEN" ]]; then - SESSION=$(screen -ls | awk '/[0-9].stack/ { print $1 }') - if [[ -n "$SESSION" ]]; then - screen -X -S $SESSION quit - fi -fi - -cleanup_tmp