11 ArgParser = common.ArgParser
12 exec_cmd = common.exec_cmd
16 delete_file = common.delete_file
17 commafy = common.commafy
20 title: Deployment Environment Adapter (DEA)
21 # DEA API version supported
28 title: Deployment Hardware Adapter (DHA)
29 # DHA API version supported
34 # Adapter to use for this definition
35 # adapter: [ipmi|libvirt]
39 # Mandatory properties are id and role.
40 # All other properties are adapter specific.
41 # For Non-Fuel nodes controlled by:
42 # - ipmi adapter you need to provide:
47 # - libvirt adapter you need to provide:
48 # libvirtName: <whatever>
49 # libvirtTemplate: [libvirt/vms/controller.xml | libvirt/vms/compute.xml]
51 # For the Fuel Node you need to provide:
52 # libvirtName: <whatever>
53 # libvirtTemplate: libvirt/vms/fuel.xml
60 # Adding the Fuel node as node id {node_id}
61 # which may not be correct - please adjust as needed.
64 DISKS = {'fuel': '30G',
70 def __init__(self, dea_file, dha_file, comment):
71 self.dea_file = dea_file
72 self.dha_file = dha_file
73 self.comment = comment
80 env_list = parse(exec_cmd('fuel env'))
82 err('Not exactly one environment')
83 self.env = env_list[0]
84 self.env_id = self.env[E['id']]
86 def download_config(self, config_type):
87 log('Download %s config for environment %s'
88 % (config_type, self.env_id))
89 exec_cmd('fuel %s --env %s --download --dir %s'
90 % (config_type, self.env_id, self.temp_dir))
92 def write(self, file, text, newline=True):
93 mode = 'a' if os.path.isfile(file) else 'w'
94 with open(file, mode) as f:
95 f.write('%s%s' % (text, ('\n' if newline else '')))
97 def write_yaml(self, file, data, newline=True):
98 self.write(file, yaml.dump(data, default_flow_style=False).strip(),
101 def get_node_by_id(self, node_list, node_id):
102 for node in node_list:
103 if node[N['id']] == node_id:
106 def reap_interface(self, node_id, interfaces):
107 interface, mac = self.get_interface(node_id)
110 if_name = self.check_dict_exists(interfaces, interface)
112 if_name = 'interfaces_%s' % str(len(interfaces) + 1)
113 interfaces[if_name] = interface
116 def reap_transformation(self, node_id, roles, transformations):
117 main_role = 'controller' if 'controller' in roles else 'compute'
118 node_file = glob.glob('%s/deployment_%s/*%s_%s.yaml'
119 % (self.temp_dir, self.env_id,
122 with open(node_file[0]) as f:
123 node_config = yaml.load(f)
124 transformation = node_config['network_scheme']['transformations']
126 tr_name = self.check_dict_exists(transformations, transformation)
128 tr_name = 'transformations_%s' % str(len(transformations) + 1)
129 transformations[tr_name] = transformation
132 def check_dict_exists(self, main_dict, dict):
133 for key, val in main_dict.iteritems():
134 if cmp(dict, val) == 0:
137 def reap_nodes_interfaces_transformations(self):
138 node_list = parse(exec_cmd('fuel node'))
139 real_node_ids = [node[N['id']] for node in node_list]
141 min_node = real_node_ids[0]
148 for real_node_id in real_node_ids:
149 node_id = int(real_node_id) - int(min_node) + 1
150 self.last_node = node_id
151 node = self.get_node_by_id(node_list, real_node_id)
152 roles = commafy(node[N['roles']])
154 err('Fuel Node %s has no role' % real_node_id)
155 dea_node = {'id': node_id,
157 dha_node = {'id': node_id}
158 if_name, mac = self.reap_interface(real_node_id, interfaces)
159 tr_name = self.reap_transformation(real_node_id, roles,
162 {'interfaces': if_name,
163 'transformations': tr_name})
166 {'pxeMac': mac if mac else None,
171 'libvirtTemplate': None})
173 dea_nodes.append(dea_node)
174 dha_nodes.append(dha_node)
176 self.write_yaml(self.dha_file, {'nodes': dha_nodes}, False)
177 self.write_yaml(self.dea_file, {'nodes': dea_nodes})
178 self.write_yaml(self.dea_file, {'interfaces': interfaces})
179 self.write_yaml(self.dea_file, {'transformations': transformations})
180 self.reap_fuel_node_info()
181 self.write_yaml(self.dha_file, {'disks': DISKS})
183 def reap_fuel_node_info(self):
186 'id': self.last_node + 1,
188 'libvirtTemplate': None,
191 'password': 'r00tme'}
193 dha_nodes.append(dha_node)
195 self.write(self.dha_file, DHA_2.format(node_id=dha_node['id']), False)
196 self.write_yaml(self.dha_file, dha_nodes)
198 def reap_environment_info(self):
199 self.write_yaml(self.dea_file,
200 {'environment_name': self.env[E['name']]})
201 self.write_yaml(self.dea_file,
202 {'environment_mode': self.env[E['mode']]})
203 wanted_release = None
204 rel_list = parse(exec_cmd('fuel release'))
206 if rel[R['id']] == self.env[E['release_id']]:
207 wanted_release = rel[R['name']]
208 self.write_yaml(self.dea_file, {'wanted_release': wanted_release})
210 def reap_fuel_settings(self):
211 data = self.read_yaml('/etc/fuel/astute.yaml')
213 del(data['ADMIN_NETWORK']['mac'])
214 del(data['ADMIN_NETWORK']['interface'])
215 for key in ['ADMIN_NETWORK', 'HOSTNAME', 'DNS_DOMAIN', 'DNS_SEARCH',
216 'DNS_UPSTREAM', 'NTP1', 'NTP2', 'NTP3', 'FUEL_ACCESS']:
217 fuel[key] = data[key]
218 self.write_yaml(self.dea_file, {'fuel': fuel})
220 def reap_network_settings(self):
221 network_file = ('%s/network_%s.yaml'
222 % (self.temp_dir, self.env_id))
223 data = self.read_yaml(network_file)
225 network['networking_parameters'] = data['networking_parameters']
226 network['networks'] = data['networks']
227 for net in network['networks']:
230 self.write_yaml(self.dea_file, {'network': network})
232 def reap_settings(self):
233 settings_file = '%s/settings_%s.yaml' % (self.temp_dir, self.env_id)
234 settings = self.read_yaml(settings_file)
235 self.write_yaml(self.dea_file, {'settings': settings})
237 def get_opnfv_astute(self, role):
238 node_files = glob.glob('%s/deployment_%s/*%s*.yaml'
239 % (self.temp_dir, self.env_id, role))
240 node_config = self.read_yaml(node_files[0])
241 return node_config['opnfv'] if 'opnfv' in node_config else {}
243 def reap_opnfv_astute(self):
244 controller_opnfv_astute = self.get_opnfv_astute('controller')
245 compute_opnfv_astute = self.get_opnfv_astute('compute')
248 'controller': controller_opnfv_astute,
249 'compute': compute_opnfv_astute}
250 self.write_yaml(self.dea_file, opnfv)
252 def get_interface(self, real_node_id):
253 exec_cmd('fuel node --node-id %s --network --download --dir %s'
254 % (real_node_id, self.temp_dir))
255 interface_file = ('%s/node_%s/interfaces.yaml'
256 % (self.temp_dir, real_node_id))
257 interfaces = self.read_yaml(interface_file)
258 interface_config = {}
260 for interface in interfaces:
262 for network in interface['assigned_networks']:
263 networks.append(network['name'])
264 if network['name'] == 'fuelweb_admin':
265 pxe_mac = interface['mac']
267 interface_config[interface['name']] = networks
268 return interface_config, pxe_mac
270 def read_yaml(self, yaml_file):
271 with open(yaml_file) as f:
276 delete_file(self.dea_file)
277 delete_file(self.dha_file)
278 self.temp_dir = exec_cmd('mktemp -d')
279 date = time.strftime('%c')
280 self.write(self.dea_file,
281 DEA_1.format(date=date, comment=self.comment), False)
282 self.write(self.dha_file,
283 DHA_1.format(date=date, comment=self.comment))
285 self.download_config('deployment')
286 self.download_config('settings')
287 self.download_config('network')
290 log('DEA file is available at %s' % self.dea_file)
291 log('DHA file is available at %s (this is just a template)'
293 shutil.rmtree(self.temp_dir)
297 self.reap_environment_info()
298 self.reap_nodes_interfaces_transformations()
299 self.reap_fuel_settings()
300 self.reap_opnfv_astute()
301 self.reap_network_settings()
308 python reap.py <dea_file> <dha_file> <comment>
311 def parse_arguments():
312 parser = ArgParser(prog='python %s' % __file__)
313 parser.add_argument('dea_file', nargs='?', action='store',
315 help='Deployment Environment Adapter: dea.yaml')
316 parser.add_argument('dha_file', nargs='?', action='store',
318 help='Deployment Hardware Adapter: dha.yaml')
319 parser.add_argument('comment', nargs='?', action='store', help='Comment')
320 args = parser.parse_args()
321 return (args.dea_file, args.dha_file, args.comment)
324 dea_file, dha_file, comment = parse_arguments()
326 r = Reap(dea_file, dha_file, comment)
329 if __name__ == '__main__':