2 # -*- coding: utf-8 -*-
6 import logging
.handlers
8 from lcm_utils
import LcmException
, LcmBase
9 from osm_common
.dbbase
import DbException
10 from copy
import deepcopy
12 __author__
= "Alfonso Tierno"
15 class VimLcm(LcmBase
):
16 # values that are encrypted at vim config because they are passwords
17 vim_config_encrypted
= ("admin_password", "nsx_password", "vcenter_password")
19 def __init__(self
, db
, msg
, fs
, lcm_tasks
, ro_config
, loop
):
21 Init, Connect to database, filesystem storage, and messaging
22 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
26 self
.logger
= logging
.getLogger('lcm.vim')
28 self
.lcm_tasks
= lcm_tasks
29 self
.ro_config
= ro_config
31 super().__init
__(db
, msg
, fs
, self
.logger
)
33 async def create(self
, vim_content
, order_id
):
34 vim_id
= vim_content
["_id"]
35 logging_text
= "Task vim_create={} ".format(vim_id
)
36 self
.logger
.debug(logging_text
+ "Enter")
42 step
= "Getting vim-id='{}' from db".format(vim_id
)
43 db_vim
= self
.db
.get_one("vim_accounts", {"_id": vim_id
})
44 db_vim_update
["_admin.deployed.RO"] = None
45 if vim_content
.get("config") and vim_content
["config"].get("sdn-controller"):
46 step
= "Getting sdn-controller-id='{}' from db".format(vim_content
["config"]["sdn-controller"])
47 db_sdn
= self
.db
.get_one("sdns", {"_id": vim_content
["config"]["sdn-controller"]})
48 if db_sdn
.get("_admin") and db_sdn
["_admin"].get("deployed") and db_sdn
["_admin"]["deployed"].get("RO"):
49 RO_sdn_id
= db_sdn
["_admin"]["deployed"]["RO"]
51 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
52 vim_content
["config"]["sdn-controller"]))
54 step
= "Creating vim at RO"
55 db_vim_update
["_admin.detailed-status"] = step
56 self
.update_db_2("vim_accounts", vim_id
, db_vim_update
)
57 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
58 vim_RO
= deepcopy(vim_content
)
59 vim_RO
.pop("_id", None)
60 vim_RO
.pop("_admin", None)
61 schema_version
= vim_RO
.pop("schema_version", None)
62 vim_RO
.pop("schema_type", None)
63 vim_RO
.pop("vim_tenant_name", None)
64 vim_RO
["type"] = vim_RO
.pop("vim_type")
65 vim_RO
.pop("vim_user", None)
66 vim_RO
.pop("vim_password", None)
68 vim_RO
["config"]["sdn-controller"] = RO_sdn_id
69 desc
= await RO
.create("vim", descriptor
=vim_RO
)
70 RO_vim_id
= desc
["uuid"]
71 db_vim_update
["_admin.deployed.RO"] = RO_vim_id
73 step
= "Creating vim_account at RO"
74 db_vim_update
["_admin.detailed-status"] = step
75 self
.update_db_2("vim_accounts", vim_id
, db_vim_update
)
77 if vim_content
.get("vim_password"):
78 vim_content
["vim_password"] = self
.db
.decrypt(vim_content
["vim_password"],
79 schema_version
=schema_version
,
81 vim_account_RO
= {"vim_tenant_name": vim_content
["vim_tenant_name"],
82 "vim_username": vim_content
["vim_user"],
83 "vim_password": vim_content
["vim_password"]
85 if vim_RO
.get("config"):
86 vim_account_RO
["config"] = vim_RO
["config"]
87 if "sdn-controller" in vim_account_RO
["config"]:
88 del vim_account_RO
["config"]["sdn-controller"]
89 if "sdn-port-mapping" in vim_account_RO
["config"]:
90 del vim_account_RO
["config"]["sdn-port-mapping"]
91 for p
in self
.vim_config_encrypted
:
92 if vim_account_RO
["config"].get(p
):
93 vim_account_RO
["config"][p
] = self
.db
.decrypt(vim_account_RO
["config"][p
],
94 schema_version
=schema_version
,
97 desc
= await RO
.attach_datacenter(RO_vim_id
, descriptor
=vim_account_RO
)
98 db_vim_update
["_admin.deployed.RO-account"] = desc
["uuid"]
99 db_vim_update
["_admin.operationalState"] = "ENABLED"
100 db_vim_update
["_admin.detailed-status"] = "Done"
102 # await asyncio.sleep(15) # TODO remove. This is for test
103 self
.logger
.debug(logging_text
+ "Exit Ok RO_vim_id={}".format(RO_vim_id
))
106 except (ROclient
.ROClientException
, DbException
) as e
:
107 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
109 except Exception as e
:
110 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
114 db_vim_update
["_admin.operationalState"] = "ERROR"
115 db_vim_update
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
117 self
.update_db_2("vim_accounts", vim_id
, db_vim_update
)
118 self
.lcm_tasks
.remove("vim_account", vim_id
, order_id
)
120 async def edit(self
, vim_content
, order_id
):
121 vim_id
= vim_content
["_id"]
122 logging_text
= "Task vim_edit={} ".format(vim_id
)
123 self
.logger
.debug(logging_text
+ "Enter")
129 step
= "Getting vim-id='{}' from db".format(vim_id
)
131 db_vim
= self
.db
.get_one("vim_accounts", {"_id": vim_id
})
133 # look if previous tasks in process
134 task_name
, task_dependency
= self
.lcm_tasks
.lookfor_related("vim_account", vim_id
, order_id
)
136 step
= "Waiting for related tasks to be completed: {}".format(task_name
)
137 self
.logger
.debug(logging_text
+ step
)
138 # TODO write this to database
139 _
, pending
= await asyncio
.wait(task_dependency
, timeout
=3600)
141 raise LcmException("Timeout waiting related tasks to be completed")
143 if db_vim
.get("_admin") and db_vim
["_admin"].get("deployed") and db_vim
["_admin"]["deployed"].get("RO"):
144 if vim_content
.get("config") and vim_content
["config"].get("sdn-controller"):
145 step
= "Getting sdn-controller-id='{}' from db".format(vim_content
["config"]["sdn-controller"])
146 db_sdn
= self
.db
.get_one("sdns", {"_id": vim_content
["config"]["sdn-controller"]})
148 # look if previous tasks in process
149 task_name
, task_dependency
= self
.lcm_tasks
.lookfor_related("sdn", db_sdn
["_id"])
151 step
= "Waiting for related tasks to be completed: {}".format(task_name
)
152 self
.logger
.debug(logging_text
+ step
)
153 # TODO write this to database
154 _
, pending
= await asyncio
.wait(task_dependency
, timeout
=3600)
156 raise LcmException("Timeout waiting related tasks to be completed")
158 if db_sdn
.get("_admin") and db_sdn
["_admin"].get("deployed") and db_sdn
["_admin"]["deployed"].get(
160 RO_sdn_id
= db_sdn
["_admin"]["deployed"]["RO"]
162 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
163 vim_content
["config"]["sdn-controller"]))
165 RO_vim_id
= db_vim
["_admin"]["deployed"]["RO"]
166 step
= "Editing vim at RO"
167 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
168 vim_RO
= deepcopy(vim_content
)
169 vim_RO
.pop("_id", None)
170 vim_RO
.pop("_admin", None)
171 schema_version
= vim_RO
.pop("schema_version", None)
172 vim_RO
.pop("schema_type", None)
173 vim_RO
.pop("vim_tenant_name", None)
174 if "vim_type" in vim_RO
:
175 vim_RO
["type"] = vim_RO
.pop("vim_type")
176 vim_RO
.pop("vim_user", None)
177 vim_RO
.pop("vim_password", None)
179 vim_RO
["config"]["sdn-controller"] = RO_sdn_id
180 # TODO make a deep update of sdn-port-mapping
182 await RO
.edit("vim", RO_vim_id
, descriptor
=vim_RO
)
184 step
= "Editing vim-account at RO tenant"
186 if "config" in vim_content
:
187 if "sdn-controller" in vim_content
["config"]:
188 del vim_content
["config"]["sdn-controller"]
189 if "sdn-port-mapping" in vim_content
["config"]:
190 del vim_content
["config"]["sdn-port-mapping"]
191 if not vim_content
["config"]:
192 del vim_content
["config"]
193 if "vim_tenant_name" in vim_content
:
194 vim_account_RO
["vim_tenant_name"] = vim_content
["vim_tenant_name"]
195 if "vim_password" in vim_content
:
196 vim_account_RO
["vim_password"] = vim_content
["vim_password"]
197 if vim_content
.get("vim_password"):
198 vim_account_RO
["vim_password"] = self
.db
.decrypt(vim_content
["vim_password"],
199 schema_version
=schema_version
,
201 if "config" in vim_content
:
202 vim_account_RO
["config"] = vim_content
["config"]
203 if vim_content
.get("config"):
204 for p
in self
.vim_config_encrypted
:
205 if vim_content
["config"].get(p
):
206 vim_account_RO
["config"][p
] = self
.db
.decrypt(vim_content
["config"][p
],
207 schema_version
=schema_version
,
210 if "vim_user" in vim_content
:
211 vim_content
["vim_username"] = vim_content
["vim_user"]
212 # vim_account must be edited always even if empty in order to ensure changes are translated to RO
213 # vim_thread. RO will remove and relaunch a new thread for this vim_account
214 await RO
.edit("vim_account", RO_vim_id
, descriptor
=vim_account_RO
)
215 db_vim_update
["_admin.operationalState"] = "ENABLED"
217 self
.logger
.debug(logging_text
+ "Exit Ok RO_vim_id={}".format(RO_vim_id
))
220 except (ROclient
.ROClientException
, DbException
) as e
:
221 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
223 except Exception as e
:
224 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
228 db_vim_update
["_admin.operationalState"] = "ERROR"
229 db_vim_update
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
231 self
.update_db_2("vim_accounts", vim_id
, db_vim_update
)
232 self
.lcm_tasks
.remove("vim_account", vim_id
, order_id
)
234 async def delete(self
, vim_id
, order_id
):
235 logging_text
= "Task vim_delete={} ".format(vim_id
)
236 self
.logger
.debug(logging_text
+ "Enter")
240 step
= "Getting vim from db"
242 db_vim
= self
.db
.get_one("vim_accounts", {"_id": vim_id
})
243 if db_vim
.get("_admin") and db_vim
["_admin"].get("deployed") and db_vim
["_admin"]["deployed"].get("RO"):
244 RO_vim_id
= db_vim
["_admin"]["deployed"]["RO"]
245 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
246 step
= "Detaching vim from RO tenant"
248 await RO
.detach_datacenter(RO_vim_id
)
249 except ROclient
.ROClientException
as e
:
250 if e
.http_code
== 404: # not found
251 self
.logger
.debug(logging_text
+ "RO_vim_id={} already detached".format(RO_vim_id
))
255 step
= "Deleting vim from RO"
257 await RO
.delete("vim", RO_vim_id
)
258 except ROclient
.ROClientException
as e
:
259 if e
.http_code
== 404: # not found
260 self
.logger
.debug(logging_text
+ "RO_vim_id={} already deleted".format(RO_vim_id
))
265 self
.logger
.error(logging_text
+ "Nohing to remove at RO")
266 self
.db
.del_one("vim_accounts", {"_id": vim_id
})
267 self
.logger
.debug(logging_text
+ "Exit Ok")
270 except (ROclient
.ROClientException
, DbException
) as e
:
271 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
273 except Exception as e
:
274 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
277 self
.lcm_tasks
.remove("vim_account", vim_id
, order_id
)
279 db_vim_update
["_admin.operationalState"] = "ERROR"
280 db_vim_update
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
282 self
.update_db_2("vim_accounts", vim_id
, db_vim_update
)
283 self
.lcm_tasks
.remove("vim_account", vim_id
, order_id
)
286 class SdnLcm(LcmBase
):
288 def __init__(self
, db
, msg
, fs
, lcm_tasks
, ro_config
, loop
):
290 Init, Connect to database, filesystem storage, and messaging
291 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
295 self
.logger
= logging
.getLogger('lcm.sdn')
297 self
.lcm_tasks
= lcm_tasks
298 self
.ro_config
= ro_config
300 super().__init
__(db
, msg
, fs
, self
.logger
)
302 async def create(self
, sdn_content
, order_id
):
303 sdn_id
= sdn_content
["_id"]
304 logging_text
= "Task sdn_create={} ".format(sdn_id
)
305 self
.logger
.debug(logging_text
+ "Enter")
311 step
= "Getting sdn from db"
312 db_sdn
= self
.db
.get_one("sdns", {"_id": sdn_id
})
313 db_sdn_update
["_admin.deployed.RO"] = None
315 step
= "Creating sdn at RO"
316 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
317 sdn_RO
= deepcopy(sdn_content
)
318 sdn_RO
.pop("_id", None)
319 sdn_RO
.pop("_admin", None)
320 schema_version
= sdn_RO
.pop("schema_version", None)
321 sdn_RO
.pop("schema_type", None)
322 sdn_RO
.pop("description", None)
323 if sdn_RO
.get("password"):
324 sdn_RO
["password"] = self
.db
.decrypt(sdn_RO
["password"], schema_version
=schema_version
, salt
=sdn_id
)
326 desc
= await RO
.create("sdn", descriptor
=sdn_RO
)
327 RO_sdn_id
= desc
["uuid"]
328 db_sdn_update
["_admin.deployed.RO"] = RO_sdn_id
329 db_sdn_update
["_admin.operationalState"] = "ENABLED"
330 self
.logger
.debug(logging_text
+ "Exit Ok RO_sdn_id={}".format(RO_sdn_id
))
333 except (ROclient
.ROClientException
, DbException
) as e
:
334 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
336 except Exception as e
:
337 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
341 db_sdn_update
["_admin.operationalState"] = "ERROR"
342 db_sdn_update
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
344 self
.update_db_2("sdns", sdn_id
, db_sdn_update
)
345 self
.lcm_tasks
.remove("sdn", sdn_id
, order_id
)
347 async def edit(self
, sdn_content
, order_id
):
348 sdn_id
= sdn_content
["_id"]
349 logging_text
= "Task sdn_edit={} ".format(sdn_id
)
350 self
.logger
.debug(logging_text
+ "Enter")
354 step
= "Getting sdn from db"
356 db_sdn
= self
.db
.get_one("sdns", {"_id": sdn_id
})
357 if db_sdn
.get("_admin") and db_sdn
["_admin"].get("deployed") and db_sdn
["_admin"]["deployed"].get("RO"):
358 RO_sdn_id
= db_sdn
["_admin"]["deployed"]["RO"]
359 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
360 step
= "Editing sdn at RO"
361 sdn_RO
= deepcopy(sdn_content
)
362 sdn_RO
.pop("_id", None)
363 sdn_RO
.pop("_admin", None)
364 schema_version
= sdn_RO
.pop("schema_version", None)
365 sdn_RO
.pop("schema_type", None)
366 sdn_RO
.pop("description", None)
367 if sdn_RO
.get("password"):
368 sdn_RO
["password"] = self
.db
.decrypt(sdn_RO
["password"], schema_version
=schema_version
, salt
=sdn_id
)
370 await RO
.edit("sdn", RO_sdn_id
, descriptor
=sdn_RO
)
371 db_sdn_update
["_admin.operationalState"] = "ENABLED"
373 self
.logger
.debug(logging_text
+ "Exit Ok RO_sdn_id".format(RO_sdn_id
))
376 except (ROclient
.ROClientException
, DbException
) as e
:
377 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
379 except Exception as e
:
380 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
384 db_sdn
["_admin.operationalState"] = "ERROR"
385 db_sdn
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
387 self
.update_db_2("sdns", sdn_id
, db_sdn_update
)
388 self
.lcm_tasks
.remove("sdn", sdn_id
, order_id
)
390 async def delete(self
, sdn_id
, order_id
):
391 logging_text
= "Task sdn_delete={} ".format(sdn_id
)
392 self
.logger
.debug(logging_text
+ "Enter")
396 step
= "Getting sdn from db"
398 db_sdn
= self
.db
.get_one("sdns", {"_id": sdn_id
})
399 if db_sdn
.get("_admin") and db_sdn
["_admin"].get("deployed") and db_sdn
["_admin"]["deployed"].get("RO"):
400 RO_sdn_id
= db_sdn
["_admin"]["deployed"]["RO"]
401 RO
= ROclient
.ROClient(self
.loop
, **self
.ro_config
)
402 step
= "Deleting sdn from RO"
404 await RO
.delete("sdn", RO_sdn_id
)
405 except ROclient
.ROClientException
as e
:
406 if e
.http_code
== 404: # not found
407 self
.logger
.debug(logging_text
+ "RO_sdn_id={} already deleted".format(RO_sdn_id
))
412 self
.logger
.error(logging_text
+ "Skipping. There is not RO information at database")
413 self
.db
.del_one("sdns", {"_id": sdn_id
})
414 self
.logger
.debug("sdn_delete task sdn_id={} Exit Ok".format(sdn_id
))
417 except (ROclient
.ROClientException
, DbException
) as e
:
418 self
.logger
.error(logging_text
+ "Exit Exception {}".format(e
))
420 except Exception as e
:
421 self
.logger
.critical(logging_text
+ "Exit Exception {}".format(e
), exc_info
=True)
425 db_sdn
["_admin.operationalState"] = "ERROR"
426 db_sdn
["_admin.detailed-status"] = "ERROR {}: {}".format(step
, exc
)
428 self
.update_db_2("sdns", sdn_id
, db_sdn_update
)
429 self
.lcm_tasks
.remove("sdn", sdn_id
, order_id
)