Enforcing virtual routers, config/analytics/database nodes
Change-Id: I33f003e6fd9062a04a3c6f69621591ff5757a513
diff --git a/README.rst b/README.rst
index 574d476..4aae3e1 100644
--- a/README.rst
+++ b/README.rst
@@ -703,30 +703,138 @@
pci: 0000:81:00.1
...
+Contrail client
+---------------
+
+Basic parameters with identity and host configs
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ identity:
+ user: admin
+ project: admin
+ password: adminpass
+ host: keystone_host
+ config:
+ host: contrail_api_host
+ port: contrail_api_ort
+
+Enforcing virtual routers
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ virtual_router:
+ cmp01:
+ ip_address: 172.16.0.11
+ dpdk_enabled: True
+ cmp02:
+ ip_address: 172.16.0.12
+ dpdk_enabled: True
+
+Enforcing control nodes
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ bgp_router:
+ ntw01:
+ type: control-node
+ ip_address: 172.16.0.11
+ nwt02:
+ type: control-node
+ ip_address: 172.16.0.12
+ nwt03:
+ type: control-node
+ ip_address: 172.16.0.13
+
+
+Enforcing edge BGP routers
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ bgp_router:
+ mx01:
+ type: router
+ ip_address: 172.16.0.21
+ asn: 64512
+ mx02:
+ type: router
+ ip_address: 172.16.0.22
+ asn: 64512
+
+Enforcing config nodes
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ config_node:
+ ctl01:
+ ip_address: 172.16.0.21
+ ctl02:
+ ip_address: 172.16.0.22
+
+Enforcing database nodes
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ database_node:
+ ntw01:
+ ip_address: 172.16.0.21
+ ntw02:
+ ip_address: 172.16.0.22
+
+Enforcing analytics nodes
+
+.. code-block:: bash
+
+ opencontrail:
+ client:
+ ...
+ analytics_node:
+ nal01:
+ ip_address: 172.16.0.31
+ nal02:
+ ip_address: 172.16.0.32
+
+
Usage
=====
Basic installation
-==================
+------------------
Add control BGP
-===============
+
+.. code-block:: bash
python /etc/contrail/provision_control.py --api_server_ip 192.168.1.11 --api_server_port 8082 --host_name network1.contrail.domain.com --host_ip 192.168.1.11 --router_asn 64512
-Compute node installation
-=========================
+Install compute node
-.. code-block:: yaml
+.. code-block:: bash
yum install contrail-vrouter contrail-openstack-vrouter
salt-call state.sls nova,opencontrail
Add virtual router
-==================
-.. code-block:: yaml
+.. code-block:: bash
python /etc/contrail/provision_vrouter.py --host_name hostnode1.intra.domain.com --host_ip 10.0.100.101 --api_server_ip 10.0.100.30 --oper add --admin_user admin --admin_password cloudlab --admin_tenant_name admin
@@ -735,7 +843,7 @@
reboot
Service debugging
-=================
+-----------------
Display vhost XMPP connection status
@@ -759,31 +867,6 @@
http://<compute-node>:8085/Snh_SandeshTraceRequest?x=XmppMessageTrace
-Documentation and Bugs
-============================
-
-To learn how to deploy OpenStack Salt, consult the documentation available
-online at:
-
- https://wiki.openstack.org/wiki/OpenStackSalt
-
-In the unfortunate event that bugs are discovered, they should be reported to
-the appropriate bug tracker. If you obtained the software from a 3rd party
-operating system vendor, it is often wise to use their own bug tracker for
-reporting problems. In all other cases use the master OpenStack bug tracker,
-available at:
-
- http://bugs.launchpad.net/openstack-salt
-
-Developers wishing to work on the OpenStack Salt project should always base
-their work on the latest formulas code, available from the master GIT
-repository at:
-
- https://git.openstack.org/cgit/openstack/salt-formula-opencontrail
-
-Developers should also join the discussion on the IRC list, at:
-
- https://wiki.openstack.org/wiki/Meetings/openstack-salt
Documentation and Bugs
======================
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())
diff --git a/_states/contrail.py b/_states/contrail.py
new file mode 100644
index 0000000..f117667
--- /dev/null
+++ b/_states/contrail.py
@@ -0,0 +1,202 @@
+#!/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.
+'''
+Management of Contrail resources
+================================
+
+:depends: - vnc_api Python module
+
+
+Enforce the virtual router existence
+------------------------------------
+
+.. code-block:: yaml
+
+ virtual_router:
+ contrail.virtual_router_present:
+ name: cmp01
+ ip_address: 10.0.0.23
+ dpdk_enabled: False
+
+
+Enforce the virtual router absence
+----------------------------------
+
+.. code-block:: yaml
+
+ virtual_router_cmp01:
+ contrail.virtual_router_absent:
+ name: cmp01
+
+
+Enforce the analytics node existence
+------------------------------------
+
+.. code-block:: yaml
+
+ analytics_node01:
+ contrail.analytics_node_present:
+ name: nal01
+ ip_address: 10.0.0.13
+
+
+Enforce the config node existence
+---------------------------------
+
+.. code-block:: yaml
+
+ config_node01:
+ contrail.config_node_present:
+ name: ntw01
+ ip_address: 10.0.0.23
+
+
+Enforce the database node existence
+-----------------------------------
+
+.. code-block:: yaml
+
+ config_node01:
+ contrail.database_node_present:
+ name: ntw01
+ ip_address: 10.0.0.33
+
+'''
+
+def __virtual__():
+ '''
+ Load Contrail module
+ '''
+ return 'contrail'
+
+
+def virtual_router_present(name, ip_address, dpdk_enabled=False, **kwargs):
+ '''
+ Ensures that the Contrail virtual router exists.
+
+ :param name: Virtual router name
+ :param ip_address: Virtual router IP address
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Virtual router "{0}" already exists'.format(name)}
+ virtual_router = __salt__['contrail.virtual_router_get'](name, **kwargs)
+ if 'Error' not in virtual_router:
+ pass
+ else:
+ __salt__['contrail.virtual_router_create'](name, ip_address, dpdk_enabled, **kwargs)
+ ret['comment'] = 'Virtual router {0} has been created'.format(name)
+ ret['changes']['VirtualRouter'] = 'Created'
+ return ret
+
+
+def virtual_router_absent(name, **kwargs):
+ '''
+ Ensure that the Contrail virtual router doesn't exist
+
+ :param name: The name of the virtual router that should not exist
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Virtual router "{0}" is already absent'.format(name)}
+ virtual_router = __salt__['contrail.virtual_router_get'](name, **kwargs)
+ if 'Error' not in virtual_router:
+ __salt__['contrail.virtual_router_delete'](name, **kwargs)
+ ret['comment'] = 'Virtual router {0} has been deleted'.format(name)
+ ret['changes']['VirtualRouter'] = 'Deleted'
+
+ return ret
+
+
+def analytics_node_present(name, ip_address, **kwargs):
+ '''
+ Ensures that the Contrail analytics node exists.
+
+ :param name: Analytics node name
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Analytics node {0} already exists'.format(name)}
+ analytics_node = __salt__['contrail.analytics_node_get'](name, **kwargs)
+ if 'Error' not in analytics_node:
+ pass
+ else:
+ __salt__['contrail.analytics_node_create'](name, ip_address, **kwargs)
+ ret['comment'] = 'Analytics node {0} has been created'.format(name)
+ ret['changes']['AnalyticsNode'] = 'Created'
+ return ret
+
+
+def config_node_present(name, ip_address, **kwargs):
+ '''
+ Ensures that the Contrail config node exists.
+
+ :param name: Config node name
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Config node {0} already exists'.format(name)}
+ config_node = __salt__['contrail.config_node_get'](name, **kwargs)
+ if 'Error' not in config_node:
+ pass
+ else:
+ __salt__['contrail.config_node_create'](name, ip_address, **kwargs)
+ ret['comment'] = 'Config node {0} has been created'.format(name)
+ ret['changes']['ConfigNode'] = 'Created'
+ return ret
+
+
+def bgp_router_present(name, type, ip_address, asn=64512, **kwargs):
+ '''
+ Ensures that the Contrail BGP router exists.
+
+ :param name: BGP router name
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'BGP router {0} already exists'.format(name)}
+ bgp_router = __salt__['contrail.bgp_router_get'](name, **kwargs)
+ if 'Error' not in bgp_router:
+ pass
+ else:
+ __salt__['contrail.bgp_router_create'](name, type, ip_address, asn, **kwargs)
+ ret['comment'] = 'BGP router {0} has been created'.format(name)
+ ret['changes']['BgpRouter'] = 'Created'
+ return ret
+
+
+def database_node_present(name, ip_address, **kwargs):
+ '''
+ Ensures that the Contrail database node exists.
+
+ :param name: Database node name
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Database node {0} already exists'.format(name)}
+ database_node = __salt__['contrail.database_node_get'](name, **kwargs)
+ if 'Error' not in database_node:
+ pass
+ else:
+ __salt__['contrail.database_node_create'](name, ip_address, **kwargs)
+ ret['comment'] = 'Database node {0} has been created'.format(name)
+ ret['changes']['DatabaseNode'] = 'Created'
+ return ret
diff --git a/metadata/service/client/cluster.yml b/metadata/service/client/cluster.yml
index 169367b..fabf22c 100644
--- a/metadata/service/client/cluster.yml
+++ b/metadata/service/client/cluster.yml
@@ -2,18 +2,19 @@
- opencontrail
parameters:
_param:
- opencontrail_version: 2.2
+ opencontrail_version: 3.0
opencontrail:
client:
+ enabled: True
version: ${_param:opencontrail_version}
identity:
engine: keystone
- host: ${_param:cluster_vip_address}
+ host: ${_param:openstack_control_address}
port: 35357
tenant: admin
user: admin
password: ${_param:keystone_admin_password}
api:
engine: contrail
- host: ${_param:cluster_vip_address}
+ host: ${_param:opencontrail_control_address}
port: 8082
diff --git a/metadata/service/client/single.yml b/metadata/service/client/single.yml
index fb9abd7..67038c2 100644
--- a/metadata/service/client/single.yml
+++ b/metadata/service/client/single.yml
@@ -2,9 +2,10 @@
- opencontrail
parameters:
_param:
- opencontrail_version: 2.2
+ opencontrail_version: 3.0
opencontrail:
client:
+ enabled: True
version: ${_param:opencontrail_version}
identity:
engine: keystone
diff --git a/opencontrail/client.sls b/opencontrail/client.sls
index bece6f1..2b4334d 100644
--- a/opencontrail/client.sls
+++ b/opencontrail/client.sls
@@ -14,4 +14,87 @@
- pkg: opencontrail_client_packages
{%- endif %}
-{%- endif %}
\ No newline at end of file
+{%- for virtual_router_name, virtual_router in client.get('virtual_router', {}).items() %}
+
+opencontrail_client_virtual_router_{{ virtual_router_name }}:
+ contrail.virtual_router_present:
+ - name: {{ virtual_router.get('name', virtual_router_name) }}
+ - ip_address: {{ virtual_router.ip_address }}
+ - dpdk_enabled: {{ virtual_router.get('dpdk_enabled', False) }}
+ - user: {{ client.identity.user }}
+ - password: {{ client.identity.password }}
+ - project: {{ client.identity.tenant }}
+ - auth_host_ip: {{ client.identity.host }}
+ - api_server_ip: {{ client.api.host }}
+ - api_server_port: {{ client.api.port }}
+ - api_base_url: '/'
+
+{%- endfor %}
+
+{%- for config_node_name, config_node in client.get('config_node', {}).items() %}
+
+opencontrail_client_config_node_{{ config_node_name }}:
+ contrail.config_node_present:
+ - name: {{ config_node.get('name', config_node_name) }}
+ - ip_address: {{ config_node.ip_address }}
+ - user: {{ client.identity.user }}
+ - password: {{ client.identity.password }}
+ - project: {{ client.identity.tenant }}
+ - auth_host_ip: {{ client.identity.host }}
+ - api_server_ip: {{ client.api.host }}
+ - api_server_port: {{ client.api.port }}
+ - api_base_url: '/'
+
+{%- endfor %}
+
+{%- for bgp_router_name, bgp_router in client.get('bgp_router', {}).items() %}
+
+opencontrail_client_bgp_router_{{ bgp_router_name }}:
+ contrail.bgp_router_present:
+ - name: {{ bgp_router.get('name', bgp_router_name) }}
+ - ip_address: {{ bgp_router.ip_address }}
+ - type: {{ bgp_router.type }}
+ - asn: {{ bgp_router.get('asn', 64512) }}
+ - user: {{ client.identity.user }}
+ - password: {{ client.identity.password }}
+ - project: {{ client.identity.tenant }}
+ - auth_host_ip: {{ client.identity.host }}
+ - api_server_ip: {{ client.api.host }}
+ - api_server_port: {{ client.api.port }}
+ - api_base_url: '/'
+
+{%- endfor %}
+
+{%- for analytics_node_name, analytics_node in client.get('analytics_node', {}).items() %}
+
+opencontrail_client_analytics_node_{{ analytics_node_name }}:
+ contrail.analytics_node_present:
+ - name: {{ analytics_node.get('name', analytics_node_name) }}
+ - ip_address: {{ analytics_node.ip_address }}
+ - user: {{ client.identity.user }}
+ - password: {{ client.identity.password }}
+ - project: {{ client.identity.tenant }}
+ - auth_host_ip: {{ client.identity.host }}
+ - api_server_ip: {{ client.api.host }}
+ - api_server_port: {{ client.api.port }}
+ - api_base_url: '/'
+
+{%- endfor %}
+
+{%- for database_node_name, database_node in client.get('database_node', {}).items() %}
+
+opencontrail_client_database_node_{{ database_node_name }}:
+ contrail.database_node_present:
+ - name: {{ database_node.get('name', database_node_name) }}
+ - ip_address: {{ database_node.ip_address }}
+ - user: {{ client.identity.user }}
+ - password: {{ client.identity.password }}
+ - project: {{ client.identity.tenant }}
+ - auth_host_ip: {{ client.identity.host }}
+ - api_server_ip: {{ client.api.host }}
+ - api_server_port: {{ client.api.port }}
+ - api_base_url: '/'
+
+{%- endfor %}
+
+{%- endif %}