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