Enforcing virtual routers, config/analytics/database nodes
Change-Id: I33f003e6fd9062a04a3c6f69621591ff5757a513
diff --git a/_modules/contrail.py b/_modules/contrail.py
new file mode 100644
index 0000000..2cd1747
--- /dev/null
+++ b/_modules/contrail.py
@@ -0,0 +1,506 @@
+#!/usr/bin/python
+# Copyright 2017 Mirantis, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from netaddr import IPNetwork
+
+try:
+ from vnc_api import vnc_api
+ from vnc_api.gen.resource_client import VirtualRouter, AnalyticsNode, \
+ ConfigNode, DatabaseNode, BgpRouter
+ from vnc_api.gen.resource_xsd import AddressFamilies, BgpSessionAttributes, \
+ BgpSession, BgpPeeringAttributes, BgpRouterParams
+ HAS_CONTRAIL = True
+except ImportError:
+ HAS_CONTRAIL = False
+
+__opts__ = {}
+
+
+def __virtual__():
+ '''
+ Only load this module if vnc_api library is installed.
+ '''
+ if HAS_CONTRAIL:
+ return 'contrail'
+
+ return False
+
+
+def _auth(**kwargs):
+ '''
+ Set up Contrail API credentials.
+ '''
+ user = kwargs.get('user')
+ password = kwargs.get('password')
+ tenant_name = kwargs.get('project')
+ api_host = kwargs.get('api_server_ip')
+ api_port = kwargs.get('api_server_port')
+ api_base_url = kwargs.get('api_base_url')
+ use_ssl = False
+ auth_host = kwargs.get('auth_host_ip')
+ vnc_lib = vnc_api.VncApi(user, password, tenant_name,
+ api_host, api_port, api_base_url, wait_for_connect=True,
+ api_server_use_ssl=use_ssl, auth_host=auth_host)
+
+ return vnc_lib
+
+
+def _get_config(vnc_client, global_system_config = 'default-global-system-config'):
+ try:
+ gsc_obj = vnc_client.global_system_config_read(id=global_system_config)
+ except vnc_api.NoIdError:
+ gsc_obj = vnc_client.global_system_config_read(fq_name_str=global_system_config)
+ except:
+ gsc_obj = None
+
+ return gsc_obj
+
+
+def _get_rt_inst_obj(vnc_client):
+
+ # TODO pick fqname hardcode from common
+ rt_inst_obj = vnc_client.routing_instance_read(
+ fq_name=['default-domain', 'default-project',
+ 'ip-fabric', '__default__'])
+
+ return rt_inst_obj
+
+
+def _get_ip(ip_w_pfx):
+ return str(IPNetwork(ip_w_pfx).ip)
+
+
+
+def virtual_router_list(**kwargs):
+ '''
+ Return a list of all Contrail virtual routers
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.virtual_router_list
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ vrouter_objs = vnc_client._objects_list('virtual-router', detail=True)
+ for vrouter_obj in vrouter_objs:
+ ret[vrouter_obj.name] = {
+ 'ip_address': vrouter_obj.virtual_router_ip_address,
+ 'dpdk_enabled': vrouter_obj.virtual_router_dpdk_enabled
+ }
+ return ret
+
+
+def virtual_router_get(name, **kwargs):
+ '''
+ Return a specific Contrail virtual router
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.virtual_router_get cmp01
+ '''
+ ret = {}
+ vrouter_objs = virtual_router_list(**kwargs)
+ if name in vrouter_objs:
+ ret[name] = vrouter_objs.get(name)
+ if len(ret) == 0:
+ return {'Error': 'Error in retrieving virtual router.'}
+ return ret
+
+
+def virtual_router_create(name, ip_address, dpdk_enabled=False, **kwargs):
+ '''
+ Create specific Contrail virtual router
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.virtual_router_create cmp02 10.10.10.102
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ vrouter_objs = virtual_router_list(**kwargs)
+ if name in vrouter_objs:
+ return {'Error': 'Virtual router %s already exists' % name}
+ else:
+ vrouter_obj = VirtualRouter(
+ name, gsc_obj,
+ virtual_router_ip_address=ip_address)
+ vrouter_obj.set_virtual_router_dpdk_enabled(dpdk_enabled)
+ vnc_client.virtual_router_create(vrouter_obj)
+ ret = virtual_router_list(**kwargs)
+ return ret[name]
+
+
+def virtual_router_delete(name, **kwargs):
+ '''
+ Delete specific Contrail virtual router
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.virtual_router_delete cmp01
+ '''
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ vrouter_obj = VirtualRouter(name, gsc_obj)
+ vnc_client.virtual_router_delete(
+ fq_name=vrouter_obj.get_fq_name())
+
+
+def analytics_node_list(**kwargs):
+ '''
+ Return a list of all Contrail analytics nodes
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.analytics_node_list
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ node_objs = vnc_client._objects_list('analytics-node', detail=True)
+ for node_obj in node_objs:
+ ret[node_obj.name] = node_obj.__dict__
+ return ret
+
+
+def analytics_node_get(name, **kwargs):
+ '''
+ Return a specific Contrail analytics node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.analytics_node_get nal01
+ '''
+ ret = {}
+ vrouter_objs = analytics_node_list(**kwargs)
+ if name in vrouter_objs:
+ ret[name] = vrouter_objs.get(name)
+ if len(ret) == 0:
+ return {'Error': 'Error in retrieving analytics node.'}
+ return ret
+
+
+def analytics_node_create(name, ip_address, **kwargs):
+ '''
+ Create specific Contrail analytics node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.analytics_node_create ntw03 10.10.10.103
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ analytics_node_objs = analytics_node_list(**kwargs)
+ if name in analytics_node_objs:
+ return {'Error': 'Analytics node %s already exists' % name}
+ else:
+ analytics_node_obj = AnalyticsNode(
+ name, gsc_obj,
+ analytics_node_ip_address=ip_address)
+ vnc_client.analytics_node_create(analytics_node_obj)
+ ret = analytics_node_list(**kwargs)
+ return ret[name]
+
+
+def analytics_node_delete(name, **kwargs):
+ '''
+ Delete specific Contrail analytics node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.analytics_node_delete cmp01
+ '''
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ analytics_node_obj = AnalyticsNode(name, gsc_obj)
+ vnc_client.analytics_node_delete(
+ fq_name=analytics_node_obj.get_fq_name())
+
+
+def config_node_list(**kwargs):
+ '''
+ Return a list of all Contrail config nodes
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.config_node_list
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ node_objs = vnc_client._objects_list('config-node', detail=True)
+ for node_obj in node_objs:
+ ret[node_obj.name] = node_obj.__dict__
+ return ret
+
+
+def config_node_get(name, **kwargs):
+ '''
+ Return a specific Contrail config node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.config_node_get nal01
+ '''
+ ret = {}
+ vrouter_objs = config_node_list(**kwargs)
+ if name in vrouter_objs:
+ ret[name] = vrouter_objs.get(name)
+ if len(ret) == 0:
+ return {'Error': 'Error in retrieving config node.'}
+ return ret
+
+
+def config_node_create(name, ip_address, **kwargs):
+ '''
+ Create specific Contrail config node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.config_node_create ntw03 10.10.10.103
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ config_node_objs = config_node_list(**kwargs)
+ if name in config_node_objs:
+ return {'Error': 'Config node %s already exists' % name}
+ else:
+ config_node_obj = ConfigNode(
+ name, gsc_obj,
+ config_node_ip_address=ip_address)
+ vnc_client.config_node_create(config_node_obj)
+ ret = config_node_list(**kwargs)
+ return ret[name]
+
+
+def config_node_delete(name, **kwargs):
+ '''
+ Delete specific Contrail config node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.config_node_delete cmp01
+ '''
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ config_node_obj = ConfigNode(name, gsc_obj)
+ vnc_client.config_node_delete(
+ fq_name=config_node_obj.get_fq_name())
+
+
+def bgp_router_list(**kwargs):
+ '''
+ Return a list of all Contrail BGP routers
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.bgp_router_list
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ bgp_router_objs = vnc_client._objects_list('bgp-router', detail=True)
+ for bgp_router_obj in bgp_router_objs:
+ ret[bgp_router_obj.name] = bgp_router_obj.__dict__
+ return ret
+
+
+def bgp_router_get(name, **kwargs):
+ '''
+ Return a specific Contrail BGP router
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.bgp_router_get nal01
+ '''
+ ret = {}
+ bgp_router_objs = bgp_router_list(**kwargs)
+ if name in bgp_router_objs:
+ ret[name] = bgp_router_objs.get(name)
+ if len(ret) == 0:
+ return {'Error': 'Error in retrieving BGP router.'}
+ return ret
+
+
+def bgp_router_create(name, type, ip_address, asn=64512, **kwargs):
+ '''
+ Create specific Contrail control node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.bgp_router_create ntw03 control-node 10.10.10.103
+ salt '*' contrail.bgp_router_create mx01 router 10.10.10.105
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+
+ bgp_router_objs = bgp_router_list(**kwargs)
+ if name in bgp_router_objs:
+ return {'Error': 'control node %s already exists' % name}
+ else:
+ address_families = ['route-target', 'inet-vpn', 'e-vpn', 'erm-vpn',
+ 'inet6-vpn']
+ if type != 'control-node':
+ address_families.remove('erm-vpn')
+
+ bgp_addr_fams = AddressFamilies(address_families)
+ bgp_sess_attrs = [
+ BgpSessionAttributes(address_families=bgp_addr_fams)]
+ bgp_sessions = [BgpSession(attributes=bgp_sess_attrs)]
+ bgp_peering_attrs = BgpPeeringAttributes(session=bgp_sessions)
+ rt_inst_obj = _get_rt_inst_obj(vnc_client)
+
+ if type == 'control-node':
+ vendor = 'contrail'
+ elif type == 'router':
+ vendor = 'mx'
+ else:
+ vendor = 'unknown'
+
+ router_params = BgpRouterParams(router_type=type,
+ vendor=vendor, autonomous_system=int(asn),
+ identifier=_get_ip(ip_address),
+ address=_get_ip(ip_address),
+ port=179, address_families=bgp_addr_fams)
+ bgp_router_obj = BgpRouter(name, rt_inst_obj,
+ bgp_router_parameters=router_params)
+ vnc_client.bgp_router_create(bgp_router_obj)
+ ret = bgp_router_list(**kwargs)
+ return ret[name]
+
+
+def bgp_router_delete(name, **kwargs):
+ '''
+ Delete specific Contrail control node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.bgp_router_delete mx01
+ '''
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_control(vnc_client)
+ bgp_router_obj = BgpRouter(name, gsc_obj)
+ vnc_client.bgp_router_delete(
+ fq_name=bgp_router_obj.get_fq_name())
+
+
+def database_node_list(**kwargs):
+ '''
+ Return a list of all Contrail database nodes
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.database_node_list
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ node_objs = vnc_client._objects_list('database-node', detail=True)
+ for node_obj in node_objs:
+ ret[node_obj.name] = node_obj.__dict__
+ return ret
+
+
+def database_node_get(name, **kwargs):
+ '''
+ Return a specific Contrail database node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.database_node_get nal01
+ '''
+ ret = {}
+ vrouter_objs = database_node_list(**kwargs)
+ if name in vrouter_objs:
+ ret[name] = vrouter_objs.get(name)
+ if len(ret) == 0:
+ return {'Error': 'Error in retrieving database node.'}
+ return ret
+
+
+def database_node_create(name, ip_address, **kwargs):
+ '''
+ Create specific Contrail database node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.database_node_create ntw03 10.10.10.103
+ '''
+ ret = {}
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_config(vnc_client)
+ database_node_objs = database_node_list(**kwargs)
+ if name in database_node_objs:
+ return {'Error': 'Database node %s already exists' % name}
+ else:
+ database_node_obj = DatabaseNode(
+ name, gsc_obj,
+ database_node_ip_address=ip_address)
+ vnc_client.database_node_create(database_node_obj)
+ ret = database_node_list(**kwargs)
+ return ret[name]
+
+
+def database_node_delete(name, **kwargs):
+ '''
+ Delete specific Contrail database node
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' contrail.database_node_delete cmp01
+ '''
+ vnc_client = _auth(**kwargs)
+ gsc_obj = _get_database(vnc_client)
+ database_node_obj = databaseNode(name, gsc_obj)
+ vnc_client.database_node_delete(
+ fq_name=database_node_obj.get_fq_name())