summaryrefslogtreecommitdiffstats
path: root/fuel/deploy/cloud
diff options
context:
space:
mode:
Diffstat (limited to 'fuel/deploy/cloud')
-rw-r--r--fuel/deploy/cloud/configure_environment.py78
-rw-r--r--fuel/deploy/cloud/configure_network.py74
-rw-r--r--fuel/deploy/cloud/configure_nodes.py114
-rw-r--r--fuel/deploy/cloud/configure_settings.py59
-rw-r--r--fuel/deploy/cloud/deploy.py107
-rw-r--r--fuel/deploy/cloud/deployment.py97
6 files changed, 529 insertions, 0 deletions
diff --git a/fuel/deploy/cloud/configure_environment.py b/fuel/deploy/cloud/configure_environment.py
new file mode 100644
index 000000000..2d68c1ba8
--- /dev/null
+++ b/fuel/deploy/cloud/configure_environment.py
@@ -0,0 +1,78 @@
+###############################################################################
+# 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 common
+
+from configure_settings import ConfigureSettings
+from configure_network import ConfigureNetwork
+from configure_nodes import ConfigureNodes
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+parse = common.parse
+err = common.err
+log = common.log
+delete = common.delete
+create_dir_if_not_exists = common.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/fuel/deploy/cloud/configure_network.py b/fuel/deploy/cloud/configure_network.py
new file mode 100644
index 000000000..00278949d
--- /dev/null
+++ b/fuel/deploy/cloud/configure_network.py
@@ -0,0 +1,74 @@
+###############################################################################
+# 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 common
+import yaml
+import io
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+parse = common.parse
+err = common.err
+check_file_exists = common.check_file_exists
+log = common.log
+backup = common.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/fuel/deploy/cloud/configure_nodes.py b/fuel/deploy/cloud/configure_nodes.py
new file mode 100644
index 000000000..e76d222c0
--- /dev/null
+++ b/fuel/deploy/cloud/configure_nodes.py
@@ -0,0 +1,114 @@
+###############################################################################
+# 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 common
+import yaml
+import io
+import glob
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+parse = common.parse
+err = common.err
+check_file_exists = common.check_file_exists
+log = common.log
+backup = common.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/fuel/deploy/cloud/configure_settings.py b/fuel/deploy/cloud/configure_settings.py
new file mode 100644
index 000000000..fa918fd3d
--- /dev/null
+++ b/fuel/deploy/cloud/configure_settings.py
@@ -0,0 +1,59 @@
+###############################################################################
+# 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 common
+import yaml
+import io
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+parse = common.parse
+err = common.err
+check_file_exists = common.check_file_exists
+log = common.log
+backup = common.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/fuel/deploy/cloud/deploy.py b/fuel/deploy/cloud/deploy.py
new file mode 100644
index 000000000..705dda59c
--- /dev/null
+++ b/fuel/deploy/cloud/deploy.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
+###############################################################################
+
+
+import os
+import yaml
+import io
+import glob
+
+import common
+from dea import DeploymentEnvironmentAdapter
+from configure_environment import ConfigureEnvironment
+from deployment import Deployment
+
+YAML_CONF_DIR = '/var/lib/opnfv'
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+parse = common.parse
+err = common.err
+check_file_exists = common.check_file_exists
+log = common.log
+commafy = common.commafy
+ArgParser = common.ArgParser
+
+
+class Deploy(object):
+
+ def __init__(self, dea_file, blade_node_file, no_health_check):
+ self.dea = DeploymentEnvironmentAdapter(dea_file)
+ self.blade_node_file = blade_node_file
+ self.no_health_check = no_health_check
+ self.macs_per_blade = {}
+ self.blades = self.dea.get_node_ids()
+ self.blade_node_dict = {}
+ self.node_roles_dict = {}
+ self.env_id = None
+ self.wanted_release = self.dea.get_property('wanted_release')
+
+ def get_blade_node_mapping(self):
+ with io.open(self.blade_node_file, 'r') as stream:
+ self.blade_node_dict = yaml.load(stream)
+
+ 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.get_blade_node_mapping()
+
+ 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')
+ parser.add_argument('blade_node_file', action='store',
+ help='Blade Node mapping: blade_node.yaml')
+ args = parser.parse_args()
+ check_file_exists(args.dea_file)
+ check_file_exists(args.blade_node_file)
+ return (args.dea_file, args.blade_node_file, args.no_health_check)
+
+
+def main():
+ dea_file, blade_node_file, no_health_check = parse_arguments()
+ deploy = Deploy(dea_file, blade_node_file, no_health_check)
+ deploy.deploy()
+
+if __name__ == '__main__':
+ main()
diff --git a/fuel/deploy/cloud/deployment.py b/fuel/deploy/cloud/deployment.py
new file mode 100644
index 000000000..90f24fd0b
--- /dev/null
+++ b/fuel/deploy/cloud/deployment.py
@@ -0,0 +1,97 @@
+###############################################################################
+# 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 common
+import os
+import shutil
+import glob
+import yaml
+import io
+import time
+
+N = common.N
+E = common.E
+R = common.R
+RO = common.RO
+exec_cmd = common.exec_cmd
+run_proc = common.run_proc
+parse = common.parse
+err = common.err
+log = common.log
+
+
+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
+
+ 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)
+ exec_cmd('rm %s' % LOG_FILE)
+
+ if ready:
+ log('Environment %s successfully deployed' % self.env_id)
+ else:
+ 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()