fix bug 802 decrypt vrops_password at vim_account for schema_version>=1.1
[osm/LCM.git] / osm_lcm / vim_sdn.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2018 Telefonica S.A.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
16 # under the License.
17 ##
18
19 import asyncio
20 import logging
21 import logging.handlers
22 import ROclient
23 from lcm_utils import LcmException, LcmBase
24 from osm_common.dbbase import DbException
25 from copy import deepcopy
26
27 __author__ = "Alfonso Tierno"
28
29
30 class VimLcm(LcmBase):
31 # values that are encrypted at vim config because they are passwords
32 vim_config_encrypted = {"1.1": ("admin_password", "nsx_password", "vcenter_password"),
33 "default": ("admin_password", "nsx_password", "vcenter_password", "vrops_password")}
34
35 def __init__(self, db, msg, fs, lcm_tasks, ro_config, loop):
36 """
37 Init, Connect to database, filesystem storage, and messaging
38 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
39 :return: None
40 """
41
42 self.logger = logging.getLogger('lcm.vim')
43 self.loop = loop
44 self.lcm_tasks = lcm_tasks
45 self.ro_config = ro_config
46
47 super().__init__(db, msg, fs, self.logger)
48
49 async def create(self, vim_content, order_id):
50 vim_id = vim_content["_id"]
51 vim_content.pop("op_id", None)
52 logging_text = "Task vim_create={} ".format(vim_id)
53 self.logger.debug(logging_text + "Enter")
54 db_vim = None
55 db_vim_update = {}
56 exc = None
57 RO_sdn_id = None
58 try:
59 step = "Getting vim-id='{}' from db".format(vim_id)
60 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
61 if vim_content.get("config") and vim_content["config"].get("sdn-controller"):
62 step = "Getting sdn-controller-id='{}' from db".format(vim_content["config"]["sdn-controller"])
63 db_sdn = self.db.get_one("sdns", {"_id": vim_content["config"]["sdn-controller"]})
64 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
65 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
66 else:
67 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
68 vim_content["config"]["sdn-controller"]))
69
70 step = "Creating vim at RO"
71 db_vim_update["_admin.deployed.RO"] = None
72 db_vim_update["_admin.detailed-status"] = step
73 self.update_db_2("vim_accounts", vim_id, db_vim_update)
74 RO = ROclient.ROClient(self.loop, **self.ro_config)
75 vim_RO = deepcopy(vim_content)
76 vim_RO.pop("_id", None)
77 vim_RO.pop("_admin", None)
78 schema_version = vim_RO.pop("schema_version", None)
79 vim_RO.pop("schema_type", None)
80 vim_RO.pop("vim_tenant_name", None)
81 vim_RO["type"] = vim_RO.pop("vim_type")
82 vim_RO.pop("vim_user", None)
83 vim_RO.pop("vim_password", None)
84 if RO_sdn_id:
85 vim_RO["config"]["sdn-controller"] = RO_sdn_id
86 desc = await RO.create("vim", descriptor=vim_RO)
87 RO_vim_id = desc["uuid"]
88 db_vim_update["_admin.deployed.RO"] = RO_vim_id
89 self.logger.debug(logging_text + "VIM created at RO_vim_id={}".format(RO_vim_id))
90
91 step = "Creating vim_account at RO"
92 db_vim_update["_admin.detailed-status"] = step
93 self.update_db_2("vim_accounts", vim_id, db_vim_update)
94
95 if vim_content.get("vim_password"):
96 vim_content["vim_password"] = self.db.decrypt(vim_content["vim_password"],
97 schema_version=schema_version,
98 salt=vim_id)
99 vim_account_RO = {"vim_tenant_name": vim_content["vim_tenant_name"],
100 "vim_username": vim_content["vim_user"],
101 "vim_password": vim_content["vim_password"]
102 }
103 if vim_RO.get("config"):
104 vim_account_RO["config"] = vim_RO["config"]
105 if "sdn-controller" in vim_account_RO["config"]:
106 del vim_account_RO["config"]["sdn-controller"]
107 if "sdn-port-mapping" in vim_account_RO["config"]:
108 del vim_account_RO["config"]["sdn-port-mapping"]
109 vim_config_encrypted_keys = self.vim_config_encrypted.get(schema_version) or \
110 self.vim_config_encrypted.get("default")
111 for p in vim_config_encrypted_keys:
112 if vim_account_RO["config"].get(p):
113 vim_account_RO["config"][p] = self.db.decrypt(vim_account_RO["config"][p],
114 schema_version=schema_version,
115 salt=vim_id)
116
117 desc = await RO.attach("vim_account", RO_vim_id, descriptor=vim_account_RO)
118 db_vim_update["_admin.deployed.RO-account"] = desc["uuid"]
119 db_vim_update["_admin.operationalState"] = "ENABLED"
120 db_vim_update["_admin.detailed-status"] = "Done"
121
122 # await asyncio.sleep(15) # TODO remove. This is for test
123 self.logger.debug(logging_text + "Exit Ok VIM account created at RO_vim_account_id={}".format(desc["uuid"]))
124 return
125
126 except (ROclient.ROClientException, DbException) as e:
127 self.logger.error(logging_text + "Exit Exception {}".format(e))
128 exc = e
129 except Exception as e:
130 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
131 exc = e
132 finally:
133 if exc and db_vim:
134 db_vim_update["_admin.operationalState"] = "ERROR"
135 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
136 try:
137 if db_vim_update:
138 self.update_db_2("vim_accounts", vim_id, db_vim_update)
139 except DbException as e:
140 self.logger.error(logging_text + "Cannot update database: {}".format(e))
141
142 self.lcm_tasks.remove("vim_account", vim_id, order_id)
143
144 async def edit(self, vim_content, order_id):
145 vim_id = vim_content["_id"]
146 vim_content.pop("op_id", None)
147 logging_text = "Task vim_edit={} ".format(vim_id)
148 self.logger.debug(logging_text + "Enter")
149 db_vim = None
150 exc = None
151 RO_sdn_id = None
152 RO_vim_id = None
153 db_vim_update = {}
154 step = "Getting vim-id='{}' from db".format(vim_id)
155 try:
156 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
157
158 # look if previous tasks in process
159 task_name, task_dependency = self.lcm_tasks.lookfor_related("vim_account", vim_id, order_id)
160 if task_dependency:
161 step = "Waiting for related tasks to be completed: {}".format(task_name)
162 self.logger.debug(logging_text + step)
163 # TODO write this to database
164 _, pending = await asyncio.wait(task_dependency, timeout=3600)
165 if pending:
166 raise LcmException("Timeout waiting related tasks to be completed")
167
168 if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"):
169 if vim_content.get("config") and vim_content["config"].get("sdn-controller"):
170 step = "Getting sdn-controller-id='{}' from db".format(vim_content["config"]["sdn-controller"])
171 db_sdn = self.db.get_one("sdns", {"_id": vim_content["config"]["sdn-controller"]})
172
173 # look if previous tasks in process
174 task_name, task_dependency = self.lcm_tasks.lookfor_related("sdn", db_sdn["_id"])
175 if task_dependency:
176 step = "Waiting for related tasks to be completed: {}".format(task_name)
177 self.logger.debug(logging_text + step)
178 # TODO write this to database
179 _, pending = await asyncio.wait(task_dependency, timeout=3600)
180 if pending:
181 raise LcmException("Timeout waiting related tasks to be completed")
182
183 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get(
184 "RO"):
185 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
186 else:
187 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
188 vim_content["config"]["sdn-controller"]))
189
190 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
191 step = "Editing vim at RO"
192 RO = ROclient.ROClient(self.loop, **self.ro_config)
193 vim_RO = deepcopy(vim_content)
194 vim_RO.pop("_id", None)
195 vim_RO.pop("_admin", None)
196 schema_version = vim_RO.pop("schema_version", None)
197 vim_RO.pop("schema_type", None)
198 vim_RO.pop("vim_tenant_name", None)
199 if "vim_type" in vim_RO:
200 vim_RO["type"] = vim_RO.pop("vim_type")
201 vim_RO.pop("vim_user", None)
202 vim_RO.pop("vim_password", None)
203 if RO_sdn_id:
204 vim_RO["config"]["sdn-controller"] = RO_sdn_id
205 # TODO make a deep update of sdn-port-mapping
206 if vim_RO:
207 await RO.edit("vim", RO_vim_id, descriptor=vim_RO)
208
209 step = "Editing vim-account at RO tenant"
210 vim_account_RO = {}
211 if "config" in vim_content:
212 if "sdn-controller" in vim_content["config"]:
213 del vim_content["config"]["sdn-controller"]
214 if "sdn-port-mapping" in vim_content["config"]:
215 del vim_content["config"]["sdn-port-mapping"]
216 if not vim_content["config"]:
217 del vim_content["config"]
218 if "vim_tenant_name" in vim_content:
219 vim_account_RO["vim_tenant_name"] = vim_content["vim_tenant_name"]
220 if "vim_password" in vim_content:
221 vim_account_RO["vim_password"] = vim_content["vim_password"]
222 if vim_content.get("vim_password"):
223 vim_account_RO["vim_password"] = self.db.decrypt(vim_content["vim_password"],
224 schema_version=schema_version,
225 salt=vim_id)
226 if "config" in vim_content:
227 vim_account_RO["config"] = vim_content["config"]
228 if vim_content.get("config"):
229 vim_config_encrypted_keys = self.vim_config_encrypted.get(schema_version) or \
230 self.vim_config_encrypted.get("default")
231 for p in vim_config_encrypted_keys:
232 if vim_content["config"].get(p):
233 vim_account_RO["config"][p] = self.db.decrypt(vim_content["config"][p],
234 schema_version=schema_version,
235 salt=vim_id)
236
237 if "vim_user" in vim_content:
238 vim_content["vim_username"] = vim_content["vim_user"]
239 # vim_account must be edited always even if empty in order to ensure changes are translated to RO
240 # vim_thread. RO will remove and relaunch a new thread for this vim_account
241 await RO.edit("vim_account", RO_vim_id, descriptor=vim_account_RO)
242 db_vim_update["_admin.operationalState"] = "ENABLED"
243
244 self.logger.debug(logging_text + "Exit Ok RO_vim_id={}".format(RO_vim_id))
245 return
246
247 except (ROclient.ROClientException, DbException) as e:
248 self.logger.error(logging_text + "Exit Exception {}".format(e))
249 exc = e
250 except Exception as e:
251 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
252 exc = e
253 finally:
254 if exc and db_vim:
255 db_vim_update["_admin.operationalState"] = "ERROR"
256 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
257 try:
258 if db_vim_update:
259 self.update_db_2("vim_accounts", vim_id, db_vim_update)
260 except DbException as e:
261 self.logger.error(logging_text + "Cannot update database: {}".format(e))
262
263 self.lcm_tasks.remove("vim_account", vim_id, order_id)
264
265 async def delete(self, vim_id, order_id):
266 logging_text = "Task vim_delete={} ".format(vim_id)
267 self.logger.debug(logging_text + "Enter")
268 db_vim = None
269 db_vim_update = {}
270 exc = None
271 step = "Getting vim from db"
272 try:
273 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
274 if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"):
275 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
276 RO = ROclient.ROClient(self.loop, **self.ro_config)
277 step = "Detaching vim from RO tenant"
278 try:
279 await RO.detach("vim_account", RO_vim_id)
280 except ROclient.ROClientException as e:
281 if e.http_code == 404: # not found
282 self.logger.debug(logging_text + "RO_vim_id={} already detached".format(RO_vim_id))
283 else:
284 raise
285
286 step = "Deleting vim from RO"
287 try:
288 await RO.delete("vim", RO_vim_id)
289 except ROclient.ROClientException as e:
290 if e.http_code == 404: # not found
291 self.logger.debug(logging_text + "RO_vim_id={} already deleted".format(RO_vim_id))
292 else:
293 raise
294 else:
295 # nothing to delete
296 self.logger.error(logging_text + "Nohing to remove at RO")
297 self.db.del_one("vim_accounts", {"_id": vim_id})
298 db_vim = None
299 self.logger.debug(logging_text + "Exit Ok")
300 return
301
302 except (ROclient.ROClientException, DbException) as e:
303 self.logger.error(logging_text + "Exit Exception {}".format(e))
304 exc = e
305 except Exception as e:
306 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
307 exc = e
308 finally:
309 self.lcm_tasks.remove("vim_account", vim_id, order_id)
310 if exc and db_vim:
311 db_vim_update["_admin.operationalState"] = "ERROR"
312 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
313 try:
314 if db_vim and db_vim_update:
315 self.update_db_2("vim_accounts", vim_id, db_vim_update)
316 except DbException as e:
317 self.logger.error(logging_text + "Cannot update database: {}".format(e))
318 self.lcm_tasks.remove("vim_account", vim_id, order_id)
319
320
321 class WimLcm(LcmBase):
322 # values that are encrypted at wim config because they are passwords
323 wim_config_encrypted = ()
324
325 def __init__(self, db, msg, fs, lcm_tasks, ro_config, loop):
326 """
327 Init, Connect to database, filesystem storage, and messaging
328 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
329 :return: None
330 """
331
332 self.logger = logging.getLogger('lcm.vim')
333 self.loop = loop
334 self.lcm_tasks = lcm_tasks
335 self.ro_config = ro_config
336
337 super().__init__(db, msg, fs, self.logger)
338
339 async def create(self, wim_content, order_id):
340 wim_id = wim_content["_id"]
341 wim_content.pop("op_id", None)
342 logging_text = "Task wim_create={} ".format(wim_id)
343 self.logger.debug(logging_text + "Enter")
344 db_wim = None
345 db_wim_update = {}
346 exc = None
347 try:
348 step = "Getting wim-id='{}' from db".format(wim_id)
349 db_wim = self.db.get_one("wim_accounts", {"_id": wim_id})
350 db_wim_update["_admin.deployed.RO"] = None
351
352 step = "Creating wim at RO"
353 db_wim_update["_admin.detailed-status"] = step
354 self.update_db_2("wim_accounts", wim_id, db_wim_update)
355 RO = ROclient.ROClient(self.loop, **self.ro_config)
356 wim_RO = deepcopy(wim_content)
357 wim_RO.pop("_id", None)
358 wim_RO.pop("_admin", None)
359 schema_version = wim_RO.pop("schema_version", None)
360 wim_RO.pop("schema_type", None)
361 wim_RO.pop("wim_tenant_name", None)
362 wim_RO["type"] = wim_RO.pop("wim_type")
363 wim_RO.pop("wim_user", None)
364 wim_RO.pop("wim_password", None)
365 desc = await RO.create("wim", descriptor=wim_RO)
366 RO_wim_id = desc["uuid"]
367 db_wim_update["_admin.deployed.RO"] = RO_wim_id
368 self.logger.debug(logging_text + "WIM created at RO_wim_id={}".format(RO_wim_id))
369
370 step = "Creating wim_account at RO"
371 db_wim_update["_admin.detailed-status"] = step
372 self.update_db_2("wim_accounts", wim_id, db_wim_update)
373
374 if wim_content.get("wim_password"):
375 wim_content["wim_password"] = self.db.decrypt(wim_content["wim_password"],
376 schema_version=schema_version,
377 salt=wim_id)
378 wim_account_RO = {"name": wim_content["name"],
379 "user": wim_content["user"],
380 "password": wim_content["password"]
381 }
382 if wim_RO.get("config"):
383 wim_account_RO["config"] = wim_RO["config"]
384 if "wim_port_mapping" in wim_account_RO["config"]:
385 del wim_account_RO["config"]["wim_port_mapping"]
386 for p in self.wim_config_encrypted:
387 if wim_account_RO["config"].get(p):
388 wim_account_RO["config"][p] = self.db.decrypt(wim_account_RO["config"][p],
389 schema_version=schema_version,
390 salt=wim_id)
391
392 desc = await RO.attach("wim_account", RO_wim_id, descriptor=wim_account_RO)
393 db_wim_update["_admin.deployed.RO-account"] = desc["uuid"]
394 db_wim_update["_admin.operationalState"] = "ENABLED"
395 db_wim_update["_admin.detailed-status"] = "Done"
396
397 self.logger.debug(logging_text + "Exit Ok WIM account created at RO_wim_account_id={}".format(desc["uuid"]))
398 return
399
400 except (ROclient.ROClientException, DbException) as e:
401 self.logger.error(logging_text + "Exit Exception {}".format(e))
402 exc = e
403 except Exception as e:
404 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
405 exc = e
406 finally:
407 if exc and db_wim:
408 db_wim_update["_admin.operationalState"] = "ERROR"
409 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
410 try:
411 if db_wim_update:
412 self.update_db_2("wim_accounts", wim_id, db_wim_update)
413 except DbException as e:
414 self.logger.error(logging_text + "Cannot update database: {}".format(e))
415 self.lcm_tasks.remove("wim_account", wim_id, order_id)
416
417 async def edit(self, wim_content, order_id):
418 wim_id = wim_content["_id"]
419 wim_content.pop("op_id", None)
420 logging_text = "Task wim_edit={} ".format(wim_id)
421 self.logger.debug(logging_text + "Enter")
422 db_wim = None
423 exc = None
424 RO_wim_id = None
425 db_wim_update = {}
426 step = "Getting wim-id='{}' from db".format(wim_id)
427 try:
428 db_wim = self.db.get_one("wim_accounts", {"_id": wim_id})
429
430 # look if previous tasks in process
431 task_name, task_dependency = self.lcm_tasks.lookfor_related("wim_account", wim_id, order_id)
432 if task_dependency:
433 step = "Waiting for related tasks to be completed: {}".format(task_name)
434 self.logger.debug(logging_text + step)
435 # TODO write this to database
436 _, pending = await asyncio.wait(task_dependency, timeout=3600)
437 if pending:
438 raise LcmException("Timeout waiting related tasks to be completed")
439
440 if db_wim.get("_admin") and db_wim["_admin"].get("deployed") and db_wim["_admin"]["deployed"].get("RO"):
441
442 RO_wim_id = db_wim["_admin"]["deployed"]["RO"]
443 step = "Editing wim at RO"
444 RO = ROclient.ROClient(self.loop, **self.ro_config)
445 wim_RO = deepcopy(wim_content)
446 wim_RO.pop("_id", None)
447 wim_RO.pop("_admin", None)
448 schema_version = wim_RO.pop("schema_version", None)
449 wim_RO.pop("schema_type", None)
450 wim_RO.pop("wim_tenant_name", None)
451 if "wim_type" in wim_RO:
452 wim_RO["type"] = wim_RO.pop("wim_type")
453 wim_RO.pop("wim_user", None)
454 wim_RO.pop("wim_password", None)
455 # TODO make a deep update of wim_port_mapping
456 if wim_RO:
457 await RO.edit("wim", RO_wim_id, descriptor=wim_RO)
458
459 step = "Editing wim-account at RO tenant"
460 wim_account_RO = {}
461 if "config" in wim_content:
462 if "wim_port_mapping" in wim_content["config"]:
463 del wim_content["config"]["wim_port_mapping"]
464 if not wim_content["config"]:
465 del wim_content["config"]
466 if "wim_tenant_name" in wim_content:
467 wim_account_RO["wim_tenant_name"] = wim_content["wim_tenant_name"]
468 if "wim_password" in wim_content:
469 wim_account_RO["wim_password"] = wim_content["wim_password"]
470 if wim_content.get("wim_password"):
471 wim_account_RO["wim_password"] = self.db.decrypt(wim_content["wim_password"],
472 schema_version=schema_version,
473 salt=wim_id)
474 if "config" in wim_content:
475 wim_account_RO["config"] = wim_content["config"]
476 if wim_content.get("config"):
477 for p in self.wim_config_encrypted:
478 if wim_content["config"].get(p):
479 wim_account_RO["config"][p] = self.db.decrypt(wim_content["config"][p],
480 schema_version=schema_version,
481 salt=wim_id)
482
483 if "wim_user" in wim_content:
484 wim_content["wim_username"] = wim_content["wim_user"]
485 # wim_account must be edited always even if empty in order to ensure changes are translated to RO
486 # wim_thread. RO will remove and relaunch a new thread for this wim_account
487 await RO.edit("wim_account", RO_wim_id, descriptor=wim_account_RO)
488 db_wim_update["_admin.operationalState"] = "ENABLED"
489
490 self.logger.debug(logging_text + "Exit Ok RO_wim_id={}".format(RO_wim_id))
491 return
492
493 except (ROclient.ROClientException, DbException) as e:
494 self.logger.error(logging_text + "Exit Exception {}".format(e))
495 exc = e
496 except Exception as e:
497 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
498 exc = e
499 finally:
500 if exc and db_wim:
501 db_wim_update["_admin.operationalState"] = "ERROR"
502 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
503 try:
504 if db_wim_update:
505 self.update_db_2("wim_accounts", wim_id, db_wim_update)
506 except DbException as e:
507 self.logger.error(logging_text + "Cannot update database: {}".format(e))
508 self.lcm_tasks.remove("wim_account", wim_id, order_id)
509
510 async def delete(self, wim_id, order_id):
511 logging_text = "Task wim_delete={} ".format(wim_id)
512 self.logger.debug(logging_text + "Enter")
513 db_wim = None
514 db_wim_update = {}
515 exc = None
516 step = "Getting wim from db"
517 try:
518 db_wim = self.db.get_one("wim_accounts", {"_id": wim_id})
519 if db_wim.get("_admin") and db_wim["_admin"].get("deployed") and db_wim["_admin"]["deployed"].get("RO"):
520 RO_wim_id = db_wim["_admin"]["deployed"]["RO"]
521 RO = ROclient.ROClient(self.loop, **self.ro_config)
522 step = "Detaching wim from RO tenant"
523 try:
524 await RO.detach("wim_account", RO_wim_id)
525 except ROclient.ROClientException as e:
526 if e.http_code == 404: # not found
527 self.logger.debug(logging_text + "RO_wim_id={} already detached".format(RO_wim_id))
528 else:
529 raise
530
531 step = "Deleting wim from RO"
532 try:
533 await RO.delete("wim", RO_wim_id)
534 except ROclient.ROClientException as e:
535 if e.http_code == 404: # not found
536 self.logger.debug(logging_text + "RO_wim_id={} already deleted".format(RO_wim_id))
537 else:
538 raise
539 else:
540 # nothing to delete
541 self.logger.error(logging_text + "Nohing to remove at RO")
542 self.db.del_one("wim_accounts", {"_id": wim_id})
543 db_wim = None
544 self.logger.debug(logging_text + "Exit Ok")
545 return
546
547 except (ROclient.ROClientException, DbException) as e:
548 self.logger.error(logging_text + "Exit Exception {}".format(e))
549 exc = e
550 except Exception as e:
551 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
552 exc = e
553 finally:
554 self.lcm_tasks.remove("wim_account", wim_id, order_id)
555 if exc and db_wim:
556 db_wim_update["_admin.operationalState"] = "ERROR"
557 db_wim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
558 try:
559 if db_wim and db_wim_update:
560 self.update_db_2("wim_accounts", wim_id, db_wim_update)
561 except DbException as e:
562 self.logger.error(logging_text + "Cannot update database: {}".format(e))
563 self.lcm_tasks.remove("wim_account", wim_id, order_id)
564
565
566 class SdnLcm(LcmBase):
567
568 def __init__(self, db, msg, fs, lcm_tasks, ro_config, loop):
569 """
570 Init, Connect to database, filesystem storage, and messaging
571 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
572 :return: None
573 """
574
575 self.logger = logging.getLogger('lcm.sdn')
576 self.loop = loop
577 self.lcm_tasks = lcm_tasks
578 self.ro_config = ro_config
579
580 super().__init__(db, msg, fs, self.logger)
581
582 async def create(self, sdn_content, order_id):
583 sdn_id = sdn_content["_id"]
584 sdn_content.pop("op_id", None)
585 logging_text = "Task sdn_create={} ".format(sdn_id)
586 self.logger.debug(logging_text + "Enter")
587 db_sdn = None
588 db_sdn_update = {}
589 RO_sdn_id = None
590 exc = None
591 try:
592 step = "Getting sdn from db"
593 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
594 db_sdn_update["_admin.deployed.RO"] = None
595
596 step = "Creating sdn at RO"
597 db_sdn_update["_admin.detailed-status"] = step
598 self.update_db_2("sdns", sdn_id, db_sdn_update)
599
600 RO = ROclient.ROClient(self.loop, **self.ro_config)
601 sdn_RO = deepcopy(sdn_content)
602 sdn_RO.pop("_id", None)
603 sdn_RO.pop("_admin", None)
604 schema_version = sdn_RO.pop("schema_version", None)
605 sdn_RO.pop("schema_type", None)
606 sdn_RO.pop("description", None)
607 if sdn_RO.get("password"):
608 sdn_RO["password"] = self.db.decrypt(sdn_RO["password"], schema_version=schema_version, salt=sdn_id)
609
610 desc = await RO.create("sdn", descriptor=sdn_RO)
611 RO_sdn_id = desc["uuid"]
612 db_sdn_update["_admin.deployed.RO"] = RO_sdn_id
613 db_sdn_update["_admin.operationalState"] = "ENABLED"
614 self.logger.debug(logging_text + "Exit Ok RO_sdn_id={}".format(RO_sdn_id))
615 return
616
617 except (ROclient.ROClientException, DbException) as e:
618 self.logger.error(logging_text + "Exit Exception {}".format(e))
619 exc = e
620 except Exception as e:
621 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
622 exc = e
623 finally:
624 if exc and db_sdn:
625 db_sdn_update["_admin.operationalState"] = "ERROR"
626 db_sdn_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
627 try:
628 if db_sdn and db_sdn_update:
629 self.update_db_2("sdns", sdn_id, db_sdn_update)
630 except DbException as e:
631 self.logger.error(logging_text + "Cannot update database: {}".format(e))
632 self.lcm_tasks.remove("sdn", sdn_id, order_id)
633
634 async def edit(self, sdn_content, order_id):
635 sdn_id = sdn_content["_id"]
636 sdn_content.pop("op_id", None)
637 logging_text = "Task sdn_edit={} ".format(sdn_id)
638 self.logger.debug(logging_text + "Enter")
639 db_sdn = None
640 db_sdn_update = {}
641 exc = None
642 step = "Getting sdn from db"
643 try:
644 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
645 RO_sdn_id = None
646 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
647 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
648 RO = ROclient.ROClient(self.loop, **self.ro_config)
649 step = "Editing sdn at RO"
650 sdn_RO = deepcopy(sdn_content)
651 sdn_RO.pop("_id", None)
652 sdn_RO.pop("_admin", None)
653 schema_version = sdn_RO.pop("schema_version", None)
654 sdn_RO.pop("schema_type", None)
655 sdn_RO.pop("description", None)
656 if sdn_RO.get("password"):
657 sdn_RO["password"] = self.db.decrypt(sdn_RO["password"], schema_version=schema_version, salt=sdn_id)
658 if sdn_RO:
659 await RO.edit("sdn", RO_sdn_id, descriptor=sdn_RO)
660 db_sdn_update["_admin.operationalState"] = "ENABLED"
661
662 self.logger.debug(logging_text + "Exit Ok RO_sdn_id={}".format(RO_sdn_id))
663 return
664
665 except (ROclient.ROClientException, DbException) as e:
666 self.logger.error(logging_text + "Exit Exception {}".format(e))
667 exc = e
668 except Exception as e:
669 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
670 exc = e
671 finally:
672 if exc and db_sdn:
673 db_sdn["_admin.operationalState"] = "ERROR"
674 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
675 try:
676 if db_sdn_update:
677 self.update_db_2("sdns", sdn_id, db_sdn_update)
678 except DbException as e:
679 self.logger.error(logging_text + "Cannot update database: {}".format(e))
680 self.lcm_tasks.remove("sdn", sdn_id, order_id)
681
682 async def delete(self, sdn_id, order_id):
683 logging_text = "Task sdn_delete={} ".format(sdn_id)
684 self.logger.debug(logging_text + "Enter")
685 db_sdn = None
686 db_sdn_update = {}
687 exc = None
688 step = "Getting sdn from db"
689 try:
690 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
691 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
692 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
693 RO = ROclient.ROClient(self.loop, **self.ro_config)
694 step = "Deleting sdn from RO"
695 try:
696 await RO.delete("sdn", RO_sdn_id)
697 except ROclient.ROClientException as e:
698 if e.http_code == 404: # not found
699 self.logger.debug(logging_text + "RO_sdn_id={} already deleted".format(RO_sdn_id))
700 else:
701 raise
702 else:
703 # nothing to delete
704 self.logger.error(logging_text + "Skipping. There is not RO information at database")
705 self.db.del_one("sdns", {"_id": sdn_id})
706 db_sdn = None
707 self.logger.debug("sdn_delete task sdn_id={} Exit Ok".format(sdn_id))
708 return
709
710 except (ROclient.ROClientException, DbException) as e:
711 self.logger.error(logging_text + "Exit Exception {}".format(e))
712 exc = e
713 except Exception as e:
714 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
715 exc = e
716 finally:
717 if exc and db_sdn:
718 db_sdn["_admin.operationalState"] = "ERROR"
719 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
720 try:
721 if db_sdn and db_sdn_update:
722 self.update_db_2("sdns", sdn_id, db_sdn_update)
723 except DbException as e:
724 self.logger.error(logging_text + "Cannot update database: {}".format(e))
725 self.lcm_tasks.remove("sdn", sdn_id, order_id)