Merge "Remove salt-master, reclass from pkg dependencis"
diff --git a/README.rst b/README.rst
index 5f09362..d465fac 100644
--- a/README.rst
+++ b/README.rst
@@ -984,6 +984,8 @@
type: router
ip_address: 172.16.0.22
asn: 64512
+ key_type: md5
+ key: password
Enforcing config nodes
@@ -1126,6 +1128,35 @@
security_group: 'default'
virtual_network: 'virtual-network'
+Enforcing virtual networks
+
+
+.. code-block:: yaml
+
+ opencontrail:
+ client:
+ virtual_networks:
+ net01:
+ name: 'network01'
+ ip_address: '172.16.111.0'
+ ip_prefix: 24
+ asn: 64512
+ route_target: 10000
+ external: True
+ allow_transit: False
+ forwarding_mode: 'l2_l3'
+ rpf: 'disable'
+ mirror_destination: False
+ domain: 'default-domain'
+ project: 'admin'
+ ipam_domain: 'default-domain'
+ ipam_project: 'default-project'
+ ipam_name: 'default-network-ipam'
+ net02:
+ name: 'network02'
+ net03:
+ name: 'network03'
+
Contrail DNS custom forwarders
------------------------------
diff --git a/_modules/contrail.py b/_modules/contrail.py
index 38281b2..df33d78 100644
--- a/_modules/contrail.py
+++ b/_modules/contrail.py
@@ -24,9 +24,11 @@
from vnc_api.vnc_api import LinklocalServiceEntryType, \
LinklocalServicesTypes, GlobalVrouterConfig, GlobalSystemConfig
from vnc_api.gen.resource_client import VirtualRouter, AnalyticsNode, \
- ConfigNode, DatabaseNode, BgpRouter
+ ConfigNode, DatabaseNode, BgpRouter, VirtualNetwork
from vnc_api.gen.resource_xsd import AddressFamilies, BgpSessionAttributes, \
- BgpSession, BgpPeeringAttributes, BgpRouterParams
+ BgpSession, BgpPeeringAttributes, BgpRouterParams, AuthenticationData, \
+ AuthenticationKeyItem, VirtualNetworkType, IpamSubnetType, SubnetType, \
+ VnSubnetsType, RouteTargetList
HAS_CONTRAIL = True
except ImportError:
@@ -1014,7 +1016,7 @@
return ret
-def bgp_router_create(name, type, ip_address, asn=64512, **kwargs):
+def bgp_router_create(name, type, ip_address, asn=64512, key_type=None, key=None, **kwargs):
'''
Create specific Contrail control node
@@ -1036,6 +1038,9 @@
if type != 'control-node':
address_families.remove('erm-vpn')
+ key_type = None if key_type == 'None' else key_type
+ key = None if key == 'None' else key
+
bgp_addr_fams = AddressFamilies(address_families)
bgp_sess_attrs = [
BgpSessionAttributes(address_families=bgp_addr_fams)]
@@ -1043,10 +1048,16 @@
bgp_peering_attrs = BgpPeeringAttributes(session=bgp_sessions)
rt_inst_obj = _get_rt_inst_obj(vnc_client)
+ bgp_auth_data = None
+
if type == 'control-node':
vendor = 'contrail'
elif type == 'router':
vendor = 'mx'
+ if key_type == 'md5':
+ key_id = 0
+ key_items = AuthenticationKeyItem(key_id, key)
+ bgp_auth_data = AuthenticationData(key_type, [key_items])
else:
vendor = 'unknown'
@@ -1054,7 +1065,8 @@
vendor=vendor, autonomous_system=int(asn),
identifier=_get_ip(ip_address),
address=_get_ip(ip_address),
- port=179, address_families=bgp_addr_fams)
+ port=179, address_families=bgp_addr_fams,
+ auth_data=bgp_auth_data)
bgp_router_objs = bgp_router_list(**kwargs)
if name in bgp_router_objs:
@@ -1066,6 +1078,18 @@
ret['changes'].update({"vendor": {'old': bgp_router_obj.bgp_router_parameters.vendor, 'new': vendor}})
if bgp_router_obj.bgp_router_parameters.address != ip_address:
ret['changes'].update({"ip_address": {'old': bgp_router_obj.bgp_router_parameters.address, 'new': ip_address}})
+ try:
+ if bgp_router_obj.bgp_router_parameters.auth_data.key_type != key_type:
+ ret['changes'].update({"key_type": {'old': bgp_router_obj.bgp_router_parameters.auth_data.key_type, 'new': key_type}})
+ except:
+ if key_type != None:
+ ret['changes'].update({"key_type": {'old': None, 'new': key_type}})
+ if key_type == 'md5':
+ try:
+ if bgp_router_obj.bgp_router_parameters.auth_data.key_items[0].key != key:
+ ret['changes'].update({"key_type": {'old': bgp_router_obj.bgp_router_parameters.auth_data.key_items[0].key, 'new': key}})
+ except:
+ ret['changes'].update({"key_type": {'old': None, 'new': key}})
if len(ret['changes']) == 0:
return ret
@@ -1524,6 +1548,142 @@
return ret
+def virtual_network_create(name, conf=None, **kwargs):
+ '''
+ Create Contrail virtual network
+ CLI Example:
+ .. code-block:: bash
+ salt '*' contrail.virtual_network_create name
+
+ salt.cmdRun(pepperEnv, 'ntw01*', 'salt-call contrail.virtual_network_create
+ "testicek" "{"external":"True","ip":"172.16.111.0","prefix":24,
+ "asn":64512,"target":10000}" ')
+
+ Parameters:
+ name required - name of the new network
+
+ conf (dict) optional:
+ domain (string) optional - which domain use for vn creation
+ project (string) optional - which project use for vn creation
+ ipam_domain (string) optional - domain for ipam
+ ipam_project (string) optional - project for ipam
+ ipam_name (string) optional - ipam name
+ ip_prefix (string) optional - format is xxx.xxx.xxx.xxx
+ ip_prefix_len (int) optional - format is xx
+ asn (int) optional - autonomus system number
+ target (int) optional - route target number
+ external (boolean) optional - set if network is external
+
+ allow_transit (boolean) optional - enable allow transit
+ forwarding_mode (any of ['l2_l3','l2','l3']) optional
+ - packet forwarding mode for this virtual network
+ rpf (any of ['enabled','disabled']) optional
+ - Enable or disable Reverse Path Forwarding check
+ for this network
+ mirror_destination (boolean) optional
+ - Mark the vn as mirror destination network
+ '''
+ if conf is None:
+ conf = {}
+
+ # check for domain, is missing set to default-domain
+ if 'domain' in conf:
+ vn_domain = str(conf['domain'])
+ else:
+ vn_domain = 'default-domain'
+ # check for project, is missing set to admin
+ if 'project' in conf:
+ vn_project = str(conf['project'])
+ else:
+ vn_project = 'admin'
+ # check for ipam domain,default is default-domain
+ if 'ipam_domain' in conf:
+ ipam_domain = str(conf['ipam_domain'])
+ else:
+ ipam_domain = 'default-domain'
+ # check for ipam domain,default is default-domain
+ if 'ipam_project' in conf:
+ ipam_project = str(conf['ipam_project'])
+ else:
+ ipam_project = 'default-project'
+
+ if 'ipam_name' in conf:
+ ipam_name = conf['ipam_name']
+ else:
+ ipam_name = 'default-network-ipam'
+
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+
+ # list of existing vn networks
+ vn_networks = []
+ vnc_client = _auth(**kwargs)
+ prj_obj = vnc_client.project_read(fq_name=[vn_domain,
+ vn_project])
+ # check if the network exists
+ vn_networks_list = vnc_client._objects_list('virtual_network')
+ fq = [vn_domain, vn_project, name]
+ for network in vn_networks_list['virtual-networks']:
+ if fq == network['fq_name']:
+ ret['comment'] = ("Virtual network with name "
+ + name + " already exists")
+ return ret
+
+ vn_obj = VirtualNetwork(name, prj_obj)
+ vn_type_obj = VirtualNetworkType()
+ # get ipam from default project and domain
+ ipam = vnc_client.network_ipam_read(fq_name=[ipam_domain,
+ ipam_project,
+ ipam_name])
+
+ # create subnet
+ if 'ip_prefix' in conf and 'ip_prefix_len' in conf:
+ ipam_subnet_type = IpamSubnetType(subnet=SubnetType(
+ ip_prefix=conf['ip_prefix'],
+ ip_prefix_len=conf['ip_prefix_len']))
+
+ vn_subnets_type_obj = VnSubnetsType(ipam_subnets=[ipam_subnet_type])
+ vn_obj.add_network_ipam(ipam, vn_subnets_type_obj)
+
+ # add route target to the network
+ if 'asn' in conf and 'target' in conf:
+ route_target_list_obj = RouteTargetList(["target:{0}:{1}"
+ .format(conf['asn'],
+ conf['target'])])
+ vn_obj.set_route_target_list(route_target_list_obj)
+
+ if 'external' in conf:
+ vn_obj.set_router_external(conf['external'])
+
+ if 'allow_transit' in conf:
+ vn_type_obj.set_allow_transit(conf['allow_transit'])
+
+ if 'forwarding_mode' in conf:
+ if conf['forwarding_mode'] in ['l2_l3', 'l2', 'l3']:
+ vn_type_obj.set_forwarding_mode(conf['forwarding_mode'])
+
+ if 'rpf' in conf:
+ vn_type_obj.set_rpf(conf['rpf'])
+
+ if 'mirror_destination' in conf:
+ vn_type_obj.set_mirror_destination(conf['mirror_destination'])
+
+ vn_obj.set_virtual_network_properties(vn_type_obj)
+
+ # create virtual network
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = ("Virtual network with name {0} will be created"
+ .format(name))
+ else:
+ vnc_client.virtual_network_create(vn_obj)
+ ret['comment'] = ("Virtual network with name {0} was created"
+ .format(name))
+ return ret
+
+
def service_appliance_set_list(**kwargs):
'''
Return a list of Contrail service appliance set
diff --git a/_states/contrail.py b/_states/contrail.py
index ea74ce3..b729d26 100644
--- a/_states/contrail.py
+++ b/_states/contrail.py
@@ -251,6 +251,8 @@
- ip_address: 10.0.0.133
- type: mx
- asn: 64512
+ - key_type: md5
+ - key: password
Enforce the BGP router absence
@@ -336,6 +338,31 @@
global_system_config_delete:
contrail.global_system_config_absent:
- name: global-system_config
+
+
+Enforce the virtual network existence
+----------------------------------------
+
+.. code-block: yaml
+
+ virtual_network_create:
+ contrail.virtual_network_present:
+ - name: virtual_network_name
+ - conf:
+ domain: domain name
+ project: domain project
+ ipam_domain: ipam domain name
+ ipam_project: ipam project name
+ ipam_name: ipam name
+ ip_prefix: xxx.xxx.xxx.xxx
+ ip_prefix_len: 24
+ asn: 64512
+ target: 10000
+ external: False
+ allow_transit: False
+ forwading_mode: 'l2_l3'
+ rpf: 'disabled'
+ mirror_destination: False
'''
@@ -623,7 +650,7 @@
return ret
-def bgp_router_present(name, type, ip_address, asn=64512, **kwargs):
+def bgp_router_present(name, type, ip_address, asn=64512, key_type=None, key=None, **kwargs):
'''
Ensures that the Contrail BGP router exists.
@@ -634,7 +661,7 @@
'result': True,
'comment': 'BGP router {0} already exists'.format(name)}
- ret = __salt__['contrail.bgp_router_create'](name, type, ip_address, asn, **kwargs)
+ ret = __salt__['contrail.bgp_router_create'](name, type, ip_address, asn, key_type, key, **kwargs)
if len(ret['changes']) == 0:
pass
return ret
@@ -790,3 +817,15 @@
if 'Error' not in gsc:
ret = __salt__['contrail.global_system_config_delete'](name, **kwargs)
return ret
+
+
+def virtual_network_present(name, conf=None, **kwargs):
+ '''
+ Ensure that the virtual network exists.
+
+ :param name: Name of the virtual network
+ :param conf: Key:Value pairs used for network creation
+ '''
+
+ ret = __salt__['contrail.virtual_network_create'](name, conf, **kwargs)
+ return ret
diff --git a/opencontrail/client.sls b/opencontrail/client.sls
index 24370ac..ff67a3e 100644
--- a/opencontrail/client.sls
+++ b/opencontrail/client.sls
@@ -95,6 +95,8 @@
- ip_address: {{ bgp_router.ip_address }}
- type: {{ bgp_router.type }}
- asn: {{ bgp_router.get('asn', 64512) }}
+ - key_type: {{ bgp_router.get('key_type') }}
+ - key: {{ bgp_router.get('key') }}
- user: {{ client.identity.user }}
- password: {{ client.identity.password }}
- project: {{ client.identity.tenant }}
@@ -234,4 +236,63 @@
{%- endfor %} # end for physical_router
+{%- if client.virtual_networks is defined %}
+{%- for vn_name, vn in client.virtual_networks.items() %}
+create_network_{{ vn.name }}:
+ contrail.virtual_network_present:
+ - name: {{ vn.name }}
+ - conf:
+{%- if vn.ip_prefix is defined and vn.ip_prefix_len is defined %}
+ ip: {{ vn.ip_prefix }}
+ prefix: {{ vn.ip_prefix_len }}
+{%- endif %}
+
+{%- if vn.asn is defined and vn.route_target is defined %}
+ asn: {{ vn.asn }}
+ target: {{ vn.route_target }}
+{%- endif %}
+
+{%- if vn.external is defined %}
+ external: {{ vn.external }}
+{%- endif %}
+
+{%- if vn.allow_transit is defined %}
+ allow_transit: {{ vn.allow_transit }}
+{%- endif %}
+
+{%- if vn.forwarding_mode is defined %}
+ forwarding_mode: {{ vn.forwarding_mode }}
+{%- endif %}
+
+{%- if vn.rpf is defined %}
+ rpf: {{ vn.rpf }}
+{%- endif %}
+
+{%- if vn.mirror_destination is defined %}
+ mirror_destination: {{ vn.mirror_destination }}
+{%- endif %}
+
+{%- if vn.domain is defined %}
+ domain: {{ vn.domain }}
+{%- endif %}
+
+{%- if vn.project is defined %}
+ project: {{ vn.project }}
+{%- endif %}
+
+{%- if vn.ipam_domain is defined %}
+ ipam_domain: {{ vn.ipam_domain }}
+{%- endif %}
+
+{%- if vn.ipam_project is defined %}
+ ipam_project: {{ vn.ipam_project }}
+{%- endif %}
+
+{%- if vn.ipam_name is defined %}
+ ipam_name: {{ vn.ipam_name }}
+{%- endif %}
+
+{%- endfor %}
+{%- endif %} # end for virtual_network
+
{%- endif %}