summaryrefslogtreecommitdiffstats
path: root/deploy
diff options
context:
space:
mode:
Diffstat (limited to 'deploy')
-rw-r--r--deploy/README186
-rw-r--r--deploy/__init__.py8
-rw-r--r--deploy/cloud/configure_environment.py76
-rw-r--r--deploy/cloud/configure_network.py69
-rw-r--r--deploy/cloud/configure_nodes.py109
-rw-r--r--deploy/cloud/configure_settings.py55
-rw-r--r--deploy/cloud/deploy.py94
-rw-r--r--deploy/cloud/deployment.py156
-rw-r--r--deploy/common.py157
-rw-r--r--deploy/dea.py102
-rw-r--r--deploy/deploy.py321
-rw-r--r--deploy/deploy_env.py266
-rw-r--r--deploy/dha.py35
-rw-r--r--deploy/dha_adapters/__init__.py8
-rw-r--r--deploy/dha_adapters/amt_adapter.py100
-rw-r--r--deploy/dha_adapters/hardware_adapter.py60
-rw-r--r--deploy/dha_adapters/hp_adapter.py37
-rw-r--r--deploy/dha_adapters/ipmi_adapter.py119
-rw-r--r--deploy/dha_adapters/libvirt_adapter.py138
-rw-r--r--deploy/environments/__init__.py8
-rw-r--r--deploy/environments/execution_environment.py75
-rw-r--r--deploy/environments/libvirt_environment.py107
-rw-r--r--deploy/environments/virtual_fuel.py70
-rw-r--r--deploy/execution_environment.py37
-rw-r--r--deploy/fuel_patch/ks.cfg.patch19
-rw-r--r--deploy/install_fuel_master.py223
-rw-r--r--deploy/reap.py340
-rw-r--r--deploy/ssh_client.py98
-rw-r--r--deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dea.yaml901
-rw-r--r--deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dha.yaml54
-rw-r--r--deploy/templates/hardware_environment/conf/ericsson_montreal_lab/plugins_conf/.gitkeep0
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dea.yaml898
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dha.yaml49
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/plugins_conf/.gitkeep0
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dea.yaml898
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dha.yaml49
-rw-r--r--deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/plugins_conf/.gitkeep0
-rw-r--r--deploy/templates/hardware_environment/conf/opnfv_box/dea.yaml898
-rw-r--r--deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml49
-rw-r--r--deploy/templates/hardware_environment/conf/opnfv_box/plugins_conf/.gitkeep0
-rw-r--r--deploy/templates/hardware_environment/vms/fuel.xml91
-rw-r--r--deploy/templates/plugins/.gitkeep0
-rw-r--r--deploy/templates/virtual_environment/conf/dea.yaml903
-rw-r--r--deploy/templates/virtual_environment/conf/dha.yaml44
-rw-r--r--deploy/templates/virtual_environment/conf/plugins_conf/.gitkeep0
-rw-r--r--deploy/templates/virtual_environment/networks/fuel1.xml12
-rw-r--r--deploy/templates/virtual_environment/networks/fuel2.xml5
-rw-r--r--deploy/templates/virtual_environment/networks/fuel3.xml5
-rw-r--r--deploy/templates/virtual_environment/networks/fuel4.xml12
-rw-r--r--deploy/templates/virtual_environment/vms/compute.xml91
-rw-r--r--deploy/templates/virtual_environment/vms/controller.xml91
-rw-r--r--deploy/templates/virtual_environment/vms/fuel.xml93
-rw-r--r--deploy/transplant_fuel_settings.py62
53 files changed, 8278 insertions, 0 deletions
diff --git a/deploy/README b/deploy/README
new file mode 100644
index 000000000..167078bf8
--- /dev/null
+++ b/deploy/README
@@ -0,0 +1,186 @@
+
+======== PREREQUISITES ========
+
+the following dependencies and python modules are required to be installed:
+
+- for Ubuntu:
+
+sudo apt-get install -y libvirt-bin qemu-kvm python-pip fuseiso mkisofs
+sudo apt-get install -y python-dev libz-dev libxml2-dev libxslt-dev
+sudo pip install pyyaml netaddr paramiko lxml scp pycrypto ecdsa
+
+During libvirt install the user is added to the libvirtd group, so you have to
+logout then login back again
+
+
+======== PREPARE and RUN the OPNFV Autodeployment ========
+
+
+--- Step.1 Prepare the DEA and DHA configuration files and the OPNFV ISO file
+
+Make sure that you are using the right DEA - Deployment Environment Adapter and
+DHA - Deployment Hardware Adapter configuration files, the ones provided are only templates
+you will have to modify them according to your needs
+
+- If wou wish to deploy OPNFV cloud environment on top of KVM/Libvirt
+ virtualization use as example the following configuration files:
+
+ * SR1 configuration files
+
+ => templates/virtual_environment/conf/ha
+ dea.yaml
+ dha.yaml
+
+
+ * ARNO configuration files
+
+ => templates/virtual_environment/old_conf/ha
+ dea.yaml
+ dha.yaml
+
+ => templates/virtual_environment/old_conf/multinode
+ dea.yaml
+ dha.yaml
+
+
+- If you wish to deploy OPNFV cloud environment on hardware
+ use as example the following configuration files:
+
+ * SR1 configuration files
+
+ => templates/hardware_environment/conf/ericsson_montreal_lab/ha
+ dea.yaml
+ dha.yaml
+
+ => templates/hardware_environment/conf/linux_foundation_lab/pod1/ha
+ dea.yaml
+ dha.yaml
+
+ => templates/hardware_environment/conf/linux_foundation_lab/pod2/ha
+ dea.yaml
+ dha.yaml
+
+
+ * ARNO configuration files
+
+ => templates/hardware_environment/old_conf/ericsson_montreal_lab/ha
+ dea.yaml
+ dha.yaml
+
+ => templates/hardware_environment/old_conf/ericsson_montreal_lab/multinode
+ dea.yaml
+ dha.yaml
+
+ => templates/hardware_environment/old_conf/linux_foundation_lab/ha
+ dea.yaml
+ dha.yaml
+
+ => templates/hardware_environment/old_conf/linux_foundation_lab/multinode
+ dea.yaml
+ dha.yaml
+
+
+--- Step.2 Run Autodeployment ---
+
+usage: python deploy.py [-h] [-nf] [-nh] [-fo] [-co] [-c] [-iso [ISO_FILE]]
+ [-dea [DEA_FILE]] [-dha [DHA_FILE]] [-s STORAGE_DIR]
+ [-b PXE_BRIDGE] [-p FUEL_PLUGINS_DIR]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -nf Do not install Fuel Master (and Node VMs when using libvirt)
+ -nh Don't run health check after deployment
+ -fo Install Fuel Master only (and Node VMs when using libvirt)
+ -co Cleanup VMs and Virtual Networks according to what is
+ defined in DHA
+ -c Cleanup after deploy
+ -iso [ISO_FILE] ISO File [default: OPNFV.iso]
+ -dea [DEA_FILE] Deployment Environment Adapter: dea.yaml
+ -dha [DHA_FILE] Deployment Hardware Adapter: dha.yaml
+ -s STORAGE_DIR Storage Directory [default: images]
+ -b PXE_BRIDGE Linux Bridge for booting up the Fuel Master VM
+ [default: pxebr]
+ -p FUEL_PLUGINS_DIR Fuel Plugins directory
+
+
+* EXAMPLES:
+
+- Install Fuel Master and deploy OPNFV Cloud from scratch on Hardware Environment:
+
+ sudo python deploy.py -iso ~/ISO/opnfv.iso -dea ~/CONF/hardware/dea.yaml -dha ~/CONF/hardware/dha.yaml -s /mnt/images -b pxebr
+
+
+- Install Fuel Master and deploy OPNFV Cloud from scratch on Virtual Environment:
+
+ sudo python deploy.py -iso ~/ISO/opnfv.iso -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml -s /mnt/images
+
+
+- Deploy OPNFV Cloud on an already active Environment where Fuel Master VM is running so no need to install Fuel again:
+
+ sudo python deploy.py -nf -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml
+
+ => with plugin installation
+ sudo python deploy.py -nf -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml
+
+ => with cleanup after deployment is finished
+ sudo python deploy.py -nf -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml -c
+
+ => no healthcheck after deployment is completed
+ sudo python deploy.py -nf -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml -nh
+
+
+- Install Fuel Master only (and Node VMs when using virtual environment):
+
+ => for virtual environment:
+ sudo python deploy.py -iso ~/ISO/opnfv.iso -dea ~/CONF/virtual/dea.yaml -dha ~/CONF/virtual/dha.yaml -s /mnt/images
+
+ => for hardware environment:
+ sudo python deploy.py -iso ~/ISO/opnfv.iso -dea ~/CONF/hardware/dea.yaml -dha ~/CONF/hardware/dha.yaml -s /mnt/images -b pxebr
+
+
+- Cleanup a running OPNFV environment:
+
+ sudo python deploy.py -co -dha ~/CONF/virtual/dha.yaml
+
+
+* WARNINGS:
+
+=> If optional argument -s <storage_dir> is not specified, Autodeployment will use
+"<current_working_dir>/images" as default, and it will create it, if it hasn't been created before
+
+=> If optional argument -b <pxe_bridge> is not specified, Autodeployment will use "pxebr" as default,
+if the bridge does not exist, the application will terminate with an error message
+
+=> If argument -iso [ISO_FILE] is not specified, Autodeployment will use "<current_working_dir>/OPNFV.iso"
+as default, if the iso file does not exist, the application will terminate with an error message
+
+=> If argument -dea [DEA_FILE] is not specified, Autodeployment will use "<current_working_dir>/dea.yaml"
+as default, if DEA file does not exist, the application will terminate with an error message
+
+=> If argument -dha [DHA_FILE] is not specified, Autodeployment will use "<current_working_dir>/dha.yaml"
+as default, if DHA file does not exist, the application will terminate with an error message
+
+=> Optional argument -b PXE_BRIDGE is not required for Autodeployment in virtual environment,
+ even if it is specified it will not be used at all because virtual environment is using a different virtual network setup
+
+=> If optional argument -p FUEL_PLUGINS_DIR is not specified, no external plugins will be installed in Fuel
+
+
+--- Networking considerations ---
+
+For Virtual Environment:
+
+There are some NAT, IPTABLE conflicts on the edge of libvirt bridging and Fuel Master
+according to http://wiki.libvirt.org/page/Networking
+netfilter on the bridges should be disabled
+
+Add these lines to /etc/sysctl.conf
+
+cat >> /etc/sysctl.conf <<EOF
+net.bridge.bridge-nf-call-ip6tables = 0
+net.bridge.bridge-nf-call-iptables = 0
+net.bridge.bridge-nf-call-arptables = 0
+EOF
+
+and then reload configuration:
+sysctl -p /etc/sysctl.conf
diff --git a/deploy/__init__.py b/deploy/__init__.py
new file mode 100644
index 000000000..fb73157f9
--- /dev/null
+++ b/deploy/__init__.py
@@ -0,0 +1,8 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
diff --git a/deploy/cloud/configure_environment.py b/deploy/cloud/configure_environment.py
new file mode 100644
index 000000000..ed89fa600
--- /dev/null
+++ b/deploy/cloud/configure_environment.py
@@ -0,0 +1,76 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from configure_settings import ConfigureSettings
+from configure_network import ConfigureNetwork
+from configure_nodes import ConfigureNodes
+
+from common import (
+ E,
+ exec_cmd,
+ parse,
+ err,
+ log,
+ delete,
+ create_dir_if_not_exists,
+)
+
+
+class ConfigureEnvironment(object):
+
+ def __init__(self, dea, yaml_config_dir, release_id, node_id_roles_dict):
+ self.env_id = None
+ self.dea = dea
+ self.yaml_config_dir = yaml_config_dir
+ self.release_id = release_id
+ self.node_id_roles_dict = node_id_roles_dict
+ self.required_networks = []
+
+ def env_exists(self, env_name):
+ env_list = parse(exec_cmd('fuel env --list'))
+ for env in env_list:
+ if env[E['name']] == env_name and env[E['status']] == 'new':
+ self.env_id = env[E['id']]
+ return True
+ return False
+
+ def configure_environment(self):
+ log('Configure environment')
+ delete(self.yaml_config_dir)
+ create_dir_if_not_exists(self.yaml_config_dir)
+ env_name = self.dea.get_env_name()
+ env_mode = self.dea.get_env_mode()
+ env_net_segment_type = self.dea.get_env_net_segment_type()
+ log('Creating environment %s release %s, mode %s, network-mode neutron'
+ ', net-segment-type %s'
+ % (env_name, self.release_id, env_mode, env_net_segment_type))
+ exec_cmd('fuel env create --name %s --release %s --mode %s '
+ '--network-mode neutron --net-segment-type %s'
+ % (env_name, self.release_id, env_mode, env_net_segment_type))
+
+ if not self.env_exists(env_name):
+ err('Failed to create environment %s' % env_name)
+ self.config_settings()
+ self.config_network()
+ self.config_nodes()
+
+ def config_settings(self):
+ settings = ConfigureSettings(self.yaml_config_dir, self.env_id,
+ self.dea)
+ settings.config_settings()
+
+ def config_network(self):
+ network = ConfigureNetwork(self.yaml_config_dir, self.env_id, self.dea)
+ network.config_network()
+
+ def config_nodes(self):
+ nodes = ConfigureNodes(self.yaml_config_dir, self.env_id,
+ self.node_id_roles_dict, self.dea)
+ nodes.config_nodes()
diff --git a/deploy/cloud/configure_network.py b/deploy/cloud/configure_network.py
new file mode 100644
index 000000000..b3ff9e9e0
--- /dev/null
+++ b/deploy/cloud/configure_network.py
@@ -0,0 +1,69 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+
+from common import (
+ exec_cmd,
+ check_file_exists,
+ log,
+ backup,
+)
+
+
+class ConfigureNetwork(object):
+
+ def __init__(self, yaml_config_dir, env_id, dea):
+ self.yaml_config_dir = yaml_config_dir
+ self.env_id = env_id
+ self.dea = dea
+ self.required_networks = []
+
+ def download_network_config(self):
+ log('Download network config for environment %s' % self.env_id)
+ exec_cmd('fuel network --env %s --download --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def upload_network_config(self):
+ log('Upload network config for environment %s' % self.env_id)
+ exec_cmd('fuel network --env %s --upload --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def config_network(self):
+ log('Configure network')
+ self.download_network_config()
+ self.modify_network_config()
+ self.upload_network_config()
+
+ def modify_network_config(self):
+ log('Modify network config for environment %s' % self.env_id)
+ network_yaml = ('%s/network_%s.yaml'
+ % (self.yaml_config_dir, self.env_id))
+ check_file_exists(network_yaml)
+ backup(network_yaml)
+
+ network_config = self.dea.get_property('network')
+
+ with io.open(network_yaml) as stream:
+ network = yaml.load(stream)
+
+ net_names = self.dea.get_network_names()
+ net_id = {}
+ for net in network['networks']:
+ if net['name'] in net_names:
+ net_id[net['name']] = {'id': net['id'],
+ 'group_id': net['group_id']}
+
+ for network in network_config['networks']:
+ network.update(net_id[network['name']])
+
+ with io.open(network_yaml, 'w') as stream:
+ yaml.dump(network_config, stream, default_flow_style=False)
diff --git a/deploy/cloud/configure_nodes.py b/deploy/cloud/configure_nodes.py
new file mode 100644
index 000000000..a456679ab
--- /dev/null
+++ b/deploy/cloud/configure_nodes.py
@@ -0,0 +1,109 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+import glob
+
+from common import (
+ exec_cmd,
+ check_file_exists,
+ log,
+ backup,
+)
+
+
+class ConfigureNodes(object):
+
+ def __init__(self, yaml_config_dir, env_id, node_id_roles_dict, dea):
+ self.yaml_config_dir = yaml_config_dir
+ self.env_id = env_id
+ self.node_id_roles_dict = node_id_roles_dict
+ self.dea = dea
+
+ def config_nodes(self):
+ log('Configure nodes')
+ for node_id, roles_blade in self.node_id_roles_dict.iteritems():
+ exec_cmd('fuel node set --node-id %s --role %s --env %s'
+ % (node_id, roles_blade[0], self.env_id))
+
+ self.download_deployment_config()
+ for node_id, roles_blade in self.node_id_roles_dict.iteritems():
+ self.download_interface_config(node_id)
+ self.modify_node_interface(node_id, roles_blade)
+ self.modify_node_network_schemes(node_id, roles_blade)
+ self.upload_interface_config(node_id)
+ self.upload_deployment_config()
+
+ def modify_node_network_schemes(self, node_id, roles_blade):
+ log('Modify network transformations for node %s' % node_id)
+ type = self.dea.get_node_property(roles_blade[1], 'transformations')
+ transformations = self.dea.get_property(type)
+ deployment_dir = '%s/deployment_%s' % (
+ self.yaml_config_dir, self.env_id)
+ backup(deployment_dir)
+ for node_file in glob.glob(deployment_dir + '/*_%s.yaml' % node_id):
+ with io.open(node_file) as stream:
+ node = yaml.load(stream)
+
+ node['network_scheme'].update(transformations)
+
+ with io.open(node_file, 'w') as stream:
+ yaml.dump(node, stream, default_flow_style=False)
+
+ def download_deployment_config(self):
+ log('Download deployment config for environment %s' % self.env_id)
+ exec_cmd('fuel deployment --env %s --default --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def upload_deployment_config(self):
+ log('Upload deployment config for environment %s' % self.env_id)
+ exec_cmd('fuel deployment --env %s --upload --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def download_interface_config(self, node_id):
+ log('Download interface config for node %s' % node_id)
+ exec_cmd('fuel node --env %s --node %s --network --download '
+ '--dir %s' % (self.env_id, node_id, self.yaml_config_dir))
+
+ def upload_interface_config(self, node_id):
+ log('Upload interface config for node %s' % node_id)
+ exec_cmd('fuel node --env %s --node %s --network --upload '
+ '--dir %s' % (self.env_id, node_id, self.yaml_config_dir))
+
+ def modify_node_interface(self, node_id, roles_blade):
+ log('Modify interface config for node %s' % node_id)
+ interface_yaml = ('%s/node_%s/interfaces.yaml'
+ % (self.yaml_config_dir, node_id))
+ check_file_exists(interface_yaml)
+ backup('%s/node_%s' % (self.yaml_config_dir, node_id))
+
+ with io.open(interface_yaml) as stream:
+ interfaces = yaml.load(stream)
+
+ net_name_id = {}
+ for interface in interfaces:
+ for network in interface['assigned_networks']:
+ net_name_id[network['name']] = network['id']
+
+ type = self.dea.get_node_property(roles_blade[1], 'interfaces')
+ interface_config = self.dea.get_property(type)
+
+ for interface in interfaces:
+ interface['assigned_networks'] = []
+ if interface['name'] in interface_config:
+ for net_name in interface_config[interface['name']]:
+ net = {}
+ net['id'] = net_name_id[net_name]
+ net['name'] = net_name
+ interface['assigned_networks'].append(net)
+
+ with io.open(interface_yaml, 'w') as stream:
+ yaml.dump(interfaces, stream, default_flow_style=False)
diff --git a/deploy/cloud/configure_settings.py b/deploy/cloud/configure_settings.py
new file mode 100644
index 000000000..c773e1b61
--- /dev/null
+++ b/deploy/cloud/configure_settings.py
@@ -0,0 +1,55 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+
+from common import (
+ exec_cmd,
+ check_file_exists,
+ log,
+ backup,
+)
+
+
+class ConfigureSettings(object):
+
+ def __init__(self, yaml_config_dir, env_id, dea):
+ self.yaml_config_dir = yaml_config_dir
+ self.env_id = env_id
+ self.dea = dea
+
+ def download_settings(self):
+ log('Download settings for environment %s' % self.env_id)
+ exec_cmd('fuel settings --env %s --download --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def upload_settings(self):
+ log('Upload settings for environment %s' % self.env_id)
+ exec_cmd('fuel settings --env %s --upload --dir %s'
+ % (self.env_id, self.yaml_config_dir))
+
+ def config_settings(self):
+ log('Configure settings')
+ self.download_settings()
+ self.modify_settings()
+ self.upload_settings()
+
+ def modify_settings(self):
+ log('Modify settings for environment %s' % self.env_id)
+ settings_yaml = ('%s/settings_%s.yaml'
+ % (self.yaml_config_dir, self.env_id))
+ check_file_exists(settings_yaml)
+ backup(settings_yaml)
+
+ settings = self.dea.get_property('settings')
+
+ with io.open(settings_yaml, 'w') as stream:
+ yaml.dump(settings, stream, default_flow_style=False)
diff --git a/deploy/cloud/deploy.py b/deploy/cloud/deploy.py
new file mode 100644
index 000000000..14d6a9621
--- /dev/null
+++ b/deploy/cloud/deploy.py
@@ -0,0 +1,94 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+
+from dea import DeploymentEnvironmentAdapter
+from configure_environment import ConfigureEnvironment
+from deployment import Deployment
+
+from common import (
+ R,
+ exec_cmd,
+ parse,
+ check_file_exists,
+ commafy,
+ ArgParser,
+)
+
+YAML_CONF_DIR = '/var/lib/opnfv'
+
+
+class Deploy(object):
+
+ def __init__(self, dea_file, no_health_check):
+ self.dea = DeploymentEnvironmentAdapter(dea_file)
+ self.no_health_check = no_health_check
+ self.macs_per_blade = {}
+ self.blades = self.dea.get_node_ids()
+ self.blade_node_dict = self.dea.get_blade_node_map()
+ self.node_roles_dict = {}
+ self.env_id = None
+ self.wanted_release = self.dea.get_property('wanted_release')
+
+ def assign_roles_to_cluster_node_ids(self):
+ self.node_roles_dict = {}
+ for blade, node in self.blade_node_dict.iteritems():
+ roles = commafy(self.dea.get_node_role(blade))
+ self.node_roles_dict[node] = (roles, blade)
+
+ def configure_environment(self):
+ release_list = parse(exec_cmd('fuel release -l'))
+ for release in release_list:
+ if release[R['name']] == self.wanted_release:
+ break
+ config_env = ConfigureEnvironment(self.dea, YAML_CONF_DIR,
+ release[R['id']],
+ self.node_roles_dict)
+ config_env.configure_environment()
+ self.env_id = config_env.env_id
+
+ def deploy_cloud(self):
+ dep = Deployment(self.dea, YAML_CONF_DIR, self.env_id,
+ self.node_roles_dict, self.no_health_check)
+ dep.deploy()
+
+ def deploy(self):
+
+ self.assign_roles_to_cluster_node_ids()
+
+ self.configure_environment()
+
+ self.deploy_cloud()
+
+
+def parse_arguments():
+ parser = ArgParser(prog='python %s' % __file__)
+ parser.add_argument('-nh', dest='no_health_check', action='store_true',
+ default=False,
+ help='Don\'t run health check after deployment')
+ parser.add_argument('dea_file', action='store',
+ help='Deployment Environment Adapter: dea.yaml')
+ args = parser.parse_args()
+ check_file_exists(args.dea_file)
+
+ kwargs = {'dea_file': args.dea_file,
+ 'no_health_check': args.no_health_check}
+ return kwargs
+
+
+def main():
+ kwargs = parse_arguments()
+ deploy = Deploy(**kwargs)
+ deploy.deploy()
+
+if __name__ == '__main__':
+ main()
diff --git a/deploy/cloud/deployment.py b/deploy/cloud/deployment.py
new file mode 100644
index 000000000..12c1f8978
--- /dev/null
+++ b/deploy/cloud/deployment.py
@@ -0,0 +1,156 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import time
+import re
+
+from common import (
+ N,
+ E,
+ exec_cmd,
+ run_proc,
+ parse,
+ err,
+ log,
+ delete,
+)
+
+SEARCH_TEXT = 'Puppet (err)'
+LOG_FILE = '/var/log/puppet.log'
+GREP_LINES_OF_LEADING_CONTEXT = 100
+GREP_LINES_OF_TRAILING_CONTEXT = 100
+LIST_OF_CHAR_TO_BE_ESCAPED = ['[', ']', '"']
+
+class Deployment(object):
+
+ def __init__(self, dea, yaml_config_dir, env_id, node_id_roles_dict,
+ no_health_check):
+ self.dea = dea
+ self.yaml_config_dir = yaml_config_dir
+ self.env_id = env_id
+ self.node_id_roles_dict = node_id_roles_dict
+ self.no_health_check = no_health_check
+ self.pattern = re.compile(
+ '\d\d\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d')
+
+ def collect_error_logs(self):
+ for node_id, roles_blade in self.node_id_roles_dict.iteritems():
+ log_list = []
+ cmd = ('ssh -q node-%s grep \'"%s"\' %s'
+ % (node_id, SEARCH_TEXT, LOG_FILE))
+ results, _ = exec_cmd(cmd, False)
+ for result in results.splitlines():
+ log_msg = ''
+
+ sub_cmd = '"%s" %s' % (result, LOG_FILE)
+ for c in LIST_OF_CHAR_TO_BE_ESCAPED:
+ sub_cmd = sub_cmd.replace(c, '\%s' % c)
+ grep_cmd = ('grep -B%s %s'
+ % (GREP_LINES_OF_LEADING_CONTEXT, sub_cmd))
+ cmd = ('ssh -q node-%s "%s"' % (node_id, grep_cmd))
+
+ details, _ = exec_cmd(cmd, False)
+ details_list = details.splitlines()
+
+ found_prev_log = False
+ for i in range(len(details_list) - 2, -1, -1):
+ if self.pattern.match(details_list[i]):
+ found_prev_log = True
+ break
+ if found_prev_log:
+ log_msg += '\n'.join(details_list[i:-1]) + '\n'
+
+ grep_cmd = ('grep -A%s %s'
+ % (GREP_LINES_OF_TRAILING_CONTEXT, sub_cmd))
+ cmd = ('ssh -q node-%s "%s"' % (node_id, grep_cmd))
+
+ details, _ = exec_cmd(cmd, False)
+ details_list = details.splitlines()
+
+ found_next_log = False
+ for i in range(1, len(details_list)):
+ if self.pattern.match(details_list[i]):
+ found_next_log = True
+ break
+ if found_next_log:
+ log_msg += '\n'.join(details_list[:i])
+ else:
+ log_msg += details
+
+ if log_msg:
+ log_list.append(log_msg)
+
+ if log_list:
+ role = ('controller' if 'controller' in roles_blade[0]
+ else 'compute host')
+ log('_' * 40 + 'Errors in node-%s %s' % (node_id, role)
+ + '_' * 40)
+ for log_msg in log_list:
+ print(log_msg + '\n')
+
+ def run_deploy(self):
+ WAIT_LOOP = 180
+ SLEEP_TIME = 60
+ LOG_FILE = 'cloud.log'
+
+ log('Starting deployment of environment %s' % self.env_id)
+ run_proc('fuel --env %s deploy-changes | strings | tee %s'
+ % (self.env_id, LOG_FILE))
+
+ ready = False
+ for i in range(WAIT_LOOP):
+ env = parse(exec_cmd('fuel env --env %s' % self.env_id))
+ log('Environment status: %s' % env[0][E['status']])
+ r, _ = exec_cmd('tail -2 %s | head -1' % LOG_FILE, False)
+ if r:
+ log(r)
+ if env[0][E['status']] == 'operational':
+ ready = True
+ break
+ elif (env[0][E['status']] == 'error'
+ or env[0][E['status']] == 'stopped'):
+ break
+ else:
+ time.sleep(SLEEP_TIME)
+ delete(LOG_FILE)
+
+ if ready:
+ log('Environment %s successfully deployed' % self.env_id)
+ else:
+ self.collect_error_logs()
+ err('Deployment failed, environment %s is not operational'
+ % self.env_id)
+
+ def verify_node_status(self):
+ node_list = parse(exec_cmd('fuel node list'))
+ failed_nodes = []
+ for node in node_list:
+ if node[N['status']] != 'ready':
+ failed_nodes.append((node[N['id']], node[N['status']]))
+
+ if failed_nodes:
+ summary = ''
+ for node, status in failed_nodes:
+ summary += '[node %s, status %s]\n' % (node, status)
+ err('Deployment failed: %s' % summary)
+
+ def health_check(self):
+ log('Now running sanity and smoke health checks')
+ r = exec_cmd('fuel health --env %s --check sanity,smoke --force'
+ % self.env_id)
+ log(r)
+ if 'failure' in r:
+ err('Healthcheck failed!')
+
+ def deploy(self):
+ self.run_deploy()
+ self.verify_node_status()
+ if not self.no_health_check:
+ self.health_check()
diff --git a/deploy/common.py b/deploy/common.py
new file mode 100644
index 000000000..17fd2174a
--- /dev/null
+++ b/deploy/common.py
@@ -0,0 +1,157 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import subprocess
+import sys
+import os
+import logging
+import argparse
+import shutil
+import stat
+import errno
+
+N = {'id': 0, 'status': 1, 'name': 2, 'cluster': 3, 'ip': 4, 'mac': 5,
+ 'roles': 6, 'pending_roles': 7, 'online': 8}
+E = {'id': 0, 'status': 1, 'name': 2, 'mode': 3, 'release_id': 4,
+ 'changes': 5, 'pending_release_id': 6}
+R = {'id': 0, 'name': 1, 'state': 2, 'operating_system': 3, 'version': 4}
+RO = {'name': 0, 'conflicts': 1}
+CWD = os.getcwd()
+LOG = logging.getLogger(__name__)
+LOG.setLevel(logging.DEBUG)
+formatter = logging.Formatter('%(message)s')
+out_handler = logging.StreamHandler(sys.stdout)
+out_handler.setFormatter(formatter)
+LOG.addHandler(out_handler)
+LOGFILE = 'autodeploy.log'
+if os.path.isfile(LOGFILE):
+ os.remove(LOGFILE)
+out_handler = logging.FileHandler(LOGFILE, mode='w')
+out_handler.setFormatter(formatter)
+LOG.addHandler(out_handler)
+os.chmod(LOGFILE, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
+
+def exec_cmd(cmd, check=True):
+ process = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ response = process.communicate()[0].strip()
+ return_code = process.returncode
+ if check:
+ if return_code > 0:
+ raise Exception(response)
+ else:
+ return response
+ return response, return_code
+
+
+def run_proc(cmd):
+ process = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ return process
+
+
+def parse(printout):
+ parsed_list = []
+ lines = printout.splitlines()
+ for l in lines[2:]:
+ parsed = [e.strip() for e in l.split('|')]
+ parsed_list.append(parsed)
+ return parsed_list
+
+
+def clean(lines):
+ parsed_list = []
+ parsed = []
+ for l in lines.strip().splitlines():
+ parsed = []
+ cluttered = [e.strip() for e in l.split(' ')]
+ for p in cluttered:
+ if p:
+ parsed.append(p)
+ parsed_list.append(parsed)
+ return parsed if len(parsed_list) == 1 else parsed_list
+
+
+def err(message):
+ LOG.error('%s\n' % message)
+ sys.exit(1)
+
+
+def warn(message):
+ LOG.warning('%s\n' % message)
+
+
+def check_file_exists(file_path):
+ if not os.path.dirname(file_path):
+ file_path = '%s/%s' % (CWD, file_path)
+ if not os.path.isfile(file_path):
+ err('ERROR: File %s not found\n' % file_path)
+
+
+def check_dir_exists(dir_path):
+ if not os.path.dirname(dir_path):
+ dir_path = '%s/%s' % (CWD, dir_path)
+ if not os.path.isdir(dir_path):
+ err('ERROR: Directory %s not found\n' % dir_path)
+
+
+def create_dir_if_not_exists(dir_path):
+ if not os.path.isdir(dir_path):
+ log('Creating directory %s' % dir_path)
+ os.makedirs(dir_path)
+
+
+def delete(f):
+ if os.path.isfile(f):
+ log('Deleting file %s' % f)
+ os.remove(f)
+ elif os.path.isdir(f):
+ log('Deleting directory %s' % f)
+ shutil.rmtree(f)
+
+
+def commafy(comma_separated_list):
+ l = [c.strip() for c in comma_separated_list.split(',')]
+ return ','.join(l)
+
+
+def check_if_root():
+ r = exec_cmd('whoami')
+ if r != 'root':
+ err('You need be root to run this application')
+
+
+def log(message):
+ LOG.debug('%s\n' % message)
+
+
+class ArgParser(argparse.ArgumentParser):
+
+ def error(self, message):
+ sys.stderr.write('ERROR: %s\n' % message)
+ self.print_help()
+ sys.exit(2)
+
+
+def backup(path):
+ src = path
+ dst = path + '_orig'
+ delete(dst)
+ try:
+ shutil.copytree(src, dst)
+ except OSError as e:
+ if e.errno == errno.ENOTDIR:
+ shutil.copy(src, dst)
+ else:
+ raise
diff --git a/deploy/dea.py b/deploy/dea.py
new file mode 100644
index 000000000..2d2b28ae8
--- /dev/null
+++ b/deploy/dea.py
@@ -0,0 +1,102 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+import netaddr
+
+
+class DeploymentEnvironmentAdapter(object):
+
+ def __init__(self, yaml_path):
+ self.dea_struct = None
+ self.parse_yaml(yaml_path)
+ self.network_names = []
+ self.collect_network_names()
+
+ def modify_ip(self, ip_addr, index, val):
+ ip_str = str(netaddr.IPAddress(ip_addr))
+ decimal_list = map(int, ip_str.split('.'))
+ decimal_list[index] = val
+ return '.'.join(map(str, decimal_list))
+
+ def parse_yaml(self, yaml_path):
+ with io.open(yaml_path) as yaml_file:
+ self.dea_struct = yaml.load(yaml_file)
+
+ def get_env_name(self):
+ return self.get_property('environment')['name']
+
+ def get_env_mode(self):
+ return self.get_property('environment')['mode']
+
+ def get_env_net_segment_type(self):
+ return self.get_property('environment')['net_segment_type']
+
+ def get_fuel_config(self):
+ return self.dea_struct['fuel']
+
+ def get_fuel_ip(self):
+ fuel_conf = self.get_fuel_config()
+ return fuel_conf['ADMIN_NETWORK']['ipaddress']
+
+ def get_fuel_netmask(self):
+ fuel_conf = self.get_fuel_config()
+ return fuel_conf['ADMIN_NETWORK']['netmask']
+
+ def get_fuel_gateway(self):
+ ip = self.get_fuel_ip()
+ return self.modify_ip(ip, 3, 1)
+
+ def get_fuel_hostname(self):
+ fuel_conf = self.get_fuel_config()
+ return fuel_conf['HOSTNAME']
+
+ def get_fuel_dns(self):
+ fuel_conf = self.get_fuel_config()
+ return fuel_conf['DNS_UPSTREAM']
+
+ def get_node_property(self, node_id, property_name):
+ for node in self.dea_struct['nodes']:
+ if node['id'] == node_id and property_name in node:
+ return node[property_name]
+
+ def get_node_role(self, node_id):
+ return self.get_node_property(node_id, 'role')
+
+ def get_node_ids(self):
+ node_ids = []
+ for node in self.dea_struct['nodes']:
+ node_ids.append(node['id'])
+ return node_ids
+
+ def get_property(self, property_name):
+ return self.dea_struct[property_name]
+
+ def collect_network_names(self):
+ self.network_names = []
+ for network in self.dea_struct['network']['networks']:
+ self.network_names.append(network['name'])
+
+ def get_network_names(self):
+ return self.network_names
+
+ def get_dns_list(self):
+ settings = self.get_property('settings')
+ dns_list = settings['editable']['external_dns']['dns_list']['value']
+ return [d.strip() for d in dns_list.split(',')]
+
+ def get_ntp_list(self):
+ settings = self.get_property('settings')
+ ntp_list = settings['editable']['external_ntp']['ntp_list']['value']
+ return [n.strip() for n in ntp_list.split(',')]
+
+ def get_blade_node_map(self):
+ return self.dea_struct['blade_node_map']
diff --git a/deploy/deploy.py b/deploy/deploy.py
new file mode 100644
index 000000000..4e209a932
--- /dev/null
+++ b/deploy/deploy.py
@@ -0,0 +1,321 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import os
+import io
+import re
+import sys
+import netaddr
+import yaml
+
+from dea import DeploymentEnvironmentAdapter
+from dha import DeploymentHardwareAdapter
+from install_fuel_master import InstallFuelMaster
+from deploy_env import CloudDeploy
+from execution_environment import ExecutionEnvironment
+
+from common import (
+ log,
+ exec_cmd,
+ err,
+ warn,
+ check_file_exists,
+ create_dir_if_not_exists,
+ delete,
+ check_if_root,
+ ArgParser,
+)
+
+FUEL_VM = 'fuel'
+PATCH_DIR = 'fuel_patch'
+WORK_DIR = '~/deploy'
+CWD = os.getcwd()
+
+
+class cd:
+
+ def __init__(self, new_path):
+ self.new_path = os.path.expanduser(new_path)
+
+ def __enter__(self):
+ self.saved_path = CWD
+ os.chdir(self.new_path)
+
+ def __exit__(self, etype, value, traceback):
+ os.chdir(self.saved_path)
+
+
+class AutoDeploy(object):
+
+ def __init__(self, no_fuel, fuel_only, no_health_check, cleanup_only,
+ cleanup, storage_dir, pxe_bridge, iso_file, dea_file,
+ dha_file, fuel_plugins_dir, fuel_plugins_conf_dir,
+ no_plugins):
+ self.no_fuel = no_fuel
+ self.fuel_only = fuel_only
+ self.no_health_check = no_health_check
+ self.cleanup_only = cleanup_only
+ self.cleanup = cleanup
+ self.storage_dir = storage_dir
+ self.pxe_bridge = pxe_bridge
+ self.iso_file = iso_file
+ self.dea_file = dea_file
+ self.dha_file = dha_file
+ self.fuel_plugins_dir = fuel_plugins_dir
+ self.fuel_plugins_conf_dir = fuel_plugins_conf_dir
+ self.no_plugins = no_plugins
+ self.dea = (DeploymentEnvironmentAdapter(dea_file)
+ if not cleanup_only else None)
+ self.dha = DeploymentHardwareAdapter(dha_file)
+ self.fuel_conf = {}
+ self.fuel_node_id = self.dha.get_fuel_node_id()
+ self.fuel_username, self.fuel_password = self.dha.get_fuel_access()
+ self.tmp_dir = None
+
+ def modify_ip(self, ip_addr, index, val):
+ ip_str = str(netaddr.IPAddress(ip_addr))
+ decimal_list = map(int, ip_str.split('.'))
+ decimal_list[index] = val
+ return '.'.join(map(str, decimal_list))
+
+ def collect_fuel_info(self):
+ self.fuel_conf['ip'] = self.dea.get_fuel_ip()
+ self.fuel_conf['gw'] = self.dea.get_fuel_gateway()
+ self.fuel_conf['dns1'] = self.dea.get_fuel_dns()
+ self.fuel_conf['netmask'] = self.dea.get_fuel_netmask()
+ self.fuel_conf['hostname'] = self.dea.get_fuel_hostname()
+ self.fuel_conf['showmenu'] = 'yes'
+
+ def install_fuel_master(self):
+ log('Install Fuel Master')
+ new_iso = ('%s/deploy-%s'
+ % (self.tmp_dir, os.path.basename(self.iso_file)))
+ self.patch_iso(new_iso)
+ self.iso_file = new_iso
+ self.install_iso()
+
+ def install_iso(self):
+ fuel = InstallFuelMaster(self.dea_file, self.dha_file,
+ self.fuel_conf['ip'], self.fuel_username,
+ self.fuel_password, self.fuel_node_id,
+ self.iso_file, WORK_DIR,
+ self.fuel_plugins_dir, self.no_plugins)
+ fuel.install()
+
+ def patch_iso(self, new_iso):
+ tmp_orig_dir = '%s/origiso' % self.tmp_dir
+ tmp_new_dir = '%s/newiso' % self.tmp_dir
+ try:
+ self.copy(tmp_orig_dir, tmp_new_dir)
+ self.patch(tmp_new_dir, new_iso)
+ except Exception as e:
+ exec_cmd('fusermount -u %s' % tmp_orig_dir, False)
+ delete(self.tmp_dir)
+ err(e)
+
+ def copy(self, tmp_orig_dir, tmp_new_dir):
+ log('Copying...')
+ os.makedirs(tmp_orig_dir)
+ os.makedirs(tmp_new_dir)
+ exec_cmd('fuseiso %s %s' % (self.iso_file, tmp_orig_dir))
+ with cd(tmp_orig_dir):
+ exec_cmd('find . | cpio -pd %s' % tmp_new_dir)
+ exec_cmd('fusermount -u %s' % tmp_orig_dir)
+ delete(tmp_orig_dir)
+ exec_cmd('chmod -R 755 %s' % tmp_new_dir)
+
+ def patch(self, tmp_new_dir, new_iso):
+ log('Patching...')
+ patch_dir = '%s/%s' % (CWD, PATCH_DIR)
+ ks_path = '%s/ks.cfg.patch' % patch_dir
+
+ with cd(tmp_new_dir):
+ exec_cmd('cat %s | patch -p0' % ks_path)
+ delete('.rr_moved')
+ isolinux = 'isolinux/isolinux.cfg'
+ log('isolinux.cfg before: %s'
+ % exec_cmd('grep netmask %s' % isolinux))
+ self.update_fuel_isolinux(isolinux)
+ log('isolinux.cfg after: %s'
+ % exec_cmd('grep netmask %s' % isolinux))
+
+ iso_linux_bin = 'isolinux/isolinux.bin'
+ exec_cmd('mkisofs -quiet -r -J -R -b %s '
+ '-no-emul-boot -boot-load-size 4 '
+ '-boot-info-table -hide-rr-moved '
+ '-x "lost+found:" -o %s .'
+ % (iso_linux_bin, new_iso))
+
+ def update_fuel_isolinux(self, file):
+ with io.open(file) as f:
+ data = f.read()
+ for key, val in self.fuel_conf.iteritems():
+ pattern = r'%s=[^ ]\S+' % key
+ replace = '%s=%s' % (key, val)
+ data = re.sub(pattern, replace, data)
+ with io.open(file, 'w') as f:
+ f.write(data)
+
+ def deploy_env(self):
+ dep = CloudDeploy(self.dea, self.dha, self.fuel_conf['ip'],
+ self.fuel_username, self.fuel_password,
+ self.dea_file, self.fuel_plugins_conf_dir,
+ WORK_DIR, self.no_health_check)
+ return dep.deploy()
+
+ def setup_execution_environment(self):
+ exec_env = ExecutionEnvironment(self.storage_dir, self.pxe_bridge,
+ self.dha_file, self.dea)
+ exec_env.setup_environment()
+
+ def cleanup_execution_environment(self):
+ exec_env = ExecutionEnvironment(self.storage_dir, self.pxe_bridge,
+ self.dha_file, self.dea)
+ exec_env.cleanup_environment()
+
+ def create_tmp_dir(self):
+ self.tmp_dir = '%s/fueltmp' % CWD
+ delete(self.tmp_dir)
+ create_dir_if_not_exists(self.tmp_dir)
+
+ def deploy(self):
+ self.collect_fuel_info()
+ if not self.no_fuel:
+ self.setup_execution_environment()
+ self.create_tmp_dir()
+ self.install_fuel_master()
+ if not self.fuel_only:
+ return self.deploy_env()
+ return True
+
+ def run(self):
+ check_if_root()
+ if self.cleanup_only:
+ self.cleanup_execution_environment()
+ else:
+ deploy_success = self.deploy()
+ if self.cleanup:
+ self.cleanup_execution_environment()
+ return deploy_success
+ return True
+
+def check_bridge(pxe_bridge, dha_path):
+ with io.open(dha_path) as yaml_file:
+ dha_struct = yaml.load(yaml_file)
+ if dha_struct['adapter'] != 'libvirt':
+ log('Using Linux Bridge %s for booting up the Fuel Master VM'
+ % pxe_bridge)
+ r = exec_cmd('ip link show %s' % pxe_bridge)
+ if pxe_bridge in r and 'state DOWN' in r:
+ err('Linux Bridge {0} is not Active, bring'
+ ' it UP first: [ip link set dev {0} up]'.format(pxe_bridge))
+
+
+def check_fuel_plugins_dir(dir):
+ msg = None
+ if not dir:
+ msg = 'Fuel Plugins Directory not specified!'
+ elif not os.path.isdir(dir):
+ msg = 'Fuel Plugins Directory does not exist!'
+ elif not os.listdir(dir):
+ msg = 'Fuel Plugins Directory is empty!'
+ if msg:
+ warn('%s No external plugins will be installed!' % msg)
+
+
+def parse_arguments():
+ parser = ArgParser(prog='python %s' % __file__)
+ parser.add_argument('-nf', dest='no_fuel', action='store_true',
+ default=False,
+ help='Do not install Fuel Master (and Node VMs when '
+ 'using libvirt)')
+ parser.add_argument('-nh', dest='no_health_check', action='store_true',
+ default=False,
+ help='Don\'t run health check after deployment')
+ parser.add_argument('-fo', dest='fuel_only', action='store_true',
+ default=False,
+ help='Install Fuel Master only (and Node VMs when '
+ 'using libvirt)')
+ parser.add_argument('-co', dest='cleanup_only', action='store_true',
+ default=False,
+ help='Cleanup VMs and Virtual Networks according to '
+ 'what is defined in DHA')
+ parser.add_argument('-c', dest='cleanup', action='store_true',
+ default=False,
+ help='Cleanup after deploy')
+ if {'-iso', '-dea', '-dha', '-h'}.intersection(sys.argv):
+ parser.add_argument('-iso', dest='iso_file', action='store', nargs='?',
+ default='%s/OPNFV.iso' % CWD,
+ help='ISO File [default: OPNFV.iso]')
+ parser.add_argument('-dea', dest='dea_file', action='store', nargs='?',
+ default='%s/dea.yaml' % CWD,
+ help='Deployment Environment Adapter: dea.yaml')
+ parser.add_argument('-dha', dest='dha_file', action='store', nargs='?',
+ default='%s/dha.yaml' % CWD,
+ help='Deployment Hardware Adapter: dha.yaml')
+ else:
+ parser.add_argument('iso_file', action='store', nargs='?',
+ default='%s/OPNFV.iso' % CWD,
+ help='ISO File [default: OPNFV.iso]')
+ parser.add_argument('dea_file', action='store', nargs='?',
+ default='%s/dea.yaml' % CWD,
+ help='Deployment Environment Adapter: dea.yaml')
+ parser.add_argument('dha_file', action='store', nargs='?',
+ default='%s/dha.yaml' % CWD,
+ help='Deployment Hardware Adapter: dha.yaml')
+ parser.add_argument('-s', dest='storage_dir', action='store',
+ default='%s/images' % CWD,
+ help='Storage Directory [default: images]')
+ parser.add_argument('-b', dest='pxe_bridge', action='store',
+ default='pxebr',
+ help='Linux Bridge for booting up the Fuel Master VM '
+ '[default: pxebr]')
+ parser.add_argument('-p', dest='fuel_plugins_dir', action='store',
+ help='Fuel Plugins directory')
+ parser.add_argument('-pc', dest='fuel_plugins_conf_dir', action='store',
+ help='Fuel Plugins Configuration directory')
+ parser.add_argument('-np', dest='no_plugins', action='store_true',
+ default=False, help='Do not install Fuel Plugins')
+
+ args = parser.parse_args()
+ log(args)
+
+ check_file_exists(args.dha_file)
+
+ if not args.cleanup_only:
+ check_file_exists(args.dea_file)
+ check_fuel_plugins_dir(args.fuel_plugins_dir)
+
+ if not args.no_fuel and not args.cleanup_only:
+ log('Using OPNFV ISO file: %s' % args.iso_file)
+ check_file_exists(args.iso_file)
+ log('Using image directory: %s' % args.storage_dir)
+ create_dir_if_not_exists(args.storage_dir)
+ check_bridge(args.pxe_bridge, args.dha_file)
+
+ kwargs = {'no_fuel': args.no_fuel, 'fuel_only': args.fuel_only,
+ 'no_health_check': args.no_health_check,
+ 'cleanup_only': args.cleanup_only, 'cleanup': args.cleanup,
+ 'storage_dir': args.storage_dir, 'pxe_bridge': args.pxe_bridge,
+ 'iso_file': args.iso_file, 'dea_file': args.dea_file,
+ 'dha_file': args.dha_file,
+ 'fuel_plugins_dir': args.fuel_plugins_dir,
+ 'fuel_plugins_conf_dir': args.fuel_plugins_conf_dir,
+ 'no_plugins': args.no_plugins}
+ return kwargs
+
+
+def main():
+ kwargs = parse_arguments()
+ d = AutoDeploy(**kwargs)
+ sys.exit(d.run())
+
+if __name__ == '__main__':
+ main()
diff --git a/deploy/deploy_env.py b/deploy/deploy_env.py
new file mode 100644
index 000000000..735ea66a3
--- /dev/null
+++ b/deploy/deploy_env.py
@@ -0,0 +1,266 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import os
+import io
+import yaml
+import glob
+import time
+import shutil
+
+from ssh_client import SSHClient
+
+from common import (
+ err,
+ log,
+ parse,
+ N,
+ E,
+ R,
+ delete,
+)
+
+CLOUD_DEPLOY_FILE = 'deploy.py'
+BLADE_RESTART_TIMES = 3
+
+
+class CloudDeploy(object):
+
+ def __init__(self, dea, dha, fuel_ip, fuel_username, fuel_password,
+ dea_file, fuel_plugins_conf_dir, work_dir, no_health_check):
+ self.dea = dea
+ self.dha = dha
+ self.fuel_ip = fuel_ip
+ self.fuel_username = fuel_username
+ self.fuel_password = fuel_password
+ self.dea_file = dea_file
+ self.updated_dea_file = (
+ '%s/.%s' % (os.path.dirname(self.dea_file),
+ os.path.basename(self.dea_file)))
+ shutil.copy2(self.dea_file, self.updated_dea_file)
+ self.fuel_plugins_conf_dir = fuel_plugins_conf_dir
+ self.work_dir = work_dir
+ self.no_health_check = no_health_check
+ self.file_dir = os.path.dirname(os.path.realpath(__file__))
+ self.ssh = SSHClient(self.fuel_ip, self.fuel_username,
+ self.fuel_password)
+ self.node_ids = self.dha.get_node_ids()
+ self.wanted_release = self.dea.get_property('wanted_release')
+ self.blade_node_dict = {}
+ self.macs_per_blade = {}
+
+ def merge_plugin_config_files_to_dea_file(self):
+ plugins_conf_dir = (
+ self.fuel_plugins_conf_dir if self.fuel_plugins_conf_dir
+ else '%s/plugins_conf' % os.path.dirname(self.dea_file))
+ if os.path.isdir(plugins_conf_dir):
+ with io.open(self.updated_dea_file) as stream:
+ updated_dea = yaml.load(stream)
+ for plugin_file in glob.glob('%s/*.yaml' % plugins_conf_dir):
+ with io.open(plugin_file) as stream:
+ plugin_conf = yaml.load(stream)
+ updated_dea['settings']['editable'].update(plugin_conf)
+ with io.open(self.updated_dea_file, 'w') as stream:
+ yaml.dump(updated_dea, stream, default_flow_style=False)
+
+ def upload_cloud_deployment_files(self):
+ with self.ssh as s:
+ s.exec_cmd('rm -rf %s' % self.work_dir, False)
+ s.exec_cmd('mkdir %s' % self.work_dir)
+ s.scp_put(self.updated_dea_file, '%s/%s' % (
+ self.work_dir, os.path.basename(self.dea_file)))
+ s.scp_put('%s/common.py' % self.file_dir, self.work_dir)
+ s.scp_put('%s/dea.py' % self.file_dir, self.work_dir)
+ for f in glob.glob('%s/cloud/*' % self.file_dir):
+ s.scp_put(f, self.work_dir)
+
+ def power_off_nodes(self):
+ for node_id in self.node_ids:
+ self.dha.node_power_off(node_id)
+
+ def power_on_nodes(self):
+ for node_id in self.node_ids:
+ self.dha.node_power_on(node_id)
+
+ def set_boot_order(self, boot_order_list):
+ for node_id in self.node_ids:
+ self.dha.node_set_boot_order(node_id, boot_order_list[:])
+
+ def get_mac_addresses(self):
+ self.macs_per_blade = {}
+ for node_id in self.node_ids:
+ self.macs_per_blade[node_id] = self.dha.get_node_pxe_mac(node_id)
+
+ def run_cloud_deploy(self, deploy_app):
+ log('START CLOUD DEPLOYMENT')
+ deploy_app = '%s/%s' % (self.work_dir, deploy_app)
+ dea_file = '%s/%s' % (self.work_dir, os.path.basename(self.dea_file))
+ with self.ssh as s:
+ status = s.run('python %s %s %s' % (
+ deploy_app, ('-nh' if self.no_health_check else ''), dea_file))
+ return status
+
+ def check_supported_release(self):
+ log('Check supported release: %s' % self.wanted_release)
+ found = False
+ release_list = parse(self.ssh.exec_cmd('fuel release -l'))
+ for release in release_list:
+ if release[R['name']] == self.wanted_release:
+ found = True
+ break
+ if not found:
+ err('This Fuel does not contain the following release: %s'
+ % self.wanted_release)
+
+ def check_previous_installation(self):
+ log('Check previous installation')
+ env_list = parse(self.ssh.exec_cmd('fuel env list'))
+ if env_list:
+ self.cleanup_fuel_environments(env_list)
+ node_list = parse(self.ssh.exec_cmd('fuel node list'))
+ if node_list:
+ self.cleanup_fuel_nodes(node_list)
+
+ def cleanup_fuel_environments(self, env_list):
+ WAIT_LOOP = 60
+ SLEEP_TIME = 10
+ for env in env_list:
+ log('Deleting environment %s' % env[E['id']])
+ self.ssh.exec_cmd('fuel env --env %s --delete --force'
+ % env[E['id']])
+ all_env_erased = False
+ for i in range(WAIT_LOOP):
+ env_list = parse(self.ssh.exec_cmd('fuel env list'))
+ if env_list:
+ time.sleep(SLEEP_TIME)
+ else:
+ all_env_erased = True
+ break
+ if not all_env_erased:
+ err('Could not erase these environments %s'
+ % [(env[E['id']], env[E['status']]) for env in env_list])
+
+ def cleanup_fuel_nodes(self, node_list):
+ for node in node_list:
+ if node[N['status']] == 'discover':
+ log('Deleting node %s' % node[N['id']])
+ self.ssh.exec_cmd('fuel node --node-id %s --delete-from-db '
+ '--force' % node[N['id']])
+ self.ssh.exec_cmd('cobbler system remove --name node-%s'
+ % node[N['id']], False)
+
+ def check_prerequisites(self):
+ log('Check prerequisites')
+ with self.ssh:
+ self.check_supported_release()
+ self.check_previous_installation()
+
+ def wait_for_discovered_blades(self):
+ log('Wait for discovered blades')
+ discovered_macs = []
+ restart_times = BLADE_RESTART_TIMES
+
+ for blade in self.node_ids:
+ self.blade_node_dict[blade] = None
+
+ with self.ssh:
+ all_discovered = self.discovery_waiting_loop(discovered_macs)
+
+ while not all_discovered and restart_times != 0:
+ restart_times -= 1
+ for blade in self.get_not_discovered_blades():
+ self.dha.node_reset(blade)
+ with self.ssh:
+ all_discovered = self.discovery_waiting_loop(discovered_macs)
+
+ if not all_discovered:
+ err('Not all blades have been discovered: %s'
+ % self.not_discovered_blades_summary())
+
+ with io.open(self.updated_dea_file) as stream:
+ updated_dea = yaml.load(stream)
+ updated_dea.update({'blade_node_map': self.blade_node_dict})
+ with io.open(self.updated_dea_file, 'w') as stream:
+ yaml.dump(updated_dea, stream, default_flow_style=False)
+
+ def discovery_waiting_loop(self, discovered_macs):
+ WAIT_LOOP = 360
+ SLEEP_TIME = 10
+ all_discovered = False
+ for i in range(WAIT_LOOP):
+ node_list = parse(self.ssh.exec_cmd('fuel node list'))
+ if node_list:
+ self.node_discovery(node_list, discovered_macs)
+ if self.all_blades_discovered():
+ all_discovered = True
+ break
+ else:
+ time.sleep(SLEEP_TIME)
+ return all_discovered
+
+ def node_discovery(self, node_list, discovered_macs):
+ for node in node_list:
+ if (node[N['status']] == 'discover' and
+ node[N['online']] == 'True' and
+ node[N['mac']] not in discovered_macs):
+ discovered_macs.append(node[N['mac']])
+ blade = self.find_mac_in_dict(node[N['mac']])
+ if blade:
+ log('Blade %s discovered as Node %s with MAC %s'
+ % (blade, node[N['id']], node[N['mac']]))
+ self.blade_node_dict[blade] = int(node[N['id']])
+
+ def find_mac_in_dict(self, mac):
+ for blade, mac_list in self.macs_per_blade.iteritems():
+ if mac in mac_list:
+ return blade
+
+ def all_blades_discovered(self):
+ for blade, node_id in self.blade_node_dict.iteritems():
+ if not node_id:
+ return False
+ return True
+
+ def not_discovered_blades_summary(self):
+ summary = ''
+ for blade, node_id in self.blade_node_dict.iteritems():
+ if not node_id:
+ summary += '\n[blade %s]' % blade
+ return summary
+
+ def get_not_discovered_blades(self):
+ not_discovered_blades = []
+ for blade, node_id in self.blade_node_dict.iteritems():
+ if not node_id:
+ not_discovered_blades.append(blade)
+ return not_discovered_blades
+
+ def set_boot_order_nodes(self):
+ self.power_off_nodes()
+ self.set_boot_order(['pxe', 'disk'])
+ self.power_on_nodes()
+
+ def deploy(self):
+
+ self.set_boot_order_nodes()
+
+ self.check_prerequisites()
+
+ self.get_mac_addresses()
+
+ self.wait_for_discovered_blades()
+
+ self.merge_plugin_config_files_to_dea_file()
+
+ self.upload_cloud_deployment_files()
+
+ delete(self.updated_dea_file)
+
+ return self.run_cloud_deploy(CLOUD_DEPLOY_FILE)
diff --git a/deploy/dha.py b/deploy/dha.py
new file mode 100644
index 000000000..cb413cbb0
--- /dev/null
+++ b/deploy/dha.py
@@ -0,0 +1,35 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+
+from dha_adapters.libvirt_adapter import LibvirtAdapter
+from dha_adapters.ipmi_adapter import IpmiAdapter
+from dha_adapters.hp_adapter import HpAdapter
+from dha_adapters.amt_adapter import AmtAdapter
+
+class DeploymentHardwareAdapter(object):
+
+ def __new__(cls, yaml_path):
+ with io.open(yaml_path) as yaml_file:
+ dha_struct = yaml.load(yaml_file)
+ type = dha_struct['adapter']
+
+ if cls is DeploymentHardwareAdapter:
+ if type == 'libvirt':
+ return LibvirtAdapter(yaml_path)
+ if type == 'ipmi':
+ return IpmiAdapter(yaml_path)
+ if type == 'hp':
+ return HpAdapter(yaml_path)
+ if type == 'amt':
+ return AmtAdapter(yaml_path)
+ return super(DeploymentHardwareAdapter, cls).__new__(cls)
diff --git a/deploy/dha_adapters/__init__.py b/deploy/dha_adapters/__init__.py
new file mode 100644
index 000000000..fb73157f9
--- /dev/null
+++ b/deploy/dha_adapters/__init__.py
@@ -0,0 +1,8 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
diff --git a/deploy/dha_adapters/amt_adapter.py b/deploy/dha_adapters/amt_adapter.py
new file mode 100644
index 000000000..02025b9dd
--- /dev/null
+++ b/deploy/dha_adapters/amt_adapter.py
@@ -0,0 +1,100 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# liyi.meng@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from hardware_adapter import HardwareAdapter
+
+from common import (
+ log,
+ exec_cmd,
+ err,
+)
+
+
+'''
+This is hardware adapter for Intel AMT based system. It use amttool to interact
+ with the targeting node. It dose not support vPro v9. if the targeting system
+ is v9 or later, we need to consider a new adpater with using lib
+ like https://github.com/sdague/amt
+'''
+class AmtAdapter(HardwareAdapter):
+
+ def __init__(self, yaml_path):
+ super(AmtAdapter, self).__init__(yaml_path)
+ #amttool dose not allow you change bios setting permanently.
+ # so we have to make a workaround to make it IPMI like.
+ self.boot_order = {}
+
+ def node_get_boot_dev(self, node_id):
+ if node_id in self.boot_order:
+ dev = self.boot_order[node_id][0]
+ if dev == 'pxe':
+ return 'PXE-boot'
+ elif dev == 'iso':
+ return 'cd-boot'
+ elif dev == 'disk':
+ return 'HD-boot'
+ else:
+ return 'HD-boot'
+
+ def get_access_info(self, node_id):
+ ip = self.get_node_property(node_id, 'amtIp')
+ username = self.get_node_property(node_id, 'amtUser')
+ password = self.get_node_property(node_id, 'amtPass')
+ return ip, username, password
+
+ def amt_cmd(self, node_id):
+ ip, username, password = self.get_access_info(node_id)
+ # We first Setup password for amttool, then use ping to wake up the node over LAN
+ cmd = 'export AMT_PASSWORD={0};' \
+ 'ping {1} -W 5 -c 1 -q;' \
+ 'yes | amttool {1}'.format(password, ip)
+ return cmd
+
+ def get_node_pxe_mac(self, node_id):
+ mac_list = []
+ mac_list.append(self.get_node_property(node_id, 'pxeMac').lower())
+ return mac_list
+
+ def node_power_on(self, node_id):
+ log('Power ON Node %s' % node_id)
+ cmd_prefix = self.amt_cmd(node_id)
+ resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False)
+ if 'Powerstate: S0' not in resp:
+ dev = self.node_get_boot_dev(node_id)
+ resp, ret = exec_cmd('{0} powerup {1}'.format(cmd_prefix, dev), check=False)
+ if 'pt_status: success' not in resp:
+ err('Could Not Power ON Node %s' % node_id)
+
+ def node_power_off(self, node_id):
+ log('Power OFF Node %s' % node_id)
+ cmd_prefix = self.amt_cmd(node_id)
+ resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False)
+ if "Powerstate: S0" in resp:
+ resp, ret = exec_cmd('{0} powerdown'.format(cmd_prefix), check=False)
+ if 'pt_status: success' not in resp:
+ err('Could Not Power OFF Node %s' % node_id)
+
+ def node_reset(self, node_id):
+ log('RESET Node %s' % node_id)
+ cmd_prefix = self.amt_cmd(node_id)
+ dev = self.node_get_boot_dev(node_id)
+ resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False)
+ if 'Powerstate: S0' in resp:
+ resp, ret = exec_cmd('{0} reset {1}'.format(cmd_prefix, dev), check=False)
+ if 'pt_status: success' not in resp:
+ err('Could Not RESET Node %s' % node_id)
+ else:
+ err('Cannot RESET Node %s because it\'s not Active, state: %s'
+ % (node_id, resp))
+
+ def node_set_boot_order(self, node_id, boot_order_list):
+ log('Set boot order %s on Node %s' % (boot_order_list, node_id))
+ self.boot_order[node_id] = boot_order_list
+
diff --git a/deploy/dha_adapters/hardware_adapter.py b/deploy/dha_adapters/hardware_adapter.py
new file mode 100644
index 000000000..2cd5ab842
--- /dev/null
+++ b/deploy/dha_adapters/hardware_adapter.py
@@ -0,0 +1,60 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+
+
+class HardwareAdapter(object):
+
+ def __init__(self, yaml_path):
+ self.dha_struct = None
+ self.parse_yaml(yaml_path)
+
+ def parse_yaml(self, yaml_path):
+ with io.open(yaml_path) as yaml_file:
+ self.dha_struct = yaml.load(yaml_file)
+
+ def get_adapter_type(self):
+ return self.dha_struct['adapter']
+
+ def get_all_node_ids(self):
+ node_ids = []
+ for node in self.dha_struct['nodes']:
+ node_ids.append(node['id'])
+ node_ids.sort()
+ return node_ids
+
+ def get_fuel_node_id(self):
+ for node in self.dha_struct['nodes']:
+ if 'isFuel' in node and node['isFuel']:
+ return node['id']
+
+ def get_node_ids(self):
+ node_ids = []
+ fuel_node_id = self.get_fuel_node_id()
+ for node in self.dha_struct['nodes']:
+ if node['id'] != fuel_node_id:
+ node_ids.append(node['id'])
+ node_ids.sort()
+ return node_ids
+
+ def get_node_property(self, node_id, property_name):
+ for node in self.dha_struct['nodes']:
+ if node['id'] == node_id and property_name in node:
+ return node[property_name]
+
+ def get_fuel_access(self):
+ for node in self.dha_struct['nodes']:
+ if 'isFuel' in node and node['isFuel']:
+ return node['username'], node['password']
+
+ def get_disks(self):
+ return self.dha_struct['disks']
diff --git a/deploy/dha_adapters/hp_adapter.py b/deploy/dha_adapters/hp_adapter.py
new file mode 100644
index 000000000..13bb3491a
--- /dev/null
+++ b/deploy/dha_adapters/hp_adapter.py
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from ipmi_adapter import IpmiAdapter
+from ssh_client import SSHClient
+
+from common import (
+ log,
+)
+
+DEV = {'pxe': 'bootsource5',
+ 'disk': 'bootsource3',
+ 'iso': 'bootsource1'}
+
+ROOT = '/system1/bootconfig1'
+
+
+class HpAdapter(IpmiAdapter):
+
+ def __init__(self, yaml_path):
+ super(HpAdapter, self).__init__(yaml_path)
+
+ def node_set_boot_order(self, node_id, boot_order_list):
+ log('Set boot order %s on Node %s' % (boot_order_list, node_id))
+ ip, username, password = self.get_access_info(node_id)
+ ssh = SSHClient(ip, username, password)
+ with ssh as s:
+ for order, dev in enumerate(boot_order_list):
+ s.exec_cmd('set %s/%s bootorder=%s'
+ % (ROOT, DEV[dev], order + 1))
diff --git a/deploy/dha_adapters/ipmi_adapter.py b/deploy/dha_adapters/ipmi_adapter.py
new file mode 100644
index 000000000..8fda4f9f0
--- /dev/null
+++ b/deploy/dha_adapters/ipmi_adapter.py
@@ -0,0 +1,119 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import time
+from hardware_adapter import HardwareAdapter
+
+from common import (
+ log,
+ exec_cmd,
+ err,
+)
+
+
+class IpmiAdapter(HardwareAdapter):
+
+ def __init__(self, yaml_path):
+ super(IpmiAdapter, self).__init__(yaml_path)
+
+ def get_access_info(self, node_id):
+ ip = self.get_node_property(node_id, 'ipmiIp')
+ username = self.get_node_property(node_id, 'ipmiUser')
+ password = self.get_node_property(node_id, 'ipmiPass')
+ return ip, username, password
+
+ def ipmi_cmd(self, node_id):
+ ip, username, password = self.get_access_info(node_id)
+ cmd = 'ipmitool -I lanplus -A password'
+ cmd += ' -H %s -U %s -P %s' % (ip, username, password)
+ return cmd
+
+ def get_node_pxe_mac(self, node_id):
+ mac_list = []
+ mac_list.append(self.get_node_property(node_id, 'pxeMac').lower())
+ return mac_list
+
+ def node_power_on(self, node_id):
+ WAIT_LOOP = 200
+ SLEEP_TIME = 3
+ log('Power ON Node %s' % node_id)
+ cmd_prefix = self.ipmi_cmd(node_id)
+ state = exec_cmd('%s chassis power status' % cmd_prefix)
+ if state == 'Chassis Power is off':
+ exec_cmd('%s chassis power on' % cmd_prefix)
+ done = False
+ for i in range(WAIT_LOOP):
+ state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
+ False)
+ if state == 'Chassis Power is on':
+ done = True
+ break
+ else:
+ time.sleep(SLEEP_TIME)
+ if not done:
+ err('Could Not Power ON Node %s' % node_id)
+
+ def node_power_off(self, node_id):
+ WAIT_LOOP = 200
+ SLEEP_TIME = 3
+ log('Power OFF Node %s' % node_id)
+ cmd_prefix = self.ipmi_cmd(node_id)
+ state = exec_cmd('%s chassis power status' % cmd_prefix)
+ if state == 'Chassis Power is on':
+ done = False
+ exec_cmd('%s chassis power off' % cmd_prefix)
+ for i in range(WAIT_LOOP):
+ state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
+ False)
+ if state == 'Chassis Power is off':
+ done = True
+ break
+ else:
+ time.sleep(SLEEP_TIME)
+ if not done:
+ err('Could Not Power OFF Node %s' % node_id)
+
+ def node_reset(self, node_id):
+ WAIT_LOOP = 600
+ log('RESET Node %s' % node_id)
+ cmd_prefix = self.ipmi_cmd(node_id)
+ state = exec_cmd('%s chassis power status' % cmd_prefix)
+ if state == 'Chassis Power is on':
+ was_shut_off = False
+ done = False
+ exec_cmd('%s chassis power reset' % cmd_prefix)
+ for i in range(WAIT_LOOP):
+ state, _ = exec_cmd('%s chassis power status' % cmd_prefix,
+ False)
+ if state == 'Chassis Power is off':
+ was_shut_off = True
+ elif state == 'Chassis Power is on' and was_shut_off:
+ done = True
+ break
+ time.sleep(1)
+ if not done:
+ err('Could Not RESET Node %s' % node_id)
+ else:
+ err('Cannot RESET Node %s because it\'s not Active, state: %s'
+ % (node_id, state))
+
+ def node_set_boot_order(self, node_id, boot_order_list):
+ log('Set boot order %s on Node %s' % (boot_order_list, node_id))
+ boot_order_list.reverse()
+ cmd_prefix = self.ipmi_cmd(node_id)
+ for dev in boot_order_list:
+ if dev == 'pxe':
+ exec_cmd('%s chassis bootdev pxe options=persistent'
+ % cmd_prefix)
+ elif dev == 'iso':
+ exec_cmd('%s chassis bootdev cdrom' % cmd_prefix)
+ elif dev == 'disk':
+ exec_cmd('%s chassis bootdev disk options=persistent'
+ % cmd_prefix)
diff --git a/deploy/dha_adapters/libvirt_adapter.py b/deploy/dha_adapters/libvirt_adapter.py
new file mode 100644
index 000000000..d6a30d75e
--- /dev/null
+++ b/deploy/dha_adapters/libvirt_adapter.py
@@ -0,0 +1,138 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from lxml import etree
+from hardware_adapter import HardwareAdapter
+
+from common import (
+ log,
+ exec_cmd,
+ err,
+ delete,
+)
+
+DEV = {'pxe': 'network',
+ 'disk': 'hd',
+ 'iso': 'cdrom'}
+
+
+class LibvirtAdapter(HardwareAdapter):
+
+ def __init__(self, yaml_path):
+ super(LibvirtAdapter, self).__init__(yaml_path)
+ self.parser = etree.XMLParser(remove_blank_text=True)
+
+ def node_power_off(self, node_id):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ log('Power OFF Node %s' % vm_name)
+ state = exec_cmd('virsh domstate %s' % vm_name)
+ if state == 'running':
+ exec_cmd('virsh destroy %s' % vm_name, False)
+
+ def node_power_on(self, node_id):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ log('Power ON Node %s' % vm_name)
+ state = exec_cmd('virsh domstate %s' % vm_name)
+ if state == 'shut off':
+ exec_cmd('virsh start %s' % vm_name)
+
+ def node_reset(self, node_id):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ log('Reset Node %s' % vm_name)
+ exec_cmd('virsh reset %s' % vm_name)
+
+ def translate(self, boot_order_list):
+ translated = []
+ for boot_dev in boot_order_list:
+ if boot_dev in DEV:
+ translated.append(DEV[boot_dev])
+ else:
+ err('Boot device %s not recognized' % boot_dev)
+ return translated
+
+ def node_set_boot_order(self, node_id, boot_order_list):
+ boot_order_list = self.translate(boot_order_list)
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ temp_dir = exec_cmd('mktemp -d')
+ log('Set boot order %s on Node %s' % (boot_order_list, vm_name))
+ resp = exec_cmd('virsh dumpxml %s' % vm_name)
+ xml_dump = etree.fromstring(resp, self.parser)
+ os = xml_dump.xpath('/domain/os')
+ for o in os:
+ for bootelem in ['boot', 'bootmenu']:
+ boot = o.xpath(bootelem)
+ for b in boot:
+ o.remove(b)
+ for dev in boot_order_list:
+ b = etree.Element('boot')
+ b.set('dev', dev)
+ o.append(b)
+ bmenu = etree.Element('bootmenu')
+ bmenu.set('enable', 'no')
+ o.append(bmenu)
+ tree = etree.ElementTree(xml_dump)
+ xml_file = temp_dir + '/%s.xml' % vm_name
+ with open(xml_file, 'w') as f:
+ tree.write(f, pretty_print=True, xml_declaration=True)
+ exec_cmd('virsh define %s' % xml_file)
+ delete(temp_dir)
+
+ def node_zero_mbr(self, node_id):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ resp = exec_cmd('virsh dumpxml %s' % vm_name)
+ xml_dump = etree.fromstring(resp)
+ disks = xml_dump.xpath('/domain/devices/disk')
+ for disk in disks:
+ if disk.get('device') == 'disk':
+ sources = disk.xpath('source')
+ for source in sources:
+ disk_file = source.get('file')
+ disk_size = exec_cmd('ls -l %s' % disk_file).split()[4]
+ delete(disk_file)
+ exec_cmd('fallocate -l %s %s' % (disk_size, disk_file))
+
+ def node_eject_iso(self, node_id):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ device = self.get_name_of_device(vm_name, 'cdrom')
+ exec_cmd('virsh change-media %s --eject %s --config --live'
+ % (vm_name, device), False)
+
+ def node_insert_iso(self, node_id, iso_file):
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ device = self.get_name_of_device(vm_name, 'cdrom')
+ exec_cmd('virsh change-media %s --insert %s %s'
+ % (vm_name, device, iso_file))
+
+ def get_node_pxe_mac(self, node_id):
+ mac_list = []
+ vm_name = self.get_node_property(node_id, 'libvirtName')
+ resp = exec_cmd('virsh dumpxml %s' % vm_name)
+ xml_dump = etree.fromstring(resp)
+ interfaces = xml_dump.xpath('/domain/devices/interface')
+ for interface in interfaces:
+ macs = interface.xpath('mac')
+ for mac in macs:
+ mac_list.append(mac.get('address').lower())
+ return mac_list
+
+ def get_name_of_device(self, vm_name, device_type):
+ resp = exec_cmd('virsh dumpxml %s' % vm_name)
+ xml_dump = etree.fromstring(resp)
+ disks = xml_dump.xpath('/domain/devices/disk')
+ for disk in disks:
+ if disk.get('device') == device_type:
+ targets = disk.xpath('target')
+ for target in targets:
+ device = target.get('dev')
+ if device:
+ return device
+
+ def get_virt_net_conf_dir(self):
+ return self.dha_struct['virtNetConfDir']
diff --git a/deploy/environments/__init__.py b/deploy/environments/__init__.py
new file mode 100644
index 000000000..fb73157f9
--- /dev/null
+++ b/deploy/environments/__init__.py
@@ -0,0 +1,8 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
diff --git a/deploy/environments/execution_environment.py b/deploy/environments/execution_environment.py
new file mode 100644
index 000000000..38e5bcdf7
--- /dev/null
+++ b/deploy/environments/execution_environment.py
@@ -0,0 +1,75 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from lxml import etree
+from dha_adapters.libvirt_adapter import LibvirtAdapter
+
+from common import (
+ exec_cmd,
+ log,
+ delete,
+)
+
+
+class ExecutionEnvironment(object):
+
+ def __init__(self, storage_dir, dha_file, root_dir):
+ self.storage_dir = storage_dir
+ self.dha = LibvirtAdapter(dha_file)
+ self.root_dir = root_dir
+ self.parser = etree.XMLParser(remove_blank_text=True)
+ self.fuel_node_id = self.dha.get_fuel_node_id()
+
+ def delete_vm(self, node_id):
+ vm_name = self.dha.get_node_property(node_id, 'libvirtName')
+ r, c = exec_cmd('virsh dumpxml %s' % vm_name, False)
+ if c:
+ return
+ self.undefine_vm_delete_disk(r, vm_name)
+
+ def undefine_vm_delete_disk(self, printout, vm_name):
+ disk_files = []
+ xml_dump = etree.fromstring(printout, self.parser)
+ disks = xml_dump.xpath('/domain/devices/disk')
+ for disk in disks:
+ sources = disk.xpath('source')
+ for source in sources:
+ source_file = source.get('file')
+ if source_file:
+ disk_files.append(source_file)
+ log('Deleting VM %s with disks %s' % (vm_name, disk_files))
+ exec_cmd('virsh destroy %s' % vm_name, False)
+ exec_cmd('virsh undefine %s' % vm_name, False)
+ for file in disk_files:
+ delete(file)
+
+ def define_vm(self, vm_name, temp_vm_file, disk_path):
+ log('Creating VM %s with disks %s' % (vm_name, disk_path))
+ with open(temp_vm_file) as f:
+ vm_xml = etree.parse(f)
+ names = vm_xml.xpath('/domain/name')
+ for name in names:
+ name.text = vm_name
+ uuids = vm_xml.xpath('/domain/uuid')
+ for uuid in uuids:
+ uuid.getparent().remove(uuid)
+ disks = vm_xml.xpath('/domain/devices/disk')
+ for disk in disks:
+ if (disk.get('type') == 'file' and
+ disk.get('device') == 'disk'):
+ sources = disk.xpath('source')
+ for source in sources:
+ disk.remove(source)
+ source = etree.Element('source')
+ source.set('file', disk_path)
+ disk.append(source)
+ with open(temp_vm_file, 'w') as f:
+ vm_xml.write(f, pretty_print=True, xml_declaration=True)
+ exec_cmd('virsh define %s' % temp_vm_file)
diff --git a/deploy/environments/libvirt_environment.py b/deploy/environments/libvirt_environment.py
new file mode 100644
index 000000000..af2d3f8fb
--- /dev/null
+++ b/deploy/environments/libvirt_environment.py
@@ -0,0 +1,107 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from lxml import etree
+import glob
+from execution_environment import ExecutionEnvironment
+
+from common import (
+ exec_cmd,
+ log,
+ check_dir_exists,
+ check_file_exists,
+ delete,
+)
+
+
+class LibvirtEnvironment(ExecutionEnvironment):
+
+ def __init__(self, storage_dir, dha_file, dea, root_dir):
+ super(LibvirtEnvironment, self).__init__(
+ storage_dir, dha_file, root_dir)
+ self.dea = dea
+ self.network_dir = '%s/%s' % (self.root_dir,
+ self.dha.get_virt_net_conf_dir())
+ self.node_ids = self.dha.get_all_node_ids()
+ self.net_names = self.collect_net_names()
+
+ def create_storage(self, node_id, disk_path, disk_sizes):
+ if node_id == self.fuel_node_id:
+ disk_size = disk_sizes['fuel']
+ else:
+ roles = self.dea.get_node_role(node_id)
+ role = 'controller' if 'controller' in roles else 'compute'
+ disk_size = disk_sizes[role]
+ exec_cmd('fallocate -l %s %s' % (disk_size, disk_path))
+
+ def create_vms(self):
+ temp_dir = exec_cmd('mktemp -d')
+ disk_sizes = self.dha.get_disks()
+ for node_id in self.node_ids:
+ vm_name = self.dha.get_node_property(node_id, 'libvirtName')
+ vm_template = '%s/%s' % (self.root_dir,
+ self.dha.get_node_property(
+ node_id, 'libvirtTemplate'))
+ check_file_exists(vm_template)
+ disk_path = '%s/%s.raw' % (self.storage_dir, vm_name)
+ self.create_storage(node_id, disk_path, disk_sizes)
+ temp_vm_file = '%s/%s' % (temp_dir, vm_name)
+ exec_cmd('cp %s %s' % (vm_template, temp_vm_file))
+ self.define_vm(vm_name, temp_vm_file, disk_path)
+ delete(temp_dir)
+
+ def start_vms(self):
+ for node_id in self.node_ids:
+ self.dha.node_power_on(node_id)
+
+ def create_networks(self):
+ for net_file in glob.glob('%s/*' % self.network_dir):
+ exec_cmd('virsh net-define %s' % net_file)
+ for net in self.net_names:
+ log('Creating network %s' % net)
+ exec_cmd('virsh net-autostart %s' % net)
+ exec_cmd('virsh net-start %s' % net)
+
+ def delete_networks(self):
+ for net in self.net_names:
+ log('Deleting network %s' % net)
+ exec_cmd('virsh net-destroy %s' % net, False)
+ exec_cmd('virsh net-undefine %s' % net, False)
+
+ def get_net_name(self, net_file):
+ with open(net_file) as f:
+ net_xml = etree.parse(f)
+ name_list = net_xml.xpath('/network/name')
+ for name in name_list:
+ net_name = name.text
+ return net_name
+
+ def collect_net_names(self):
+ net_list = []
+ for net_file in glob.glob('%s/*' % self.network_dir):
+ name = self.get_net_name(net_file)
+ net_list.append(name)
+ return net_list
+
+ def delete_vms(self):
+ for node_id in self.node_ids:
+ self.delete_vm(node_id)
+
+
+ def setup_environment(self):
+ check_dir_exists(self.network_dir)
+ self.cleanup_environment()
+ self.create_networks()
+ self.create_vms()
+ self.start_vms()
+
+ def cleanup_environment(self):
+ self.delete_vms()
+ self.delete_networks()
diff --git a/deploy/environments/virtual_fuel.py b/deploy/environments/virtual_fuel.py
new file mode 100644
index 000000000..705eee48b
--- /dev/null
+++ b/deploy/environments/virtual_fuel.py
@@ -0,0 +1,70 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+from lxml import etree
+from execution_environment import ExecutionEnvironment
+
+from common import (
+ exec_cmd,
+ check_file_exists,
+ check_if_root,
+ delete,
+)
+
+
+class VirtualFuel(ExecutionEnvironment):
+
+ def __init__(self, storage_dir, pxe_bridge, dha_file, root_dir):
+ super(VirtualFuel, self).__init__(storage_dir, dha_file, root_dir)
+ self.pxe_bridge = pxe_bridge
+
+ def set_vm_nic(self, temp_vm_file):
+ with open(temp_vm_file) as f:
+ vm_xml = etree.parse(f)
+ interfaces = vm_xml.xpath('/domain/devices/interface')
+ for interface in interfaces:
+ interface.getparent().remove(interface)
+ interface = etree.Element('interface')
+ interface.set('type', 'bridge')
+ source = etree.SubElement(interface, 'source')
+ source.set('bridge', self.pxe_bridge)
+ model = etree.SubElement(interface, 'model')
+ model.set('type', 'virtio')
+ devices = vm_xml.xpath('/domain/devices')
+ if devices:
+ device = devices[0]
+ device.append(interface)
+ with open(temp_vm_file, 'w') as f:
+ vm_xml.write(f, pretty_print=True, xml_declaration=True)
+
+ def create_vm(self):
+ temp_dir = exec_cmd('mktemp -d')
+ vm_name = self.dha.get_node_property(self.fuel_node_id, 'libvirtName')
+ vm_template = '%s/%s' % (self.root_dir,
+ self.dha.get_node_property(
+ self.fuel_node_id, 'libvirtTemplate'))
+ check_file_exists(vm_template)
+ disk_path = '%s/%s.raw' % (self.storage_dir, vm_name)
+ disk_sizes = self.dha.get_disks()
+ disk_size = disk_sizes['fuel']
+ exec_cmd('fallocate -l %s %s' % (disk_size, disk_path))
+ temp_vm_file = '%s/%s' % (temp_dir, vm_name)
+ exec_cmd('cp %s %s' % (vm_template, temp_vm_file))
+ self.set_vm_nic(temp_vm_file)
+ self.define_vm(vm_name, temp_vm_file, disk_path)
+ delete(temp_dir)
+
+ def setup_environment(self):
+ check_if_root()
+ self.cleanup_environment()
+ self.create_vm()
+
+ def cleanup_environment(self):
+ self.delete_vm(self.fuel_node_id)
diff --git a/deploy/execution_environment.py b/deploy/execution_environment.py
new file mode 100644
index 000000000..b2d268253
--- /dev/null
+++ b/deploy/execution_environment.py
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import yaml
+import io
+import os
+
+from environments.libvirt_environment import LibvirtEnvironment
+from environments.virtual_fuel import VirtualFuel
+
+
+class ExecutionEnvironment(object):
+
+ def __new__(cls, storage_dir, pxe_bridge, dha_path, dea):
+
+ with io.open(dha_path) as yaml_file:
+ dha_struct = yaml.load(yaml_file)
+
+ type = dha_struct['adapter']
+
+ root_dir = os.path.dirname(os.path.realpath(__file__))
+
+ if cls is ExecutionEnvironment:
+ if type == 'libvirt':
+ return LibvirtEnvironment(storage_dir, dha_path, dea, root_dir)
+
+ if type in ['ipmi', 'hp', 'amt']:
+ return VirtualFuel(storage_dir, pxe_bridge, dha_path, root_dir)
+
+ return super(ExecutionEnvironment, cls).__new__(cls)
diff --git a/deploy/fuel_patch/ks.cfg.patch b/deploy/fuel_patch/ks.cfg.patch
new file mode 100644
index 000000000..189695792
--- /dev/null
+++ b/deploy/fuel_patch/ks.cfg.patch
@@ -0,0 +1,19 @@
+*** ks.cfg.orig Wed Apr 15 21:47:09 2015
+--- ks.cfg Wed Apr 15 21:47:24 2015
+***************
+*** 35,41 ****
+ default_drive=`echo ${drives} ${removable_drives} | awk '{print $1}'`
+
+ installdrive="undefined"
+! forceformat="no"
+ for I in `cat /proc/cmdline`; do case "$I" in *=*) eval $I;; esac ; done
+
+ set ${drives} ${removable_drives}
+--- 35,41 ----
+ default_drive=`echo ${drives} ${removable_drives} | awk '{print $1}'`
+
+ installdrive="undefined"
+! forceformat="yes"
+ for I in `cat /proc/cmdline`; do case "$I" in *=*) eval $I;; esac ; done
+
+ set ${drives} ${removable_drives}
diff --git a/deploy/install_fuel_master.py b/deploy/install_fuel_master.py
new file mode 100644
index 000000000..e3a7327c0
--- /dev/null
+++ b/deploy/install_fuel_master.py
@@ -0,0 +1,223 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+import time
+import os
+import glob
+from ssh_client import SSHClient
+from dha_adapters.libvirt_adapter import LibvirtAdapter
+
+from common import (
+ log,
+ err,
+ clean,
+ delete,
+)
+
+TRANSPLANT_FUEL_SETTINGS = 'transplant_fuel_settings.py'
+BOOTSTRAP_ADMIN = '/usr/local/sbin/bootstrap_admin_node'
+FUEL_CLIENT_CONFIG = '/etc/fuel/client/config.yaml'
+PLUGINS_DIR = '~/plugins'
+LOCAL_PLUGIN_FOLDER = '/opt/opnfv'
+IGNORABLE_FUEL_ERRORS = ['does not update installed package',
+ 'Couldn\'t resolve host']
+
+
+class InstallFuelMaster(object):
+
+ def __init__(self, dea_file, dha_file, fuel_ip, fuel_username,
+ fuel_password, fuel_node_id, iso_file, work_dir,
+ fuel_plugins_dir, no_plugins):
+ self.dea_file = dea_file
+ self.dha = LibvirtAdapter(dha_file)
+ self.fuel_ip = fuel_ip
+ self.fuel_username = fuel_username
+ self.fuel_password = fuel_password
+ self.fuel_node_id = fuel_node_id
+ self.iso_file = iso_file
+ self.iso_dir = os.path.dirname(self.iso_file)
+ self.work_dir = work_dir
+ self.fuel_plugins_dir = fuel_plugins_dir
+ self.no_plugins = no_plugins
+ self.file_dir = os.path.dirname(os.path.realpath(__file__))
+ self.ssh = SSHClient(self.fuel_ip, self.fuel_username,
+ self.fuel_password)
+
+ def install(self):
+ log('Start Fuel Installation')
+
+ self.dha.node_power_off(self.fuel_node_id)
+
+ log('Zero the MBR')
+ self.dha.node_zero_mbr(self.fuel_node_id)
+
+ self.dha.node_set_boot_order(self.fuel_node_id, ['disk', 'iso'])
+
+ try:
+ self.proceed_with_installation()
+ except Exception as e:
+ self.post_install_cleanup()
+ err(e)
+
+ def proceed_with_installation(self):
+ log('Eject ISO')
+ self.dha.node_eject_iso(self.fuel_node_id)
+
+ log('Insert ISO %s' % self.iso_file)
+ self.dha.node_insert_iso(self.fuel_node_id, self.iso_file)
+
+ self.dha.node_power_on(self.fuel_node_id)
+
+ log('Waiting for Fuel master to accept SSH')
+ self.wait_for_node_up()
+
+ log('Wait until Fuel menu is up')
+ fuel_menu_pid = self.wait_until_fuel_menu_up()
+
+ log('Inject our own astute.yaml settings')
+ self.inject_own_astute_yaml()
+
+ log('Let the Fuel deployment continue')
+ log('Found FUEL menu as PID %s, now killing it' % fuel_menu_pid)
+ self.ssh_exec_cmd('kill %s' % fuel_menu_pid, False)
+
+ log('Wait until installation complete')
+ self.wait_until_installation_completed()
+
+ log('Waiting for one minute for Fuel to stabilize')
+ time.sleep(60)
+
+ self.delete_deprecated_fuel_client_config()
+
+ if not self.no_plugins:
+
+ self.collect_plugin_files()
+
+ self.install_plugins()
+
+ self.post_install_cleanup()
+
+ log('Fuel Master installed successfully !')
+
+ def collect_plugin_files(self):
+ with self.ssh as s:
+ s.exec_cmd('mkdir %s' % PLUGINS_DIR)
+ if self.fuel_plugins_dir:
+ for f in glob.glob('%s/*.rpm' % self.fuel_plugins_dir):
+ s.scp_put(f, PLUGINS_DIR)
+
+ def install_plugins(self):
+ log('Installing Fuel Plugins')
+ plugin_files = []
+ with self.ssh as s:
+ for plugin_location in [PLUGINS_DIR, LOCAL_PLUGIN_FOLDER]:
+ r = s.exec_cmd('find %s -type f -name \'*.rpm\''
+ % plugin_location)
+ plugin_files.extend(r.splitlines())
+ for f in plugin_files:
+ log('Found plugin %s, installing ...' % f)
+ r, e = s.exec_cmd('fuel plugins --install %s' % f, False)
+ printout = r + e if e else r
+ if e and all([err not in printout
+ for err in IGNORABLE_FUEL_ERRORS]):
+ raise Exception('Installation of Fuel Plugin %s '
+ 'failed: %s' % (f, e))
+
+ def wait_for_node_up(self):
+ WAIT_LOOP = 60
+ SLEEP_TIME = 10
+ success = False
+ for i in range(WAIT_LOOP):
+ try:
+ self.ssh.open()
+ success = True
+ break
+ except Exception:
+ log('Trying to SSH into Fuel VM %s ... sleeping %s seconds'
+ % (self.fuel_ip, SLEEP_TIME))
+ time.sleep(SLEEP_TIME)
+ finally:
+ self.ssh.close()
+
+ if not success:
+ raise Exception('Could not SSH into Fuel VM %s' % self.fuel_ip)
+
+ def wait_until_fuel_menu_up(self):
+ WAIT_LOOP = 60
+ SLEEP_TIME = 10
+ CMD = 'ps -ef'
+ SEARCH = 'fuelmenu'
+ fuel_menu_pid = None
+ with self.ssh:
+ for i in range(WAIT_LOOP):
+ ret = self.ssh.exec_cmd(CMD)
+ fuel_menu_pid = self.get_fuel_menu_pid(ret, SEARCH)
+ if not fuel_menu_pid:
+ time.sleep(SLEEP_TIME)
+ else:
+ break
+ if not fuel_menu_pid:
+ raise Exception('Could not find the Fuel Menu Process ID')
+ return fuel_menu_pid
+
+ def get_fuel_menu_pid(self, printout, search):
+ for line in printout.splitlines():
+ if line.endswith(search):
+ return clean(line)[1]
+
+ def ssh_exec_cmd(self, cmd, check=True):
+ with self.ssh:
+ ret = self.ssh.exec_cmd(cmd, check=check)
+ return ret
+
+ def inject_own_astute_yaml(self):
+ with self.ssh as s:
+ s.exec_cmd('rm -rf %s' % self.work_dir, False)
+ s.exec_cmd('mkdir %s' % self.work_dir)
+ s.scp_put(self.dea_file, self.work_dir)
+ s.scp_put('%s/common.py' % self.file_dir, self.work_dir)
+ s.scp_put('%s/dea.py' % self.file_dir, self.work_dir)
+ s.scp_put('%s/transplant_fuel_settings.py'
+ % self.file_dir, self.work_dir)
+ log('Modifying Fuel astute')
+ s.run('python %s/%s %s/%s'
+ % (self.work_dir, TRANSPLANT_FUEL_SETTINGS,
+ self.work_dir, os.path.basename(self.dea_file)))
+
+ def wait_until_installation_completed(self):
+ WAIT_LOOP = 360
+ SLEEP_TIME = 10
+ CMD = 'ps -ef | grep %s | grep -v grep' % BOOTSTRAP_ADMIN
+
+ install_completed = False
+ with self.ssh:
+ for i in range(WAIT_LOOP):
+ ret = self.ssh.exec_cmd(CMD)
+ if not ret:
+ install_completed = True
+ break
+ else:
+ time.sleep(SLEEP_TIME)
+
+ if not install_completed:
+ raise Exception('Fuel installation did not complete')
+
+ def post_install_cleanup(self):
+ log('Eject ISO file %s' % self.iso_file)
+ self.dha.node_eject_iso(self.fuel_node_id)
+ delete(self.iso_dir)
+
+ def delete_deprecated_fuel_client_config(self):
+ with self.ssh as s:
+ response, error = s.exec_cmd('fuel -v', False)
+ if (error and
+ 'DEPRECATION WARNING' in error and FUEL_CLIENT_CONFIG in error):
+ log('Delete deprecated fuel client config %s' % FUEL_CLIENT_CONFIG)
+ with self.ssh as s:
+ s.exec_cmd('rm %s' % FUEL_CLIENT_CONFIG, False)
diff --git a/deploy/reap.py b/deploy/reap.py
new file mode 100644
index 000000000..b7080cdae
--- /dev/null
+++ b/deploy/reap.py
@@ -0,0 +1,340 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import time
+import os
+import yaml
+import glob
+import shutil
+
+from common import (
+ N,
+ E,
+ R,
+ ArgParser,
+ exec_cmd,
+ parse,
+ err,
+ log,
+ delete,
+ commafy,
+)
+
+DEA_1 = '''
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version: 1.1
+created: {date}
+comment: {comment}
+'''
+
+DHA_1 = '''
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version: 1.1
+created: {date}
+comment: {comment}
+
+# Adapter to use for this definition
+# adapter: [ipmi|libvirt]
+adapter:
+
+# Node list.
+# Mandatory properties are id and role.
+# All other properties are adapter specific.
+# For Non-Fuel nodes controlled by:
+# - ipmi adapter you need to provide:
+# pxeMac
+# ipmiIp
+# ipmiUser
+# ipmiPass
+# - libvirt adapter you need to provide:
+# libvirtName: <whatever>
+# libvirtTemplate: [libvirt/vms/controller.xml | libvirt/vms/compute.xml]
+#
+# For the Fuel Node you need to provide:
+# libvirtName: <whatever>
+# libvirtTemplate: libvirt/vms/fuel.xml
+# isFuel: yes
+# username: root
+# password: r00tme
+'''
+
+DHA_2 = '''
+# Adding the Fuel node as node id {node_id}
+# which may not be correct - please adjust as needed.
+'''
+
+DISKS = {'fuel': '30G',
+ 'controller': '30G',
+ 'compute': '30G'}
+
+
+class Reap(object):
+
+ def __init__(self, dea_file, dha_file, comment):
+ self.dea_file = dea_file
+ self.dha_file = dha_file
+ self.comment = comment
+ self.temp_dir = None
+ self.env = None
+ self.env_id = None
+ self.last_node = None
+
+ def get_env(self):
+ env_list = parse(exec_cmd('fuel env'))
+ if len(env_list) > 1:
+ err('Not exactly one environment')
+ self.env = env_list[0]
+ self.env_id = self.env[E['id']]
+
+ def download_config(self, config_type):
+ log('Download %s config for environment %s'
+ % (config_type, self.env_id))
+ exec_cmd('fuel %s --env %s --download --dir %s'
+ % (config_type, self.env_id, self.temp_dir))
+
+ def write(self, file, text, newline=True):
+ mode = 'a' if os.path.isfile(file) else 'w'
+ with open(file, mode) as f:
+ f.write('%s%s' % (text, ('\n' if newline else '')))
+
+ def write_yaml(self, file, data, newline=True):
+ self.write(file, yaml.dump(data, default_flow_style=False).strip(),
+ newline)
+
+ def get_node_by_id(self, node_list, node_id):
+ for node in node_list:
+ if node[N['id']] == node_id:
+ return node
+
+ def reap_interface(self, node_id, interfaces):
+ interface, mac = self.get_interface(node_id)
+ if_name = None
+ if interfaces:
+ if_name = self.check_dict_exists(interfaces, interface)
+ if not if_name:
+ if_name = 'interfaces_%s' % str(len(interfaces) + 1)
+ interfaces[if_name] = interface
+ return if_name, mac
+
+ def reap_transformation(self, node_id, roles, transformations):
+ main_role = 'controller' if 'controller' in roles else 'compute'
+ node_file = glob.glob('%s/deployment_%s/*%s_%s.yaml'
+ % (self.temp_dir, self.env_id,
+ main_role, node_id))
+ tr_name = None
+ with open(node_file[0]) as f:
+ node_config = yaml.load(f)
+ transformation = {'transformations':
+ node_config['network_scheme']['transformations']}
+ if transformations:
+ tr_name = self.check_dict_exists(transformations, transformation)
+ if not tr_name:
+ tr_name = 'transformations_%s' % str(len(transformations) + 1)
+ transformations[tr_name] = transformation
+ return tr_name
+
+ def check_dict_exists(self, main_dict, dict):
+ for key, val in main_dict.iteritems():
+ if cmp(dict, val) == 0:
+ return key
+
+ def reap_nodes_interfaces_transformations(self):
+ node_list = parse(exec_cmd('fuel node'))
+ real_node_ids = [node[N['id']] for node in node_list]
+ real_node_ids.sort()
+ min_node = real_node_ids[0]
+
+ interfaces = {}
+ transformations = {}
+ dea_nodes = []
+ dha_nodes = []
+
+ for real_node_id in real_node_ids:
+ node_id = int(real_node_id) - int(min_node) + 1
+ self.last_node = node_id
+ node = self.get_node_by_id(node_list, real_node_id)
+ roles = commafy(node[N['roles']])
+ if not roles:
+ err('Fuel Node %s has no role' % real_node_id)
+ dea_node = {'id': node_id,
+ 'role': roles}
+ dha_node = {'id': node_id}
+ if_name, mac = self.reap_interface(real_node_id, interfaces)
+ tr_name = self.reap_transformation(real_node_id, roles,
+ transformations)
+ dea_node.update(
+ {'interfaces': if_name,
+ 'transformations': tr_name})
+
+ dha_node.update(
+ {'pxeMac': mac if mac else None,
+ 'ipmiIp': None,
+ 'ipmiUser': None,
+ 'ipmiPass': None,
+ 'libvirtName': None,
+ 'libvirtTemplate': None})
+
+ dea_nodes.append(dea_node)
+ dha_nodes.append(dha_node)
+
+ self.write_yaml(self.dha_file, {'nodes': dha_nodes}, False)
+ self.write_yaml(self.dea_file, {'nodes': dea_nodes})
+ self.write_yaml(self.dea_file, interfaces)
+ self.write_yaml(self.dea_file, transformations)
+ self.reap_fuel_node_info()
+ self.write_yaml(self.dha_file, {'disks': DISKS})
+
+ def reap_fuel_node_info(self):
+ dha_nodes = []
+ dha_node = {
+ 'id': self.last_node + 1,
+ 'libvirtName': None,
+ 'libvirtTemplate': None,
+ 'isFuel': True,
+ 'username': 'root',
+ 'password': 'r00tme'}
+
+ dha_nodes.append(dha_node)
+
+ self.write(self.dha_file, DHA_2.format(node_id=dha_node['id']), False)
+ self.write_yaml(self.dha_file, dha_nodes)
+
+ def reap_environment_info(self):
+ network_file = ('%s/network_%s.yaml'
+ % (self.temp_dir, self.env_id))
+ network = self.read_yaml(network_file)
+ env = {'environment':
+ {'name': self.env[E['name']],
+ 'mode': self.env[E['mode']],
+ 'net_segment_type':
+ network['networking_parameters']['segmentation_type']}}
+ self.write_yaml(self.dea_file, env)
+ wanted_release = None
+ rel_list = parse(exec_cmd('fuel release'))
+ for rel in rel_list:
+ if rel[R['id']] == self.env[E['release_id']]:
+ wanted_release = rel[R['name']]
+ self.write_yaml(self.dea_file, {'wanted_release': wanted_release})
+
+ def reap_fuel_settings(self):
+ data = self.read_yaml('/etc/fuel/astute.yaml')
+ fuel = {}
+ del data['ADMIN_NETWORK']['mac']
+ del data['ADMIN_NETWORK']['interface']
+ for key in ['ADMIN_NETWORK', 'HOSTNAME', 'DNS_DOMAIN', 'DNS_SEARCH',
+ 'DNS_UPSTREAM', 'NTP1', 'NTP2', 'NTP3', 'FUEL_ACCESS']:
+ fuel[key] = data[key]
+ for key in fuel['ADMIN_NETWORK'].keys():
+ if key not in ['ipaddress', 'netmask',
+ 'dhcp_pool_start', 'dhcp_pool_end']:
+ del fuel['ADMIN_NETWORK'][key]
+ self.write_yaml(self.dea_file, {'fuel': fuel})
+
+ def reap_network_settings(self):
+ network_file = ('%s/network_%s.yaml'
+ % (self.temp_dir, self.env_id))
+ data = self.read_yaml(network_file)
+ network = {}
+ network['networking_parameters'] = data['networking_parameters']
+ network['networks'] = data['networks']
+ for net in network['networks']:
+ del net['id']
+ del net['group_id']
+ self.write_yaml(self.dea_file, {'network': network})
+
+ def reap_settings(self):
+ settings_file = '%s/settings_%s.yaml' % (self.temp_dir, self.env_id)
+ settings = self.read_yaml(settings_file)
+ self.write_yaml(self.dea_file, {'settings': settings})
+
+ def get_interface(self, real_node_id):
+ exec_cmd('fuel node --node-id %s --network --download --dir %s'
+ % (real_node_id, self.temp_dir))
+ interface_file = ('%s/node_%s/interfaces.yaml'
+ % (self.temp_dir, real_node_id))
+ interfaces = self.read_yaml(interface_file)
+ interface_config = {}
+ pxe_mac = None
+ for interface in interfaces:
+ networks = []
+ for network in interface['assigned_networks']:
+ networks.append(network['name'])
+ if network['name'] == 'fuelweb_admin':
+ pxe_mac = interface['mac']
+ if networks:
+ interface_config[interface['name']] = networks
+ return interface_config, pxe_mac
+
+ def read_yaml(self, yaml_file):
+ with open(yaml_file) as f:
+ data = yaml.load(f)
+ return data
+
+ def intro(self):
+ delete(self.dea_file)
+ delete(self.dha_file)
+ self.temp_dir = exec_cmd('mktemp -d')
+ date = time.strftime('%c')
+ self.write(self.dea_file,
+ DEA_1.format(date=date, comment=self.comment), False)
+ self.write(self.dha_file,
+ DHA_1.format(date=date, comment=self.comment))
+ self.get_env()
+ self.download_config('deployment')
+ self.download_config('settings')
+ self.download_config('network')
+
+ def finale(self):
+ log('DEA file is available at %s' % self.dea_file)
+ log('DHA file is available at %s (this is just a template)'
+ % self.dha_file)
+ shutil.rmtree(self.temp_dir)
+
+ def reap(self):
+ self.intro()
+ self.reap_environment_info()
+ self.reap_nodes_interfaces_transformations()
+ self.reap_fuel_settings()
+ self.reap_network_settings()
+ self.reap_settings()
+ self.finale()
+
+
+def usage():
+ print '''
+ Usage:
+ python reap.py <dea_file> <dha_file> <comment>
+ '''
+
+
+def parse_arguments():
+ parser = ArgParser(prog='python %s' % __file__)
+ parser.add_argument('dea_file', nargs='?', action='store',
+ default='dea.yaml',
+ help='Deployment Environment Adapter: dea.yaml')
+ parser.add_argument('dha_file', nargs='?', action='store',
+ default='dha.yaml',
+ help='Deployment Hardware Adapter: dha.yaml')
+ parser.add_argument('comment', nargs='?', action='store', help='Comment')
+ args = parser.parse_args()
+ return (args.dea_file, args.dha_file, args.comment)
+
+
+def main():
+ dea_file, dha_file, comment = parse_arguments()
+
+ r = Reap(dea_file, dha_file, comment)
+ r.reap()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/deploy/ssh_client.py b/deploy/ssh_client.py
new file mode 100644
index 000000000..df780961f
--- /dev/null
+++ b/deploy/ssh_client.py
@@ -0,0 +1,98 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import paramiko
+import scp
+
+from common import (
+ log,
+ err,
+)
+
+TIMEOUT = 600
+
+class SSHClient(object):
+
+ def __init__(self, host, username, password):
+ self.host = host
+ self.username = username
+ self.password = password
+ self.client = None
+
+ def open(self, timeout=TIMEOUT):
+ self.client = paramiko.SSHClient()
+ self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ self.client.connect(self.host, username=self.username,
+ password=self.password, look_for_keys=False,
+ timeout=timeout)
+
+ def close(self):
+ if self.client is not None:
+ self.client.close()
+ self.client = None
+
+ def __enter__(self):
+ self.open()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ self.close()
+
+ def exec_cmd(self, command, check=True, sudo=False, timeout=TIMEOUT):
+ if sudo and self.username != 'root':
+ command = "sudo -S -p '' %s" % command
+ stdin, stdout, stderr = self.client.exec_command(command,
+ timeout=timeout)
+ if sudo:
+ stdin.write(self.password + '\n')
+ stdin.flush()
+ response = stdout.read().strip()
+ error = stderr.read().strip()
+
+ if check:
+ if error:
+ self.close()
+ raise Exception(error)
+ else:
+ return response
+ return response, error
+
+ def run(self, command):
+ transport = self.client.get_transport()
+ transport.set_keepalive(1)
+ chan = transport.open_session()
+ chan.exec_command(command)
+ while not chan.exit_status_ready():
+ if chan.recv_ready():
+ data = chan.recv(1024)
+ while data:
+ log(data.strip())
+ data = chan.recv(1024)
+
+ if chan.recv_stderr_ready():
+ error_buff = chan.recv_stderr(1024)
+ while error_buff:
+ log(error_buff.strip())
+ error_buff = chan.recv_stderr(1024)
+ return chan.recv_exit_status()
+
+ def scp_get(self, remote, local='.', dir=False):
+ try:
+ with scp.SCPClient(self.client.get_transport()) as _scp:
+ _scp.get(remote, local, dir)
+ except Exception as e:
+ err(e)
+
+ def scp_put(self, local, remote='.', dir=False):
+ try:
+ with scp.SCPClient(self.client.get_transport()) as _scp:
+ _scp.put(local, remote, dir)
+ except Exception as e:
+ err(e)
diff --git a/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dea.yaml b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dea.yaml
new file mode 100644
index 000000000..c7d741880
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dea.yaml
@@ -0,0 +1,901 @@
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version:
+created:
+comment: Config for Ericsson Montreal Lab - HA deployment with Ceph and Opendaylight
+environment:
+ name: opnfv_virt
+ mode: ha
+ net_segment_type: tun
+wanted_release: Kilo on Ubuntu 14.04
+nodes:
+- id: 1
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 2
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 3
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 4
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 5
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 6
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+fuel:
+ ADMIN_NETWORK:
+ cidr: 10.20.0.0/24
+ dhcp_gateway: 10.20.0.2
+ dhcp_pool_end: 10.20.0.254
+ dhcp_pool_start: 10.20.0.3
+ ipaddress: 10.20.0.2
+ netmask: 255.255.0.0
+ DNS_DOMAIN: opnfvericsson.ca
+ DNS_SEARCH: opnfvericsson.ca
+ DNS_UPSTREAM: 10.118.32.193
+ FUEL_ACCESS:
+ password: admin
+ user: admin
+ HOSTNAME: opnfv_virt
+ NTP1: 10.118.32.193
+ NTP2: 10.118.34.193
+ NTP3: null
+interfaces_1:
+ eth0:
+ - fuelweb_admin
+ eth2:
+ - public
+ - management
+ - storage
+ - private
+transformations_1:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-ex
+ - action: add-br
+ name: br-floating
+ provider: ovs
+ - action: add-patch
+ bridges:
+ - br-floating
+ - br-ex
+ mtu: 65000
+ provider: ovs
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth2.320
+ - action: add-port
+ bridge: br-storage
+ name: eth2.220
+ - action: add-port
+ bridge: br-mesh
+ name: eth2.20
+ - action: add-port
+ bridge: br-ex
+ name: eth0
+transformations_2:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth2.320
+ - action: add-port
+ bridge: br-storage
+ name: eth2.220
+ - action: add-port
+ bridge: br-mesh
+ name: eth2.20
+network:
+ management_vip: 192.168.0.2
+ management_vrouter_vip: 192.168.0.1
+ networking_parameters:
+ base_mac: fa:16:3e:00:00:00
+ configuration_template: null
+ dns_nameservers:
+ - 10.118.32.193
+ floating_ranges:
+ - - 10.118.34.226
+ - 10.118.34.230
+ gre_id_range:
+ - 2
+ - 65535
+ internal_cidr: 192.168.111.0/24
+ internal_gateway: 192.168.111.1
+ net_l23_provider: ovs
+ segmentation_type: tun
+ vlan_range:
+ - 2022
+ - 2023
+ networks:
+ - cidr: 10.118.34.192/24
+ gateway: 10.118.34.193
+ ip_ranges:
+ - - 10.118.34.220
+ - 10.118.34.225
+ meta:
+ cidr: 172.16.0.0/24
+ configurable: true
+ floating_range_var: floating_ranges
+ ip_range:
+ - 172.16.0.2
+ - 172.16.0.126
+ map_priority: 1
+ name: public
+ notation: ip_ranges
+ render_addr_mask: public
+ render_type: null
+ use_gateway: true
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: null
+ name: public
+ vlan_start: null
+ - cidr: 192.168.0.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.0.1
+ - 192.168.0.254
+ meta:
+ cidr: 192.168.0.0/24
+ configurable: true
+ map_priority: 2
+ name: management
+ notation: cidr
+ render_addr_mask: internal
+ render_type: cidr
+ use_gateway: false
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: 101
+ name: management
+ vlan_start: 320
+ - cidr: 192.168.1.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.1.1
+ - 192.168.1.254
+ meta:
+ cidr: 192.168.1.0/24
+ configurable: true
+ map_priority: 2
+ name: storage
+ notation: cidr
+ render_addr_mask: storage
+ render_type: cidr
+ use_gateway: false
+ vlan_start: 220
+ name: storage
+ vlan_start: 102
+ - cidr: 192.168.2.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.2.1
+ - 192.168.2.254
+ meta:
+ cidr: 192.168.2.0/24
+ configurable: true
+ map_priority: 2
+ name: private
+ notation: cidr
+ render_addr_mask: null
+ render_type: cidr
+ seg_type: tun
+ use_gateway: false
+ vlan_start: 103
+ name: private
+ vlan_start: 20
+ - cidr: 10.20.0.0/16
+ gateway: 10.20.0.2
+ ip_ranges:
+ - - 10.20.0.3
+ - 10.20.0.254
+ meta:
+ configurable: false
+ map_priority: 0
+ notation: ip_ranges
+ render_addr_mask: null
+ render_type: null
+ unmovable: true
+ use_gateway: true
+ name: fuelweb_admin
+ vlan_start: null
+ public_vip: 10.118.34.220
+ public_vrouter_vip: 10.118.34.221
+ vips:
+ management:
+ ipaddr: 192.168.0.2
+ namespace: haproxy
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ public:
+ ipaddr: 10.118.34.220
+ namespace: haproxy
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter:
+ ipaddr: 192.168.0.1
+ namespace: vrouter
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter_pub:
+ ipaddr: 10.118.34.221
+ namespace: vrouter
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+settings:
+ editable:
+ access:
+ email:
+ description: Email address for Administrator
+ label: Email
+ regex:
+ error: Invalid email
+ source: ^\S+@\S+$
+ type: text
+ value: admin@localhost
+ weight: 40
+ metadata:
+ label: Access
+ weight: 10
+ password:
+ description: Password for Administrator
+ label: Password
+ regex:
+ error: Empty password
+ source: \S
+ type: password
+ value: admin
+ weight: 20
+ tenant:
+ description: Tenant (project) name for Administrator
+ label: Tenant
+ regex:
+ error: Invalid tenant name
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 30
+ user:
+ description: Username for Administrator
+ label: Username
+ regex:
+ error: Invalid username
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 10
+ additional_components:
+ ceilometer:
+ description: If selected, Ceilometer component will be installed
+ label: Install Ceilometer
+ type: checkbox
+ value: false
+ weight: 40
+ heat:
+ description: ''
+ label: ''
+ type: hidden
+ value: true
+ weight: 30
+ metadata:
+ label: Additional Components
+ weight: 20
+ mongo:
+ description: If selected, You can use external Mongo DB as ceilometer backend
+ label: Use external Mongo DB
+ restrictions:
+ - settings:additional_components.ceilometer.value == false
+ type: checkbox
+ value: false
+ weight: 40
+ murano:
+ description: If selected, Murano component will be installed
+ label: Install Murano
+ type: checkbox
+ value: false
+ weight: 20
+ sahara:
+ description: If selected, Sahara component will be installed
+ label: Install Sahara
+ type: checkbox
+ value: false
+ weight: 10
+ common:
+ auth_key:
+ description: Public key(s) to include in authorized_keys on deployed nodes
+ label: Public Key
+ type: textarea
+ value: ''
+ weight: 70
+ auto_assign_floating_ip:
+ description: If selected, OpenStack will automatically assign a floating IP
+ to a new instance
+ label: Auto assign floating IP
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider == 'neutron'
+ type: checkbox
+ value: false
+ weight: 40
+ debug:
+ description: Debug logging mode provides more information, but requires more
+ disk space.
+ label: OpenStack debug logging
+ type: checkbox
+ value: false
+ weight: 20
+ libvirt_type:
+ label: Hypervisor type
+ type: radio
+ value: kvm
+ values:
+ - data: kvm
+ description: Choose this type of hypervisor if you run OpenStack on hardware
+ label: KVM
+ - data: qemu
+ description: Choose this type of hypervisor if you run OpenStack on virtual
+ hosts.
+ label: QEMU
+ weight: 30
+ metadata:
+ label: Common
+ weight: 30
+ nova_quota:
+ description: Quotas are used to limit CPU and memory usage for tenants. Enabling
+ quotas will increase load on the Nova database.
+ label: Nova quotas
+ type: checkbox
+ value: false
+ weight: 25
+ puppet_debug:
+ description: Debug puppet logging mode provides more information, but requires
+ more disk space.
+ label: Puppet debug logging
+ type: checkbox
+ value: true
+ weight: 20
+ resume_guests_state_on_host_boot:
+ description: Whether to resume previous guests state when the host reboots.
+ If enabled, this option causes guests assigned to the host to resume their
+ previous state. If the guest was running a restart will be attempted when
+ nova-compute starts. If the guest was not running previously, a restart will
+ not be attempted.
+ label: Resume guests state on host boot
+ type: checkbox
+ value: true
+ weight: 60
+ use_cow_images:
+ description: For most cases you will want qcow format. If it's disabled, raw
+ image format will be used to run VMs. OpenStack with raw format currently
+ does not support snapshotting.
+ label: Use qcow format for images
+ type: checkbox
+ value: true
+ weight: 50
+ use_vcenter:
+ restrictions:
+ - condition: cluster:net_provider == 'nova_network'
+ type: hidden
+ value: false
+ weight: 30
+ corosync:
+ group:
+ description: ''
+ label: Group
+ type: text
+ value: 226.94.1.1
+ weight: 10
+ metadata:
+ label: Corosync
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 50
+ port:
+ description: ''
+ label: Port
+ type: text
+ value: '12000'
+ weight: 20
+ verified:
+ description: Set True only if multicast is configured correctly on router.
+ label: Need to pass network verification.
+ type: checkbox
+ value: false
+ weight: 10
+ external_dns:
+ dns_list:
+ description: List of upstream DNS servers, separated by comma
+ label: DNS list
+ regex:
+ error: Invalid IP address list
+ source: ^\*$|^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\s*,\s*(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3})*$
+ type: text
+ value: 10.118.32.193
+ weight: 10
+ metadata:
+ label: Host OS DNS Servers
+ weight: 90
+ external_mongo:
+ hosts_ip:
+ description: IP Addresses of MongoDB. Use comma to split IPs
+ label: MongoDB hosts IP
+ regex:
+ error: Invalid hosts ip sequence
+ source: ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?),)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+ type: text
+ value: ''
+ weight: 30
+ metadata:
+ label: External MongoDB
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.mongo.value == false
+ message: Ceilometer and MongoDB are not enabled on the Additional Components
+ section
+ weight: 20
+ mongo_db_name:
+ description: Mongo database name
+ label: Database name
+ regex:
+ error: Invalid database name
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ mongo_password:
+ description: Mongo database password
+ label: Password
+ regex:
+ error: Password contains spaces
+ source: ^\S*$
+ type: password
+ value: ceilometer
+ weight: 30
+ mongo_replset:
+ description: Name for Mongo replication set
+ label: Replset
+ type: text
+ value: ''
+ weight: 30
+ mongo_user:
+ description: Mongo database username
+ label: Username
+ regex:
+ error: Empty username
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ external_ntp:
+ metadata:
+ label: Host OS NTP Servers
+ weight: 100
+ ntp_list:
+ description: List of upstream NTP servers, separated by comma
+ label: NTP server list
+ regex:
+ error: Invalid NTP server list
+ source: ^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(?:\.\d{1,3}){3})\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(\.\d{1,3}){3})\s*)*$
+ type: text
+ value: 10.118.32.193, 10.118.34.193
+ weight: 10
+ kernel_params:
+ kernel:
+ description: Default kernel parameters
+ label: Initial parameters
+ type: text
+ value: console=tty0 net.ifnames=0 biosdevname=0 rootdelay=90 nomodeset
+ weight: 45
+ metadata:
+ label: Kernel parameters
+ weight: 40
+ murano_settings:
+ metadata:
+ label: Murano Settings
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.murano.value == false
+ message: Murano is not enabled on the Additional Components section
+ weight: 20
+ murano_repo_url:
+ description: ''
+ label: Murano Repository URL
+ type: text
+ value: http://storage.apps.openstack.org/
+ weight: 10
+ neutron_advanced_configuration:
+ metadata:
+ label: Neutron Advanced Configuration
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 45
+ neutron_dvr:
+ description: Enable Distributed Virtual Routers in Neutron
+ label: Neutron DVR
+ restrictions:
+ - ? networking_parameters:segmentation_type != 'vlan' and settings:neutron_advanced_configuration.neutron_l2_pop.value
+ == false
+ : DVR requires L2 population to be enabled.
+ type: checkbox
+ value: false
+ weight: 20
+ neutron_l2_pop:
+ description: Enable L2 population mechanism in Neutron
+ label: Neutron L2 population
+ restrictions:
+ - action: hide
+ condition: networking_parameters:segmentation_type == 'vlan'
+ type: checkbox
+ value: false
+ weight: 10
+ neutron_mellanox:
+ metadata:
+ enabled: true
+ label: Mellanox Neutron components
+ restrictions:
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ toggleable: false
+ weight: 50
+ plugin:
+ label: Mellanox drivers and SR-IOV plugin
+ type: radio
+ value: disabled
+ values:
+ - data: disabled
+ description: If selected, Mellanox drivers, Neutron and Cinder plugin will
+ not be installed.
+ label: Mellanox drivers and plugins disabled
+ restrictions:
+ - settings:storage.iser.value == true
+ - data: drivers_only
+ description: If selected, Mellanox Ethernet drivers will be installed to support
+ networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.
+ label: Install only Mellanox drivers
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm'
+ - data: ethernet
+ description: If selected, both Mellanox Ethernet drivers and Mellanox network
+ acceleration (Neutron) plugin will be installed.
+ label: Install Mellanox drivers and SR-IOV plugin
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider
+ == 'neutron' and networking_parameters:segmentation_type == 'vlan')
+ weight: 60
+ vf_num:
+ description: Note that one virtual function will be reserved to the storage
+ network, in case of choosing iSER.
+ label: Number of virtual NICs
+ restrictions:
+ - settings:neutron_mellanox.plugin.value != 'ethernet'
+ type: text
+ value: '16'
+ weight: 70
+ provision:
+ metadata:
+ label: Provision
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 80
+ method:
+ type: hidden
+ value: image
+ public_network_assignment:
+ assign_to_all_nodes:
+ description: When disabled, public network will be assigned to controllers only
+ label: Assign public network to all nodes
+ type: checkbox
+ value: false
+ weight: 10
+ metadata:
+ label: Public network assignment
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 50
+ public_ssl:
+ cert_data:
+ description: Certificate and private key data, concatenated into a single file
+ label: Certificate
+ restrictions:
+ - action: hide
+ condition: (settings:public_ssl.cert_source.value != 'user_uploaded') or (settings:public_ssl.horizon.value
+ == false and settings:public_ssl.services.value == false)
+ type: file
+ value: ''
+ weight: 40
+ cert_source:
+ description: From where we'll get certificate and private key
+ label: Select source for certificate
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: radio
+ value: self_signed
+ values:
+ - data: self_signed
+ description: Generate private key and certificate that will be signed by this
+ key
+ label: Self-signed
+ - data: user_uploaded
+ description: Use pre-generated key and certificate
+ label: I have my own keypair with certificate
+ weight: 30
+ horizon:
+ description: Secure access to Horizon enabling HTTPS instead of HTTP
+ label: HTTPS for Horizon
+ type: checkbox
+ value: false
+ weight: 10
+ hostname:
+ description: Your DNS entries should point to this name. Self-signed certificates
+ also will use this hostname
+ label: DNS hostname for public TLS endpoints
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: text
+ value: public.fuel.local
+ weight: 50
+ metadata:
+ label: Public TLS
+ weight: 110
+ services:
+ description: Enable TLS termination on HAProxy for OpenStack services
+ label: TLS for OpenStack public endpoints
+ type: checkbox
+ value: false
+ weight: 20
+ repo_setup:
+ metadata:
+ always_editable: true
+ label: Repositories
+ weight: 50
+ repos:
+ description: 'Please note: the first repository will be considered the operating
+ system mirror that will be used during node provisioning.
+
+ To create a local repository mirror on the Fuel master node, please follow
+ the instructions provided by running "fuel-createmirror --help" on the Fuel
+ master node.
+
+ Please make sure your Fuel master node has Internet access to the repository
+ before attempting to create a mirror.
+
+ For more details, please refer to the documentation (https://docs.mirantis.com/openstack/fuel/fuel-7.0/operations.html#external-ubuntu-ops).
+
+ '
+ extra_priority: null
+ type: custom_repo_configuration
+ value:
+ - name: ubuntu
+ priority: null
+ section: main universe multiverse
+ suite: trusty
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-updates
+ priority: null
+ section: main universe multiverse
+ suite: trusty-updates
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-security
+ priority: null
+ section: main universe multiverse
+ suite: trusty-security
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: mos
+ priority: 1050
+ section: main restricted
+ suite: mos7.0
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/x86_64
+ - name: mos-updates
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-updates
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-security
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-security
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-holdback
+ priority: 1100
+ section: main restricted
+ suite: mos7.0-holdback
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: Auxiliary
+ priority: 1150
+ section: main restricted
+ suite: auxiliary
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/auxiliary
+ storage:
+ ephemeral_ceph:
+ description: Configures Nova to store ephemeral volumes in RBD. This works best
+ if Ceph is enabled for volumes and images, too. Enables live migration of
+ all types of Ceph backed VMs (without this option, live migration will only
+ work with VMs launched from Cinder volumes).
+ label: Ceph RBD for ephemeral volumes (Nova)
+ type: checkbox
+ value: true
+ weight: 75
+ images_ceph:
+ description: Configures Glance to use the Ceph RBD backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: Ceph RBD for images (Glance)
+ restrictions:
+ - settings:storage.images_vcenter.value == true: Only one Glance backend could
+ be selected.
+ type: checkbox
+ value: true
+ weight: 30
+ images_vcenter:
+ description: Configures Glance to use the vCenter/ESXi backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: VMWare vCenter/ESXi datastore for images (Glance)
+ restrictions:
+ - action: hide
+ condition: settings:common.use_vcenter.value != true
+ - condition: settings:storage.images_ceph.value == true
+ message: Only one Glance backend could be selected.
+ type: checkbox
+ value: false
+ weight: 35
+ iser:
+ description: 'High performance block storage: Cinder volumes over iSER protocol
+ (iSCSI over RDMA). This feature requires SR-IOV capabilities in the NIC, and
+ will use a dedicated virtual function for the storage network.'
+ label: iSER protocol for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value != true or settings:common.libvirt_type.value
+ != 'kvm'
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ type: checkbox
+ value: false
+ weight: 11
+ metadata:
+ label: Storage
+ weight: 60
+ objects_ceph:
+ description: Configures RadosGW front end for Ceph RBD. This exposes S3 and
+ Swift API Interfaces. If enabled, this option will prevent Swift from installing.
+ label: Ceph RadosGW for objects (Swift API)
+ restrictions:
+ - settings:storage.images_ceph.value == false
+ type: checkbox
+ value: false
+ weight: 80
+ osd_pool_size:
+ description: Configures the default number of object replicas in Ceph. This
+ number must be equal to or lower than the number of deployed 'Storage - Ceph
+ OSD' nodes.
+ label: Ceph object replication factor
+ regex:
+ error: Invalid number
+ source: ^[1-9]\d*$
+ type: text
+ value: '2'
+ weight: 85
+ volumes_ceph:
+ description: Configures Cinder to store volumes in Ceph RBD images.
+ label: Ceph RBD for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value == true
+ type: checkbox
+ value: true
+ weight: 20
+ volumes_lvm:
+ description: It is recommended to have at least one Storage - Cinder LVM node.
+ label: Cinder LVM over iSCSI for volumes
+ restrictions:
+ - settings:storage.volumes_ceph.value == true
+ type: checkbox
+ value: false
+ weight: 10
+ syslog:
+ metadata:
+ label: Syslog
+ weight: 50
+ syslog_port:
+ description: Remote syslog port
+ label: Port
+ regex:
+ error: Invalid syslog port
+ source: ^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
+ type: text
+ value: '514'
+ weight: 20
+ syslog_server:
+ description: Remote syslog hostname
+ label: Hostname
+ type: text
+ value: ''
+ weight: 10
+ syslog_transport:
+ label: Syslog transport protocol
+ type: radio
+ value: tcp
+ values:
+ - data: udp
+ description: ''
+ label: UDP
+ - data: tcp
+ description: ''
+ label: TCP
+ weight: 30
+ workloads_collector:
+ enabled:
+ type: hidden
+ value: true
+ metadata:
+ label: Workloads Collector User
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 10
+ password:
+ type: password
+ value: sbfn1c8b
+ tenant:
+ type: text
+ value: services
+ user:
+ type: text
+ value: fuel_stats_user \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dha.yaml b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dha.yaml
new file mode 100644
index 000000000..ca446f680
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/dha.yaml
@@ -0,0 +1,54 @@
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version:
+created:
+comment: Config for Ericsson Montreal Lab
+
+# Adapter to use for this definition
+adapter: hp
+
+# Node list.
+# Mandatory property is id, all other properties are adapter specific.
+
+nodes:
+- id: 1
+ pxeMac: 14:58:D0:54:7A:D8
+ ipmiIp: 10.118.32.198
+ ipmiUser: <username>
+ ipmiPass: <password>
+- id: 2
+ pxeMac: 14:58:D0:55:E2:E0
+ ipmiIp: 10.118.32.202
+ ipmiUser: <username>
+ ipmiPass: <password>
+- id: 3
+ pxeMac: 9C:B6:54:8A:25:C0
+ ipmiIp: 10.118.32.213
+ ipmiUser: <username>
+ ipmiPass: <password>
+- id: 4
+ pxeMac: 14:58:D0:54:28:80
+ ipmiIp: 10.118.32.201
+ ipmiUser: <username>
+ ipmiPass: <password>
+- id: 5
+ pxeMac: 14:58:D0:54:E7:88
+ ipmiIp: 10.118.32.203
+ ipmiUser: <username>
+ ipmiPass: <password>
+- id: 6
+ pxeMac: 14:58:D0:54:7A:28
+ ipmiIp: 10.118.32.205
+ ipmiUser: <username>
+ ipmiPass: <password>
+# Adding the Fuel node as node id 7 which may not be correct - please
+# adjust as needed.
+- id: 7
+ libvirtName: fuel-opnfv
+ libvirtTemplate: templates/hardware_environment/vms/fuel.xml
+ isFuel: yes
+ username: root
+ password: r00tme
+
+disks:
+ fuel: 50G \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/plugins_conf/.gitkeep b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/plugins_conf/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/ericsson_montreal_lab/plugins_conf/.gitkeep
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dea.yaml b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dea.yaml
new file mode 100644
index 000000000..e2d752198
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dea.yaml
@@ -0,0 +1,898 @@
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version:
+created:
+comment: Config for LF POD1 - HA deployment with Ceph and Opendaylight
+environment:
+ name: opnfv
+ mode: ha
+ net_segment_type: tun
+wanted_release: Kilo on Ubuntu 14.04
+nodes:
+- id: 1
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 2
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 3
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 4
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 5
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+fuel:
+ ADMIN_NETWORK:
+ cidr: 10.20.0.0/24
+ dhcp_gateway: 10.20.0.2
+ dhcp_pool_end: 10.20.0.254
+ dhcp_pool_start: 10.20.0.3
+ ipaddress: 10.20.0.2
+ netmask: 255.255.0.0
+ DNS_DOMAIN: domain.tld
+ DNS_SEARCH: domain.tld
+ DNS_UPSTREAM: 8.8.8.8
+ FUEL_ACCESS:
+ password: admin
+ user: admin
+ HOSTNAME: opnfv
+ NTP1: 0.pool.ntp.org
+ NTP2: 1.pool.ntp.org
+ NTP3: 2.pool.ntp.org
+interfaces_1:
+ eth0:
+ - public
+ eth1:
+ - fuelweb_admin
+ - management
+ - storage
+ - private
+transformations_1:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-ex
+ - action: add-br
+ name: br-floating
+ provider: ovs
+ - action: add-patch
+ bridges:
+ - br-floating
+ - br-ex
+ mtu: 65000
+ provider: ovs
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth1.300
+ - action: add-port
+ bridge: br-storage
+ name: eth1.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth1.302
+ - action: add-port
+ bridge: br-ex
+ name: eth0
+transformations_2:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth1.300
+ - action: add-port
+ bridge: br-storage
+ name: eth1.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth1.302
+network:
+ management_vip: 192.168.0.2
+ management_vrouter_vip: 192.168.0.1
+ networking_parameters:
+ base_mac: fa:16:3e:00:00:00
+ configuration_template: null
+ dns_nameservers:
+ - 8.8.4.4
+ - 8.8.8.8
+ floating_ranges:
+ - - 172.30.9.160
+ - 172.30.9.254
+ gre_id_range:
+ - 2
+ - 65535
+ internal_cidr: 192.168.111.0/24
+ internal_gateway: 192.168.111.1
+ net_l23_provider: ovs
+ segmentation_type: tun
+ vlan_range:
+ - 1000
+ - 1030
+ networks:
+ - cidr: 172.30.9.0/24
+ gateway: 172.30.9.1
+ ip_ranges:
+ - - 172.30.9.64
+ - 172.30.9.159
+ meta:
+ cidr: 172.16.0.0/24
+ configurable: true
+ floating_range_var: floating_ranges
+ ip_range:
+ - 172.16.0.2
+ - 172.16.0.126
+ map_priority: 1
+ name: public
+ notation: ip_ranges
+ render_addr_mask: public
+ render_type: null
+ use_gateway: true
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: null
+ name: public
+ vlan_start: null
+ - cidr: 192.168.0.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.0.1
+ - 192.168.0.254
+ meta:
+ cidr: 192.168.0.0/24
+ configurable: true
+ map_priority: 2
+ name: management
+ notation: cidr
+ render_addr_mask: internal
+ render_type: cidr
+ use_gateway: false
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: 101
+ name: management
+ vlan_start: 300
+ - cidr: 192.168.1.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.1.1
+ - 192.168.1.254
+ meta:
+ cidr: 192.168.1.0/24
+ configurable: true
+ map_priority: 2
+ name: storage
+ notation: cidr
+ render_addr_mask: storage
+ render_type: cidr
+ use_gateway: false
+ vlan_start: 102
+ name: storage
+ vlan_start: 301
+ - cidr: 192.168.2.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.2.1
+ - 192.168.2.254
+ meta:
+ cidr: 192.168.2.0/24
+ configurable: true
+ map_priority: 2
+ name: private
+ notation: cidr
+ render_addr_mask: null
+ render_type: cidr
+ seg_type: tun
+ use_gateway: false
+ vlan_start: 103
+ name: private
+ vlan_start: 302
+ - cidr: 10.20.0.0/16
+ gateway: 10.20.0.2
+ ip_ranges:
+ - - 10.20.0.3
+ - 10.20.0.254
+ meta:
+ configurable: false
+ map_priority: 0
+ notation: ip_ranges
+ render_addr_mask: null
+ render_type: null
+ unmovable: true
+ use_gateway: true
+ name: fuelweb_admin
+ vlan_start: null
+ public_vip: 172.30.9.64
+ public_vrouter_vip: 172.30.9.65
+ vips:
+ management:
+ ipaddr: 192.168.0.2
+ namespace: haproxy
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ public:
+ ipaddr: 172.30.9.64
+ namespace: haproxy
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter:
+ ipaddr: 192.168.0.1
+ namespace: vrouter
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter_pub:
+ ipaddr: 172.30.9.65
+ namespace: vrouter
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+settings:
+ editable:
+ access:
+ email:
+ description: Email address for Administrator
+ label: Email
+ regex:
+ error: Invalid email
+ source: ^\S+@\S+$
+ type: text
+ value: admin@localhost
+ weight: 40
+ metadata:
+ label: Access
+ weight: 10
+ password:
+ description: Password for Administrator
+ label: Password
+ regex:
+ error: Empty password
+ source: \S
+ type: password
+ value: admin
+ weight: 20
+ tenant:
+ description: Tenant (project) name for Administrator
+ label: Tenant
+ regex:
+ error: Invalid tenant name
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 30
+ user:
+ description: Username for Administrator
+ label: Username
+ regex:
+ error: Invalid username
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 10
+ additional_components:
+ ceilometer:
+ description: If selected, Ceilometer component will be installed
+ label: Install Ceilometer
+ type: checkbox
+ value: false
+ weight: 40
+ heat:
+ description: ''
+ label: ''
+ type: hidden
+ value: true
+ weight: 30
+ metadata:
+ label: Additional Components
+ weight: 20
+ mongo:
+ description: If selected, You can use external Mongo DB as ceilometer backend
+ label: Use external Mongo DB
+ restrictions:
+ - settings:additional_components.ceilometer.value == false
+ type: checkbox
+ value: false
+ weight: 40
+ murano:
+ description: If selected, Murano component will be installed
+ label: Install Murano
+ type: checkbox
+ value: false
+ weight: 20
+ sahara:
+ description: If selected, Sahara component will be installed
+ label: Install Sahara
+ type: checkbox
+ value: false
+ weight: 10
+ common:
+ auth_key:
+ description: Public key(s) to include in authorized_keys on deployed nodes
+ label: Public Key
+ type: textarea
+ value: ''
+ weight: 70
+ auto_assign_floating_ip:
+ description: If selected, OpenStack will automatically assign a floating IP
+ to a new instance
+ label: Auto assign floating IP
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider == 'neutron'
+ type: checkbox
+ value: false
+ weight: 40
+ debug:
+ description: Debug logging mode provides more information, but requires more
+ disk space.
+ label: OpenStack debug logging
+ type: checkbox
+ value: false
+ weight: 20
+ libvirt_type:
+ label: Hypervisor type
+ type: radio
+ value: kvm
+ values:
+ - data: kvm
+ description: Choose this type of hypervisor if you run OpenStack on hardware
+ label: KVM
+ - data: qemu
+ description: Choose this type of hypervisor if you run OpenStack on virtual
+ hosts.
+ label: QEMU
+ weight: 30
+ metadata:
+ label: Common
+ weight: 30
+ nova_quota:
+ description: Quotas are used to limit CPU and memory usage for tenants. Enabling
+ quotas will increase load on the Nova database.
+ label: Nova quotas
+ type: checkbox
+ value: false
+ weight: 25
+ puppet_debug:
+ description: Debug puppet logging mode provides more information, but requires
+ more disk space.
+ label: Puppet debug logging
+ type: checkbox
+ value: true
+ weight: 20
+ resume_guests_state_on_host_boot:
+ description: Whether to resume previous guests state when the host reboots.
+ If enabled, this option causes guests assigned to the host to resume their
+ previous state. If the guest was running a restart will be attempted when
+ nova-compute starts. If the guest was not running previously, a restart will
+ not be attempted.
+ label: Resume guests state on host boot
+ type: checkbox
+ value: true
+ weight: 60
+ use_cow_images:
+ description: For most cases you will want qcow format. If it's disabled, raw
+ image format will be used to run VMs. OpenStack with raw format currently
+ does not support snapshotting.
+ label: Use qcow format for images
+ type: checkbox
+ value: true
+ weight: 50
+ use_vcenter:
+ restrictions:
+ - condition: cluster:net_provider == 'nova_network'
+ type: hidden
+ value: false
+ weight: 30
+ corosync:
+ group:
+ description: ''
+ label: Group
+ type: text
+ value: 226.94.1.1
+ weight: 10
+ metadata:
+ label: Corosync
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 50
+ port:
+ description: ''
+ label: Port
+ type: text
+ value: '12000'
+ weight: 20
+ verified:
+ description: Set True only if multicast is configured correctly on router.
+ label: Need to pass network verification.
+ type: checkbox
+ value: false
+ weight: 10
+ external_dns:
+ dns_list:
+ description: List of upstream DNS servers, separated by comma
+ label: DNS list
+ regex:
+ error: Invalid IP address list
+ source: ^\*$|^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\s*,\s*(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3})*$
+ type: text
+ value: 8.8.8.8, 8.8.4.4
+ weight: 10
+ metadata:
+ label: Host OS DNS Servers
+ weight: 90
+ external_mongo:
+ hosts_ip:
+ description: IP Addresses of MongoDB. Use comma to split IPs
+ label: MongoDB hosts IP
+ regex:
+ error: Invalid hosts ip sequence
+ source: ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?),)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+ type: text
+ value: ''
+ weight: 30
+ metadata:
+ label: External MongoDB
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.mongo.value == false
+ message: Ceilometer and MongoDB are not enabled on the Additional Components
+ section
+ weight: 20
+ mongo_db_name:
+ description: Mongo database name
+ label: Database name
+ regex:
+ error: Invalid database name
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ mongo_password:
+ description: Mongo database password
+ label: Password
+ regex:
+ error: Password contains spaces
+ source: ^\S*$
+ type: password
+ value: ceilometer
+ weight: 30
+ mongo_replset:
+ description: Name for Mongo replication set
+ label: Replset
+ type: text
+ value: ''
+ weight: 30
+ mongo_user:
+ description: Mongo database username
+ label: Username
+ regex:
+ error: Empty username
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ external_ntp:
+ metadata:
+ label: Host OS NTP Servers
+ weight: 100
+ ntp_list:
+ description: List of upstream NTP servers, separated by comma
+ label: NTP server list
+ regex:
+ error: Invalid NTP server list
+ source: ^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(?:\.\d{1,3}){3})\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(\.\d{1,3}){3})\s*)*$
+ type: text
+ value: 0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org
+ weight: 10
+ kernel_params:
+ kernel:
+ description: Default kernel parameters
+ label: Initial parameters
+ type: text
+ value: console=tty0 net.ifnames=0 biosdevname=0 rootdelay=90 nomodeset
+ weight: 45
+ metadata:
+ label: Kernel parameters
+ weight: 40
+ murano_settings:
+ metadata:
+ label: Murano Settings
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.murano.value == false
+ message: Murano is not enabled on the Additional Components section
+ weight: 20
+ murano_repo_url:
+ description: ''
+ label: Murano Repository URL
+ type: text
+ value: http://storage.apps.openstack.org/
+ weight: 10
+ neutron_advanced_configuration:
+ metadata:
+ label: Neutron Advanced Configuration
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 45
+ neutron_dvr:
+ description: Enable Distributed Virtual Routers in Neutron
+ label: Neutron DVR
+ restrictions:
+ - ? networking_parameters:segmentation_type != 'vlan' and settings:neutron_advanced_configuration.neutron_l2_pop.value
+ == false
+ : DVR requires L2 population to be enabled.
+ type: checkbox
+ value: false
+ weight: 20
+ neutron_l2_pop:
+ description: Enable L2 population mechanism in Neutron
+ label: Neutron L2 population
+ restrictions:
+ - action: hide
+ condition: networking_parameters:segmentation_type == 'vlan'
+ type: checkbox
+ value: false
+ weight: 10
+ neutron_mellanox:
+ metadata:
+ enabled: true
+ label: Mellanox Neutron components
+ restrictions:
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ toggleable: false
+ weight: 50
+ plugin:
+ label: Mellanox drivers and SR-IOV plugin
+ type: radio
+ value: disabled
+ values:
+ - data: disabled
+ description: If selected, Mellanox drivers, Neutron and Cinder plugin will
+ not be installed.
+ label: Mellanox drivers and plugins disabled
+ restrictions:
+ - settings:storage.iser.value == true
+ - data: drivers_only
+ description: If selected, Mellanox Ethernet drivers will be installed to support
+ networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.
+ label: Install only Mellanox drivers
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm'
+ - data: ethernet
+ description: If selected, both Mellanox Ethernet drivers and Mellanox network
+ acceleration (Neutron) plugin will be installed.
+ label: Install Mellanox drivers and SR-IOV plugin
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider
+ == 'neutron' and networking_parameters:segmentation_type == 'vlan')
+ weight: 60
+ vf_num:
+ description: Note that one virtual function will be reserved to the storage
+ network, in case of choosing iSER.
+ label: Number of virtual NICs
+ restrictions:
+ - settings:neutron_mellanox.plugin.value != 'ethernet'
+ type: text
+ value: '16'
+ weight: 70
+ provision:
+ metadata:
+ label: Provision
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 80
+ method:
+ type: hidden
+ value: image
+ public_network_assignment:
+ assign_to_all_nodes:
+ description: When disabled, public network will be assigned to controllers only
+ label: Assign public network to all nodes
+ type: checkbox
+ value: false
+ weight: 10
+ metadata:
+ label: Public network assignment
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 50
+ public_ssl:
+ cert_data:
+ description: Certificate and private key data, concatenated into a single file
+ label: Certificate
+ restrictions:
+ - action: hide
+ condition: (settings:public_ssl.cert_source.value != 'user_uploaded') or (settings:public_ssl.horizon.value
+ == false and settings:public_ssl.services.value == false)
+ type: file
+ value: ''
+ weight: 40
+ cert_source:
+ description: From where we'll get certificate and private key
+ label: Select source for certificate
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: radio
+ value: self_signed
+ values:
+ - data: self_signed
+ description: Generate private key and certificate that will be signed by this
+ key
+ label: Self-signed
+ - data: user_uploaded
+ description: Use pre-generated key and certificate
+ label: I have my own keypair with certificate
+ weight: 30
+ horizon:
+ description: Secure access to Horizon enabling HTTPS instead of HTTP
+ label: HTTPS for Horizon
+ type: checkbox
+ value: false
+ weight: 10
+ hostname:
+ description: Your DNS entries should point to this name. Self-signed certificates
+ also will use this hostname
+ label: DNS hostname for public TLS endpoints
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: text
+ value: public.fuel.local
+ weight: 50
+ metadata:
+ label: Public TLS
+ weight: 110
+ services:
+ description: Enable TLS termination on HAProxy for OpenStack services
+ label: TLS for OpenStack public endpoints
+ type: checkbox
+ value: false
+ weight: 20
+ repo_setup:
+ metadata:
+ always_editable: true
+ label: Repositories
+ weight: 50
+ repos:
+ description: 'Please note: the first repository will be considered the operating
+ system mirror that will be used during node provisioning.
+
+ To create a local repository mirror on the Fuel master node, please follow
+ the instructions provided by running "fuel-createmirror --help" on the Fuel
+ master node.
+
+ Please make sure your Fuel master node has Internet access to the repository
+ before attempting to create a mirror.
+
+ For more details, please refer to the documentation (https://docs.mirantis.com/openstack/fuel/fuel-7.0/operations.html#external-ubuntu-ops).
+
+ '
+ extra_priority: null
+ type: custom_repo_configuration
+ value:
+ - name: ubuntu
+ priority: null
+ section: main universe multiverse
+ suite: trusty
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-updates
+ priority: null
+ section: main universe multiverse
+ suite: trusty-updates
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-security
+ priority: null
+ section: main universe multiverse
+ suite: trusty-security
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: mos
+ priority: 1050
+ section: main restricted
+ suite: mos7.0
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/x86_64
+ - name: mos-updates
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-updates
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-security
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-security
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-holdback
+ priority: 1100
+ section: main restricted
+ suite: mos7.0-holdback
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: Auxiliary
+ priority: 1150
+ section: main restricted
+ suite: auxiliary
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/auxiliary
+ storage:
+ ephemeral_ceph:
+ description: Configures Nova to store ephemeral volumes in RBD. This works best
+ if Ceph is enabled for volumes and images, too. Enables live migration of
+ all types of Ceph backed VMs (without this option, live migration will only
+ work with VMs launched from Cinder volumes).
+ label: Ceph RBD for ephemeral volumes (Nova)
+ type: checkbox
+ value: true
+ weight: 75
+ images_ceph:
+ description: Configures Glance to use the Ceph RBD backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: Ceph RBD for images (Glance)
+ restrictions:
+ - settings:storage.images_vcenter.value == true: Only one Glance backend could
+ be selected.
+ type: checkbox
+ value: true
+ weight: 30
+ images_vcenter:
+ description: Configures Glance to use the vCenter/ESXi backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: VMWare vCenter/ESXi datastore for images (Glance)
+ restrictions:
+ - action: hide
+ condition: settings:common.use_vcenter.value != true
+ - condition: settings:storage.images_ceph.value == true
+ message: Only one Glance backend could be selected.
+ type: checkbox
+ value: false
+ weight: 35
+ iser:
+ description: 'High performance block storage: Cinder volumes over iSER protocol
+ (iSCSI over RDMA). This feature requires SR-IOV capabilities in the NIC, and
+ will use a dedicated virtual function for the storage network.'
+ label: iSER protocol for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value != true or settings:common.libvirt_type.value
+ != 'kvm'
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ type: checkbox
+ value: false
+ weight: 11
+ metadata:
+ label: Storage
+ weight: 60
+ objects_ceph:
+ description: Configures RadosGW front end for Ceph RBD. This exposes S3 and
+ Swift API Interfaces. If enabled, this option will prevent Swift from installing.
+ label: Ceph RadosGW for objects (Swift API)
+ restrictions:
+ - settings:storage.images_ceph.value == false
+ type: checkbox
+ value: false
+ weight: 80
+ osd_pool_size:
+ description: Configures the default number of object replicas in Ceph. This
+ number must be equal to or lower than the number of deployed 'Storage - Ceph
+ OSD' nodes.
+ label: Ceph object replication factor
+ regex:
+ error: Invalid number
+ source: ^[1-9]\d*$
+ type: text
+ value: '2'
+ weight: 85
+ volumes_ceph:
+ description: Configures Cinder to store volumes in Ceph RBD images.
+ label: Ceph RBD for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value == true
+ type: checkbox
+ value: true
+ weight: 20
+ volumes_lvm:
+ description: It is recommended to have at least one Storage - Cinder LVM node.
+ label: Cinder LVM over iSCSI for volumes
+ restrictions:
+ - settings:storage.volumes_ceph.value == true
+ type: checkbox
+ value: false
+ weight: 10
+ syslog:
+ metadata:
+ label: Syslog
+ weight: 50
+ syslog_port:
+ description: Remote syslog port
+ label: Port
+ regex:
+ error: Invalid syslog port
+ source: ^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
+ type: text
+ value: '514'
+ weight: 20
+ syslog_server:
+ description: Remote syslog hostname
+ label: Hostname
+ type: text
+ value: ''
+ weight: 10
+ syslog_transport:
+ label: Syslog transport protocol
+ type: radio
+ value: tcp
+ values:
+ - data: udp
+ description: ''
+ label: UDP
+ - data: tcp
+ description: ''
+ label: TCP
+ weight: 30
+ workloads_collector:
+ enabled:
+ type: hidden
+ value: true
+ metadata:
+ label: Workloads Collector User
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 10
+ password:
+ type: password
+ value: sbfn1c8b
+ tenant:
+ type: text
+ value: services
+ user:
+ type: text
+ value: fuel_stats_user \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dha.yaml b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dha.yaml
new file mode 100644
index 000000000..724d6d833
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/dha.yaml
@@ -0,0 +1,49 @@
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version:
+created:
+comment: Config for LF POD1
+
+# Adapter to use for this definition
+adapter: ipmi
+
+# Node list.
+# Mandatory property is id, all other properties are adapter specific.
+
+nodes:
+- id: 1
+ pxeMac: 00:25:b5:b0:00:ef
+ ipmiIp: 172.30.8.69
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 2
+ pxeMac: 00:25:b5:b0:00:cf
+ ipmiIp: 172.30.8.78
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 3
+ pxeMac: 00:25:b5:b0:00:8f
+ ipmiIp: 172.30.8.68
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 4
+ pxeMac: 00:25:b5:b0:00:6f
+ ipmiIp: 172.30.8.77
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 5
+ pxeMac: 00:25:b5:b0:00:4f
+ ipmiIp: 172.30.8.67
+ ipmiUser: admin
+ ipmiPass: octopus
+# Adding the Fuel node as node id 6 which may not be correct - please
+# adjust as needed.
+- id: 6
+ libvirtName: fuel-opnfv
+ libvirtTemplate: templates/hardware_environment/vms/fuel.xml
+ isFuel: yes
+ username: root
+ password: r00tme
+
+disks:
+ fuel: 50G \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/plugins_conf/.gitkeep b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/plugins_conf/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod1/plugins_conf/.gitkeep
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dea.yaml b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dea.yaml
new file mode 100644
index 000000000..64362793f
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dea.yaml
@@ -0,0 +1,898 @@
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version:
+created:
+comment: Config for LF POD2 - HA deployment with Ceph
+environment:
+ name: opnfv
+ mode: ha
+ net_segment_type: tun
+wanted_release: Kilo on Ubuntu 14.04
+nodes:
+- id: 1
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 2
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 3
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 4
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 5
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+fuel:
+ ADMIN_NETWORK:
+ cidr: 10.20.0.0/24
+ dhcp_gateway: 10.20.0.2
+ dhcp_pool_end: 10.20.0.254
+ dhcp_pool_start: 10.20.0.3
+ ipaddress: 10.20.0.2
+ netmask: 255.255.0.0
+ DNS_DOMAIN: domain.tld
+ DNS_SEARCH: domain.tld
+ DNS_UPSTREAM: 8.8.8.8
+ FUEL_ACCESS:
+ password: admin
+ user: admin
+ HOSTNAME: opnfv
+ NTP1: 0.pool.ntp.org
+ NTP2: 1.pool.ntp.org
+ NTP3: 2.pool.ntp.org
+interfaces_1:
+ eth0:
+ - fuelweb_admin
+ - management
+ - storage
+ - private
+ eth2:
+ - public
+transformations_1:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-ex
+ - action: add-br
+ name: br-floating
+ provider: ovs
+ - action: add-patch
+ bridges:
+ - br-floating
+ - br-ex
+ mtu: 65000
+ provider: ovs
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth0.300
+ - action: add-port
+ bridge: br-storage
+ name: eth0.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth0.302
+ - action: add-port
+ bridge: br-ex
+ name: eth2
+transformations_2:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth0.300
+ - action: add-port
+ bridge: br-storage
+ name: eth0.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth0.302
+network:
+ management_vip: 192.168.0.2
+ management_vrouter_vip: 192.168.0.1
+ networking_parameters:
+ base_mac: fa:16:3e:00:00:00
+ configuration_template: null
+ dns_nameservers:
+ - 8.8.4.4
+ - 8.8.8.8
+ floating_ranges:
+ - - 172.30.10.160
+ - 172.30.10.254
+ gre_id_range:
+ - 2
+ - 65535
+ internal_cidr: 192.168.111.0/24
+ internal_gateway: 192.168.111.1
+ net_l23_provider: ovs
+ segmentation_type: tun
+ vlan_range:
+ - 1000
+ - 1030
+ networks:
+ - cidr: 172.30.10.0/24
+ gateway: 172.30.10.1
+ ip_ranges:
+ - - 172.30.10.64
+ - 172.30.10.159
+ meta:
+ cidr: 172.16.0.0/24
+ configurable: true
+ floating_range_var: floating_ranges
+ ip_range:
+ - 172.16.0.2
+ - 172.16.0.126
+ map_priority: 1
+ name: public
+ notation: ip_ranges
+ render_addr_mask: public
+ render_type: null
+ use_gateway: true
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: null
+ name: public
+ vlan_start: null
+ - cidr: 192.168.0.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.0.1
+ - 192.168.0.254
+ meta:
+ cidr: 192.168.0.0/24
+ configurable: true
+ map_priority: 2
+ name: management
+ notation: cidr
+ render_addr_mask: internal
+ render_type: cidr
+ use_gateway: false
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: 101
+ name: management
+ vlan_start: 300
+ - cidr: 192.168.1.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.1.1
+ - 192.168.1.254
+ meta:
+ cidr: 192.168.1.0/24
+ configurable: true
+ map_priority: 2
+ name: storage
+ notation: cidr
+ render_addr_mask: storage
+ render_type: cidr
+ use_gateway: false
+ vlan_start: 102
+ name: storage
+ vlan_start: 301
+ - cidr: 192.168.2.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.2.1
+ - 192.168.2.254
+ meta:
+ cidr: 192.168.2.0/24
+ configurable: true
+ map_priority: 2
+ name: private
+ notation: cidr
+ render_addr_mask: null
+ render_type: cidr
+ seg_type: tun
+ use_gateway: false
+ vlan_start: 103
+ name: private
+ vlan_start: 302
+ - cidr: 10.20.0.0/16
+ gateway: 10.20.0.2
+ ip_ranges:
+ - - 10.20.0.3
+ - 10.20.0.254
+ meta:
+ configurable: false
+ map_priority: 0
+ notation: ip_ranges
+ render_addr_mask: null
+ render_type: null
+ unmovable: true
+ use_gateway: true
+ name: fuelweb_admin
+ vlan_start: null
+ public_vip: 172.30.10.64
+ public_vrouter_vip: 172.30.10.65
+ vips:
+ management:
+ ipaddr: 192.168.0.2
+ namespace: haproxy
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ public:
+ ipaddr: 172.30.10.64
+ namespace: haproxy
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter:
+ ipaddr: 192.168.0.1
+ namespace: vrouter
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter_pub:
+ ipaddr: 172.30.10.65
+ namespace: vrouter
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+settings:
+ editable:
+ access:
+ email:
+ description: Email address for Administrator
+ label: Email
+ regex:
+ error: Invalid email
+ source: ^\S+@\S+$
+ type: text
+ value: admin@localhost
+ weight: 40
+ metadata:
+ label: Access
+ weight: 10
+ password:
+ description: Password for Administrator
+ label: Password
+ regex:
+ error: Empty password
+ source: \S
+ type: password
+ value: admin
+ weight: 20
+ tenant:
+ description: Tenant (project) name for Administrator
+ label: Tenant
+ regex:
+ error: Invalid tenant name
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 30
+ user:
+ description: Username for Administrator
+ label: Username
+ regex:
+ error: Invalid username
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 10
+ additional_components:
+ ceilometer:
+ description: If selected, Ceilometer component will be installed
+ label: Install Ceilometer
+ type: checkbox
+ value: false
+ weight: 40
+ heat:
+ description: ''
+ label: ''
+ type: hidden
+ value: true
+ weight: 30
+ metadata:
+ label: Additional Components
+ weight: 20
+ mongo:
+ description: If selected, You can use external Mongo DB as ceilometer backend
+ label: Use external Mongo DB
+ restrictions:
+ - settings:additional_components.ceilometer.value == false
+ type: checkbox
+ value: false
+ weight: 40
+ murano:
+ description: If selected, Murano component will be installed
+ label: Install Murano
+ type: checkbox
+ value: false
+ weight: 20
+ sahara:
+ description: If selected, Sahara component will be installed
+ label: Install Sahara
+ type: checkbox
+ value: false
+ weight: 10
+ common:
+ auth_key:
+ description: Public key(s) to include in authorized_keys on deployed nodes
+ label: Public Key
+ type: textarea
+ value: ''
+ weight: 70
+ auto_assign_floating_ip:
+ description: If selected, OpenStack will automatically assign a floating IP
+ to a new instance
+ label: Auto assign floating IP
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider == 'neutron'
+ type: checkbox
+ value: false
+ weight: 40
+ debug:
+ description: Debug logging mode provides more information, but requires more
+ disk space.
+ label: OpenStack debug logging
+ type: checkbox
+ value: false
+ weight: 20
+ libvirt_type:
+ label: Hypervisor type
+ type: radio
+ value: kvm
+ values:
+ - data: kvm
+ description: Choose this type of hypervisor if you run OpenStack on hardware
+ label: KVM
+ - data: qemu
+ description: Choose this type of hypervisor if you run OpenStack on virtual
+ hosts.
+ label: QEMU
+ weight: 30
+ metadata:
+ label: Common
+ weight: 30
+ nova_quota:
+ description: Quotas are used to limit CPU and memory usage for tenants. Enabling
+ quotas will increase load on the Nova database.
+ label: Nova quotas
+ type: checkbox
+ value: false
+ weight: 25
+ puppet_debug:
+ description: Debug puppet logging mode provides more information, but requires
+ more disk space.
+ label: Puppet debug logging
+ type: checkbox
+ value: true
+ weight: 20
+ resume_guests_state_on_host_boot:
+ description: Whether to resume previous guests state when the host reboots.
+ If enabled, this option causes guests assigned to the host to resume their
+ previous state. If the guest was running a restart will be attempted when
+ nova-compute starts. If the guest was not running previously, a restart will
+ not be attempted.
+ label: Resume guests state on host boot
+ type: checkbox
+ value: true
+ weight: 60
+ use_cow_images:
+ description: For most cases you will want qcow format. If it's disabled, raw
+ image format will be used to run VMs. OpenStack with raw format currently
+ does not support snapshotting.
+ label: Use qcow format for images
+ type: checkbox
+ value: true
+ weight: 50
+ use_vcenter:
+ restrictions:
+ - condition: cluster:net_provider == 'nova_network'
+ type: hidden
+ value: false
+ weight: 30
+ corosync:
+ group:
+ description: ''
+ label: Group
+ type: text
+ value: 226.94.1.1
+ weight: 10
+ metadata:
+ label: Corosync
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 50
+ port:
+ description: ''
+ label: Port
+ type: text
+ value: '12000'
+ weight: 20
+ verified:
+ description: Set True only if multicast is configured correctly on router.
+ label: Need to pass network verification.
+ type: checkbox
+ value: false
+ weight: 10
+ external_dns:
+ dns_list:
+ description: List of upstream DNS servers, separated by comma
+ label: DNS list
+ regex:
+ error: Invalid IP address list
+ source: ^\*$|^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\s*,\s*(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3})*$
+ type: text
+ value: 8.8.8.8, 8.8.4.4
+ weight: 10
+ metadata:
+ label: Host OS DNS Servers
+ weight: 90
+ external_mongo:
+ hosts_ip:
+ description: IP Addresses of MongoDB. Use comma to split IPs
+ label: MongoDB hosts IP
+ regex:
+ error: Invalid hosts ip sequence
+ source: ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?),)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+ type: text
+ value: ''
+ weight: 30
+ metadata:
+ label: External MongoDB
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.mongo.value == false
+ message: Ceilometer and MongoDB are not enabled on the Additional Components
+ section
+ weight: 20
+ mongo_db_name:
+ description: Mongo database name
+ label: Database name
+ regex:
+ error: Invalid database name
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ mongo_password:
+ description: Mongo database password
+ label: Password
+ regex:
+ error: Password contains spaces
+ source: ^\S*$
+ type: password
+ value: ceilometer
+ weight: 30
+ mongo_replset:
+ description: Name for Mongo replication set
+ label: Replset
+ type: text
+ value: ''
+ weight: 30
+ mongo_user:
+ description: Mongo database username
+ label: Username
+ regex:
+ error: Empty username
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ external_ntp:
+ metadata:
+ label: Host OS NTP Servers
+ weight: 100
+ ntp_list:
+ description: List of upstream NTP servers, separated by comma
+ label: NTP server list
+ regex:
+ error: Invalid NTP server list
+ source: ^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(?:\.\d{1,3}){3})\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(\.\d{1,3}){3})\s*)*$
+ type: text
+ value: 0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org
+ weight: 10
+ kernel_params:
+ kernel:
+ description: Default kernel parameters
+ label: Initial parameters
+ type: text
+ value: console=tty0 net.ifnames=0 biosdevname=0 rootdelay=90 nomodeset
+ weight: 45
+ metadata:
+ label: Kernel parameters
+ weight: 40
+ murano_settings:
+ metadata:
+ label: Murano Settings
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.murano.value == false
+ message: Murano is not enabled on the Additional Components section
+ weight: 20
+ murano_repo_url:
+ description: ''
+ label: Murano Repository URL
+ type: text
+ value: http://storage.apps.openstack.org/
+ weight: 10
+ neutron_advanced_configuration:
+ metadata:
+ label: Neutron Advanced Configuration
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 45
+ neutron_dvr:
+ description: Enable Distributed Virtual Routers in Neutron
+ label: Neutron DVR
+ restrictions:
+ - ? networking_parameters:segmentation_type != 'vlan' and settings:neutron_advanced_configuration.neutron_l2_pop.value
+ == false
+ : DVR requires L2 population to be enabled.
+ type: checkbox
+ value: false
+ weight: 20
+ neutron_l2_pop:
+ description: Enable L2 population mechanism in Neutron
+ label: Neutron L2 population
+ restrictions:
+ - action: hide
+ condition: networking_parameters:segmentation_type == 'vlan'
+ type: checkbox
+ value: false
+ weight: 10
+ neutron_mellanox:
+ metadata:
+ enabled: true
+ label: Mellanox Neutron components
+ restrictions:
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ toggleable: false
+ weight: 50
+ plugin:
+ label: Mellanox drivers and SR-IOV plugin
+ type: radio
+ value: disabled
+ values:
+ - data: disabled
+ description: If selected, Mellanox drivers, Neutron and Cinder plugin will
+ not be installed.
+ label: Mellanox drivers and plugins disabled
+ restrictions:
+ - settings:storage.iser.value == true
+ - data: drivers_only
+ description: If selected, Mellanox Ethernet drivers will be installed to support
+ networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.
+ label: Install only Mellanox drivers
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm'
+ - data: ethernet
+ description: If selected, both Mellanox Ethernet drivers and Mellanox network
+ acceleration (Neutron) plugin will be installed.
+ label: Install Mellanox drivers and SR-IOV plugin
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider
+ == 'neutron' and networking_parameters:segmentation_type == 'vlan')
+ weight: 60
+ vf_num:
+ description: Note that one virtual function will be reserved to the storage
+ network, in case of choosing iSER.
+ label: Number of virtual NICs
+ restrictions:
+ - settings:neutron_mellanox.plugin.value != 'ethernet'
+ type: text
+ value: '16'
+ weight: 70
+ provision:
+ metadata:
+ label: Provision
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 80
+ method:
+ type: hidden
+ value: image
+ public_network_assignment:
+ assign_to_all_nodes:
+ description: When disabled, public network will be assigned to controllers only
+ label: Assign public network to all nodes
+ type: checkbox
+ value: false
+ weight: 10
+ metadata:
+ label: Public network assignment
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 50
+ public_ssl:
+ cert_data:
+ description: Certificate and private key data, concatenated into a single file
+ label: Certificate
+ restrictions:
+ - action: hide
+ condition: (settings:public_ssl.cert_source.value != 'user_uploaded') or (settings:public_ssl.horizon.value
+ == false and settings:public_ssl.services.value == false)
+ type: file
+ value: ''
+ weight: 40
+ cert_source:
+ description: From where we'll get certificate and private key
+ label: Select source for certificate
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: radio
+ value: self_signed
+ values:
+ - data: self_signed
+ description: Generate private key and certificate that will be signed by this
+ key
+ label: Self-signed
+ - data: user_uploaded
+ description: Use pre-generated key and certificate
+ label: I have my own keypair with certificate
+ weight: 30
+ horizon:
+ description: Secure access to Horizon enabling HTTPS instead of HTTP
+ label: HTTPS for Horizon
+ type: checkbox
+ value: false
+ weight: 10
+ hostname:
+ description: Your DNS entries should point to this name. Self-signed certificates
+ also will use this hostname
+ label: DNS hostname for public TLS endpoints
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: text
+ value: public.fuel.local
+ weight: 50
+ metadata:
+ label: Public TLS
+ weight: 110
+ services:
+ description: Enable TLS termination on HAProxy for OpenStack services
+ label: TLS for OpenStack public endpoints
+ type: checkbox
+ value: false
+ weight: 20
+ repo_setup:
+ metadata:
+ always_editable: true
+ label: Repositories
+ weight: 50
+ repos:
+ description: 'Please note: the first repository will be considered the operating
+ system mirror that will be used during node provisioning.
+
+ To create a local repository mirror on the Fuel master node, please follow
+ the instructions provided by running "fuel-createmirror --help" on the Fuel
+ master node.
+
+ Please make sure your Fuel master node has Internet access to the repository
+ before attempting to create a mirror.
+
+ For more details, please refer to the documentation (https://docs.mirantis.com/openstack/fuel/fuel-7.0/operations.html#external-ubuntu-ops).
+
+ '
+ extra_priority: null
+ type: custom_repo_configuration
+ value:
+ - name: ubuntu
+ priority: null
+ section: main universe multiverse
+ suite: trusty
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-updates
+ priority: null
+ section: main universe multiverse
+ suite: trusty-updates
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-security
+ priority: null
+ section: main universe multiverse
+ suite: trusty-security
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: mos
+ priority: 1050
+ section: main restricted
+ suite: mos7.0
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/x86_64
+ - name: mos-updates
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-updates
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-security
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-security
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-holdback
+ priority: 1100
+ section: main restricted
+ suite: mos7.0-holdback
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: Auxiliary
+ priority: 1150
+ section: main restricted
+ suite: auxiliary
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/auxiliary
+ storage:
+ ephemeral_ceph:
+ description: Configures Nova to store ephemeral volumes in RBD. This works best
+ if Ceph is enabled for volumes and images, too. Enables live migration of
+ all types of Ceph backed VMs (without this option, live migration will only
+ work with VMs launched from Cinder volumes).
+ label: Ceph RBD for ephemeral volumes (Nova)
+ type: checkbox
+ value: true
+ weight: 75
+ images_ceph:
+ description: Configures Glance to use the Ceph RBD backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: Ceph RBD for images (Glance)
+ restrictions:
+ - settings:storage.images_vcenter.value == true: Only one Glance backend could
+ be selected.
+ type: checkbox
+ value: true
+ weight: 30
+ images_vcenter:
+ description: Configures Glance to use the vCenter/ESXi backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: VMWare vCenter/ESXi datastore for images (Glance)
+ restrictions:
+ - action: hide
+ condition: settings:common.use_vcenter.value != true
+ - condition: settings:storage.images_ceph.value == true
+ message: Only one Glance backend could be selected.
+ type: checkbox
+ value: false
+ weight: 35
+ iser:
+ description: 'High performance block storage: Cinder volumes over iSER protocol
+ (iSCSI over RDMA). This feature requires SR-IOV capabilities in the NIC, and
+ will use a dedicated virtual function for the storage network.'
+ label: iSER protocol for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value != true or settings:common.libvirt_type.value
+ != 'kvm'
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ type: checkbox
+ value: false
+ weight: 11
+ metadata:
+ label: Storage
+ weight: 60
+ objects_ceph:
+ description: Configures RadosGW front end for Ceph RBD. This exposes S3 and
+ Swift API Interfaces. If enabled, this option will prevent Swift from installing.
+ label: Ceph RadosGW for objects (Swift API)
+ restrictions:
+ - settings:storage.images_ceph.value == false
+ type: checkbox
+ value: false
+ weight: 80
+ osd_pool_size:
+ description: Configures the default number of object replicas in Ceph. This
+ number must be equal to or lower than the number of deployed 'Storage - Ceph
+ OSD' nodes.
+ label: Ceph object replication factor
+ regex:
+ error: Invalid number
+ source: ^[1-9]\d*$
+ type: text
+ value: '2'
+ weight: 85
+ volumes_ceph:
+ description: Configures Cinder to store volumes in Ceph RBD images.
+ label: Ceph RBD for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value == true
+ type: checkbox
+ value: true
+ weight: 20
+ volumes_lvm:
+ description: It is recommended to have at least one Storage - Cinder LVM node.
+ label: Cinder LVM over iSCSI for volumes
+ restrictions:
+ - settings:storage.volumes_ceph.value == true
+ type: checkbox
+ value: false
+ weight: 10
+ syslog:
+ metadata:
+ label: Syslog
+ weight: 50
+ syslog_port:
+ description: Remote syslog port
+ label: Port
+ regex:
+ error: Invalid syslog port
+ source: ^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
+ type: text
+ value: '514'
+ weight: 20
+ syslog_server:
+ description: Remote syslog hostname
+ label: Hostname
+ type: text
+ value: ''
+ weight: 10
+ syslog_transport:
+ label: Syslog transport protocol
+ type: radio
+ value: tcp
+ values:
+ - data: udp
+ description: ''
+ label: UDP
+ - data: tcp
+ description: ''
+ label: TCP
+ weight: 30
+ workloads_collector:
+ enabled:
+ type: hidden
+ value: true
+ metadata:
+ label: Workloads Collector User
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 10
+ password:
+ type: password
+ value: sbfn1c8b
+ tenant:
+ type: text
+ value: services
+ user:
+ type: text
+ value: fuel_stats_user \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dha.yaml b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dha.yaml
new file mode 100644
index 000000000..cfc97094c
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/dha.yaml
@@ -0,0 +1,49 @@
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version:
+created:
+comment: Config for LF POD2 and Opendaylight
+
+# Adapter to use for this definition
+adapter: ipmi
+
+# Node list.
+# Mandatory property is id, all other properties are adapter specific.
+
+nodes:
+- id: 1
+ pxeMac: 00:25:b5:a0:00:2a
+ ipmiIp: 172.30.8.75
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 2
+ pxeMac: 00:25:b5:a0:00:3a
+ ipmiIp: 172.30.8.65
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 3
+ pxeMac: 00:25:b5:a0:00:4a
+ ipmiIp: 172.30.8.74
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 4
+ pxeMac: 00:25:b5:a0:00:5a
+ ipmiIp: 172.30.8.73
+ ipmiUser: admin
+ ipmiPass: octopus
+- id: 5
+ pxeMac: 00:25:b5:a0:00:6a
+ ipmiIp: 172.30.8.72
+ ipmiUser: admin
+ ipmiPass: octopus
+# Adding the Fuel node as node id 6 which may not be correct - please
+# adjust as needed.
+- id: 6
+ libvirtName: fuel-opnfv
+ libvirtTemplate: templates/hardware_environment/vms/fuel.xml
+ isFuel: yes
+ username: root
+ password: r00tme
+
+disks:
+ fuel: 50G \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/plugins_conf/.gitkeep b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/plugins_conf/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/linux_foundation_lab/pod2/plugins_conf/.gitkeep
diff --git a/deploy/templates/hardware_environment/conf/opnfv_box/dea.yaml b/deploy/templates/hardware_environment/conf/opnfv_box/dea.yaml
new file mode 100644
index 000000000..fa6da9c96
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/opnfv_box/dea.yaml
@@ -0,0 +1,898 @@
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version:
+created:
+comment: Config for OPNFV BOX - HA deployment with Ceph
+environment:
+ name: opnfv_box
+ mode: ha
+ net_segment_type: tun
+wanted_release: Kilo on Ubuntu 14.04
+nodes:
+- id: 1
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 2
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 3
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 4
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 5
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+fuel:
+ ADMIN_NETWORK:
+ cidr: 10.20.0.0/24
+ dhcp_gateway: 10.20.0.2
+ dhcp_pool_end: 10.20.0.254
+ dhcp_pool_start: 10.20.0.3
+ ipaddress: 10.20.0.2
+ netmask: 255.255.0.0
+ DNS_DOMAIN: domain.tld
+ DNS_SEARCH: domain.tld
+ DNS_UPSTREAM: 8.8.8.8
+ FUEL_ACCESS:
+ password: admin
+ user: admin
+ HOSTNAME: opnfv
+ NTP1: 0.pool.ntp.org
+ NTP2: 1.pool.ntp.org
+ NTP3: 2.pool.ntp.org
+interfaces_1:
+ eth0:
+ - public
+ eth1:
+ - fuelweb_admin
+ - management
+ - storage
+ - private
+transformations_1:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-ex
+ - action: add-br
+ name: br-floating
+ provider: ovs
+ - action: add-patch
+ bridges:
+ - br-floating
+ - br-ex
+ mtu: 65000
+ provider: ovs
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth1.300
+ - action: add-port
+ bridge: br-storage
+ name: eth1.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth1.302
+ - action: add-port
+ bridge: br-ex
+ name: eth0
+transformations_2:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth1.300
+ - action: add-port
+ bridge: br-storage
+ name: eth1.301
+ - action: add-port
+ bridge: br-mesh
+ name: eth1.302
+network:
+ management_vip: 192.168.0.2
+ management_vrouter_vip: 192.168.0.1
+ networking_parameters:
+ base_mac: fa:16:3e:00:00:00
+ configuration_template: null
+ dns_nameservers:
+ - 8.8.4.4
+ - 8.8.8.8
+ floating_ranges:
+ - - 172.30.10.83
+ - 172.30.10.92
+ gre_id_range:
+ - 2
+ - 65535
+ internal_cidr: 192.168.111.0/24
+ internal_gateway: 192.168.111.1
+ net_l23_provider: ovs
+ segmentation_type: tun
+ vlan_range:
+ - 1000
+ - 1030
+ networks:
+ - cidr: 172.30.10.0/24
+ gateway: 172.30.10.1
+ ip_ranges:
+ - - 172.30.10.73
+ - 172.30.10.82
+ meta:
+ cidr: 172.16.0.0/24
+ configurable: true
+ floating_range_var: floating_ranges
+ ip_range:
+ - 172.16.0.2
+ - 172.16.0.126
+ map_priority: 1
+ name: public
+ notation: ip_ranges
+ render_addr_mask: public
+ render_type: null
+ use_gateway: true
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: null
+ name: public
+ vlan_start: null
+ - cidr: 192.168.0.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.0.1
+ - 192.168.0.254
+ meta:
+ cidr: 192.168.0.0/24
+ configurable: true
+ map_priority: 2
+ name: management
+ notation: cidr
+ render_addr_mask: internal
+ render_type: cidr
+ use_gateway: false
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: 101
+ name: management
+ vlan_start: 300
+ - cidr: 192.168.1.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.1.1
+ - 192.168.1.254
+ meta:
+ cidr: 192.168.1.0/24
+ configurable: true
+ map_priority: 2
+ name: storage
+ notation: cidr
+ render_addr_mask: storage
+ render_type: cidr
+ use_gateway: false
+ vlan_start: 102
+ name: storage
+ vlan_start: 301
+ - cidr: 192.168.2.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.2.1
+ - 192.168.2.254
+ meta:
+ cidr: 192.168.2.0/24
+ configurable: true
+ map_priority: 2
+ name: private
+ notation: cidr
+ render_addr_mask: null
+ render_type: cidr
+ seg_type: tun
+ use_gateway: false
+ vlan_start: 103
+ name: private
+ vlan_start: 302
+ - cidr: 10.20.0.0/16
+ gateway: 10.20.0.2
+ ip_ranges:
+ - - 10.20.0.3
+ - 10.20.0.254
+ meta:
+ configurable: false
+ map_priority: 0
+ notation: ip_ranges
+ render_addr_mask: null
+ render_type: null
+ unmovable: true
+ use_gateway: true
+ name: fuelweb_admin
+ vlan_start: null
+ public_vip: 172.30.10.3
+ public_vrouter_vip: 172.30.10.2
+ vips:
+ management:
+ ipaddr: 192.168.0.2
+ namespace: haproxy
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ public:
+ ipaddr: 172.30.10.3
+ namespace: haproxy
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter:
+ ipaddr: 192.168.0.1
+ namespace: vrouter
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter_pub:
+ ipaddr: 172.30.10.2
+ namespace: vrouter
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+settings:
+ editable:
+ access:
+ email:
+ description: Email address for Administrator
+ label: Email
+ regex:
+ error: Invalid email
+ source: ^\S+@\S+$
+ type: text
+ value: admin@localhost
+ weight: 40
+ metadata:
+ label: Access
+ weight: 10
+ password:
+ description: Password for Administrator
+ label: Password
+ regex:
+ error: Empty password
+ source: \S
+ type: password
+ value: admin
+ weight: 20
+ tenant:
+ description: Tenant (project) name for Administrator
+ label: Tenant
+ regex:
+ error: Invalid tenant name
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 30
+ user:
+ description: Username for Administrator
+ label: Username
+ regex:
+ error: Invalid username
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 10
+ additional_components:
+ ceilometer:
+ description: If selected, Ceilometer component will be installed
+ label: Install Ceilometer
+ type: checkbox
+ value: false
+ weight: 40
+ heat:
+ description: ''
+ label: ''
+ type: hidden
+ value: true
+ weight: 30
+ metadata:
+ label: Additional Components
+ weight: 20
+ mongo:
+ description: If selected, You can use external Mongo DB as ceilometer backend
+ label: Use external Mongo DB
+ restrictions:
+ - settings:additional_components.ceilometer.value == false
+ type: checkbox
+ value: false
+ weight: 40
+ murano:
+ description: If selected, Murano component will be installed
+ label: Install Murano
+ type: checkbox
+ value: false
+ weight: 20
+ sahara:
+ description: If selected, Sahara component will be installed
+ label: Install Sahara
+ type: checkbox
+ value: false
+ weight: 10
+ common:
+ auth_key:
+ description: Public key(s) to include in authorized_keys on deployed nodes
+ label: Public Key
+ type: textarea
+ value: ''
+ weight: 70
+ auto_assign_floating_ip:
+ description: If selected, OpenStack will automatically assign a floating IP
+ to a new instance
+ label: Auto assign floating IP
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider == 'neutron'
+ type: checkbox
+ value: false
+ weight: 40
+ debug:
+ description: Debug logging mode provides more information, but requires more
+ disk space.
+ label: OpenStack debug logging
+ type: checkbox
+ value: false
+ weight: 20
+ libvirt_type:
+ label: Hypervisor type
+ type: radio
+ value: kvm
+ values:
+ - data: kvm
+ description: Choose this type of hypervisor if you run OpenStack on hardware
+ label: KVM
+ - data: qemu
+ description: Choose this type of hypervisor if you run OpenStack on virtual
+ hosts.
+ label: QEMU
+ weight: 30
+ metadata:
+ label: Common
+ weight: 30
+ nova_quota:
+ description: Quotas are used to limit CPU and memory usage for tenants. Enabling
+ quotas will increase load on the Nova database.
+ label: Nova quotas
+ type: checkbox
+ value: false
+ weight: 25
+ puppet_debug:
+ description: Debug puppet logging mode provides more information, but requires
+ more disk space.
+ label: Puppet debug logging
+ type: checkbox
+ value: true
+ weight: 20
+ resume_guests_state_on_host_boot:
+ description: Whether to resume previous guests state when the host reboots.
+ If enabled, this option causes guests assigned to the host to resume their
+ previous state. If the guest was running a restart will be attempted when
+ nova-compute starts. If the guest was not running previously, a restart will
+ not be attempted.
+ label: Resume guests state on host boot
+ type: checkbox
+ value: true
+ weight: 60
+ use_cow_images:
+ description: For most cases you will want qcow format. If it's disabled, raw
+ image format will be used to run VMs. OpenStack with raw format currently
+ does not support snapshotting.
+ label: Use qcow format for images
+ type: checkbox
+ value: true
+ weight: 50
+ use_vcenter:
+ restrictions:
+ - condition: cluster:net_provider == 'nova_network'
+ type: hidden
+ value: false
+ weight: 30
+ corosync:
+ group:
+ description: ''
+ label: Group
+ type: text
+ value: 226.94.1.1
+ weight: 10
+ metadata:
+ label: Corosync
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 50
+ port:
+ description: ''
+ label: Port
+ type: text
+ value: '12000'
+ weight: 20
+ verified:
+ description: Set True only if multicast is configured correctly on router.
+ label: Need to pass network verification.
+ type: checkbox
+ value: false
+ weight: 10
+ external_dns:
+ dns_list:
+ description: List of upstream DNS servers, separated by comma
+ label: DNS list
+ regex:
+ error: Invalid IP address list
+ source: ^\*$|^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\s*,\s*(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3})*$
+ type: text
+ value: 8.8.8.8, 8.8.4.4
+ weight: 10
+ metadata:
+ label: Host OS DNS Servers
+ weight: 90
+ external_mongo:
+ hosts_ip:
+ description: IP Addresses of MongoDB. Use comma to split IPs
+ label: MongoDB hosts IP
+ regex:
+ error: Invalid hosts ip sequence
+ source: ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?),)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+ type: text
+ value: ''
+ weight: 30
+ metadata:
+ label: External MongoDB
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.mongo.value == false
+ message: Ceilometer and MongoDB are not enabled on the Additional Components
+ section
+ weight: 20
+ mongo_db_name:
+ description: Mongo database name
+ label: Database name
+ regex:
+ error: Invalid database name
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ mongo_password:
+ description: Mongo database password
+ label: Password
+ regex:
+ error: Password contains spaces
+ source: ^\S*$
+ type: password
+ value: ceilometer
+ weight: 30
+ mongo_replset:
+ description: Name for Mongo replication set
+ label: Replset
+ type: text
+ value: ''
+ weight: 30
+ mongo_user:
+ description: Mongo database username
+ label: Username
+ regex:
+ error: Empty username
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ external_ntp:
+ metadata:
+ label: Host OS NTP Servers
+ weight: 100
+ ntp_list:
+ description: List of upstream NTP servers, separated by comma
+ label: NTP server list
+ regex:
+ error: Invalid NTP server list
+ source: ^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(?:\.\d{1,3}){3})\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(\.\d{1,3}){3})\s*)*$
+ type: text
+ value: 0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org
+ weight: 10
+ kernel_params:
+ kernel:
+ description: Default kernel parameters
+ label: Initial parameters
+ type: text
+ value: console=tty0 net.ifnames=0 biosdevname=0 rootdelay=90 nomodeset
+ weight: 45
+ metadata:
+ label: Kernel parameters
+ weight: 40
+ murano_settings:
+ metadata:
+ label: Murano Settings
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.murano.value == false
+ message: Murano is not enabled on the Additional Components section
+ weight: 20
+ murano_repo_url:
+ description: ''
+ label: Murano Repository URL
+ type: text
+ value: http://storage.apps.openstack.org/
+ weight: 10
+ neutron_advanced_configuration:
+ metadata:
+ label: Neutron Advanced Configuration
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 45
+ neutron_dvr:
+ description: Enable Distributed Virtual Routers in Neutron
+ label: Neutron DVR
+ restrictions:
+ - ? networking_parameters:segmentation_type != 'vlan' and settings:neutron_advanced_configuration.neutron_l2_pop.value
+ == false
+ : DVR requires L2 population to be enabled.
+ type: checkbox
+ value: false
+ weight: 20
+ neutron_l2_pop:
+ description: Enable L2 population mechanism in Neutron
+ label: Neutron L2 population
+ restrictions:
+ - action: hide
+ condition: networking_parameters:segmentation_type == 'vlan'
+ type: checkbox
+ value: false
+ weight: 10
+ neutron_mellanox:
+ metadata:
+ enabled: true
+ label: Mellanox Neutron components
+ restrictions:
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ toggleable: false
+ weight: 50
+ plugin:
+ label: Mellanox drivers and SR-IOV plugin
+ type: radio
+ value: disabled
+ values:
+ - data: disabled
+ description: If selected, Mellanox drivers, Neutron and Cinder plugin will
+ not be installed.
+ label: Mellanox drivers and plugins disabled
+ restrictions:
+ - settings:storage.iser.value == true
+ - data: drivers_only
+ description: If selected, Mellanox Ethernet drivers will be installed to support
+ networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.
+ label: Install only Mellanox drivers
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm'
+ - data: ethernet
+ description: If selected, both Mellanox Ethernet drivers and Mellanox network
+ acceleration (Neutron) plugin will be installed.
+ label: Install Mellanox drivers and SR-IOV plugin
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider
+ == 'neutron' and networking_parameters:segmentation_type == 'vlan')
+ weight: 60
+ vf_num:
+ description: Note that one virtual function will be reserved to the storage
+ network, in case of choosing iSER.
+ label: Number of virtual NICs
+ restrictions:
+ - settings:neutron_mellanox.plugin.value != 'ethernet'
+ type: text
+ value: '16'
+ weight: 70
+ provision:
+ metadata:
+ label: Provision
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 80
+ method:
+ type: hidden
+ value: image
+ public_network_assignment:
+ assign_to_all_nodes:
+ description: When disabled, public network will be assigned to controllers only
+ label: Assign public network to all nodes
+ type: checkbox
+ value: false
+ weight: 10
+ metadata:
+ label: Public network assignment
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 50
+ public_ssl:
+ cert_data:
+ description: Certificate and private key data, concatenated into a single file
+ label: Certificate
+ restrictions:
+ - action: hide
+ condition: (settings:public_ssl.cert_source.value != 'user_uploaded') or (settings:public_ssl.horizon.value
+ == false and settings:public_ssl.services.value == false)
+ type: file
+ value: ''
+ weight: 40
+ cert_source:
+ description: From where we'll get certificate and private key
+ label: Select source for certificate
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: radio
+ value: self_signed
+ values:
+ - data: self_signed
+ description: Generate private key and certificate that will be signed by this
+ key
+ label: Self-signed
+ - data: user_uploaded
+ description: Use pre-generated key and certificate
+ label: I have my own keypair with certificate
+ weight: 30
+ horizon:
+ description: Secure access to Horizon enabling HTTPS instead of HTTP
+ label: HTTPS for Horizon
+ type: checkbox
+ value: false
+ weight: 10
+ hostname:
+ description: Your DNS entries should point to this name. Self-signed certificates
+ also will use this hostname
+ label: DNS hostname for public TLS endpoints
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: text
+ value: public.fuel.local
+ weight: 50
+ metadata:
+ label: Public TLS
+ weight: 110
+ services:
+ description: Enable TLS termination on HAProxy for OpenStack services
+ label: TLS for OpenStack public endpoints
+ type: checkbox
+ value: false
+ weight: 20
+ repo_setup:
+ metadata:
+ always_editable: true
+ label: Repositories
+ weight: 50
+ repos:
+ description: 'Please note: the first repository will be considered the operating
+ system mirror that will be used during node provisioning.
+
+ To create a local repository mirror on the Fuel master node, please follow
+ the instructions provided by running "fuel-createmirror --help" on the Fuel
+ master node.
+
+ Please make sure your Fuel master node has Internet access to the repository
+ before attempting to create a mirror.
+
+ For more details, please refer to the documentation (https://docs.mirantis.com/openstack/fuel/fuel-7.0/operations.html#external-ubuntu-ops).
+
+ '
+ extra_priority: null
+ type: custom_repo_configuration
+ value:
+ - name: ubuntu
+ priority: null
+ section: main universe multiverse
+ suite: trusty
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-updates
+ priority: null
+ section: main universe multiverse
+ suite: trusty-updates
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-security
+ priority: null
+ section: main universe multiverse
+ suite: trusty-security
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: mos
+ priority: 1050
+ section: main restricted
+ suite: mos7.0
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/x86_64
+ - name: mos-updates
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-updates
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-security
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-security
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-holdback
+ priority: 1100
+ section: main restricted
+ suite: mos7.0-holdback
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: Auxiliary
+ priority: 1150
+ section: main restricted
+ suite: auxiliary
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/auxiliary
+ storage:
+ ephemeral_ceph:
+ description: Configures Nova to store ephemeral volumes in RBD. This works best
+ if Ceph is enabled for volumes and images, too. Enables live migration of
+ all types of Ceph backed VMs (without this option, live migration will only
+ work with VMs launched from Cinder volumes).
+ label: Ceph RBD for ephemeral volumes (Nova)
+ type: checkbox
+ value: true
+ weight: 75
+ images_ceph:
+ description: Configures Glance to use the Ceph RBD backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: Ceph RBD for images (Glance)
+ restrictions:
+ - settings:storage.images_vcenter.value == true: Only one Glance backend could
+ be selected.
+ type: checkbox
+ value: true
+ weight: 30
+ images_vcenter:
+ description: Configures Glance to use the vCenter/ESXi backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: VMWare vCenter/ESXi datastore for images (Glance)
+ restrictions:
+ - action: hide
+ condition: settings:common.use_vcenter.value != true
+ - condition: settings:storage.images_ceph.value == true
+ message: Only one Glance backend could be selected.
+ type: checkbox
+ value: false
+ weight: 35
+ iser:
+ description: 'High performance block storage: Cinder volumes over iSER protocol
+ (iSCSI over RDMA). This feature requires SR-IOV capabilities in the NIC, and
+ will use a dedicated virtual function for the storage network.'
+ label: iSER protocol for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value != true or settings:common.libvirt_type.value
+ != 'kvm'
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ type: checkbox
+ value: false
+ weight: 11
+ metadata:
+ label: Storage
+ weight: 60
+ objects_ceph:
+ description: Configures RadosGW front end for Ceph RBD. This exposes S3 and
+ Swift API Interfaces. If enabled, this option will prevent Swift from installing.
+ label: Ceph RadosGW for objects (Swift API)
+ restrictions:
+ - settings:storage.images_ceph.value == false
+ type: checkbox
+ value: false
+ weight: 80
+ osd_pool_size:
+ description: Configures the default number of object replicas in Ceph. This
+ number must be equal to or lower than the number of deployed 'Storage - Ceph
+ OSD' nodes.
+ label: Ceph object replication factor
+ regex:
+ error: Invalid number
+ source: ^[1-9]\d*$
+ type: text
+ value: '2'
+ weight: 85
+ volumes_ceph:
+ description: Configures Cinder to store volumes in Ceph RBD images.
+ label: Ceph RBD for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value == true
+ type: checkbox
+ value: true
+ weight: 20
+ volumes_lvm:
+ description: It is recommended to have at least one Storage - Cinder LVM node.
+ label: Cinder LVM over iSCSI for volumes
+ restrictions:
+ - settings:storage.volumes_ceph.value == true
+ type: checkbox
+ value: false
+ weight: 10
+ syslog:
+ metadata:
+ label: Syslog
+ weight: 50
+ syslog_port:
+ description: Remote syslog port
+ label: Port
+ regex:
+ error: Invalid syslog port
+ source: ^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
+ type: text
+ value: '514'
+ weight: 20
+ syslog_server:
+ description: Remote syslog hostname
+ label: Hostname
+ type: text
+ value: ''
+ weight: 10
+ syslog_transport:
+ label: Syslog transport protocol
+ type: radio
+ value: tcp
+ values:
+ - data: udp
+ description: ''
+ label: UDP
+ - data: tcp
+ description: ''
+ label: TCP
+ weight: 30
+ workloads_collector:
+ enabled:
+ type: hidden
+ value: true
+ metadata:
+ label: Workloads Collector User
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 10
+ password:
+ type: password
+ value: sbfn1c8b
+ tenant:
+ type: text
+ value: services
+ user:
+ type: text
+ value: fuel_stats_user \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml b/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml
new file mode 100644
index 000000000..b127ac919
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml
@@ -0,0 +1,49 @@
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version:
+created:
+comment: Config for OPNFV BOX
+
+# Adapter to use for this definition
+adapter: amt
+
+# Node list.
+# Mandatory property is id, all other properties are adapter specific.
+
+nodes:
+- id: 1
+ pxeMac: b8:ae:ed:76:4d:a4
+ amtIp: <amt_ip>
+ amtUser: <username>
+ amtPass: <password>
+- id: 2
+ pxeMac: b8:ae:ed:76:4d:94
+ amtIp: <amt_ip>
+ amtUser: <username>
+ amtPass: <password>
+- id: 3
+ pxeMac: b8:ae:ed:76:4c:eb
+ amtIp: <amt_ip>
+ amtUser: <username>
+ amtPass: <password>
+- id: 4
+ pxeMac: b8:ae:ed:76:37:62
+ amtIp: <amt_ip>
+ amtUser: <username>
+ amtPass: <password>
+- id: 5
+ pxeMac: b8:ae:ed:76:4d:95
+ amtIp: <amt_ip>
+ amtUser: <username>
+ amtPass: <password>
+# Adding the Fuel node as node id 6 which may not be correct - please
+# adjust as needed.
+- id: 6
+ libvirtName: fuel-opnfv
+ libvirtTemplate: templates/hardware_environment/vms/fuel.xml
+ isFuel: yes
+ username: root
+ password: r00tme
+
+disks:
+ fuel: 50G \ No newline at end of file
diff --git a/deploy/templates/hardware_environment/conf/opnfv_box/plugins_conf/.gitkeep b/deploy/templates/hardware_environment/conf/opnfv_box/plugins_conf/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/hardware_environment/conf/opnfv_box/plugins_conf/.gitkeep
diff --git a/deploy/templates/hardware_environment/vms/fuel.xml b/deploy/templates/hardware_environment/vms/fuel.xml
new file mode 100644
index 000000000..e3e3f80bb
--- /dev/null
+++ b/deploy/templates/hardware_environment/vms/fuel.xml
@@ -0,0 +1,91 @@
+<domain type='kvm' id='62'>
+ <name>fuel</name>
+ <memory unit='KiB'>8290304</memory>
+ <currentMemory unit='KiB'>8290304</currentMemory>
+ <vcpu placement='static'>4</vcpu>
+ <resource>
+ <partition>/machine</partition>
+ </resource>
+ <os>
+ <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='hd'/>
+ <bootmenu enable='no'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>SandyBridge</model>
+ </cpu>
+ <clock offset='utc'>
+ <timer name='rtc' tickpolicy='catchup'/>
+ <timer name='pit' tickpolicy='delay'/>
+ <timer name='hpet' present='no'/>
+ </clock>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <pm>
+ <suspend-to-mem enabled='no'/>
+ <suspend-to-disk enabled='no'/>
+ </pm>
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <target dev='hdb' bus='ide'/>
+ <readonly/>
+ </disk>
+ <controller type='usb' index='0' model='ich9-ehci1'>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci1'>
+ <master startport='0'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci2'>
+ <master startport='2'/>
+ </controller>
+ <controller type='usb' index='0' model='ich9-uhci3'>
+ <master startport='4'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'>
+ </controller>
+ <controller type='ide' index='0'>
+ </controller>
+ <controller type='virtio-serial' index='0'>
+ </controller>
+ <interface type='bridge'>
+ <model type='virtio'/>
+ </interface>
+ <serial type='pty'>
+ <source path='/dev/pts/0'/>
+ <target port='0'/>
+ </serial>
+ <console type='pty' tty='/dev/pts/0'>
+ <source path='/dev/pts/0'/>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='sv'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <sound model='ich6'>
+ </sound>
+ <video>
+ <model type='cirrus' vram='9216' heads='1'/>
+ </video>
+ <memballoon model='virtio'>
+ </memballoon>
+ </devices>
+ <seclabel type='dynamic' model='selinux' relabel='yes'>
+ <label>system_u:system_r:svirt_t:s0:c52,c932</label>
+ <imagelabel>system_u:object_r:svirt_image_t:s0:c52,c932</imagelabel>
+ </seclabel>
+</domain> \ No newline at end of file
diff --git a/deploy/templates/plugins/.gitkeep b/deploy/templates/plugins/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/plugins/.gitkeep
diff --git a/deploy/templates/virtual_environment/conf/dea.yaml b/deploy/templates/virtual_environment/conf/dea.yaml
new file mode 100644
index 000000000..c764e03e5
--- /dev/null
+++ b/deploy/templates/virtual_environment/conf/dea.yaml
@@ -0,0 +1,903 @@
+title: Deployment Environment Adapter (DEA)
+# DEA API version supported
+version:
+created:
+comment: Config for Virtual Environment - HA deployment with Ceph
+environment:
+ name: opnfv_virt
+ mode: ha
+ net_segment_type: tun
+wanted_release: Kilo on Ubuntu 14.04
+nodes:
+- id: 1
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 2
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 3
+ interfaces: interfaces_1
+ transformations: transformations_1
+ role: ceph-osd,controller
+- id: 4
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 5
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+- id: 6
+ interfaces: interfaces_1
+ transformations: transformations_2
+ role: ceph-osd,compute
+fuel:
+ ADMIN_NETWORK:
+ cidr: 10.20.0.0/24
+ dhcp_gateway: 10.20.0.2
+ dhcp_pool_end: 10.20.0.254
+ dhcp_pool_start: 10.20.0.3
+ ipaddress: 10.20.0.2
+ netmask: 255.255.0.0
+ DNS_DOMAIN: opnfvericsson.ca
+ DNS_SEARCH: opnfvericsson.ca
+ DNS_UPSTREAM: 10.118.32.193
+ FUEL_ACCESS:
+ password: admin
+ user: admin
+ HOSTNAME: opnfv_virt
+ NTP1: 10.118.32.193
+ NTP2: 10.118.34.193
+ NTP3: null
+interfaces_1:
+ eth0:
+ - fuelweb_admin
+ - management
+ eth1:
+ - storage
+ eth2:
+ - private
+ eth3:
+ - public
+transformations_1:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-ex
+ - action: add-br
+ name: br-floating
+ provider: ovs
+ - action: add-patch
+ bridges:
+ - br-floating
+ - br-ex
+ mtu: 65000
+ provider: ovs
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth0.101
+ - action: add-port
+ bridge: br-storage
+ name: eth1.102
+ - action: add-port
+ bridge: br-mesh
+ name: eth2.103
+ - action: add-port
+ bridge: br-ex
+ name: eth3
+transformations_2:
+ transformations:
+ - action: add-br
+ name: br-fw-admin
+ - action: add-br
+ name: br-mgmt
+ - action: add-br
+ name: br-storage
+ - action: add-br
+ name: br-mesh
+ - action: add-port
+ bridge: br-fw-admin
+ name: eth0
+ - action: add-port
+ bridge: br-mgmt
+ name: eth0.101
+ - action: add-port
+ bridge: br-storage
+ name: eth1.102
+ - action: add-port
+ bridge: br-mesh
+ name: eth2.103
+network:
+ management_vip: 192.168.0.2
+ management_vrouter_vip: 192.168.0.1
+ networking_parameters:
+ base_mac: fa:16:3e:00:00:00
+ configuration_template: null
+ dns_nameservers:
+ - 10.118.32.193
+ floating_ranges:
+ - - 172.16.0.130
+ - 172.16.0.254
+ gre_id_range:
+ - 2
+ - 65535
+ internal_cidr: 192.168.111.0/24
+ internal_gateway: 192.168.111.1
+ net_l23_provider: ovs
+ segmentation_type: tun
+ vlan_range:
+ - 1000
+ - 1030
+ networks:
+ - cidr: 172.16.0.0/24
+ gateway: 172.16.0.1
+ ip_ranges:
+ - - 172.16.0.2
+ - 172.16.0.126
+ meta:
+ cidr: 172.16.0.0/24
+ configurable: true
+ floating_range_var: floating_ranges
+ ip_range:
+ - 172.16.0.2
+ - 172.16.0.126
+ map_priority: 1
+ name: public
+ notation: ip_ranges
+ render_addr_mask: public
+ render_type: null
+ use_gateway: true
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: null
+ name: public
+ vlan_start: null
+ - cidr: 192.168.0.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.0.1
+ - 192.168.0.254
+ meta:
+ cidr: 192.168.0.0/24
+ configurable: true
+ map_priority: 2
+ name: management
+ notation: cidr
+ render_addr_mask: internal
+ render_type: cidr
+ use_gateway: false
+ vips:
+ - haproxy
+ - vrouter
+ vlan_start: 101
+ name: management
+ vlan_start: 101
+ - cidr: 192.168.1.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.1.1
+ - 192.168.1.254
+ meta:
+ cidr: 192.168.1.0/24
+ configurable: true
+ map_priority: 2
+ name: storage
+ notation: cidr
+ render_addr_mask: storage
+ render_type: cidr
+ use_gateway: false
+ vlan_start: 102
+ name: storage
+ vlan_start: 102
+ - cidr: 192.168.2.0/24
+ gateway: null
+ ip_ranges:
+ - - 192.168.2.1
+ - 192.168.2.254
+ meta:
+ cidr: 192.168.2.0/24
+ configurable: true
+ map_priority: 2
+ name: private
+ notation: cidr
+ render_addr_mask: null
+ render_type: cidr
+ seg_type: tun
+ use_gateway: false
+ vlan_start: 103
+ name: private
+ vlan_start: 103
+ - cidr: 10.20.0.0/16
+ gateway: 10.20.0.2
+ ip_ranges:
+ - - 10.20.0.3
+ - 10.20.0.254
+ meta:
+ configurable: false
+ map_priority: 0
+ notation: ip_ranges
+ render_addr_mask: null
+ render_type: null
+ unmovable: true
+ use_gateway: true
+ name: fuelweb_admin
+ vlan_start: null
+ public_vip: 172.16.0.3
+ public_vrouter_vip: 172.16.0.2
+ vips:
+ management:
+ ipaddr: 192.168.0.2
+ namespace: haproxy
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ public:
+ ipaddr: 172.16.0.3
+ namespace: haproxy
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter:
+ ipaddr: 192.168.0.1
+ namespace: vrouter
+ network_role: mgmt/vip
+ node_roles:
+ - controller
+ - primary-controller
+ vrouter_pub:
+ ipaddr: 172.16.0.2
+ namespace: vrouter
+ network_role: public/vip
+ node_roles:
+ - controller
+ - primary-controller
+settings:
+ editable:
+ access:
+ email:
+ description: Email address for Administrator
+ label: Email
+ regex:
+ error: Invalid email
+ source: ^\S+@\S+$
+ type: text
+ value: admin@localhost
+ weight: 40
+ metadata:
+ label: Access
+ weight: 10
+ password:
+ description: Password for Administrator
+ label: Password
+ regex:
+ error: Empty password
+ source: \S
+ type: password
+ value: admin
+ weight: 20
+ tenant:
+ description: Tenant (project) name for Administrator
+ label: Tenant
+ regex:
+ error: Invalid tenant name
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 30
+ user:
+ description: Username for Administrator
+ label: Username
+ regex:
+ error: Invalid username
+ source: ^(?!services$)(?!nova$)(?!glance$)(?!keystone$)(?!neutron$)(?!cinder$)(?!swift$)(?!ceph$)(?![Gg]uest$)(?!.*
+ +.*$).+
+ type: text
+ value: admin
+ weight: 10
+ additional_components:
+ ceilometer:
+ description: If selected, Ceilometer component will be installed
+ label: Install Ceilometer
+ type: checkbox
+ value: false
+ weight: 40
+ heat:
+ description: ''
+ label: ''
+ type: hidden
+ value: true
+ weight: 30
+ metadata:
+ label: Additional Components
+ weight: 20
+ mongo:
+ description: If selected, You can use external Mongo DB as ceilometer backend
+ label: Use external Mongo DB
+ restrictions:
+ - settings:additional_components.ceilometer.value == false
+ type: checkbox
+ value: false
+ weight: 40
+ murano:
+ description: If selected, Murano component will be installed
+ label: Install Murano
+ type: checkbox
+ value: false
+ weight: 20
+ sahara:
+ description: If selected, Sahara component will be installed
+ label: Install Sahara
+ type: checkbox
+ value: false
+ weight: 10
+ common:
+ auth_key:
+ description: Public key(s) to include in authorized_keys on deployed nodes
+ label: Public Key
+ type: textarea
+ value: ''
+ weight: 70
+ auto_assign_floating_ip:
+ description: If selected, OpenStack will automatically assign a floating IP
+ to a new instance
+ label: Auto assign floating IP
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider == 'neutron'
+ type: checkbox
+ value: false
+ weight: 40
+ debug:
+ description: Debug logging mode provides more information, but requires more
+ disk space.
+ label: OpenStack debug logging
+ type: checkbox
+ value: false
+ weight: 20
+ libvirt_type:
+ label: Hypervisor type
+ type: radio
+ value: kvm
+ values:
+ - data: kvm
+ description: Choose this type of hypervisor if you run OpenStack on hardware
+ label: KVM
+ - data: qemu
+ description: Choose this type of hypervisor if you run OpenStack on virtual
+ hosts.
+ label: QEMU
+ weight: 30
+ metadata:
+ label: Common
+ weight: 30
+ nova_quota:
+ description: Quotas are used to limit CPU and memory usage for tenants. Enabling
+ quotas will increase load on the Nova database.
+ label: Nova quotas
+ type: checkbox
+ value: false
+ weight: 25
+ puppet_debug:
+ description: Debug puppet logging mode provides more information, but requires
+ more disk space.
+ label: Puppet debug logging
+ type: checkbox
+ value: true
+ weight: 20
+ resume_guests_state_on_host_boot:
+ description: Whether to resume previous guests state when the host reboots.
+ If enabled, this option causes guests assigned to the host to resume their
+ previous state. If the guest was running a restart will be attempted when
+ nova-compute starts. If the guest was not running previously, a restart will
+ not be attempted.
+ label: Resume guests state on host boot
+ type: checkbox
+ value: true
+ weight: 60
+ use_cow_images:
+ description: For most cases you will want qcow format. If it's disabled, raw
+ image format will be used to run VMs. OpenStack with raw format currently
+ does not support snapshotting.
+ label: Use qcow format for images
+ type: checkbox
+ value: true
+ weight: 50
+ use_vcenter:
+ restrictions:
+ - condition: cluster:net_provider == 'nova_network'
+ type: hidden
+ value: false
+ weight: 30
+ corosync:
+ group:
+ description: ''
+ label: Group
+ type: text
+ value: 226.94.1.1
+ weight: 10
+ metadata:
+ label: Corosync
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 50
+ port:
+ description: ''
+ label: Port
+ type: text
+ value: '12000'
+ weight: 20
+ verified:
+ description: Set True only if multicast is configured correctly on router.
+ label: Need to pass network verification.
+ type: checkbox
+ value: false
+ weight: 10
+ external_dns:
+ dns_list:
+ description: List of upstream DNS servers, separated by comma
+ label: DNS list
+ regex:
+ error: Invalid IP address list
+ source: ^\*$|^(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3}(?:\s*,\s*(?:\d|1?\d\d|2[0-4]\d|25[0-5])(?:\.(?:\d|1?\d\d|2[0-4]\d|25[0-5])){3})*$
+ type: text
+ value: 10.118.32.193
+ weight: 10
+ metadata:
+ label: Host OS DNS Servers
+ weight: 90
+ external_mongo:
+ hosts_ip:
+ description: IP Addresses of MongoDB. Use comma to split IPs
+ label: MongoDB hosts IP
+ regex:
+ error: Invalid hosts ip sequence
+ source: ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?),)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
+ type: text
+ value: ''
+ weight: 30
+ metadata:
+ label: External MongoDB
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.mongo.value == false
+ message: Ceilometer and MongoDB are not enabled on the Additional Components
+ section
+ weight: 20
+ mongo_db_name:
+ description: Mongo database name
+ label: Database name
+ regex:
+ error: Invalid database name
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ mongo_password:
+ description: Mongo database password
+ label: Password
+ regex:
+ error: Password contains spaces
+ source: ^\S*$
+ type: password
+ value: ceilometer
+ weight: 30
+ mongo_replset:
+ description: Name for Mongo replication set
+ label: Replset
+ type: text
+ value: ''
+ weight: 30
+ mongo_user:
+ description: Mongo database username
+ label: Username
+ regex:
+ error: Empty username
+ source: ^\w+$
+ type: text
+ value: ceilometer
+ weight: 30
+ external_ntp:
+ metadata:
+ label: Host OS NTP Servers
+ weight: 100
+ ntp_list:
+ description: List of upstream NTP servers, separated by comma
+ label: NTP server list
+ regex:
+ error: Invalid NTP server list
+ source: ^\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(?:\.\d{1,3}){3})\s*(?:,\s*(?:(?:\w+(?:-+\w+)*\.)+[a-z]+|\d{1,3}(\.\d{1,3}){3})\s*)*$
+ type: text
+ value: 10.118.32.193, 10.118.34.193
+ weight: 10
+ kernel_params:
+ kernel:
+ description: Default kernel parameters
+ label: Initial parameters
+ type: text
+ value: console=tty0 net.ifnames=0 biosdevname=0 rootdelay=90 nomodeset
+ weight: 45
+ metadata:
+ label: Kernel parameters
+ weight: 40
+ murano_settings:
+ metadata:
+ label: Murano Settings
+ restrictions:
+ - action: hide
+ condition: settings:additional_components.murano.value == false
+ message: Murano is not enabled on the Additional Components section
+ weight: 20
+ murano_repo_url:
+ description: ''
+ label: Murano Repository URL
+ type: text
+ value: http://storage.apps.openstack.org/
+ weight: 10
+ neutron_advanced_configuration:
+ metadata:
+ label: Neutron Advanced Configuration
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 45
+ neutron_dvr:
+ description: Enable Distributed Virtual Routers in Neutron
+ label: Neutron DVR
+ restrictions:
+ - ? networking_parameters:segmentation_type != 'vlan' and settings:neutron_advanced_configuration.neutron_l2_pop.value
+ == false
+ : DVR requires L2 population to be enabled.
+ type: checkbox
+ value: false
+ weight: 20
+ neutron_l2_pop:
+ description: Enable L2 population mechanism in Neutron
+ label: Neutron L2 population
+ restrictions:
+ - action: hide
+ condition: networking_parameters:segmentation_type == 'vlan'
+ type: checkbox
+ value: false
+ weight: 10
+ neutron_mellanox:
+ metadata:
+ enabled: true
+ label: Mellanox Neutron components
+ restrictions:
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ toggleable: false
+ weight: 50
+ plugin:
+ label: Mellanox drivers and SR-IOV plugin
+ type: radio
+ value: disabled
+ values:
+ - data: disabled
+ description: If selected, Mellanox drivers, Neutron and Cinder plugin will
+ not be installed.
+ label: Mellanox drivers and plugins disabled
+ restrictions:
+ - settings:storage.iser.value == true
+ - data: drivers_only
+ description: If selected, Mellanox Ethernet drivers will be installed to support
+ networking over Mellanox NIC. Mellanox Neutron plugin will not be installed.
+ label: Install only Mellanox drivers
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm'
+ - data: ethernet
+ description: If selected, both Mellanox Ethernet drivers and Mellanox network
+ acceleration (Neutron) plugin will be installed.
+ label: Install Mellanox drivers and SR-IOV plugin
+ restrictions:
+ - settings:common.libvirt_type.value != 'kvm' or not (cluster:net_provider
+ == 'neutron' and networking_parameters:segmentation_type == 'vlan')
+ weight: 60
+ vf_num:
+ description: Note that one virtual function will be reserved to the storage
+ network, in case of choosing iSER.
+ label: Number of virtual NICs
+ restrictions:
+ - settings:neutron_mellanox.plugin.value != 'ethernet'
+ type: text
+ value: '16'
+ weight: 70
+ provision:
+ metadata:
+ label: Provision
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 80
+ method:
+ type: hidden
+ value: image
+ public_network_assignment:
+ assign_to_all_nodes:
+ description: When disabled, public network will be assigned to controllers only
+ label: Assign public network to all nodes
+ type: checkbox
+ value: false
+ weight: 10
+ metadata:
+ label: Public network assignment
+ restrictions:
+ - action: hide
+ condition: cluster:net_provider != 'neutron'
+ weight: 50
+ public_ssl:
+ cert_data:
+ description: Certificate and private key data, concatenated into a single file
+ label: Certificate
+ restrictions:
+ - action: hide
+ condition: (settings:public_ssl.cert_source.value != 'user_uploaded') or (settings:public_ssl.horizon.value
+ == false and settings:public_ssl.services.value == false)
+ type: file
+ value: ''
+ weight: 40
+ cert_source:
+ description: From where we'll get certificate and private key
+ label: Select source for certificate
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: radio
+ value: self_signed
+ values:
+ - data: self_signed
+ description: Generate private key and certificate that will be signed by this
+ key
+ label: Self-signed
+ - data: user_uploaded
+ description: Use pre-generated key and certificate
+ label: I have my own keypair with certificate
+ weight: 30
+ horizon:
+ description: Secure access to Horizon enabling HTTPS instead of HTTP
+ label: HTTPS for Horizon
+ type: checkbox
+ value: false
+ weight: 10
+ hostname:
+ description: Your DNS entries should point to this name. Self-signed certificates
+ also will use this hostname
+ label: DNS hostname for public TLS endpoints
+ restrictions:
+ - action: hide
+ condition: settings:public_ssl.horizon.value == false and settings:public_ssl.services.value
+ == false
+ type: text
+ value: public.fuel.local
+ weight: 50
+ metadata:
+ label: Public TLS
+ weight: 110
+ services:
+ description: Enable TLS termination on HAProxy for OpenStack services
+ label: TLS for OpenStack public endpoints
+ type: checkbox
+ value: false
+ weight: 20
+ repo_setup:
+ metadata:
+ always_editable: true
+ label: Repositories
+ weight: 50
+ repos:
+ description: 'Please note: the first repository will be considered the operating
+ system mirror that will be used during node provisioning.
+
+ To create a local repository mirror on the Fuel master node, please follow
+ the instructions provided by running "fuel-createmirror --help" on the Fuel
+ master node.
+
+ Please make sure your Fuel master node has Internet access to the repository
+ before attempting to create a mirror.
+
+ For more details, please refer to the documentation (https://docs.mirantis.com/openstack/fuel/fuel-7.0/operations.html#external-ubuntu-ops).
+
+ '
+ extra_priority: null
+ type: custom_repo_configuration
+ value:
+ - name: ubuntu
+ priority: null
+ section: main universe multiverse
+ suite: trusty
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-updates
+ priority: null
+ section: main universe multiverse
+ suite: trusty-updates
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: ubuntu-security
+ priority: null
+ section: main universe multiverse
+ suite: trusty-security
+ type: deb
+ uri: http://archive.ubuntu.com/ubuntu/
+ - name: mos
+ priority: 1050
+ section: main restricted
+ suite: mos7.0
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/x86_64
+ - name: mos-updates
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-updates
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-security
+ priority: 1050
+ section: main restricted
+ suite: mos7.0-security
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: mos-holdback
+ priority: 1100
+ section: main restricted
+ suite: mos7.0-holdback
+ type: deb
+ uri: http://mirror.fuel-infra.org/mos-repos/ubuntu/7.0/
+ - name: Auxiliary
+ priority: 1150
+ section: main restricted
+ suite: auxiliary
+ type: deb
+ uri: http://10.20.0.2:8080/2015.1.0-7.0/ubuntu/auxiliary
+ storage:
+ ephemeral_ceph:
+ description: Configures Nova to store ephemeral volumes in RBD. This works best
+ if Ceph is enabled for volumes and images, too. Enables live migration of
+ all types of Ceph backed VMs (without this option, live migration will only
+ work with VMs launched from Cinder volumes).
+ label: Ceph RBD for ephemeral volumes (Nova)
+ type: checkbox
+ value: true
+ weight: 75
+ images_ceph:
+ description: Configures Glance to use the Ceph RBD backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: Ceph RBD for images (Glance)
+ restrictions:
+ - settings:storage.images_vcenter.value == true: Only one Glance backend could
+ be selected.
+ type: checkbox
+ value: true
+ weight: 30
+ images_vcenter:
+ description: Configures Glance to use the vCenter/ESXi backend to store images.
+ If enabled, this option will prevent Swift from installing.
+ label: VMWare vCenter/ESXi datastore for images (Glance)
+ restrictions:
+ - action: hide
+ condition: settings:common.use_vcenter.value != true
+ - condition: settings:storage.images_ceph.value == true
+ message: Only one Glance backend could be selected.
+ type: checkbox
+ value: false
+ weight: 35
+ iser:
+ description: 'High performance block storage: Cinder volumes over iSER protocol
+ (iSCSI over RDMA). This feature requires SR-IOV capabilities in the NIC, and
+ will use a dedicated virtual function for the storage network.'
+ label: iSER protocol for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value != true or settings:common.libvirt_type.value
+ != 'kvm'
+ - action: hide
+ condition: not ('experimental' in version:feature_groups)
+ type: checkbox
+ value: false
+ weight: 11
+ metadata:
+ label: Storage
+ weight: 60
+ objects_ceph:
+ description: Configures RadosGW front end for Ceph RBD. This exposes S3 and
+ Swift API Interfaces. If enabled, this option will prevent Swift from installing.
+ label: Ceph RadosGW for objects (Swift API)
+ restrictions:
+ - settings:storage.images_ceph.value == false
+ type: checkbox
+ value: false
+ weight: 80
+ osd_pool_size:
+ description: Configures the default number of object replicas in Ceph. This
+ number must be equal to or lower than the number of deployed 'Storage - Ceph
+ OSD' nodes.
+ label: Ceph object replication factor
+ regex:
+ error: Invalid number
+ source: ^[1-9]\d*$
+ type: text
+ value: '2'
+ weight: 85
+ volumes_ceph:
+ description: Configures Cinder to store volumes in Ceph RBD images.
+ label: Ceph RBD for volumes (Cinder)
+ restrictions:
+ - settings:storage.volumes_lvm.value == true
+ type: checkbox
+ value: true
+ weight: 20
+ volumes_lvm:
+ description: It is recommended to have at least one Storage - Cinder LVM node.
+ label: Cinder LVM over iSCSI for volumes
+ restrictions:
+ - settings:storage.volumes_ceph.value == true
+ type: checkbox
+ value: false
+ weight: 10
+ syslog:
+ metadata:
+ label: Syslog
+ weight: 50
+ syslog_port:
+ description: Remote syslog port
+ label: Port
+ regex:
+ error: Invalid syslog port
+ source: ^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$
+ type: text
+ value: '514'
+ weight: 20
+ syslog_server:
+ description: Remote syslog hostname
+ label: Hostname
+ type: text
+ value: ''
+ weight: 10
+ syslog_transport:
+ label: Syslog transport protocol
+ type: radio
+ value: tcp
+ values:
+ - data: udp
+ description: ''
+ label: UDP
+ - data: tcp
+ description: ''
+ label: TCP
+ weight: 30
+ workloads_collector:
+ enabled:
+ type: hidden
+ value: true
+ metadata:
+ label: Workloads Collector User
+ restrictions:
+ - action: hide
+ condition: 'true'
+ weight: 10
+ password:
+ type: password
+ value: sbfn1c8b
+ tenant:
+ type: text
+ value: services
+ user:
+ type: text
+ value: fuel_stats_user \ No newline at end of file
diff --git a/deploy/templates/virtual_environment/conf/dha.yaml b/deploy/templates/virtual_environment/conf/dha.yaml
new file mode 100644
index 000000000..b671dd311
--- /dev/null
+++ b/deploy/templates/virtual_environment/conf/dha.yaml
@@ -0,0 +1,44 @@
+title: Deployment Hardware Adapter (DHA)
+# DHA API version supported
+version:
+created:
+comment: Config for Virtual Environment
+
+# Adapter to use for this definition
+adapter: libvirt
+
+# Node list.
+# Mandatory property is id, all other properties are adapter specific.
+
+nodes:
+- id: 1
+ libvirtName: controller1
+ libvirtTemplate: templates/virtual_environment/vms/controller.xml
+- id: 2
+ libvirtName: controller2
+ libvirtTemplate: templates/virtual_environment/vms/controller.xml
+- id: 3
+ libvirtName: controller3
+ libvirtTemplate: templates/virtual_environment/vms/controller.xml
+- id: 4
+ libvirtName: compute1
+ libvirtTemplate: templates/virtual_environment/vms/compute.xml
+- id: 5
+ libvirtName: compute2
+ libvirtTemplate: templates/virtual_environment/vms/compute.xml
+- id: 6
+ libvirtName: compute3
+ libvirtTemplate: templates/virtual_environment/vms/compute.xml
+- id: 7
+ libvirtName: fuel-master
+ libvirtTemplate: templates/virtual_environment/vms/fuel.xml
+ isFuel: yes
+ username: root
+ password: r00tme
+
+virtNetConfDir: templates/virtual_environment/networks
+
+disks:
+ fuel: 50G
+ controller: 60G
+ compute: 50G \ No newline at end of file
diff --git a/deploy/templates/virtual_environment/conf/plugins_conf/.gitkeep b/deploy/templates/virtual_environment/conf/plugins_conf/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/deploy/templates/virtual_environment/conf/plugins_conf/.gitkeep
diff --git a/deploy/templates/virtual_environment/networks/fuel1.xml b/deploy/templates/virtual_environment/networks/fuel1.xml
new file mode 100644
index 000000000..7b2b15423
--- /dev/null
+++ b/deploy/templates/virtual_environment/networks/fuel1.xml
@@ -0,0 +1,12 @@
+<network>
+ <name>fuel1</name>
+ <forward mode='nat'>
+ <nat>
+ <port start='1024' end='65535'/>
+ </nat>
+ </forward>
+ <bridge name='fuel1' stp='on' delay='0'/>
+ <ip address='10.20.0.1' netmask='255.255.255.0'>
+ </ip>
+</network>
+
diff --git a/deploy/templates/virtual_environment/networks/fuel2.xml b/deploy/templates/virtual_environment/networks/fuel2.xml
new file mode 100644
index 000000000..615c92094
--- /dev/null
+++ b/deploy/templates/virtual_environment/networks/fuel2.xml
@@ -0,0 +1,5 @@
+<network>
+ <name>fuel2</name>
+ <bridge name='fuel2' stp='on' delay='0'/>
+</network>
+
diff --git a/deploy/templates/virtual_environment/networks/fuel3.xml b/deploy/templates/virtual_environment/networks/fuel3.xml
new file mode 100644
index 000000000..2383e6c1f
--- /dev/null
+++ b/deploy/templates/virtual_environment/networks/fuel3.xml
@@ -0,0 +1,5 @@
+<network>
+ <name>fuel3</name>
+ <bridge name='fuel3' stp='on' delay='0'/>
+</network>
+
diff --git a/deploy/templates/virtual_environment/networks/fuel4.xml b/deploy/templates/virtual_environment/networks/fuel4.xml
new file mode 100644
index 000000000..5b69f912d
--- /dev/null
+++ b/deploy/templates/virtual_environment/networks/fuel4.xml
@@ -0,0 +1,12 @@
+<network>
+ <name>fuel4</name>
+ <forward mode='nat'>
+ <nat>
+ <port start='1024' end='65535'/>
+ </nat>
+ </forward>
+ <bridge name='fuel4' stp='on' delay='0'/>
+ <ip address='172.16.0.1' netmask='255.255.255.0'>
+ </ip>
+</network>
+
diff --git a/deploy/templates/virtual_environment/vms/compute.xml b/deploy/templates/virtual_environment/vms/compute.xml
new file mode 100644
index 000000000..fbef4bda7
--- /dev/null
+++ b/deploy/templates/virtual_environment/vms/compute.xml
@@ -0,0 +1,91 @@
+<domain type='kvm'>
+ <name>compute</name>
+ <memory unit='KiB'>8388608</memory>
+ <currentMemory unit='KiB'>8388608</currentMemory>
+ <vcpu placement='static'>2</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-1.0'>hvm</type>
+ <boot dev='network'/>
+ <boot dev='hd'/>
+ <bios rebootTimeout='30000'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>SandyBridge</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='vme'/>
+ <feature policy='require' name='dtes64'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='erms'/>
+ <feature policy='require' name='xtpr'/>
+ <feature policy='require' name='smep'/>
+ <feature policy='require' name='pcid'/>
+ <feature policy='require' name='est'/>
+ <feature policy='require' name='monitor'/>
+ <feature policy='require' name='smx'/>
+ <feature policy='require' name='tm'/>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='osxsave'/>
+ <feature policy='require' name='ht'/>
+ <feature policy='require' name='pdcm'/>
+ <feature policy='require' name='fsgsbase'/>
+ <feature policy='require' name='f16c'/>
+ <feature policy='require' name='ds'/>
+ <feature policy='require' name='tm2'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='pbe'/>
+ <feature policy='require' name='ds_cpl'/>
+ <feature policy='require' name='rdrand'/>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='disk.raw'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <controller type='usb' index='0'>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='network'>
+ <source network='fuel1'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel2'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel3'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel4'/>
+ <model type='virtio'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' keymap='sv'/>
+ <sound model='ich6'>
+ </sound>
+ <video>
+ <model type='cirrus' vram='9216' heads='1'/>
+ </video>
+ <memballoon model='virtio'>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/deploy/templates/virtual_environment/vms/controller.xml b/deploy/templates/virtual_environment/vms/controller.xml
new file mode 100644
index 000000000..3ff28218d
--- /dev/null
+++ b/deploy/templates/virtual_environment/vms/controller.xml
@@ -0,0 +1,91 @@
+<domain type='kvm'>
+ <name>controller</name>
+ <memory unit='KiB'>8388608</memory>
+ <currentMemory unit='KiB'>8388608</currentMemory>
+ <vcpu placement='static'>2</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-1.0'>hvm</type>
+ <boot dev='network'/>
+ <boot dev='hd'/>
+ <bios rebootTimeout='30000'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>SandyBridge</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='vme'/>
+ <feature policy='require' name='dtes64'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='erms'/>
+ <feature policy='require' name='xtpr'/>
+ <feature policy='require' name='smep'/>
+ <feature policy='require' name='pcid'/>
+ <feature policy='require' name='est'/>
+ <feature policy='require' name='monitor'/>
+ <feature policy='require' name='smx'/>
+ <feature policy='require' name='tm'/>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='osxsave'/>
+ <feature policy='require' name='ht'/>
+ <feature policy='require' name='pdcm'/>
+ <feature policy='require' name='fsgsbase'/>
+ <feature policy='require' name='f16c'/>
+ <feature policy='require' name='ds'/>
+ <feature policy='require' name='tm2'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='pbe'/>
+ <feature policy='require' name='ds_cpl'/>
+ <feature policy='require' name='rdrand'/>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/kvm</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='disk.raw'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <controller type='usb' index='0'>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='network'>
+ <source network='fuel1'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel2'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel3'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='network'>
+ <source network='fuel4'/>
+ <model type='virtio'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' keymap='sv'/>
+ <sound model='ich6'>
+ </sound>
+ <video>
+ <model type='cirrus' vram='9216' heads='1'/>
+ </video>
+ <memballoon model='virtio'>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/deploy/templates/virtual_environment/vms/fuel.xml b/deploy/templates/virtual_environment/vms/fuel.xml
new file mode 100644
index 000000000..1a3286001
--- /dev/null
+++ b/deploy/templates/virtual_environment/vms/fuel.xml
@@ -0,0 +1,93 @@
+<domain type='kvm'>
+ <name>fuel</name>
+ <memory unit='KiB'>2097152</memory>
+ <currentMemory unit='KiB'>2097152</currentMemory>
+ <vcpu placement='static'>2</vcpu>
+ <resource>
+ <partition>/machine</partition>
+ </resource>
+ <os>
+ <type arch='x86_64' machine='pc-1.0'>hvm</type>
+ <boot dev='hd'/>
+ <boot dev='cdrom'/>
+ <bootmenu enable='no'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <cpu mode='custom' match='exact'>
+ <model fallback='allow'>SandyBridge</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='vme'/>
+ <feature policy='require' name='dtes64'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='erms'/>
+ <feature policy='require' name='xtpr'/>
+ <feature policy='require' name='smep'/>
+ <feature policy='require' name='pcid'/>
+ <feature policy='require' name='est'/>
+ <feature policy='require' name='monitor'/>
+ <feature policy='require' name='smx'/>
+ <feature policy='require' name='tm'/>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='osxsave'/>
+ <feature policy='require' name='ht'/>
+ <feature policy='require' name='pdcm'/>
+ <feature policy='require' name='fsgsbase'/>
+ <feature policy='require' name='f16c'/>
+ <feature policy='require' name='ds'/>
+ <feature policy='require' name='tm2'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='pbe'/>
+ <feature policy='require' name='ds_cpl'/>
+ <feature policy='require' name='rdrand'/>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/kvm</emulator>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='disk.raw'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <controller type='ide' index='0'>
+ </controller>
+ <controller type='usb' index='0'>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <interface type='network'>
+ <source network='fuel1'/>
+ <model type='virtio'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='sv'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <sound model='ich6'>
+ </sound>
+ <video>
+ <model type='cirrus' vram='9216' heads='1'/>
+ </video>
+ <memballoon model='virtio'>
+ </memballoon>
+ </devices>
+ <seclabel type='dynamic' model='apparmor' relabel='yes'/>
+</domain>
+
diff --git a/deploy/transplant_fuel_settings.py b/deploy/transplant_fuel_settings.py
new file mode 100644
index 000000000..e57a4fbc6
--- /dev/null
+++ b/deploy/transplant_fuel_settings.py
@@ -0,0 +1,62 @@
+###############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+# szilard.cserey@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+###############################################################################
+
+
+import sys
+import io
+import yaml
+from dea import DeploymentEnvironmentAdapter
+
+from common import (
+ check_file_exists,
+)
+
+ASTUTE_YAML = '/etc/fuel/astute.yaml'
+
+
+def usage():
+ print '''
+ Usage:
+ python transplant_fuel_settings.py <deafile>
+ '''
+
+
+def parse_arguments():
+ if len(sys.argv) != 2:
+ usage()
+ sys.exit(1)
+ dea_file = sys.argv[-1]
+ check_file_exists(dea_file)
+ return dea_file
+
+
+def transplant(dea, astute):
+ fuel_conf = dea.get_fuel_config()
+ for key in fuel_conf.iterkeys():
+ if key == 'ADMIN_NETWORK':
+ for skey in fuel_conf[key].iterkeys():
+ astute[key][skey] = fuel_conf[key][skey]
+ else:
+ astute[key] = fuel_conf[key]
+ return astute
+
+
+def main():
+ dea_file = parse_arguments()
+ check_file_exists(ASTUTE_YAML)
+ dea = DeploymentEnvironmentAdapter(dea_file)
+ with io.open(ASTUTE_YAML) as stream:
+ astute = yaml.load(stream)
+ transplant(dea, astute)
+ with io.open(ASTUTE_YAML, 'w') as stream:
+ yaml.dump(astute, stream, default_flow_style=False)
+
+
+if __name__ == '__main__':
+ main()