split code into several files
[osm/LCM.git] / osm_lcm / vim_sdn.py
1 #!/usr/bin/python3
2 # -*- coding: utf-8 -*-
3
4 import asyncio
5 import logging
6 import logging.handlers
7 import ROclient
8 from lcm_utils import LcmException, LcmBase
9 from osm_common.dbbase import DbException
10 from copy import deepcopy
11
12 __author__ = "Alfonso Tierno"
13
14
15 class VimLcm(LcmBase):
16
17 def __init__(self, db, msg, fs, lcm_tasks, ro_config, loop):
18 """
19 Init, Connect to database, filesystem storage, and messaging
20 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
21 :return: None
22 """
23
24 self.logger = logging.getLogger('lcm.vim')
25 self.loop = loop
26 self.lcm_tasks = lcm_tasks
27 self.ro_config = ro_config
28
29 super().__init__(db, msg, fs, self.logger)
30
31 async def create(self, vim_content, order_id):
32 vim_id = vim_content["_id"]
33 logging_text = "Task vim_create={} ".format(vim_id)
34 self.logger.debug(logging_text + "Enter")
35 db_vim = None
36 db_vim_update = {}
37 exc = None
38 RO_sdn_id = None
39 try:
40 step = "Getting vim-id='{}' from db".format(vim_id)
41 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
42 db_vim_update["_admin.deployed.RO"] = None
43 if vim_content.get("config") and vim_content["config"].get("sdn-controller"):
44 step = "Getting sdn-controller-id='{}' from db".format(vim_content["config"]["sdn-controller"])
45 db_sdn = self.db.get_one("sdns", {"_id": vim_content["config"]["sdn-controller"]})
46 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
47 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
48 else:
49 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
50 vim_content["config"]["sdn-controller"]))
51
52 step = "Creating vim at RO"
53 db_vim_update["_admin.detailed-status"] = step
54 self.update_db_2("vim_accounts", vim_id, db_vim_update)
55 RO = ROclient.ROClient(self.loop, **self.ro_config)
56 vim_RO = deepcopy(vim_content)
57 vim_RO.pop("_id", None)
58 vim_RO.pop("_admin", None)
59 vim_RO.pop("schema_version", None)
60 vim_RO.pop("schema_type", None)
61 vim_RO.pop("vim_tenant_name", None)
62 vim_RO["type"] = vim_RO.pop("vim_type")
63 vim_RO.pop("vim_user", None)
64 vim_RO.pop("vim_password", None)
65 if RO_sdn_id:
66 vim_RO["config"]["sdn-controller"] = RO_sdn_id
67 desc = await RO.create("vim", descriptor=vim_RO)
68 RO_vim_id = desc["uuid"]
69 db_vim_update["_admin.deployed.RO"] = RO_vim_id
70
71 step = "Creating vim_account at RO"
72 db_vim_update["_admin.detailed-status"] = step
73 self.update_db_2("vim_accounts", vim_id, db_vim_update)
74
75 vim_account_RO = {"vim_tenant_name": vim_content["vim_tenant_name"],
76 "vim_username": vim_content["vim_user"],
77 "vim_password": vim_content["vim_password"]
78 }
79 if vim_RO.get("config"):
80 vim_account_RO["config"] = vim_RO["config"]
81 if "sdn-controller" in vim_account_RO["config"]:
82 del vim_account_RO["config"]["sdn-controller"]
83 if "sdn-port-mapping" in vim_account_RO["config"]:
84 del vim_account_RO["config"]["sdn-port-mapping"]
85 desc = await RO.attach_datacenter(RO_vim_id, descriptor=vim_account_RO)
86 db_vim_update["_admin.deployed.RO-account"] = desc["uuid"]
87 db_vim_update["_admin.operationalState"] = "ENABLED"
88 db_vim_update["_admin.detailed-status"] = "Done"
89
90 # await asyncio.sleep(15) # TODO remove. This is for test
91 self.logger.debug(logging_text + "Exit Ok RO_vim_id={}".format(RO_vim_id))
92 return
93
94 except (ROclient.ROClientException, DbException) as e:
95 self.logger.error(logging_text + "Exit Exception {}".format(e))
96 exc = e
97 except Exception as e:
98 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
99 exc = e
100 finally:
101 if exc and db_vim:
102 db_vim_update["_admin.operationalState"] = "ERROR"
103 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
104 if db_vim_update:
105 self.update_db_2("vim_accounts", vim_id, db_vim_update)
106 self.lcm_tasks.remove("vim_account", vim_id, order_id)
107
108 async def edit(self, vim_content, order_id):
109 vim_id = vim_content["_id"]
110 logging_text = "Task vim_edit={} ".format(vim_id)
111 self.logger.debug(logging_text + "Enter")
112 db_vim = None
113 exc = None
114 RO_sdn_id = None
115 RO_vim_id = None
116 db_vim_update = {}
117 step = "Getting vim-id='{}' from db".format(vim_id)
118 try:
119 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
120
121 # look if previous tasks in process
122 task_name, task_dependency = self.lcm_tasks.lookfor_related("vim_account", vim_id, order_id)
123 if task_dependency:
124 step = "Waiting for related tasks to be completed: {}".format(task_name)
125 self.logger.debug(logging_text + step)
126 # TODO write this to database
127 await asyncio.wait(task_dependency, timeout=3600)
128
129 if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"):
130 if vim_content.get("config") and vim_content["config"].get("sdn-controller"):
131 step = "Getting sdn-controller-id='{}' from db".format(vim_content["config"]["sdn-controller"])
132 db_sdn = self.db.get_one("sdns", {"_id": vim_content["config"]["sdn-controller"]})
133
134 # look if previous tasks in process
135 task_name, task_dependency = self.lcm_tasks.lookfor_related("sdn", db_sdn["_id"])
136 if task_dependency:
137 step = "Waiting for related tasks to be completed: {}".format(task_name)
138 self.logger.debug(logging_text + step)
139 # TODO write this to database
140 await asyncio.wait(task_dependency, timeout=3600)
141
142 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get(
143 "RO"):
144 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
145 else:
146 raise LcmException("sdn-controller={} is not available. Not deployed at RO".format(
147 vim_content["config"]["sdn-controller"]))
148
149 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
150 step = "Editing vim at RO"
151 RO = ROclient.ROClient(self.loop, **self.ro_config)
152 vim_RO = deepcopy(vim_content)
153 vim_RO.pop("_id", None)
154 vim_RO.pop("_admin", None)
155 vim_RO.pop("schema_version", None)
156 vim_RO.pop("schema_type", None)
157 vim_RO.pop("vim_tenant_name", None)
158 if "vim_type" in vim_RO:
159 vim_RO["type"] = vim_RO.pop("vim_type")
160 vim_RO.pop("vim_user", None)
161 vim_RO.pop("vim_password", None)
162 if RO_sdn_id:
163 vim_RO["config"]["sdn-controller"] = RO_sdn_id
164 # TODO make a deep update of sdn-port-mapping
165 if vim_RO:
166 await RO.edit("vim", RO_vim_id, descriptor=vim_RO)
167
168 step = "Editing vim-account at RO tenant"
169 vim_account_RO = {}
170 if "config" in vim_content:
171 if "sdn-controller" in vim_content["config"]:
172 del vim_content["config"]["sdn-controller"]
173 if "sdn-port-mapping" in vim_content["config"]:
174 del vim_content["config"]["sdn-port-mapping"]
175 if not vim_content["config"]:
176 del vim_content["config"]
177 for k in ("vim_tenant_name", "vim_password", "config"):
178 if k in vim_content:
179 vim_account_RO[k] = vim_content[k]
180 if "vim_user" in vim_content:
181 vim_content["vim_username"] = vim_content["vim_user"]
182 # vim_account must be edited always even if empty in order to ensure changes are translated to RO
183 # vim_thread. RO will remove and relaunch a new thread for this vim_account
184 await RO.edit("vim_account", RO_vim_id, descriptor=vim_account_RO)
185 db_vim_update["_admin.operationalState"] = "ENABLED"
186
187 self.logger.debug(logging_text + "Exit Ok RO_vim_id={}".format(RO_vim_id))
188 return
189
190 except (ROclient.ROClientException, DbException) as e:
191 self.logger.error(logging_text + "Exit Exception {}".format(e))
192 exc = e
193 except Exception as e:
194 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
195 exc = e
196 finally:
197 if exc and db_vim:
198 db_vim_update["_admin.operationalState"] = "ERROR"
199 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
200 if db_vim_update:
201 self.update_db_2("vim_accounts", vim_id, db_vim_update)
202 self.lcm_tasks.remove("vim_account", vim_id, order_id)
203
204 async def delete(self, vim_id, order_id):
205 logging_text = "Task vim_delete={} ".format(vim_id)
206 self.logger.debug(logging_text + "Enter")
207 db_vim = None
208 db_vim_update = {}
209 exc = None
210 step = "Getting vim from db"
211 try:
212 db_vim = self.db.get_one("vim_accounts", {"_id": vim_id})
213 if db_vim.get("_admin") and db_vim["_admin"].get("deployed") and db_vim["_admin"]["deployed"].get("RO"):
214 RO_vim_id = db_vim["_admin"]["deployed"]["RO"]
215 RO = ROclient.ROClient(self.loop, **self.ro_config)
216 step = "Detaching vim from RO tenant"
217 try:
218 await RO.detach_datacenter(RO_vim_id)
219 except ROclient.ROClientException as e:
220 if e.http_code == 404: # not found
221 self.logger.debug(logging_text + "RO_vim_id={} already detached".format(RO_vim_id))
222 else:
223 raise
224
225 step = "Deleting vim from RO"
226 try:
227 await RO.delete("vim", RO_vim_id)
228 except ROclient.ROClientException as e:
229 if e.http_code == 404: # not found
230 self.logger.debug(logging_text + "RO_vim_id={} already deleted".format(RO_vim_id))
231 else:
232 raise
233 else:
234 # nothing to delete
235 self.logger.error(logging_text + "Nohing to remove at RO")
236 self.db.del_one("vim_accounts", {"_id": vim_id})
237 self.logger.debug(logging_text + "Exit Ok")
238 return
239
240 except (ROclient.ROClientException, DbException) as e:
241 self.logger.error(logging_text + "Exit Exception {}".format(e))
242 exc = e
243 except Exception as e:
244 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
245 exc = e
246 finally:
247 self.lcm_tasks.remove("vim_account", vim_id, order_id)
248 if exc and db_vim:
249 db_vim_update["_admin.operationalState"] = "ERROR"
250 db_vim_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
251 if db_vim_update:
252 self.update_db_2("vim_accounts", vim_id, db_vim_update)
253 self.lcm_tasks.remove("vim_account", vim_id, order_id)
254
255
256 class SdnLcm(LcmBase):
257
258 def __init__(self, db, msg, fs, lcm_tasks, ro_config, loop):
259 """
260 Init, Connect to database, filesystem storage, and messaging
261 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
262 :return: None
263 """
264
265 self.logger = logging.getLogger('lcm.sdn')
266 self.loop = loop
267 self.lcm_tasks = lcm_tasks
268 self.ro_config = ro_config
269
270 super().__init__(db, msg, fs, self.logger)
271
272 async def create(self, sdn_content, order_id):
273 sdn_id = sdn_content["_id"]
274 logging_text = "Task sdn_create={} ".format(sdn_id)
275 self.logger.debug(logging_text + "Enter")
276 db_sdn = None
277 db_sdn_update = {}
278 RO_sdn_id = None
279 exc = None
280 try:
281 step = "Getting sdn from db"
282 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
283 db_sdn_update["_admin.deployed.RO"] = None
284
285 step = "Creating sdn at RO"
286 RO = ROclient.ROClient(self.loop, **self.ro_config)
287 sdn_RO = deepcopy(sdn_content)
288 sdn_RO.pop("_id", None)
289 sdn_RO.pop("_admin", None)
290 sdn_RO.pop("schema_version", None)
291 sdn_RO.pop("schema_type", None)
292 sdn_RO.pop("description", None)
293 desc = await RO.create("sdn", descriptor=sdn_RO)
294 RO_sdn_id = desc["uuid"]
295 db_sdn_update["_admin.deployed.RO"] = RO_sdn_id
296 db_sdn_update["_admin.operationalState"] = "ENABLED"
297 self.logger.debug(logging_text + "Exit Ok RO_sdn_id={}".format(RO_sdn_id))
298 return
299
300 except (ROclient.ROClientException, DbException) as e:
301 self.logger.error(logging_text + "Exit Exception {}".format(e))
302 exc = e
303 except Exception as e:
304 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
305 exc = e
306 finally:
307 if exc and db_sdn:
308 db_sdn_update["_admin.operationalState"] = "ERROR"
309 db_sdn_update["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
310 if db_sdn_update:
311 self.update_db_2("sdns", sdn_id, db_sdn_update)
312 self.lcm_tasks.remove("sdn", sdn_id, order_id)
313
314 async def edit(self, sdn_content, order_id):
315 sdn_id = sdn_content["_id"]
316 logging_text = "Task sdn_edit={} ".format(sdn_id)
317 self.logger.debug(logging_text + "Enter")
318 db_sdn = None
319 db_sdn_update = {}
320 exc = None
321 step = "Getting sdn from db"
322 try:
323 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
324 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
325 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
326 RO = ROclient.ROClient(self.loop, **self.ro_config)
327 step = "Editing sdn at RO"
328 sdn_RO = deepcopy(sdn_content)
329 sdn_RO.pop("_id", None)
330 sdn_RO.pop("_admin", None)
331 sdn_RO.pop("schema_version", None)
332 sdn_RO.pop("schema_type", None)
333 sdn_RO.pop("description", None)
334 if sdn_RO:
335 await RO.edit("sdn", RO_sdn_id, descriptor=sdn_RO)
336 db_sdn_update["_admin.operationalState"] = "ENABLED"
337
338 self.logger.debug(logging_text + "Exit Ok RO_sdn_id".format(RO_sdn_id))
339 return
340
341 except (ROclient.ROClientException, DbException) as e:
342 self.logger.error(logging_text + "Exit Exception {}".format(e))
343 exc = e
344 except Exception as e:
345 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
346 exc = e
347 finally:
348 if exc and db_sdn:
349 db_sdn["_admin.operationalState"] = "ERROR"
350 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
351 if db_sdn_update:
352 self.update_db_2("sdns", sdn_id, db_sdn_update)
353 self.lcm_tasks.remove("sdn", sdn_id, order_id)
354
355 async def delete(self, sdn_id, order_id):
356 logging_text = "Task sdn_delete={} ".format(sdn_id)
357 self.logger.debug(logging_text + "Enter")
358 db_sdn = None
359 db_sdn_update = {}
360 exc = None
361 step = "Getting sdn from db"
362 try:
363 db_sdn = self.db.get_one("sdns", {"_id": sdn_id})
364 if db_sdn.get("_admin") and db_sdn["_admin"].get("deployed") and db_sdn["_admin"]["deployed"].get("RO"):
365 RO_sdn_id = db_sdn["_admin"]["deployed"]["RO"]
366 RO = ROclient.ROClient(self.loop, **self.ro_config)
367 step = "Deleting sdn from RO"
368 try:
369 await RO.delete("sdn", RO_sdn_id)
370 except ROclient.ROClientException as e:
371 if e.http_code == 404: # not found
372 self.logger.debug(logging_text + "RO_sdn_id={} already deleted".format(RO_sdn_id))
373 else:
374 raise
375 else:
376 # nothing to delete
377 self.logger.error(logging_text + "Skipping. There is not RO information at database")
378 self.db.del_one("sdns", {"_id": sdn_id})
379 self.logger.debug("sdn_delete task sdn_id={} Exit Ok".format(sdn_id))
380 return
381
382 except (ROclient.ROClientException, DbException) as e:
383 self.logger.error(logging_text + "Exit Exception {}".format(e))
384 exc = e
385 except Exception as e:
386 self.logger.critical(logging_text + "Exit Exception {}".format(e), exc_info=True)
387 exc = e
388 finally:
389 if exc and db_sdn:
390 db_sdn["_admin.operationalState"] = "ERROR"
391 db_sdn["_admin.detailed-status"] = "ERROR {}: {}".format(step, exc)
392 if db_sdn_update:
393 self.update_db_2("sdns", sdn_id, db_sdn_update)
394 self.lcm_tasks.remove("sdn", sdn_id, order_id)