Adds stripped down ODL CSIT deployment
[apex.git] / lib / python / apex / deploy_settings.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                        'ceph']
24
25 OPT_DEPLOY_SETTINGS = ['performance', 'vsperf', 'ceph_device']
26
27 VALID_ROLES = ['Controller', 'Compute', 'ObjectStorage']
28 VALID_PERF_OPTS = ['kernel', 'nova', 'vpp']
29 VALID_DATAPLANES = ['ovs', 'ovs_dpdk', 'fdio']
30
31
32 class DeploySettings(dict):
33     """
34     This class parses a APEX deploy settings yaml file into an object
35
36     Currently the parsed object is dumped into a bash global definition file
37     for deploy.sh consumption. This object will later be used directly as
38     deployment script move to python.
39     """
40     def __init__(self, filename):
41         init_dict = {}
42         if isinstance(filename, str):
43             with open(filename, 'r') as deploy_settings_file:
44                 init_dict = yaml.safe_load(deploy_settings_file)
45         else:
46             # assume input is a dict to build from
47             init_dict = filename
48
49         super().__init__(init_dict)
50         self._validate_settings()
51
52     def _validate_settings(self):
53         """
54         Validates the deploy settings file provided
55
56         DeploySettingsException will be raised if validation fails.
57         """
58
59         if 'deploy_options' not in self:
60             raise DeploySettingsException("No deploy options provided in"
61                                           " deploy settings file")
62         if 'global_params' not in self:
63             raise DeploySettingsException("No global options provided in"
64                                           " deploy settings file")
65
66         deploy_options = self['deploy_options']
67         if not isinstance(deploy_options, dict):
68             raise DeploySettingsException("deploy_options should be a list")
69
70         for setting, value in deploy_options.items():
71             if setting not in REQ_DEPLOY_SETTINGS + OPT_DEPLOY_SETTINGS:
72                 raise DeploySettingsException("Invalid deploy_option {} "
73                                               "specified".format(setting))
74             if setting == 'dataplane':
75                 if value not in VALID_DATAPLANES:
76                     planes = ' '.join(VALID_DATAPLANES)
77                     raise DeploySettingsException(
78                         "Invalid dataplane {} specified. Valid dataplanes:"
79                         " {}".format(value, planes))
80
81         for req_set in REQ_DEPLOY_SETTINGS:
82             if req_set not in deploy_options:
83                 if req_set == 'dataplane':
84                     self['deploy_options'][req_set] = 'ovs'
85                 else:
86                     self['deploy_options'][req_set] = False
87
88         if 'performance' in deploy_options:
89             if not isinstance(deploy_options['performance'], dict):
90                 raise DeploySettingsException("Performance deploy_option"
91                                               "must be a dictionary.")
92             for role, role_perf_sets in deploy_options['performance'].items():
93                 if role not in VALID_ROLES:
94                     raise DeploySettingsException("Performance role {}"
95                                                   "is not valid, choose"
96                                                   "from {}".format(
97                                                       role,
98                                                       " ".join(VALID_ROLES)
99                                                   ))
100
101                 for key in role_perf_sets:
102                     if key not in VALID_PERF_OPTS:
103                         raise DeploySettingsException("Performance option {} "
104                                                       "is not valid, choose"
105                                                       "from {}".format(
106                                                           key,
107                                                           " ".join(
108                                                               VALID_PERF_OPTS)
109                                                       ))
110
111     def _dump_performance(self):
112         """
113         Creates performance settings string for bash consumption.
114
115         Output will be in the form of a list that can be iterated over in
116         bash, with each string being the direct input to the performance
117         setting script in the form <role> <category> <key> <value> to
118         facilitate modification of the correct image.
119         """
120         bash_str = 'performance_options=(\n'
121         deploy_options = self['deploy_options']
122         for role, settings in deploy_options['performance'].items():
123             for category, options in settings.items():
124                 for key, value in options.items():
125                     bash_str += "\"{} {} {} {}\"\n".format(role,
126                                                            category,
127                                                            key,
128                                                            value)
129         bash_str += ')\n'
130         bash_str += '\n'
131         bash_str += 'performance_roles=(\n'
132         for role in self['deploy_options']['performance']:
133             bash_str += role + '\n'
134         bash_str += ')\n'
135         bash_str += '\n'
136
137         return bash_str
138
139     def _dump_deploy_options_array(self):
140         """
141         Creates deploy settings array in bash syntax.
142         """
143         bash_str = ''
144         for key, value in self['deploy_options'].items():
145             if not isinstance(value, bool):
146                 bash_str += "deploy_options_array[{}]=\"{}\"\n".format(key,
147                                                                        value)
148             else:
149                 bash_str += "deploy_options_array[{}]={}\n".format(key,
150                                                                    value)
151         return bash_str
152
153     def dump_bash(self, path=None):
154         """
155         Prints settings for bash consumption.
156
157         If optional path is provided, bash string will be written to the file
158         instead of stdout.
159         """
160         bash_str = ''
161         for key, value in self['global_params'].items():
162             bash_str += "{}={}\n".format(key, value)
163         if 'performance' in self['deploy_options']:
164             bash_str += self._dump_performance()
165         bash_str += self._dump_deploy_options_array()
166
167         if path:
168             with open(path, 'w') as file:
169                 file.write(bash_str)
170         else:
171             print(bash_str)
172
173
174 class DeploySettingsException(Exception):
175     def __init__(self, value):
176         self.value = value
177
178     def __str__(self):
179         return self.value