Merge "Add python-redis to overcloud"
[apex.git] / lib / python / apex / deploy_env.py
1 ##############################################################################
2 # Copyright (c) 2016 Michael Chapman (michapma@redhat.com) and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10
11 import yaml
12 import logging
13
14 REQ_DEPLOY_SETTINGS = ['sdn_controller',
15                        'odl_version',
16                        'sdn_l3',
17                        'tacker',
18                        'congress',
19                        'dataplane',
20                        'sfc',
21                        'vpn',
22                        'vpp']
23
24 OPT_DEPLOY_SETTINGS = ['performance']
25
26 VALID_ROLES = ['Controller', 'Compute', 'ObjectStorage']
27 VALID_PERF_OPTS = ['kernel', 'nova']
28 VALID_DATAPLANES = ['ovs', 'ovs_dpdk', 'fdio']
29
30
31 class DeploySettings:
32     """
33     This class parses a APEX deploy settings yaml file into an object
34
35     Currently the parsed object is dumped into a bash global definition file
36     for deploy.sh consumption. This object will later be used directly as
37     deployment script move to python.
38     """
39     def __init__(self, filename):
40         with open(filename, 'r') as settings_file:
41             self.deploy_settings = yaml.load(settings_file)
42             self._validate_settings()
43
44     def _validate_settings(self):
45         """
46         Validates the deploy settings file provided
47
48         DeploySettingsException will be raised if validation fails.
49         """
50
51         if 'deploy_options' not in self.deploy_settings:
52             raise DeploySettingsException("No deploy options provided in"
53                                           " deploy settings file")
54         if 'global_params' not in self.deploy_settings:
55             raise DeploySettingsException("No global options provided in"
56                                           " deploy settings file")
57
58         deploy_options = self.deploy_settings['deploy_options']
59         if not isinstance(deploy_options, dict):
60             raise DeploySettingsException("deploy_options should be a list")
61
62         for setting, value in deploy_options.items():
63             if setting not in REQ_DEPLOY_SETTINGS + OPT_DEPLOY_SETTINGS:
64                 raise DeploySettingsException("Invalid deploy_option {} "
65                                               "specified".format(setting))
66             if setting == 'dataplane':
67                 if value not in VALID_DATAPLANES:
68                     planes = ' '.join(VALID_DATAPLANES)
69                     raise DeploySettingsException(
70                         "Invalid dataplane {} specified. Valid dataplanes:"
71                         " {}".format(value, planes))
72
73         for req_set in REQ_DEPLOY_SETTINGS:
74             if req_set not in deploy_options:
75                 if req_set == 'dataplane':
76                     self.deploy_settings['deploy_options'][req_set] = 'ovs'
77                 else:
78                     self.deploy_settings['deploy_options'][req_set] = False
79
80         if 'performance' in deploy_options:
81             if not isinstance(deploy_options['performance'], dict):
82                 raise DeploySettingsException("Performance deploy_option"
83                                               "must be a dictionary.")
84             for role, role_perf_sets in deploy_options['performance'].items():
85                 if role not in VALID_ROLES:
86                     raise DeploySettingsException("Performance role {}"
87                                                   "is not valid, choose"
88                                                   "from {}".format(
89                                                       role,
90                                                       " ".join(VALID_ROLES)
91                                                   ))
92
93                 for key in role_perf_sets:
94                     if key not in VALID_PERF_OPTS:
95                         raise DeploySettingsException("Performance option {} "
96                                                       "is not valid, choose"
97                                                       "from {}".format(
98                                                           key,
99                                                           " ".join(
100                                                               VALID_PERF_OPTS)
101                                                       ))
102
103     def _dump_performance(self):
104         """
105         Creates performance settings string for bash consumption.
106
107         Output will be in the form of a list that can be iterated over in
108         bash, with each string being the direct input to the performance
109         setting script in the form <role> <category> <key> <value> to
110         facilitate modification of the correct image.
111         """
112         bash_str = 'performance_options=(\n'
113         deploy_options = self.deploy_settings['deploy_options']
114         for role, settings in deploy_options['performance'].items():
115             for category, options in settings.items():
116                 for key, value in options.items():
117                     bash_str += "\"{} {} {} {}\"\n".format(role,
118                                                            category,
119                                                            key,
120                                                            value)
121         bash_str += ')\n'
122         bash_str += '\n'
123         bash_str += 'performance_roles=(\n'
124         for role in self.deploy_settings['deploy_options']['performance']:
125             bash_str += role + '\n'
126         bash_str += ')\n'
127         bash_str += '\n'
128
129         return bash_str
130
131     def _dump_deploy_options_array(self):
132         """
133         Creates deploy settings array in bash syntax.
134         """
135         bash_str = ''
136         for key, value in self.deploy_settings['deploy_options'].items():
137             if not isinstance(value, bool):
138                 bash_str += "deploy_options_array[{}]=\"{}\"\n".format(key,
139                                                                        value)
140             else:
141                 bash_str += "deploy_options_array[{}]={}\n".format(key,
142                                                                    value)
143         return bash_str
144
145     def dump_bash(self, path=None):
146         """
147         Prints settings for bash consumption.
148
149         If optional path is provided, bash string will be written to the file
150         instead of stdout.
151         """
152         bash_str = ''
153         for key, value in self.deploy_settings['global_params'].items():
154             bash_str += "{}={}\n".format(key, value)
155         if 'performance' in self.deploy_settings['deploy_options']:
156             bash_str += self._dump_performance()
157         bash_str += self._dump_deploy_options_array()
158
159         if path:
160             with open(path, 'w') as file:
161                 file.write(bash_str)
162         else:
163             print(bash_str)
164
165
166 class DeploySettingsException(Exception):
167     def __init__(self, value):
168         self.value = value
169
170     def __str__(self):
171         return self.value