vCenter integration for Fuel 9.0kilo

These changes allow to deploy contrail with vCenter integration:
 - Allows to deploy ContrailVM on each ESXi node
 - Allows to deploy nova-compute with vCenter configuration
 - Allows to deploy Openstack with vCenter
 - Unlocks vCenter tab in FUEL-UI
 - Added contrail-vmware role for vRouter
 - Added functionality to deploy(node have to be created by hands)
 vRouter by FUEL on ESXi

Change-Id: I1a01f3aecd459f6b837ffdb9f4c59883b5df8535
This commit is contained in:
Andrey Kirilochkin
2016-06-07 18:03:57 -05:00
parent e57fb5fce3
commit 52e2e228fd
60 changed files with 2156 additions and 81 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
.tox
.build
*.pyc
*.pyo
repositories/centos/*
repositories/ubuntu/*
deployment_scripts/puppet/modules/inifile

View File

@@ -4,10 +4,3 @@
bind: !!pairs
- "cluster:net_provider": "neutron"
- "cluster:net_segment_type": "tun"
compatible:
- name: 'hypervisor:kvm'
- name: 'hypervisor:qemu'
incompatible:
- name: 'hypervisor:vmware'
description: 'Contrail plugin is not compatible with VMware for now'

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env python
# Copyright 2015 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.
# This script is used to get the vcenter settings from FUEL and share them
# to other roles. By-default FUEL puts these settings only on compute-vmware
# node. We need them on controller, compute and contrail-vmware nodes.
# We gather the data from env and convert it to the appropriate format
# used by the plugin and put as a hiera extension on all nodes.
#
# Example: $0 <env_id>
# Example: ./get_vmware_settings.py 5
#
# By AKirilochkin@mirantis.com
import os
import sys
import yaml
from fuelclient.objects import Environment
env = Environment(sys.argv[1])
attrs_json = env.get_vmware_settings_data()
try:
attrs_json = attrs_json['editable']['value']['availability_zones'][0]
except:
print 'Could not parse vmware data from API'
complist = []
for comps in attrs_json['nova_computes']:
compute = {
'availability_zone_name' : attrs_json['az_name'],
'datastore_regex' : comps['datastore_regex'],
'service_name' : comps['service_name'],
'target_node' : comps['target_node']['current']['id'],
'vc_cluster' : comps['vsphere_cluster'],
'vc_host' : attrs_json['vcenter_host'],
'vc_password' : attrs_json['vcenter_password'],
'vc_user' : attrs_json['vcenter_username'],
}
complist.append(compute)
vcenter = {
'vcenter': {
'esxi_vlan_interface' : "",
'computes' : complist,
},
}
path = '/var/lib/fuel/contrail/'
try:
os.makedirs(path)
except OSError:
if os.path.exists(path):
pass
else:
raise
filepath = path + '{CLUSTER}.yaml'
with open(filepath.format(CLUSTER=sys.argv[1]), 'w') as outfile:
outfile.write(yaml.safe_dump(vcenter))

View File

@@ -13,5 +13,4 @@
# under the License.
notice('MODULAR: contrail/common-repo.pp')
class { 'contrail::common_repo': }
include contrail::common_repo

View File

@@ -14,4 +14,4 @@
notice('MODULAR: contrail/compute-hiera.pp')
class { 'contrail::compute::hiera': }
include contrail::compute::hiera

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/contrail-compute-aggregate.pp')
include contrail
class { 'contrail::compute::aggregate': }
include contrail::compute::aggregate

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-firewall.pp')
include contrail
class { 'contrail::compute::firewall': }
include contrail::compute::firewall

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-hugepages.pp')
include contrail
class { 'contrail::compute::hugepages': }
include contrail::compute::hugepages

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-network.pp')
include contrail
class { 'contrail::compute::network': }
include contrail::compute::network

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-nova.pp')
include contrail
class { 'contrail::compute::nova': }
include contrail::compute::nova

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/contrail-compute-override.pp')
include contrail
class { 'contrail::compute::compute_override': }
include contrail::compute::compute_override

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-provision.pp')
include contrail
class { 'contrail::provision::compute': }
include contrail::provision::compute

View File

@@ -14,4 +14,4 @@
notice('MODULAR: contrail/contrail-compute-repo.pp')
class { 'contrail::compute::compute_repo':}
include contrail::compute::compute_repo

View File

@@ -0,0 +1,19 @@
# Copyright 2016 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.
notice('MODULAR: contrail/contrail-compute-vmware-pkg.pp')
include contrail
include contrail::compute::vmware_pkg

View File

@@ -0,0 +1,19 @@
# Copyright 2016 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.
notice('MODULAR: contrail/contrail-compute-vmware-repo.pp')
include contrail
include contrail::compute::vmware_repo

View File

@@ -0,0 +1,19 @@
# Copyright 2016 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.
notice('MODULAR: contrail/contrail-compute-vmware.pp')
include contrail
include contrail::compute::vmware

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-compute-vrouter.pp')
include contrail
class { 'contrail::compute::vrouter': }
include contrail::compute::vrouter

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-config-provision.pp')
include contrail
class { 'contrail::provision::config': }
include contrail::provision::config

View File

@@ -15,6 +15,6 @@
notice('MODULAR: contrail/contrail-config.pp')
include contrail
class { 'contrail::config': }
class { 'contrail::analytics': }
class { 'contrail::webui': }
include contrail::config
include contrail::analytics
include contrail::webui

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-control-provision.pp')
include contrail
class { 'contrail::provision::control': }
include contrail::provision::control

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-control.pp')
include contrail
class { 'contrail::control': }
include contrail::control

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/contrail-controller-aggregate.pp')
include contrail
class { 'contrail::controller::aggregate': }
include contrail::controller::aggregate

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-db-provision.pp')
include contrail
class { 'contrail::provision::db': }
include contrail::provision::db

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/contrail-db.pp')
include contrail
class { 'contrail::database': }
include contrail::database

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/contrail-utils.pp')
include contrail
class { 'contrail::utils': }
include contrail::utils

View File

@@ -0,0 +1,19 @@
# Copyright 2016 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.
notice('MODULAR: contrail/contrail-vmware.pp')
include contrail
include contrail::contrail_vmware

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/controller-config.pp')
include contrail
class { 'contrail::controller': }
include contrail::controller

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/controller-hiera-post.pp')
include contrail
class { 'contrail::controller::hiera_post':}
include contrail::controller::hiera_post

View File

@@ -14,4 +14,4 @@
notice('MODULAR: contrail/controller-hiera-pre.pp')
class { 'contrail::controller::hiera_pre':}
include contrail::controller::hiera_pre

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/controller-provision.pp')
include contrail
class { 'contrail::provision::controller': }
include contrail::provision::controller

View File

@@ -15,5 +15,4 @@
notice('MODULAR: contrail/controller-scheduler.pp')
include contrail
class { 'contrail::controller::scheduler': }
include contrail::controller::scheduler

View File

@@ -15,4 +15,4 @@
notice('MODULAR: contrail/controller-vip.pp')
include contrail
class { 'contrail::vip': }
include contrail::vip

View File

@@ -0,0 +1,19 @@
# Copyright 2016 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.
notice('MODULAR: contrail/controller-vmware.pp')
include contrail
include contrail::controller::vmware

View File

@@ -0,0 +1,81 @@
import time
from fabfile.utils.fabos import *
from fabric.contrib.files import exists
from fabfile.tasks.install import install_pkg_node
from fabfile.tasks.install import create_install_repo_node
from fabfile.tasks.install import apt_install
@task
#@parallel(pool_size=20)
#use compute role because in testbed we will set only ContrailVM ips
@roles('compute')
def prepare_contrailvm(pkg):
"""Install local repository of contrail packages on ContrailVM"""
time.sleep(30)
with settings(password='c0ntrail123', connection_attempts=10):
sudo('echo > /etc/apt/sources.list')
execute(install_pkg_node, pkg, env.host_string)
execute(create_install_repo_node, env.host_string)
@task
#@parallel(pool_size=20)
#use compute role because in testbed we will set conly ContrailVM ips
@roles('compute')
def fab_install_vrouter():
"""Install vrouter packages on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
vrouter_pkg = ['contrail-vrouter-dkms', 'contrail-vrouter-common', 'contrail-nova-vif']
apt_install(vrouter_pkg)
@task
@parallel(pool_size=20)
def disable_add_vnc_config():
"""Disable provision vrouter when exucute setup-vnc-compute on ContrailVM.
On ContrailVMs we don't have access to managment network, so we don't
have access to keystone."""
with settings(password='c0ntrail123', connection_attempts=20):
patched_file = '/usr/local/lib/python2.7/dist-packages/contrail_provisioning/compute/common.py'
cmd = 'sed -i "s~python\ /opt/contrail/utils/provision_vrouter\.py~echo~g" %s' % patched_file
sudo(cmd)
@task
def provision_contrailvm(cmd):
"""Create configuration files on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
sudo(cmd)
@task
def deploy_agent_param():
"""Deploy agent_param.tmpl on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
cmd = '/opt/contrail/bin/vnagent_param_setup.sh'
sudo(cmd)
@task
def change_hostname(hostname):
"""Change hostname on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
cmd = 'echo %s > /etc/hostname' % hostname
sudo(cmd)
@task
def set_ntp(ntp):
"""Set proper ntp server on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
sudo('sed -i "/^server/g" /etc/ntp.conf')
sudo('echo "server %s" >> /etc/ntp.conf' % ntp)
@task
def redeploy_vrouter_module():
"""Deploy agent_param.tmpl on ContrailVM"""
with settings(password='c0ntrail123', connection_attempts=10):
cmd = 'dkms uninstall vrouter/3.0.2.0'
cmd1 = 'dpkg -i /opt/contrail/contrail_install_repo/contrail-vrouter-dkms*'
sudo(cmd)
sudo(cmd1)

View File

@@ -0,0 +1,37 @@
<%-
contrail_data=scope.function_hiera_hash(['contrail', {}])
-%>
[DEFAULT]
compute_driver=nova.virt.vmwareapi.contrailVCDriver
log_file=nova-compute-vmware-<%= @availability_zone_name %>-<%= @service_name %>.log
host=<%= @availability_zone_name %>-<%= @service_name %>
[vmware]
cache_prefix=$host
<% @vc_cluster.split(',').map(&:strip).each do |cluster_name| -%>
cluster_name=<%= cluster_name %>
<% end %>
vcenter_dvswitch=<%= contrail_data['contrail_vcenter_dvswitch'] %>
host_ip=<%= @vc_host %>
host_username=<%= @vc_user %>
host_password=<%= @vc_password %>
api_retry_count=<%= @api_retry_count %>
maximum_objects=<%= @maximum_objects %>
task_poll_interval=<%= @task_poll_interval %>
<% if @datastore_regex and !@datastore_regex.empty? -%>
datastore_regex=<%= @datastore_regex %>
<% end -%>
<% if @vlan_interface and !@vlan_interface.empty? -%>
vlan_interface=<%= @vlan_interface %>
<% end -%>
use_linked_clone=<%= @use_linked_clone %>
<% if @wsdl_location -%>
wsdl_location=<%= @wsdl_location %>
<% end -%>
[libvirt]
virt_type=vmwareapi

View File

@@ -0,0 +1,437 @@
diff --git a/nova/virt/vmwareapi/__init__.py b/nova/virt/vmwareapi/__init__.py
index d9e0443..62516c1 100644
--- a/nova/virt/vmwareapi/__init__.py
+++ b/nova/virt/vmwareapi/__init__.py
@@ -17,5 +17,7 @@
"""
# NOTE(sdague) for nicer compute_driver specification
from nova.virt.vmwareapi import driver
+from nova.virt.vmwareapi import contrailVC
VMwareVCDriver = driver.VMwareVCDriver
+contrailVCDriver = contrailVC.ContrailVCDriver
diff --git a/nova/virt/vmwareapi/contrailVC.py b/nova/virt/vmwareapi/contrailVC.py
new file mode 100644
index 0000000..dc56feb
--- /dev/null
+++ b/nova/virt/vmwareapi/contrailVC.py
@@ -0,0 +1,318 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
+# Copyright (c) 2012 VMware, Inc.
+# Copyright (c) 2011 Citrix Systems, Inc.
+# Copyright 2011 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.
+
+"""
+Contrail wrapper around VCenter
+"""
+
+import re
+import time
+import socket
+import sys
+import uuid
+
+from oslo.config import cfg
+from oslo_vmware import vim_util as oslo_vmware_vim_util
+from oslo.vmware import exceptions as vexc
+from oslo_log import log as logging
+from oslo_utils import uuidutils
+from nova import exception
+from nova.openstack.common import loopingcall
+from nova.virt import driver
+from nova.virt.vmwareapi import error_util
+from nova.virt.vmwareapi import host
+from nova.virt.vmwareapi import vim_util
+from nova.virt.vmwareapi import vm_util
+from nova.virt.vmwareapi import vmops
+from nova.virt.vmwareapi import volumeops
+from nova.virt.vmwareapi import network_util
+
+from nova.virt.vmwareapi.driver import VMwareVCDriver
+from bitstring import BitArray
+#from thrift.transport import TTransport, TSocket
+#from thrift.transport.TTransport import TTransportException
+#from thrift.protocol import TBinaryProtocol, TProtocol
+#from nova_contrail_vif.gen_py.instance_service import InstanceService
+#from nova_contrail_vif.gen_py.instance_service import ttypes
+
+LOG = logging.getLogger(__name__)
+
+vmwareapi_contrail_opts = [
+ cfg.StrOpt('vcenter_dvswitch',
+ help='Vswitch name to use to instantiate VMs incase of Contaril VCenter solution'),
+ ]
+CONF = cfg.CONF
+CONF.register_opts(vmwareapi_contrail_opts, 'vmware')
+
+INVALID_VLAN_ID = 4096
+MAX_VLAN_ID = 4095
+
+class VCPVlans(object):
+ """The private-vlan object"""
+
+ def __init__(self, vc_session):
+ self._vlan_id_bits = BitArray(MAX_VLAN_ID + 1)
+ self._init_pvlans(vc_session)
+ #end __init__()
+
+ def _init_pvlans(self, session):
+ self._vlan_id_bits.set(1)
+
+ dvs_mor = vm_util.get_dvs_ref_from_name(session,
+ CONF.vmware.vcenter_dvswitch);
+ config_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvs_mor,
+ "VmwareDistributedVirtualSwitch",
+ "config")
+ if not config_ret:
+ return
+
+ for pvlan_map_entry in config_ret.pvlanConfig:
+ if pvlan_map_entry.pvlanType == "isolated":
+ self._vlan_id_bits[pvlan_map_entry.secondaryVlanId] = 0
+
+ port_grps_mor_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvs_mor,
+ "VmwareDistributedVirtualSwitch",
+ "portgroup")
+ if not port_grps_mor_ret:
+ return
+
+ port_grps_mor = port_grps_mor_ret.ManagedObjectReference
+
+ for port_grp_mor in port_grps_mor:
+ cfg_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ port_grp_mor,
+ "DistributedVirtualPortgroup",
+ "config")
+ if not cfg_ret:
+ continue;
+
+ if not cfg_ret.defaultPortConfig:
+ continue;
+
+ if not cfg_ret.defaultPortConfig.vlan:
+ continue;
+
+ if hasattr(cfg_ret.defaultPortConfig.vlan, "pvlanId"):
+ self._vlan_id_bits[cfg_ret.defaultPortConfig.vlan.pvlanId] = 1
+
+ #end _init_vlans()
+
+ def alloc_pvlan(self):
+ vid = self._vlan_id_bits.find('0b0')
+ if vid:
+ self._vlan_id_bits[vid[0]] = 1
+ return vid[0]
+ return INVALID_VLAN_ID
+ #end alloc_vlan()
+
+ def free_pvlan(self, vlan_id):
+ if vlan_id < 0 or vlan_id > MAX_VLAN_ID:
+ return
+ self._vlan_id_bits[vlan_id] = 0
+ #end free_vlan()
+
+#end VCPVlans
+
+
+class ContrailVCDriver(VMwareVCDriver):
+ """Sub class of VC"""
+
+ def __init__(self, virtapi, read_only=False, scheme="https"):
+ super(ContrailVCDriver, self).__init__(virtapi)
+ if CONF.vmware.vcenter_dvswitch is None:
+ raise Exception(_("Must specify vcenter_dvswitch, to use "
+ "compute_driver=vmwareapi.contrailVCDriver"))
+ self.Vlan = VCPVlans(self._session)
+
+ def spawn(self, context, instance, image_meta, injected_files,
+ admin_password, network_info=None, block_device_info=None):
+ session = self._session
+ _vmops = self._get_vmops_for_compute_node(instance.node)
+ if network_info:
+ for vif in network_info:
+ network_uuid = vif['network']['id']
+ network_ref=None
+ try:
+ network_ref = network_util.get_network_with_the_name(session,
+ network_uuid, _vmops._cluster)
+ except vexc.VMwareDriverException:
+ LOG.debug("Network %s not found on cluster!", network_uuid)
+
+ if not network_ref:
+ vif['network']['bridge'] = vif['network']['id']
+ pvlan_id = self.Vlan.alloc_pvlan()
+ if pvlan_id == INVALID_VLAN_ID:
+ raise exception.NovaException("Vlan id space is full")
+
+ try:
+ network_util.create_dvport_group(session,
+ network_uuid,
+ CONF.vmware.vcenter_dvswitch,
+ pvlan_id, _vmops._cluster)
+ except vexc.DuplicateName:
+ self.Vlan.free_pvlan(pvlan_id)
+ else:
+ vif['network']['bridge'] = vif['network']['id']
+ #LOG.debug(_("Network %s found on host!") % network_uuid)
+
+ args = {'should_create_vlan':False, 'vlan':'0'}
+ vif['network']._set_meta(args)
+
+ super(ContrailVCDriver, self).spawn(context, instance, image_meta,
+ injected_files, admin_password,
+ network_info, block_device_info)
+
+ def destroy(self, context, instance, network_info, block_device_info=None,
+ destroy_disks=True, migrate_data=None):
+ session = self._session
+ _vmops = self._get_vmops_for_compute_node(instance.node)
+
+ super(ContrailVCDriver, self).destroy(context, instance, network_info,
+ block_device_info, destroy_disks,
+ migrate_data)
+
+ if not network_info:
+ return
+
+ for vif in network_info:
+ network_uuid = vif['network']['id']
+ network_ref=None
+ try:
+ network_ref = network_util.get_network_with_the_name(session,
+ network_uuid, _vmops._cluster);
+ except vexc.VMwareDriverException:
+ LOG.debug("Network %s not found on cluster!", network_uuid)
+
+ if not network_ref:
+ continue;
+
+ dvpg_mor = oslo_vmware_vim_util.get_moref(network_ref['dvpg'], network_ref['type']);
+
+ vms_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvpg_mor,
+ "DistributedVirtualPortgroup",
+ "vm")
+ if not (vms_ret) or not (vms_ret.ManagedObjectReference):
+ cfg_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvpg_mor,
+ "DistributedVirtualPortgroup",
+ "config")
+ if (cfg_ret) and (cfg_ret.defaultPortConfig) and (cfg_ret.defaultPortConfig.vlan) :
+ if hasattr(cfg_ret.defaultPortConfig.vlan, "pvlanId"):
+ pvlan_id = cfg_ret.defaultPortConfig.vlan.pvlanId
+
+ # No VM exists on the dvPortGroup. Delete the network.
+ # Only if delete network is successful, free pvlan.
+ # This is to avoid it getting reused when old
+ # network is hanging around due to failed n/w delete operation
+ try:
+ network_util.delete_dvport_group(session, dvpg_mor)
+ if pvlan_id:
+ self.Vlan.free_pvlan(pvlan_id)
+ except Exception as excep:
+ LOG.warn(("In contrailVC:dvportgroup:delete, "
+ "got this exception while destroying "
+ "the dvportGroup: %s") % str(excep))
+
+ def plug_vifs(self, instance, network_info):
+ """Plug VIFs into networks."""
+ # vif plug is done by vcenter plugin. Not done here.
+ return
+
+ def attach_interface(self, instance, image_meta, vif):
+ """Attach an interface to the instance."""
+ session = self._session
+ _vmops = self._get_vmops_for_compute_node(instance.node)
+ network_uuid = vif['network']['id']
+ network_mor=None
+ try:
+ network_mor = network_util.get_network_with_the_name(session,
+ network_uuid, _vmops._cluster);
+ except vexc.VMwareDriverException:
+ LOG.debug("Network %s not found on cluster!", network_uuid)
+
+ if not network_mor:
+ vif['network']['bridge'] = vif['network']['id']
+ pvlan_id = self.Vlan.alloc_pvlan()
+ #LOG.debug(_("Allocated pvlan for network %s") % network_uuid)
+ if pvlan_id == INVALID_VLAN_ID:
+ raise exception.NovaException("Vlan id space is full")
+
+ #LOG.debug(_("creating %s port-group on cluster!") % network_uuid)
+ network_util.create_dvport_group(session,
+ network_uuid,
+ CONF.vmware.vcenter_dvswitch,
+ pvlan_id, _vmops._cluster)
+ else:
+ vif['network']['bridge'] = vif['network']['id']
+ #LOG.debug(_("Network %s found on host!") % network_uuid)
+
+ args = {'should_create_vlan':False, 'vlan':'0'}
+ vif['network']._set_meta(args)
+
+ super(ContrailVCDriver, self).attach_interface(instance, image_meta, vif)
+
+ def detach_interface(self, instance, vif):
+ """Detach an interface from the instance."""
+ super(ContrailVCDriver, self).detach_interface(instance, vif)
+
+ session = self._session
+ _vmops = self._get_vmops_for_compute_node(instance.node)
+ network_uuid = vif['network']['id']
+ dvpg_mor=None
+ try:
+ dvpg_mor = network_util.get_network_with_the_name(session,
+ network_uuid, _vmops._cluster);
+ except vexc.VMwareDriverException:
+ LOG.debug("Network %s not found on cluster!", network_uuid)
+
+ if not dvpg_mor:
+ return;
+
+ vms_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvpg_mor,
+ "DistributedVirtualPortgroup",
+ "vm")
+ if not (vms_ret) or (vms_ret.ManagedObjectReference):
+ cfg_ret = session._call_method(vim_util,
+ "get_dynamic_property",
+ dvpg_mor,
+ "DistributedVirtualPortgroup",
+ "config")
+ if not cfg_ret:
+ return;
+
+ if not cfg_ret.defaultPortConfig:
+ return;
+
+ if not cfg_ret.defaultPortConfig.vlan:
+ return;
+
+ if hasattr(cfg_ret.defaultPortConfig.vlan, "pvlanId"):
+ self.Vlan.free_pvlan(cfg_ret.defaultPortConfig.vlan.pvlanId)
+
+ self.remove_dvport_group(dvpg_mor)
diff --git a/nova/virt/vmwareapi/network_util.py b/nova/virt/vmwareapi/network_util.py
index a1a44e9..46b1f11 100644
--- a/nova/virt/vmwareapi/network_util.py
+++ b/nova/virt/vmwareapi/network_util.py
@@ -196,3 +196,43 @@ def create_port_group(session, pg_name, vswitch_name, vlan_id=0, cluster=None):
LOG.debug("Port Group %s already exists.", pg_name)
LOG.debug("Created Port Group with name %s on "
"the ESX host", pg_name)
+
+
+def create_dvport_group(session, pg_name, vswitch_name, vlan_id=0, cluster=None):
+ """Creates a port group on the host system with the vlan tags
+ supplied. VLAN id 0 means no vlan id association.
+ """
+ client_factory = session.vim.client.factory
+ dvs_mor = vm_util.get_dvs_ref_from_name(session, vswitch_name);
+
+ add_prt_grp_spec = vm_util.get_add_dvswitch_port_group_spec(
+ client_factory,
+ vswitch_name,
+ pg_name,
+ vlan_id)
+ try:
+ pg_create_task = session._call_method( session.vim,
+ "CreateDVPortgroup_Task", dvs_mor,
+ spec=add_prt_grp_spec)
+ session._wait_for_task(pg_create_task)
+
+ except vexc.DuplicateName:
+ # There can be a race condition when two instances try
+ # adding port groups at the same time. One succeeds, then
+ # the other one will get an exception. Since we are
+ # concerned with the port group being created, which is done
+ # by the other call, we can ignore the exception.
+ LOG.debug(_("Port Group %s already exists."), pg_name)
+ raise
+
+ LOG.debug(_("Created Port Group with name %s on "
+ "the ESX host") % pg_name)
+
+
+def delete_dvport_group(session, dvpg_mor):
+ if not dvpg_mor:
+ return;
+
+ destroy_task = session._call_method(session.vim, "Destroy_Task",
+ dvpg_mor)
+ session._wait_for_task(destroy_task)
diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py
index 8c48fd4..fa69beb 100644
--- a/nova/virt/vmwareapi/vm_util.py
+++ b/nova/virt/vmwareapi/vm_util.py
@@ -171,6 +171,7 @@ def get_vm_create_spec(client_factory, instance, data_store_name,
config_spec.guestId = os_type
# The name is the unique identifier for the VM.
config_spec.instanceUuid = instance.uuid
+ config_spec.annotation = instance.display_name
# set the Hardware version
config_spec.version = extra_specs.hw_version
@@ -1473,6 +1474,40 @@ def power_off_instance(session, instance, vm_ref=None):
LOG.debug("VM already powered off", instance=instance)
+def get_add_dvswitch_port_group_spec(client_factory, dvswitch_name,
+ port_group_name, vlan_id):
+ """Builds the distributed virtual switch port group add spec."""
+ config_spec = client_factory.create('ns0:DVPortgroupConfigSpec')
+ config_spec.name = port_group_name
+ config_spec.description = port_group_name
+ config_spec.numPorts = '128'
+ config_spec.autoExpand = 'True'
+ config_spec.type = 'earlyBinding'
+
+ vlan_spec = client_factory.create('ns0:VmwareDistributedVirtualSwitchPvlanSpec')
+ vlan_spec.pvlanId = int(vlan_id)
+ vlan_spec.inherited = 'False'
+
+ port_config_spec = client_factory.create('ns0:VMwareDVSPortSetting')
+ port_config_spec.vlan = vlan_spec
+ config_spec.defaultPortConfig = port_config_spec
+
+ return config_spec
+
+def get_dvs_ref_from_name(session, dvs_name):
+ """Get reference to the Distributd Virtual Switch with the name specified."""
+ dvs = session._call_method(vim_util, "get_objects",
+ "VmwareDistributedVirtualSwitch", ["summary.name"])
+ return _get_object_from_results(session, dvs, dvs_name,
+ _get_object_for_value)
+
+def get_dvportgroup_ref_from_name(session, dvpg_name):
+ """Get reference to the Distributd Virtual Switch with the name specified."""
+ pgs = session._call_method(vim_util, "get_objects",
+ "DistributedVirtualPortgroup", ["name"])
+ return _get_object_from_results(session, pgs, dvpg_name,
+ _get_object_for_value)
+
def find_rescue_device(hardware_devices, instance):
"""Returns the rescue device.

View File

@@ -0,0 +1,37 @@
# Copyright 2016 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.
require 'yaml'
module Puppet::Parser::Functions
newfunction(:create_esxi_map, :type => :rvalue, :doc => <<-EOS
Produce array of lines for Contrail VMware plugin map file
EOS
) do |args|
vcenter_hash = function_hiera_hash(['vcenter'], {})
compute_vmware_clusters = vcenter_hash['computes'][0]['vc_cluster'].split(',')
contrail_hash = function_hiera_hash(["contrail", {}])
esxi_hash = YAML.load contrail_hash['contrail_vcenter_esxi_for_fabric']
map_elements = Array.new
esxi_hash.each do |esxi_name, esxi_values|
if compute_vmware_clusters.include?(esxi_values['cluster'])
contrail_vm_ip = esxi_values['contrail_vm']['host'].split('@')[1]
map_elements << [esxi_values['ip'], contrail_vm_ip].join(':')
end
end
return map_elements.sort
end
end

View File

@@ -0,0 +1,27 @@
# Copyright 2016 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.
require 'yaml'
module Puppet::Parser::Functions
newfunction(:fetch_esxi_data, :type => :rvalue, :doc => <<-EOS
Return esxi data regarding to contrailVM
EOS
) do |args|
host = args[0]
hiera = function_hiera_hash(["contrail", {}])
fail 'There is no section "contrail_vcenter_esxi_for_fabric" in the "contrail" data!' unless hiera["contrail_vcenter_esxi_for_fabric"]
user_fab = YAML.load hiera["contrail_vcenter_esxi_for_fabric"]
user_fab.map{ |k, v| v if v["contrail_vm"]["host"] == host}[0]
end
end

View File

@@ -0,0 +1,33 @@
# Copyright 2016 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.
require 'yaml'
module Puppet::Parser::Functions
newfunction(:get_contrailvm_ips, :type => :rvalue, :doc => <<-EOS
Return list of ContrailVM ips
EOS
) do |args|
vm_ips = []
hiera = function_hiera_hash(["contrail", {}])
fail 'There is no section "contrail_vcenter_esxi_for_fabric" in the "contrail" data!' unless hiera["contrail_vcenter_esxi_for_fabric"]
user_fab = YAML.load hiera["contrail_vcenter_esxi_for_fabric"]
user_fab.each do |_, v|
if v.key?("contrail_vm")
vm_ips << v["contrail_vm"]["host"]
end
end
return vm_ips
end
end

View File

@@ -0,0 +1,35 @@
# Copyright 2016 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.
require 'yaml'
require 'json'
module Puppet::Parser::Functions
newfunction(:prepare_user_fab, :type => :rvalue, :doc => <<-EOS
Prepare user data for putting in testbed.py
EOS
) do |args|
hiera = function_hiera(["contrail"])
default_fab = args[0]
user_fab = YAML.load hiera["contrail_vcenter_esxi_for_fabric"]
full_fab = user_fab
full_fab.each { |k, v|
full_fab[k]["vcenter_server"] = default_fab["vcenter_server"]
full_fab[k]["contrail_vm"]["mode"] = default_fab["mode"]
full_fab[k]["contrail_vm"]["vmdk"] = default_fab["vmdk"]
}
pretty_fab = JSON.pretty_generate full_fab
return pretty_fab
end
end

View File

@@ -19,7 +19,8 @@ class contrail::common_repo {
case $::operatingsystem {
CentOS: {
yumrepo {'mos': priority => 1, exclude => 'python-thrift,nodejs'} # Contrail requires newer python-thrift and nodejs from it's repo
#NOTE: Contrail requires newer python-thrift and nodejs from its repo
yumrepo {'mos': priority => 1, exclude => 'python-thrift,nodejs'}
package {'yum-plugin-priorities': ensure => present }
}
Ubuntu: {
@@ -35,4 +36,13 @@ class contrail::common_repo {
}
default: {}
}
install_ssh_keys {'vmware_root_ssh_key':
ensure => present,
user => 'root',
private_key_name => 'id_rsa_vmware',
public_key_name => 'id_rsa_vmware.pub',
private_key_path => '/var/lib/astute/vmware/vmware',
public_key_path => '/var/lib/astute/vmware/vmware.pub',
}
}

View File

@@ -0,0 +1,55 @@
# Copyright 2016 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.
class contrail::compute::vmware {
nova_config {
'DEFAULT/network_api_class': value => 'nova.network.neutronv2.api.API';
'DEFAULT/security_group_api': value => 'neutron';
'DEFAULT/firewall_driver': value => 'nova.virt.firewall.NoopFirewallDriver';
'DEFAULT/heal_instance_info_cache_interval': value => '0';
'neutron/url': value => "${contrail::internal_neutron_protocol}://${contrail::internal_neutron_endpoint}:9696";
'neutron/url_timeout': value => '300';
'neutron/admin_auth_url': value => "${contrail::internal_auth_protocol}://${contrail::internal_auth_address}:35357/v2.0/";
'neutron/admin_tenant_name': value => 'services';
'neutron/admin_username': value => 'neutron';
'neutron/admin_password': value => $contrail::service_token;
}
# Config file
file { ['/etc/contrail', '/var/log/contrail']:
ensure => directory,
mode => '0750',
}
file {'/etc/contrail/ESXiToVRouterIp.map':
content => template('contrail/ESXiToVRouterIp.map.erb')
}
file {'/etc/contrail/contrail-vcenter-plugin.conf':
ensure => present,
content => template('contrail/contrail-vcenter-plugin.conf.erb'),
}~>
# Enable and start service
service { 'contrail-vcenter-plugin':
ensure => running,
enable => true,
}
Nova_Config <||> ~>
service { 'nova-compute':
ensure => running,
enable => true,
}
}

View File

@@ -0,0 +1,67 @@
# Copyright 2016 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.
class contrail::compute::vmware_pkg {
$patch_path = '/usr/lib/python2.7/dist-packages'
Package {
ensure => installed,
}
Exec {
path => ['/usr/local/sbin', '/usr/local/bin', '/usr/sbin',
'/usr/bin', '/sbin', '/bin'],
}
#Create a pinning
$vcenter_compute_pkgs = [
'python-bitstring', 'python-novaclient',
'tzdata', 'tzdata-java', 'openjdk-7-jre-headless']
apt::pin { 'vcenter_compute_pkgs_pin':
explanation => 'Set override for packages from contrail repository',
priority => 1400,
label => 'contrail',
packages => $vcenter_compute_pkgs,
} ->
group { 'libvirtd':
ensure => 'present',
} ->
package { $vcenter_compute_pkgs: } ->
package {['nova-compute', 'nova-compute-kvm', 'nova-common', 'python-nova']:}
if $contrail::patch_nova_vmware {
file { "${patch_path}/nova-vmware.patch":
ensure => present,
mode => '0644',
source => 'puppet:///modules/contrail/nova-vmware.patch',
}->
exec { 'patch-nova-vmware':
command => 'patch -p1 < nova-vmware.patch',
onlyif => 'patch --dry-run -p1 < nova-vmware.patch',
cwd => $patch_path,
require => Package['python-nova'],
}
}
# Install vCenter-specific contrail packages
package { ['libxml-commons-external-java', 'libxml-commons-resolver1.1-java',
'libxerces2-java', 'libslf4j-java', 'libnetty-java', 'libjline-java',
'libzookeeper-java']: } ->
package { 'contrail-install-vcenter-plugin': } ->
package { ['libcontrail-java-api', 'libcontrail-vijava',
'libcontrail-vrouter-java-api']: } ->
package { 'contrail-vcenter-plugin': }
}

View File

@@ -0,0 +1,57 @@
# Copyright 2016 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.
class contrail::compute::vmware_repo {
# NOTE(AKirilochkin) This need to install qemu-kvm and qemu-system-x86
if roles_include('compute-vmware') {
include ::contrail::compute::compute_repo
}
# NOTE(AKirilochkin) This is only for contrail plugin repository
apt::pin { 'contrail':
priority => 1400,
label => 'contrail',
originator => 'contrail',
}
apt::pin { 'fixup_fox_libnl':
explanation => 'Fix for libnl from contrail repo',
packages => 'libnl-route-3-200',
priority => '1500',
originator => 'infra-mirror-9.0-master trusty',
}
# [FIXME] Temporary dirty hack. Fix execution of core manifests compute.pp and
# compute-vmware.pp. When contrail packages was installed, instead of libvirtd
# we will have libvirt-bin files.
file { '/etc/default/libvirtd':
ensure => present,
content => '',
}
file { '/etc/init.d/libvirtd':
ensure => present,
mode => '0755',
content => '',
}
file { '/opt/contrail':
ensure => directory,
}
file { '/etc/puppet/modules/vmware/templates/nova-compute.conf.erb':
source => 'puppet:///modules/contrail/nova-compute.conf.erb_fixed',
}
}

View File

@@ -14,9 +14,9 @@
class contrail::compute::vrouter {
# facter uses underscore instead of dot as a separator for interface name with vlan
$phys_dev_facter = regsubst($::contrail::phys_dev, '\.' , '_')
$dev_mac = getvar("::macaddress_${phys_dev_facter}")
# facter uses underscore instead of dot as a separator for interface name with vlan
$phys_dev_facter = regsubst($::contrail::phys_dev, '\.' , '_')
$dev_mac = getvar("::macaddress_${phys_dev_facter}")
if $contrail::compute_dpdk_enabled {
if empty($dev_mac) {
@@ -75,7 +75,7 @@ $dev_mac = getvar("::macaddress_${phys_dev_facter}")
} ->
exec { 'remove-ovs-modules':
command => '/sbin/modprobe -r openvswitch',
onlyif => '/sbin/lsmod | grep -q openvswitch',
onlyif => '/sbin/lsmod | grep -q ^openvswitch',
} ->
file {'/etc/contrail/agent_param':
ensure => present,

View File

@@ -0,0 +1,181 @@
# Copyright 2016 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.
class contrail::contrail_vmware {
if $contrail::use_vcenter and $contrail::provision_vmware_type == 'fuel'{
$self_ip = $contrail::address
$cfgm_ip = $contrail::contrail_private_vip
$ncontrols = size($contrail::contrail_control_ips)
$amqp_server_ip = $contrail::contrail_private_vip
$service_token = $contrail::admin_token
$orchestrator = $contrail::orchestrator
$hypervisor = $contrail::hypervisor
$keystone_ip = $contrail::mos_mgmt_vip
$keystone_admin_user = $contrail::neutron_user
$keystone_admin_password = $contrail::service_token
$service_tenant_name = $contrail::service_tenant
$internal_vip = $contrail::mos_mgmt_vip
$external_vip = $contrail::mos_public_vip
$contrail_internal_vip = $contrail::contrail_private_vip
$mgmt_self_ip = $::ipaddress_br_mgmt
# Fetching the esxi data from hash
$esxi_data = fetch_esxi_data("root@${self_ip}")
$vmware = $esxi_data['ip']
$vmware_username = $esxi_data['username']
$vmware_passwd = $esxi_data['password']
$vmware_iface_name = $esxi_data['contrail_vm']['vmware_iface_name']
$vmware_vmpg_vswitch = $esxi_data['fabric_vswitch']
$vmware_vmpg_vswitch_mtu = '9000'
$mode = $contrail::mode
$contrailvm_ntp = $contrail::contrailvm_ntp
$phys_dev_facter = regsubst($::contrail::phys_dev, '\.' , '_')
$dev_mac = getvar("::macaddress_${phys_dev_facter}")
$delete_packages = ['openvswitch-common', 'openvswitch-datapath-dkms',
'openvswitch-datapath-lts-saucy-dkms', 'openvswitch-switch', 'nova-network',
'nova-api']
$install_packages = ['contrail-install-packages', 'contrail-fabric-utils',
'contrail-setup', 'contrail-vrouter-dkms', 'contrail-vrouter-common',
'contrail-nova-vif', 'open-vm-tools', 'iproute2']
l23network::l3::ifconfig { $vmware_iface_name: ipaddr => 'none' }
$sysctl_settings = {
'net.nf_conntrack_max' => { value => '1048576'},
'kernel.panic' => { value => '60'},
'net.ipv4.conf.default.arp_accept' => { value => '1'},
'net.core.netdev_max_backlog' => { value => '261144'},
'net.ipv4.tcp_keepalive_intvl' => { value => '3'},
'net.ipv4.tcp_keepalive_time' => { value => '30'},
'net.ipv4.tcp_keepalive_probes' => { value => '8'},
'net.ipv4.conf.all.arp_accept' => { value => '1'},
'net.ipv4.tcp_retries2' => { value => '5'},
'net.ipv4.conf.all.rp_filter' => { value => '2'},
'net.ipv4.conf.default.rp_filter' => { value => '2'},
'kernel.core_pattern' => { value => '/var/crashes/core.%e.%p.%h.%t'},
}
$sysctl_defaults = {
require => File['/var/crashes'],
}
create_resources(sysctl::value, $sysctl_settings, $sysctl_defaults)
file_line { 'kexec-tools':
path => '/etc/default/kdump-tools',
match => 'crashkernel=.*\([ | \"]\)',
line => 'crashkernel=384M-2G:64M,2G-16G:128M,16G-:256M\1',
}
if !is_pkg_installed('contrail-openstack-vrouter') {
file { 'create_supervisor_vrouter_override':
ensure => present,
path => '/etc/init/supervisor-vrouter.override',
content => 'manual',
before => Class['contrail::package'],
}
}
class { 'contrail::package':
install => [$install_packages],
remove => [$delete_packages],
} ->
file {'/var/crashes':
ensure => directory,
mode => '1777',
} ->
file_line { 'use_kdump':
path => '/etc/default/kdump-tools',
match => 'USE_KDUMP=.*',
line => 'USE_KDUMP=1',
} ->
exec { 'remove-ovs-modules':
command => '/sbin/modprobe -r openvswitch',
onlyif => '/sbin/lsmod | grep -q ^openvswitch',
} ->
file {'/etc/contrail/agent_param':
ensure => present,
content => template('contrail/agent_param.erb'),
require => Class[Contrail::Package],
} ->
contrail_vrouter_agent_config {
'DEFAULT/platform' : value => 'default';
'DEFAULT/physical_interface_address' : value => $contrail::phys_dev_pci;
'DEFAULT/physical_interface_mac' : value => $dev_mac;
'DEFAULT/log_file' : value => '/var/log/contrail/contrail-vrouter-agent.log';
'DEFAULT/log_level' : value => 'SYS_NOTICE';
'DEFAULT/log_local' : value => '1';
'DEFAULT/log_flow' : value => '1';
'DEFAULT/use_syslog' : value => '1';
'DEFAULT/syslog_facility' : value => 'LOG_LOCAL0';
'DEFAULT/headless_mode' : value => true;
'DISCOVERY/server' : value => $contrail::contrail_private_vip;
'DISCOVERY/max_control_nodes' : value => '2';
'HYPERVISOR/type' : value => 'vmware';
'HYPERVISOR/vmware_mode' : value => 'vcenter';
'HYPERVISOR/vmware_physical_interface' : value => $vmware_iface_name;
'METADATA/metadata_proxy_secret' : value => $contrail::metadata_secret;
'NETWORKS/control_network_ip' : value => $contrail::address;
'VIRTUAL-HOST-INTERFACE/name' : value => 'vhost0';
'VIRTUAL-HOST-INTERFACE/ip' : value => "${contrail::address}/${contrail::netmask_short}";
'VIRTUAL-HOST-INTERFACE/physical_interface' : value => $contrail::phys_dev;
'VIRTUAL-HOST-INTERFACE/gateway' : value => pick($contrail::gateway, false);
'SERVICE-INSTANCE/netns_command' : value => '/usr/bin/opencontrail-vrouter-netns';
'FLOWS/thread_count' : value => '2';
} ->
contrail_vrouter_nodemgr_config {
'DISCOVERY/server': value => $contrail::contrail_private_vip;
'DISCOVERY/port': value => '5998';
} ->
exec { 'remove_supervisor_override':
command => '/bin/rm /etc/init/supervisor-vrouter.override',
onlyif => '/usr/bin/test -f /etc/init/supervisor-vrouter.override',
require => Class['Contrail::Package'],
}
service {'supervisor-vrouter':
ensure => running,
enable => true,
subscribe => [Class[Contrail::Package],
Exec['remove-ovs-modules'],
File['/etc/contrail/agent_param']],
} ->
exec { 'register_contrailvm_vrouter':
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "python provision_vrouter.py --host_name ${::fqdn} --host_ip ${self_ip} \
--api_server_ip ${contrail_internal_vip} --api_server_port ${contrail::api_server_port} \
--oper add --admin_user ${keystone_admin_user} --admin_password ${keystone_admin_password} \
--admin_tenant_name ${service_tenant_name} --openstack_ip ${internal_vip} \
&& touch /opt/contrail/register_contrailvm_vrouter-DONE",
creates => '/opt/contrail/register_contrailvm_vrouter-DONE',
}
exec {'command when file not exists':
command => 'touch /tmp/contrail-reboot-require && touch /opt/contrail/reboot-DONE',
onlyif => 'test ! -f /opt/contrail/reboot-DONE',
path => ['/usr/bin','/usr/sbin','/bin','/sbin'],
}
Contrail_vrouter_nodemgr_config <||> ~> Service['supervisor-vrouter']
Contrail_vrouter_agent_config <||> ~> Service['supervisor-vrouter']
}
}

View File

@@ -0,0 +1,152 @@
# Copyright 2016 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.
class contrail::controller::vmware {
if $contrail::use_vcenter and $contrail::provision_type_vmware == 'fabric' {
$vcenter_server_cluster = $contrail::vcenter_hash['computes'][0]['vc_cluster']
$pkgs = ['contrail-fabric-utils','contrail-setup']
$pip_pkgs = ['Fabric-1.7.5']
apt::pin {'fix_python_ecdsa':
priority => 1400,
label => 'contrail',
packages => 'python-ecdsa'
} ->
class { 'contrail::package':
install => $pkgs,
pip_install => $pip_pkgs,
} ->
exec {'retrieve latest install packages':
command => '/usr/bin/apt-get download contrail-install-packages && /bin/ln -s -f contrail-install-packages*.deb latest-contrail-install-packages.deb',
creates => '/opt/contrail/latest-contrail-install-packages.deb',
cwd => '/opt/contrail',
} ->
exec {'retrieve vmdk':
command => "/usr/bin/curl -fLO ${contrail::vmdk_vm_image}",
creates => '/opt/contrail/ContrailVM-disk1.vmdk',
cwd => '/opt/contrail',
} ->
file { '/opt/contrail/utils/fabfile/testbeds/testbed.py':
content => template('contrail/vmware_testbed.py.erb'),
mode => '0775',
} ->
file_line{'vmware_pub_authorized_keys':
path => '/root/.ssh/authorized_keys',
line => file('/var/lib/astute/vmware/vmware.pub'),
}
file { '/opt/contrail/utils/fabfile/tasks/additional_tasks.py':
mode => '0644',
source => 'puppet:///modules/contrail/additional_tasks.py',
before => Exec['fab_prepare_contrailvm'],
require => Class['contrail::package'],
} ->
file_line { 'add_additional_tasks':
path => '/opt/contrail/utils/fabfile/__init__.py',
line => 'from tasks.additional_tasks import *',
before => Exec['fab_prepare_contrailvm'],
}
if $contrail::env == 'dev' {
file_line { 'change_memsize1':
path => '/opt/contrail/utils/fabfile/templates/compute_vmx_template.py',
line => 'memsize = "2048"',
match => '^memsize',
require => Class['contrail::package'],
before => Exec['fab_prov_esxi'],
}
file_line { 'change_memsize2':
path => '/opt/contrail/utils/fabfile/templates/compute_vmx_template.py',
line => 'sched.mem.min = "2048"',
match => '^sched\.mem\.min',
require => Class['contrail::package'],
before => Exec['fab_prov_esxi'],
}
service { 'ssh':
ensure => running,
enable => true,
}
augeas { 'ssh_root_access_yes':
context => '/files/etc/ssh/sshd_config',
changes => ['set PermitRootLogin yes',
'set PasswordAuthentication yes'],
} ->
# NOTE(AKirilochkin): This is dirty hack. We have to restart sshd right now
# to make fab-scripts work with non-root feature.
# Then restart sshd again after setting set to default.
# By default puppet will schedule this event at the very end of manifest.
exec {'restart_ssh' :
command => '/sbin/restart ssh',
} ->
exec { 'fab_prov_esxi':
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => 'fab prov_esxi && touch /opt/contrail/fab_prov_esxi-DONE',
require => File_Line['vmware_pub_authorized_keys'],
creates => '/opt/contrail/fab_prov_esxi-DONE',
} ->
exec { 'fab_prepare_contrailvm':
timeout => 3300,
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => 'fab prepare_contrailvm:/opt/contrail/latest-contrail-install-packages.deb && touch /opt/contrail/fab_prepare_contrailvm-DONE',
creates => '/opt/contrail/fab_prepare_contrailvm-DONE',
} ->
exec { 'fab_install_vrouter':
timeout => 3300,
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => 'fab fab_install_vrouter && touch /opt/contrail/fab_install_vrouter-DONE',
creates => '/opt/contrail/fab_install_vrouter-DONE',
} ->
exec { 'fab_setup_vcenter':
timeout => 3300,
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => 'fab setup_vcenter && touch /opt/contrail/fab_setup_vcenter-DONE',
creates => '/opt/contrail/fab_setup_vcenter-DONE',
} ->
contrail::provision_contrailvm {$contrail::contrail_vcenter_vm_ips:
} ->
augeas { 'ssh_root_access_no':
context => '/files/etc/ssh/sshd_config',
changes => ['set PermitRootLogin no',
'set PasswordAuthentication no'],
notify => Service['ssh']
}
}
}
}

View File

@@ -69,7 +69,7 @@ class contrail {
$public_ssl = get_ssl_property($ssl_hash, $public_ssl_hash, 'horizon', 'public', 'usage', false)
$public_ssl_path = get_ssl_property($ssl_hash, $public_ssl_hash, 'horizon', 'public', 'path', [''])
#NOTE(AK858F): Modern way to get the ssl values with understandable variables names
#NOTE(AKirilochkin): Modern way to get the ssl values with understandable variables names
$public_horizon_endpoint = get_ssl_property($ssl_hash, {}, 'horizon', 'public', 'hostname', [$mos_public_vip])
$public_horizon_protocol = get_ssl_property($ssl_hash, {}, 'horizon', 'public', 'protocol', 'http')
@@ -88,7 +88,7 @@ class contrail {
$internal_auth_address = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'hostname', [hiera('service_endpoint', ''), $mos_mgmt_vip])
$internal_auth_protocol = get_ssl_property($ssl_hash, {}, 'keystone', 'internal', 'protocol', 'http')
#NOTE(AK858F): There are duplicate variables with the different names, we have
#NOTE(AKirilochkin): There are duplicate variables with the different names, we have
# to switch to one format
# Internal SSL for keystone connections
@@ -142,6 +142,7 @@ class contrail {
# Package override
$patch_nova = pick($settings['patch_nova'], false)
$patch_nova_vmware = pick($settings['patch_nova_vmware'], false)
$install_contrail_qemu_lv = pick($settings['install_contrail_qemu_lv'], false )
if $install_contrail_qemu_lv and $compute_dpdk_enabled {
@@ -150,6 +151,36 @@ class contrail {
$libvirt_name = 'libvirtd'
}
# vCenter settings
$use_vcenter = hiera('use_vcenter', false)
$vcenter_hash = hiera_hash('vcenter', {})
if $use_vcenter {
$mode = 'vcenter'
$orchestrator = 'openstack'
$hypervisor = 'libvirt'
$vmdk_vm_image = pick($settings['vmdk_vm_image'], "http://${::contrail::master_ip}:8080/plugins/contrail-3.0/ContrailVM-disk1.vmdk")
$vcenter_server_ip = $vcenter_hash['computes'][0]['vc_host']
$vcenter_server_user = $vcenter_hash['computes'][0]['vc_user']
$vcenter_server_pass = $vcenter_hash['computes'][0]['vc_password']
$vcenter_server_name = $vcenter_hash['computes'][0]['availability_zone_name']
$contrail_vcenter_datacenter = $settings['contrail_vcenter_datacenter']
$contrail_vcenter_dvswitch = $settings['contrail_vcenter_dvswitch']
$contrail_vcenter_dvportgroup = $settings['contrail_vcenter_dvportgroup']
$contrail_vcenter_dvportgroup_numberofports = $settings['contrail_vcenter_dvportgroup_numberofports']
$contrail_vcenter_esxi_for_fabric = $settings['contrail_vcenter_esxi_for_fabric']
$provision_vmware = $settings['provision_vmware']
$contrailvm_ntp = $settings['contrailvm_ntp']
$provision_vmware_type = $settings['provision_vmware_type']
$contrail_vcenter_vm_ips = get_contrailvm_ips()
$contrail_compute_vmware_nodes_hash = get_nodes_hash_by_roles($network_metadata, ['compute-vmware'])
$contrail_compute_vmware_ips = values(get_node_to_ipaddr_map_by_network_role($contrail_compute_vmware_nodes_hash, 'neutron/mesh'))
$primary_controller_role = hiera('primary_controller_role', ['primary-controller'])
$contrail_fab_build_node_hash = get_nodes_hash_by_roles($network_metadata, $primary_controller_role)
$contrail_fab_build_ip = values(get_node_to_ipaddr_map_by_network_role($contrail_fab_build_node_hash, 'neutron/mesh'))
$contrail_fab_default = {'vmdk' => '/opt/contrail/ContrailVM-disk1.vmdk', 'vcenter_server' => 'vcenter1', 'mode' => $mode }
}
# Settings for RabbitMQ on contrail controllers
$rabbit = hiera_hash('rabbit')
$rabbit_password = $rabbit['password']

View File

@@ -32,7 +32,7 @@ class contrail::provision::compute {
if $contrail::compute_dpdk_enabled {
exec { 'provision-vrouter':
command => "contrail-provision-vrouter \
--api_server_ip ${contrail::contrail_mgmt_vip} --api_server_port ${contrail::api_server_port}--openstack_ip ${contrail::keystone_address} \
--api_server_ip ${contrail::contrail_mgmt_vip} --api_server_port ${contrail::api_server_port} --openstack_ip ${contrail::keystone_address} \
--oper add --host_name ${::fqdn} --host_ip ${contrail::address} \
--admin_user '${contrail::neutron_user}' --admin_tenant_name '${contrail::service_tenant}' --admin_password '${contrail::service_token}' \
--dpdk_enabled \

View File

@@ -0,0 +1,145 @@
# Copyright 2016 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.
define contrail::provision_contrailvm (
$host = split($title, '@'),
)
{
$self_ip = $host[1]
$cfgm_ip = $contrail::contrail_private_vip
$ncontrols = size($contrail::contrail_control_ips)
$amqp_server_ip = $contrail::contrail_private_vip
$service_token = $contrail::admin_token
$orchestrator = 'openstack'
$hypervisor = 'libvirt'
$keystone_ip = $contrail::mos_mgmt_vip
#$openstack_mgmt_ip
$keystone_auth_protocol = 'http'
$keystone_auth_port = '35357'
$quantum_service_protocol = 'http'
$keystone_admin_user = 'neutron'
$keystone_admin_password = $contrail::service_token
#$nova_password admin
#$neutron_password
$service_tenant_name = 'services'
$internal_vip = $contrail::mos_mgmt_vip
$external_vip = $contrail::mos_public_vip
$contrail_internal_vip = $contrail::contrail_private_vip
$mgmt_self_ip = $host[1]
$esxi_data = fetch_esxi_data($title)
$vmware = $esxi_data['ip']
$vmware_username = $esxi_data['username']
$vmware_passwd = $esxi_data['password']
$vmware_vmpg_vswitch = $esxi_data['fabric_vswitch']
$vmware_vmpg_vswitch_mtu = '9000'
$mode = 'vcenter'
$oktets = split($self_ip, '\.')
$last_oktet = $oktets[3]
$vm_hostname = "ContrailVM-${last_oktet}"
$contrailvm_ntp = $contrail::contrailvm_ntp
$provisioning_cmd = "setup-vnc-compute --self_ip ${self_ip} \
--cfgm_ip ${cfgm_ip} \
--ncontrols ${ncontrols} \
--amqp_server_ip ${amqp_server_ip} \
--service_token ${service_token} \
--orchestrator ${orchestrator} \
--hypervisor ${hypervisor} \
--keystone_ip ${keystone_ip} \
--keystone_auth_protocol ${keystone_auth_protocol} \
--keystone_auth_port ${keystone_auth_port} \
--quantum_service_protocol ${quantum_service_protocol} \
--keystone_admin_user ${keystone_admin_user} \
--keystone_admin_password ${keystone_admin_password} \
--service_tenant_name ${service_tenant_name} \
--internal_vip ${internal_vip} \
--external_vip ${external_vip} \
--no_contrail_openstack \
--no_nova_config \
--contrail_internal_vip ${contrail_internal_vip} \
--mgmt_self_ip ${mgmt_self_ip} \
--vmware ${vmware} \
--vmware_username ${vmware_username} \
--vmware_passwd ${vmware_passwd} \
--vmware_vmpg_vswitch ${vmware_vmpg_vswitch} \
--vmware_vmpg_vswitch_mtu ${vmware_vmpg_vswitch_mtu} \
--mode ${mode}"
$register_cmd = "python provision_vrouter.py --host_name ${vm_hostname} \
--host_ip ${self_ip} \
--api_server_ip ${contrail_internal_vip} \
--oper add \
--admin_user ${keystone_admin_user} \
--admin_password ${keystone_admin_password} \
--admin_tenant_name ${service_tenant_name} \
--openstack_ip ${internal_vip}"
exec { "disable_add_vnc_config-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} disable_add_vnc_config && touch /opt/contrail/disable_add_vnc_config-${self_ip}-DONE",
creates => "/opt/contrail/disable_add_vnc_config-${self_ip}-DONE",
} ->
exec { "change_hostname-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} change_hostname:'${vm_hostname}' && touch /opt/contrail/change_hostname-${self_ip}-DONE",
creates => "/opt/contrail/change_hostname-${self_ip}-DONE",
} ->
exec { "deploy_agent_param_${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} deploy_agent_param && touch /opt/contrail/fab_deploy_agent_param-${self_ip}-DONE",
creates => "/opt/contrail/fab_deploy_agent_param-${self_ip}-DONE",
} ->
exec { "redeploy_vrouter_module_${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} redeploy_vrouter_module && touch /opt/contrail/fab_redeploy_vrouter_module-${self_ip}-DONE",
creates => "/opt/contrail/fab_redeploy_vrouter_module-${self_ip}-DONE",
} ->
exec{ "set_ntp-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} set_ntp:'${contrailvm_ntp}' && touch /opt/contrail/set_ntp-${self_ip}-DONE",
creates => "/opt/contrail/set_ntp-${self_ip}-DONE",
} ->
exec { "provision_contrailvm-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} provision_contrailvm:'${provisioning_cmd}' && touch /opt/contrail/provision_contrailvm-${self_ip}-DONE",
creates => "/opt/contrail/provision_contrailvm-${self_ip}-DONE",
} ->
exec { "register_contrailvm_vrouter-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "${register_cmd} && touch /opt/contrail/register_contrailvm_vrouter-${self_ip}-DONE",
creates => "/opt/contrail/register_contrailvm_vrouter-${self_ip}-DONE",
} ->
exec { "reboot_contrailvm-${self_ip}":
path => '/usr/local/bin:/bin:/usr/bin/',
cwd => '/opt/contrail/utils',
command => "fab -H ${title} provision_contrailvm:'reboot' && touch /opt/contrail/reboot_contrailvm-${self_ip}-DONE",
creates => "/opt/contrail/reboot_contrailvm-${self_ip}-DONE",
}
}

View File

@@ -0,0 +1,4 @@
<% scope.function_create_esxi_map([]).each do |line| -%>
<%= line %>
<% end %>

View File

@@ -145,11 +145,11 @@ config.analytics.ca = '';
// vcenter related parameters
config.vcenter = {};
config.vcenter.server_ip = '127.0.0.1'; //vCenter IP
config.vcenter.server_ip = '<%= scope.lookupvar('contrail::vcenter_server_ip') %>'; //vCenter IP
config.vcenter.server_port = '443'; //Port
config.vcenter.authProtocol = 'https'; //http or https
config.vcenter.datacenter = 'vcenter'; //datacenter name
config.vcenter.dvsswitch = 'vswitch'; //dvsswitch name
config.vcenter.datacenter = '<%= scope.lookupvar('contrail::contrail_vcenter_datacenter') %>'; //datacenter name
config.vcenter.dvsswitch = '<%= scope.lookupvar('contrail::contrail_vcenter_dvswitch') %>'; //dvsswitch name
config.vcenter.strictSSL = false; //Validate the certificate or ignore
config.vcenter.ca = ''; //specify the certificate key file
config.vcenter.wsdl = '/usr/src/contrail/contrail-web-core/webroot/js/vim.wsdl';

View File

@@ -0,0 +1,36 @@
#
# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
#
# Vcenter Plugin configuration options
#
[DEFAULT]
# Everything in this section is optional
# Vcenter plugin URL
vcenter.url=https://<%= scope.lookupvar('contrail::vcenter_server_ip') %>/sdk
#Vcenter credentials
vcenter.username=<%= scope.lookupvar('contrail::vcenter_server_user') %>
vcenter.password=<%= scope.lookupvar('contrail::vcenter_server_pass') %>
vcenter.datacenter=<%= scope.lookupvar('contrail::contrail_vcenter_datacenter') %>
vcenter.dvswitch=<%= scope.lookupvar('contrail::contrail_vcenter_dvswitch') %>
vcenter.ipfabricpg=contrail-fab-pg
mode=vcenter-as-compute
auth_url=<%= scope.lookupvar('contrail::internal_auth_protocol') %>://<%= scope.lookupvar('contrail::internal_auth_address') %>:35357/v2.0
admin_user=neutron
admin_password=<%= scope.lookupvar('contrail::service_token') %>
admin_tenant_name=services
# IP address and port to be used to connect to api server.
api.hostname=<%= scope.lookupvar('contrail::contrail_private_vip') %>
api.port=8082
zookeeper.serverlist=<%= scope.lookupvar('contrail::contrail_db_ips').map{ |ip| "#{ip}:2181" }.join(',') %>
# HTTP Introspect
introspect.port=8234

View File

@@ -0,0 +1,24 @@
SERVICE_TOKEN=<%= scope.lookupvar('contrail::service_token') %>
AUTH_PROTOCOL=<%= scope.lookupvar('contrail::keystone_protocol') %>
QUANTUM_PROTOCOL=<%= scope.lookupvar('contrail::neutron_protocol') %>
ADMIN_TOKEN=<%= scope.lookupvar('contrail::admin_token') %>
CONTROLLER=<% scope.lookupvar('contrail::mos_mgmt_vip') %>
AMQP_SERVER=<%= scope.lookupvar('contrail::contrail_private_vip') %>
HYPERVISOR=<%= scope.lookupvar('contrail::hypervisor') %>
NOVA_PASSWORD=<%= scope.lookupvar('contrail::admin_token') %>
NEUTRON_PASSWORD=<%= scope.lookupvar('contrail::admin_token') %>
SERVICE_TENANT_NAME=<%= scope.lookupvar('service_tenant_name') %>
QUANTUM=<%= scope.lookupvar('contrail::contrail_private_vip') %>
QUANTUM_PORT=None
COMPUTE=<%= scope.lookupvar('self_ip') %>
SELF_MGMT_IP=<%= scope.lookupvar('::ipaddress_br_mgmt') %>
CONTROLLER_MGMT=<%= scope.lookupvar('::ipaddress_br_mgmt') %>
<%- if scope.lookupvar('contrail::node_role') == 'contrail-vmware' then -%>
VMWARE_IP=<%= scope.lookupvar('vmware') %>
VMWARE_USERNAME=<%= scope.lookupvar('vmware_username') %>
VMWARE_PASSWD=<%= scope.lookupvar('vmware_passwd') %>
VMWARE_VMPG_VSWITCH=<%= scope.lookupvar('vmware_vmpg_vswitch') %>
INTERNAL_VIP=<%= scope.lookupvar('contrail::mos_mgmt_vip') %>
CONTRAIL_INTERNAL_VIP=<%= scope.lookupvar('contrail::contrail_private_vip') %>
EXTERNAL_VIP=<%= scope.lookupvar('contrail::mos_public_vip') %>
<%- end -%>

View File

@@ -0,0 +1,82 @@
# Note(AKirilochkin):
# This file provides configuration for fabric subsystem. This is default way how Juniper deploys
# the contrail things. We have used this as a default solution to get default configuration.
# The better way is to use FUEL-based deployment to have all nodes managed by FUEL.
<%-
fab_default=scope.lookupvar('contrail::contrail_fab_default')
contrailvm=scope.lookupvar('contrail::contrail_vcenter_vm_ips')
vcenter_compute=scope.lookupvar('contrail::contrail_compute_vmware_ips')[0]
fab_build=scope.lookupvar('contrail::contrail_fab_build_ip')[0]
-%>
from fabric.api import env
#Role definition of the hosts.
env.roledefs = {
'compute' : <%= contrailvm %>,
'vcenter_compute' : ["root@<%= vcenter_compute %>"],
'build' : ["root@<%= fab_build %>"],
'all' : ["root@<%= fab_build %>"],
'cfgm' : ["root@<%= fab_build %>"],
'control' : ["root@<%= fab_build %>"],
'openstack' : ["root@<%= fab_build %>"],
}
env.passwords = {
<%- contrailvm.each do |ip| -%>
'<%= ip %>': 'c0ntrail123',
<%- end -%>
}
env.command_timeout=3600
#Openstack admin password
env.openstack_admin_password = '<%= scope.lookupvar('contrail::admin_password') %>'
#Default ssh key for fabric usage
env.key_filename = '/var/lib/astute/vmware/vmware'
env.keystone = {
'admin_token' : '<%= scope.lookupvar('contrail::admin_token') %>',
'service_tenant' : 'services',
'manage_neutron' : 'no',
}
env.ha = {
'internal_vip' : '<%= scope.lookupvar('contrail::mos_mgmt_vip') %>',
'external_vip' : '<%= scope.lookupvar('contrail::mos_public_vip') %>',
'contrail_internal_vip' : '<%= scope.lookupvar('contrail::contrail_private_vip') %>',
'contrail_external_vip' : '<%= scope.lookupvar('contrail::mos_public_vip') %>',
}
env.openstack = {
'service_token' : '<%= scope.lookupvar('contrail::admin_token') %>',
}
#service token need to define to do restore of backup data
service_token = '<%= scope.lookupvar('contrail::admin_token') %>'
#To disable installing contrail interface rename package
env.interface_rename = False
#vcenter provisioning
env.vcenter_servers = {
'vcenter1': {
'server':'<%= scope.lookupvar('contrail::vcenter_server_ip') %>',
'port': '443',
'username': '<%= scope.lookupvar('contrail::vcenter_server_user') %>',
'password': '<%= scope.lookupvar('contrail::vcenter_server_pass') %>',
'auth': 'https',
'datacenter': '<%= scope.lookupvar('contrail::contrail_vcenter_datacenter') %>',
'cluster': <%= scope.lookupvar('vcenter_server_cluster').split(',').map(&:strip) %>,
'vcenter_compute': '<%= scope.lookupvar('contrail::contrail_compute_vmware_ips')[0] %>',
'dv_switch': { 'dv_switch_name': '<%= scope.lookupvar('contrail::contrail_vcenter_dvswitch') %>',},
'dv_port_group': {
'dv_portgroup_name': '<%= scope.lookupvar('contrail::contrail_vcenter_dvportgroup') %>',
'number_of_ports': '<%= scope.lookupvar('contrail::contrail_vcenter_dvportgroup_numberofports') %>',
},
},
}
# The compute vm provisioning on ESXI host
esxi_hosts = <%= scope.function_prepare_user_fab([fab_default]) %>

View File

@@ -0,0 +1 @@
DISCOVERY=<%= scope.lookupvar('contrail::contrail_private_vip') %>

View File

@@ -87,11 +87,96 @@
strategy:
type: parallel
#
# Contrail VMware vRouter role
- id: contrail-vmware
type: group
role: [contrail-vmware]
tasks: [hiera, globals, setup_repositories, tools, logging, netconfig, hosts, deploy_start, dns-client, ntp-client]
required_for: [deploy_end, primary-contrail-control, primary-contrail-db, primary-controller]
requires: [deploy_start]
parameters:
strategy:
type: parallel
##########################################################
# Tasks
##########################################################
##############
#1. Copy ssh keys to vmware
##############
- id: vmware_copy_keys
type: copy_files
version: 2.0.0
groups: ['/.*/']
required_for: [pre_deployment_end]
requires: [vmware_generate_keys]
cross-depends:
- name: vmware_generate_keys
role: master
parameters:
files:
- src: /var/lib/fuel/keys/{CLUSTER_ID}/vmware/vmware
dst: /var/lib/astute/vmware/vmware
- src: /var/lib/fuel/keys/{CLUSTER_ID}/vmware/vmware.pub
dst: /var/lib/astute/vmware/vmware.pub
permissions: '0600'
dir_permissions: '0700'
cwd: /
- id: copy_vmware_data
type: copy_files
version: 2.0.0
groups: ['/.*/']
required_for: [pre_deployment_end]
requires: [gather_vmware_data]
cross-depends:
- name: gather_vmware_data
role: master
parameters:
files:
- src: /var/lib/fuel/contrail/{CLUSTER_ID}.yaml
dst: /etc/hiera/override/plugins.yaml
permissions: '0600'
dir_permissions: '0700'
cwd: /
condition:
yaql_exp: &use_vcenter '$.use_vcenter and changed($.use_vcenter)'
- id: gather_vmware_data
type: shell
version: 2.0.0
role: master
requires: [pre_deployment_start]
required_for: [copy_vmware_data]
parameters:
cmd: /usr/bin/python /var/www/nailgun/plugins/contrail-3.0/deployment_scripts/get_vmware_settings.py {CLUSTER_ID}
timeout: 180
cwd: /
condition:
yaql_exp: *use_vcenter
#############
#1. Install Contrail utils, java
#2. Generate keys
#############
- id: vmware_generate_keys
type: shell
version: 2.0.0
role: master
requires: [pre_deployment_start]
required_for: [vmware_copy_keys]
parameters:
cmd: sh /etc/puppet/modules/osnailyfacter/modular/astute/generate_keys.sh -p /var/lib/fuel/keys/ -i {CLUSTER_ID} -s 'vmware'
timeout: 180
cwd: /
#############
#3. Install Contrail utils, java
##############
- id: contrail-utils
type: puppet
version: 2.0.0
@@ -104,7 +189,7 @@
timeout: 720
#############
#2. Install Cassandra and wait cluster to bootstrap
#4. Install Cassandra and wait cluster to bootstrap
#############
- id: contrail-db-primary
@@ -118,7 +203,11 @@
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 3600
# This task is a anchor for make dependency between fuel keystone tasks and contrail db setup
##############
#5. This task is an anchor to create a dependency between fuel keystone
# tasks and contrail db setup
#############
- id: contrail-keystone
type: skipped
version: 2.0.0
@@ -129,7 +218,7 @@
- name: contrail-db-primary
################
#3. Deploy other Cassandra servers
#6. Deploy other Cassandra servers
################
- id: contrail-db-all
@@ -139,14 +228,14 @@
required_for: [deploy_end]
requires: [contrail-utils]
cross-depends:
- name: contrail-db-primary
- name: contrail-db-primary
parameters:
puppet_manifest: puppet/manifests/contrail-db.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 3600
###############
#4. Install and configure Contrail Config, Contrail Analytics, Contrail WebUI
#7. Install and configure Contrail Config, Contrail Analytics, Contrail WebUI
# this task is performed on one node initially to allow discovery service to start up
###############
@@ -157,16 +246,16 @@
required_for: [deploy_end]
requires: [contrail-utils, deploy_start]
cross-depends:
- name: /contrail-db(-primary|-all)/
- name: openstack-haproxy-contrail
- name: primary-keystone
- name: /contrail-db(-primary|-all)/
- name: openstack-haproxy-contrail
- name: primary-keystone
parameters:
puppet_manifest: puppet/manifests/contrail-config.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 1440
################
#5. Provision Primary Control config
#8. Provision Primary Control config
################
- id: contrail-config-provision-primary
@@ -181,7 +270,7 @@
timeout: 1440
################
#6. Perform same actions on other contrail-config nodes
#9. Perform same actions on other contrail-config nodes
################
- id: contrail-config-all
@@ -191,8 +280,8 @@
required_for: [deploy_end]
requires: [contrail-utils]
cross-depends:
- name: contrail-config-primary
- name: contrail-config-provision-primary
- name: contrail-config-primary
- name: contrail-config-provision-primary
parameters:
puppet_manifest: puppet/manifests/contrail-config.pp
puppet_modules: puppet/modules:/etc/puppet/modules
@@ -201,7 +290,7 @@
type: parallel
###############
#7. Provision Contrail Config
#10. Provision Contrail Config
###############
- id: contrail-config-provision-all
@@ -218,7 +307,7 @@
type: parallel
################
#8. Install and configure Contrail Control Node
#11. Install and configure Contrail Control Node
################
- id: contrail-control-primary
@@ -237,7 +326,7 @@
timeout: 1440
################
#9. Provision Primary Contrail control
#12. Provision Primary Contrail control
################
- id: contrail-control-provision-primary
@@ -252,7 +341,7 @@
timeout: 1440
##############
#10. Install other Contrail Control Nodes
#13. Install other Contrail Control Nodes
##############
- id: contrail-control-all
@@ -273,7 +362,7 @@
################
#11. Provision Contrail control
#14. Provision Contrail control
################
- id: contrail-control-provision-all
@@ -292,7 +381,7 @@
type: parallel
###############
# Provision Control db
#15. Provision Control db
###############
- id: contrail-db-provision-all
@@ -452,6 +541,20 @@
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 120
#################
# Configure vmware integration
#################
- id: primary-controller-vmware
type: puppet
groups: [primary-controller]
required_for: [post_deployment_end]
requires: [controller-hiera-post]
parameters:
puppet_manifest: puppet/manifests/controller-vmware.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 3600
#################
# Create networks for ostf-tests and provision route target
#################
@@ -473,9 +576,8 @@
role: self
- name: contrail-config-all
policy: all
- name: contrail-config-primary
policy: all
- name: openstack-controller-contrail
- name: openstack-controller-provision
role: primary-controller
policy: all
strategy:
type: one-by-one
@@ -484,6 +586,43 @@
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
##############################################################
# Compute vmware tasks section
##############################################################
# Set proper apt pin for Contrail repository
- id: contrail-compute-vmware-repo
type: puppet
groups: [compute-vmware]
required_for: [tools]
requires: [deploy_start, globals]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-vmware-repo.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
- id: contrail-compute-vmware-pkg
type: puppet
groups: [compute-vmware]
required_for: [top-role-compute-vmware]
requires: [deploy_start, globals, contrail-compute-vmware-repo, contrail-override-repository]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-vmware-pkg.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
# Deploy contrail vCenter plugin
- id: contrail-compute-vmware
type: puppet
groups: [compute-vmware]
required_for: [post_deployment_end]
requires: [post_deployment_start]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-vmware.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
##############################################################
# Compute tasks section
##############################################################
@@ -509,7 +648,7 @@
- id: compute-hiera
type: puppet
version: 2.0.0
groups: [compute]
groups: [compute, compute-vmware]
required_for: [netconfig]
requires: [deploy_start, globals]
parameters:
@@ -522,13 +661,12 @@
groups: [compute]
type: skipped
version: 2.0.0
#
# Set apt pin for packeges that need to be override
- id: contrail-override-repository
type: puppet
version: 2.0.0
groups: [compute]
groups: [compute, compute-vmware]
required_for: [deploy_end]
requires: [top-role-compute, enable_nova_compute_service, openstack-network-end, compute-hiera]
parameters:
@@ -540,7 +678,7 @@
- id: contrail-compute-hugepages
type: puppet
version: 2.0.0
groups: [compute]
groups: [compute, compute-vmware]
required_for: [deploy_end]
requires: [top-role-compute, enable_nova_compute_service, openstack-network-end, contrail-override-repository]
parameters:
@@ -622,3 +760,40 @@
puppet_manifest: puppet/manifests/contrail-compute-aggregate.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 120
- id: contrail-vmware-task
type: puppet
version: 2.0.0
groups: [contrail-vmware]
required_for: [contrail-vmware-network]
requires: [hosts, ssl-dns-setup]
parameters:
puppet_manifest: puppet/manifests/contrail-vmware.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
cross-depends:
- name: contrail-db-provision-all
- id: contrail-vmware-network
type: puppet
version: 2.0.0
groups: [contrail-vmware]
required_for: [contrail-vmware-reboot]
requires: [contrail-vmware-task]
parameters:
puppet_manifest: puppet/manifests/contrail-compute-network.pp
puppet_modules: puppet/modules:/etc/puppet/modules
timeout: 720
# Reboot contrail-wmware nodes, if it need.
- id: contrail-vmware-reboot
type: shell
version: 2.0.0
groups: [contrail-vmware]
required_for: [deploy_end]
requires: [contrail-vmware-task]
parameters:
cmd: if [ -f /tmp/contrail-reboot-require ]; then /sbin/reboot; fi
timeout: 720

View File

@@ -38,7 +38,7 @@ attributes:
weight: 60
type: "text"
regex:
source: '^(429496729[0-6]|42949672[0-8]\d|4294967[01]\d{2}|429496[0-6]\d{3}|42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|4[01]\d{8}|[1-3]\d{9}|[1-9]\d{8}|[1-9]\d{7}|[1-9]\d{6}|[1-9]\d{5}|[1-9]\d{4}|[1-9]\d{3}|[1-9]\d{2}|[1-9]\d|\d)$'
source: '^(?:(6553[0-5])|(655[0-2]\d)|(65[0-4]\d{2})|(6[0-4]\d{3})|([1-5]\d{4})|([1-9]\d{1,3})|([1-9]))$'
error: "Invalid target"
contrail_global_dpdk:
value: false
@@ -70,7 +70,7 @@ attributes:
install_contrail_qemu_lv:
value: true
label: "Install Qemu and Libvirt from Contrail"
description: "Install Qemu and Libvirt packages from contrail repository"
description: "Install Qemu and Libvirt packages from contrail repository. This option should be enabled for environment with VCenter"
weight: 150
type: "checkbox"
restrictions:
@@ -85,4 +85,173 @@ attributes:
restrictions:
- condition: "not (settings:contrail.metadata.enabled == true and settings:contrail.contrail_global_dpdk.value == true)"
action: "hide"
contrail_vcenter_datacenter:
value: "Datacenter"
label: "vCenter Datacenter"
description: "vCenter Datacenter for Contrail"
weight: 160
type: "text"
regex:
source: '^\w+$'
error: "Invalid vCenter Datacenter"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
contrail_vcenter_dvswitch:
value: "Contrail_dvSwitch"
label: "vCenter dvSwitch"
description: "vCenter dvSwitch for Contrail"
weight: 170
type: "text"
regex:
source: '^\w+$'
error: "Invalid vCenter dvSwitch"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
contrail_vcenter_dvportgroup:
value: "Contrail_DV_Port_Group"
label: "vCenter DV Port Group"
description: "vCenter DV Port Group for Contrail"
weight: 180
type: "text"
regex:
source: '^\w+$'
error: "Invalid vCenter DV Port Group"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
contrail_vcenter_dvportgroup_numberofports:
value: "3"
label: "vCenter DV Port Group number of ports"
description: "vCenter number of ports DV Port Group for Contrail"
weight: 190
type: "text"
regex:
source: '^[1-9]\d*$'
error: "Invalid vCenter DV Port Group number of ports"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
patch_nova_vmware:
value: true
label: "Patch Nova for VCenter support"
description: "Patch python-nova on compute-vmware package for VCenter Contrail compatibility."
weight: 140
type: "checkbox"
restrictions:
- action: "hide"
condition: "settings:contrail.metadata.enabled == false"
- action: "hide"
condition: "settings:common.use_vcenter.value == false"
provision_vmware:
value: true
label: "Provision VMware hosts"
description: >
Enable this option to allow the plugin to provision ContrailVMs to ESXi hosts
and create Contrail_dvSwitch.
Can be disabled, if VMs are already created or this must be done manually.
weight: 192
type: "checkbox"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
provision_vmware_type:
value: "fuel"
label: "Select the type of ContrailVM provision."
description: "Fabric - Creates the network topology, bootstraps the VM and configures it. Fuel - uses precreated VM bootstrap it by PXE. You still have to configure ESXi network topology by-hand."
weight: 194
type: "radio"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
- condition: "settings:contrail.metadata.enabled == false"
action: "hide"
- condition: "not (settings:contrail.provision_vmware.value == true)"
action: "hide"
values:
- data: "fuel"
label: "Fuel"
- data: "fabric"
label: "Fabric"
contrail_vcenter_esxi_for_fabric:
value: |
'esxi1':
# The username of VMware ESXi ssh-access [Scope: Fabric]
'username': 'root'
# The ip-address of ESXi [Scope: Fabric and Fuel]
'ip': 'e.s.x.i'
# The private vSwitch [Scope: Fabric and Fuel]
'fabric_vswitch': 'vSwitch3'
# for example vnic0 [Scope: Fabric]
'uplink_nic': ''
# The cluster name [Scope: Fabric]
'cluster': 'cluster1'
# Where vm have to be stored [Scope: Fabric]
'datastore': '/vmfs/volumes/datastore1'
# The ssh password of ESXi [Scope: Fabric]
'password': 'esxi_ssh_password'
# These options are used by Fabric to deploy the ContrailVM [Scope: Fabric]
'contrail_vm':
# You still have to configure DHCP in private net to dootstrap the VM [Scope: Fabric]
'mac': '01:12:23:34:56:AB'
# The interface name, connected to Contrail_dvSwitch [Scope: Fuel]"
"vmware_iface_name": "ens161"
# This ip should be configured in DCHP and binded to mac [Scope: Fabric and Fuel]"
'host': 'root@192.168.x.y'
label: "vCenter ESXi data"
description: "vCenter ESXi data in YAML format"
weight: 200
type: "textarea"
regex:
source: '.'
error: "Invalid vCenter ESXi data"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
- condition: "not (settings:contrail.provision_vmware.value == true)"
action: "hide"
vmdk_vm_image:
value: ""
label: "ContrailVM image for ESXi"
description: "URL to download ContrailVM image. Keep empty if you have it on FUEL-master in contrail-plugin folder at /var/www/nailgun/plugins/contrail-3.0/ContrailVM-disk1.vmdk"
weight: 196
type: "text"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
- condition: "not (settings:contrail.provision_vmware.value == true)"
action: "hide"
- condition: "settings:contrail.provision_vmware_type.value == 'fuel'"
action: "hide"
contrailvm_ntp:
value: "10.109.3.1"
label: "NTP server for ContrailVM"
description: "NTP server address for ContrailVM, reachable from Private network. Should be deployed by-hands. [Scope: Fabric]"
weight: 205
type: "text"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
- condition: "not (settings:contrail.provision_vmware.value == true)"
action: "hide"
- condition: "settings:contrail.provision_vmware_type.value == 'fuel'"
action: "hide"
contrail_environment:
type: "select"
weight: 210
value: "prod"
label: "ContrailVM flavor"
description: "Choose the flavor for ContrailVM. Flavor with less RAM may be used for development/test environments."
values:
- data: "dev"
label: "development"
- data: "prod"
label: "production"
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: "hide"
- condition: "not (settings:contrail.provision_vmware.value == true)"
action: "hide"
- condition: "settings:contrail.provision_vmware_type.value == 'fuel'"
action: "hide"

View File

@@ -9,6 +9,7 @@ contrail-db:
- compute
- ceph-osd
- cinder
- contrail-vmware
contrail-config:
name: Contrail - Config
@@ -23,6 +24,7 @@ contrail-config:
- compute
- ceph-osd
- cinder
- contrail-vmware
contrail-control:
name: Contrail - Control
@@ -36,6 +38,7 @@ contrail-control:
- compute
- ceph-osd
- cinder
- contrail-vmware
dpdk:
name: DPDK compute
@@ -51,3 +54,25 @@ dpdk:
- contrail-control
- ceph-osd
- cinder
- contrail-vmware
contrail-vmware:
name: Contrail - VMware
description: >
Contrail VMware vRouter role. Provides bridge between ESXi-host and Contrail.
has_primary: false
public_ip_required: false
weight: 100
conflicts:
- controller
- contrail-db
- contrail-config
- contrail-control
- ceph-osd
- cinder
- dpdk
- compute
restrictions:
- condition: "settings:common.use_vcenter.value == false"
action: hide

19
post_install.sh Normal file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
# Copyright 2015 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.
# NOTE(AKirilochkin): These lines should be enabled if patch is not applied.
#sed -i -e "/if common_attrs.get('use_vcenter', {}).get('value') is True and/,+5 d" /usr/lib/python2.7/site-packages/nailgun/api/v1/validators/cluster.py
#sed -i -e 's#vCenterNetworkBackends:\["network:neutron:core:nsx"#vCenterNetworkBackends:\["network:neutron:contrail","network:neutron:core:nsx"#' /usr/share/nailgun/static/build/bundle.js
#systemctl restart nailgun.service