6f742c295001b87c816d95f189f7051840e3ac4a
1 # -*- coding: utf-8 -*-
5 import logging
.handlers
8 from lcm_utils
import LcmException
, LcmBase
9 from osm_common
.dbbase
import DbException
12 __author__
= "Felipe Vicens, Pol Alemany, Alfonso Tierno"
15 class NetsliceLcm(LcmBase
):
17 def __init__(self
, db
, msg
, fs
, lcm_tasks
, ro_config
, vca_config
, loop
):
19 Init, Connect to database, filesystem storage, and messaging
20 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
24 self
.logger
= logging
.getLogger('lcm.netslice')
26 self
.lcm_tasks
= lcm_tasks
27 self
.ns
= ns
.NsLcm(db
, msg
, fs
, lcm_tasks
, ro_config
, vca_config
, loop
)
29 super().__init
__(db
, msg
, fs
, self
.logger
)
31 # TODO: check logging_text within the self.logger.info/debug
32 async def instantiate(self
, nsir_id
, nsilcmop_id
):
33 logging_text
= "Task netslice={} instantiate={} ".format(nsir_id
, nsilcmop_id
)
34 self
.logger
.debug(logging_text
+ "Enter")
35 # get all needed from database
39 db_nsir_update
= {"_admin.nsilcmop": nsilcmop_id
}
40 db_nsilcmop_update
= {}
41 nsilcmop_operation_state
= None
44 step
= "Getting nsir={} from db".format(nsir_id
)
45 db_nsir
= self
.db
.get_one("nsis", {"_id": nsir_id
})
46 step
= "Getting nsilcmop={} from db".format(nsilcmop_id
)
47 db_nsilcmop
= self
.db
.get_one("nsilcmops", {"_id": nsilcmop_id
})
49 # look if previous tasks is in process
50 task_name
, task_dependency
= self
.lcm_tasks
.lookfor_related("nsi", nsir_id
, nsilcmop_id
)
52 step
= db_nsilcmop_update
["detailed-status"] = \
53 "Waiting for related tasks to be completed: {}".format(task_name
)
54 self
.logger
.debug(logging_text
+ step
)
55 self
.update_db_2("nsilcmops", nsilcmop_id
, db_nsilcmop_update
)
56 _
, pending
= await asyncio
.wait(task_dependency
, timeout
=3600)
58 raise LcmException("Timeout waiting related tasks to be completed")
60 # Empty list to keep track of network service records status in the netslice
61 nsir_admin
= db_nsir
["_admin"]
63 nsir_admin
["nsrs-detailed-list"] = []
65 # Slice status Creating
66 db_nsir_update
["detailed-status"] = "creating"
67 db_nsir_update
["operational-status"] = "init"
68 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
70 # Iterate over the network services operation ids to instantiate NSs
71 # TODO: (future improvement) look another way check the tasks instead of keep asking
72 # -> https://docs.python.org/3/library/asyncio-task.html#waiting-primitives
73 # steps: declare ns_tasks, add task when terminate is called, await asyncio.wait(vca_task_list, timeout=300)
75 nslcmop_ids
= db_nsilcmop
["operationParams"].get("nslcmops_ids")
76 for nslcmop_id
in nslcmop_ids
:
77 nslcmop
= self
.db
.get_one("nslcmops", {"_id": nslcmop_id
})
78 nsr_id
= nslcmop
.get("nsInstanceId")
79 step
= "Launching ns={} instantiate={} task".format(nsr_id
, nslcmop
)
80 task
= asyncio
.ensure_future(self
.ns
.instantiate(nsr_id
, nslcmop_id
))
81 self
.lcm_tasks
.register("ns", nsr_id
, nslcmop_id
, "ns_instantiate", task
)
83 # Wait until Network Slice is ready
84 step
= nsir_status_detailed
= " Waiting nsi ready. nsi_id={}".format(nsir_id
)
85 nsrs_detailed_list_old
= None
86 self
.logger
.debug(logging_text
+ step
)
88 # TODO: substitute while for await (all task to be done or not)
89 deployment_timeout
= 2 * 3600 # Two hours
90 while deployment_timeout
> 0:
91 # Check ns instantiation status
93 nsrs_detailed_list
= []
94 for nslcmop_item
in nslcmop_ids
:
95 nslcmop
= self
.db
.get_one("nslcmops", {"_id": nslcmop_item
})
96 status
= nslcmop
.get("operationState")
97 # TODO: (future improvement) other possible status: ROLLING_BACK,ROLLED_BACK
98 nsrs_detailed_list
.append({"nsrId": nslcmop
["nsInstanceId"], "status": nslcmop
["operationState"],
100 nsir_status_detailed
+ "; {}".format(nslcmop
.get("detailed-status"))})
101 if status
not in ["COMPLETED", "PARTIALLY_COMPLETED", "FAILED", "FAILED_TEMP"]:
104 if nsrs_detailed_list
!= nsrs_detailed_list_old
:
105 nsir_admin
["nsrs-detailed-list"] = nsrs_detailed_list
106 nsrs_detailed_list_old
= nsrs_detailed_list
107 db_nsir_update
["_admin"] = nsir_admin
108 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
111 step
= "Network Slice Instance is ready. nsi_id={}".format(nsir_id
)
112 for items
in nsrs_detailed_list
:
113 if "FAILED" in items
.values():
114 raise LcmException("Error deploying NSI: {}".format(nsir_id
))
117 # TODO: future improvement due to synchronism -> await asyncio.wait(vca_task_list, timeout=300)
118 await asyncio
.sleep(5, loop
=self
.loop
)
119 deployment_timeout
-= 5
121 if deployment_timeout
<= 0:
122 raise LcmException("Timeout waiting nsi to be ready. nsi_id={}".format(nsir_id
))
124 db_nsir_update
["operational-status"] = "running"
125 db_nsir_update
["detailed-status"] = "done"
126 db_nsir_update
["config-status"] = "configured"
127 db_nsilcmop_update
["operationState"] = nsilcmop_operation_state
= "COMPLETED"
128 db_nsilcmop_update
["statusEnteredTime"] = time()
129 db_nsilcmop_update
["detailed-status"] = "done"
132 except (LcmException
, DbException
) as e
:
133 self
.logger
.error(logging_text
+ "Exit Exception while '{}': {}".format(step
, e
))
135 except asyncio
.CancelledError
:
136 self
.logger
.error(logging_text
+ "Cancelled Exception while '{}'".format(step
))
137 exc
= "Operation was cancelled"
138 except Exception as e
:
139 exc
= traceback
.format_exc()
140 self
.logger
.critical(logging_text
+ "Exit Exception {} while '{}': {}".format(type(e
).__name
__, step
, e
),
145 db_nsir_update
["detailed-status"] = "ERROR {}: {}".format(step
, exc
)
146 db_nsir_update
["operational-status"] = "failed"
148 db_nsilcmop_update
["detailed-status"] = "FAILED {}: {}".format(step
, exc
)
149 db_nsilcmop_update
["operationState"] = nsilcmop_operation_state
= "FAILED"
150 db_nsilcmop_update
["statusEnteredTime"] = time()
152 db_nsir_update
["_admin.nsiState"] = "INSTANTIATED"
153 db_nsir_update
["_admin.nsilcmop"] = None
154 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
157 self
.update_db_2("nsilcmops", nsilcmop_id
, db_nsilcmop_update
)
158 if nsilcmop_operation_state
:
160 await self
.msg
.aiowrite("nsi", "instantiated", {"nsir_id": nsir_id
, "nsilcmop_id": nsilcmop_id
,
161 "operationState": nsilcmop_operation_state
})
162 except Exception as e
:
163 self
.logger
.error(logging_text
+ "kafka_write notification Exception {}".format(e
))
164 self
.logger
.debug(logging_text
+ "Exit")
165 self
.lcm_tasks
.remove("nsi", nsir_id
, nsilcmop_id
, "nsi_instantiate")
167 async def terminate(self
, nsir_id
, nsilcmop_id
):
168 logging_text
= "Task nsi={} terminate={} ".format(nsir_id
, nsilcmop_id
)
169 self
.logger
.debug(logging_text
+ "Enter")
173 db_nsir_update
= {"_admin.nsilcmop": nsilcmop_id
}
174 db_nsilcmop_update
= {}
175 nsilcmop_operation_state
= None
177 step
= "Getting nsir={} from db".format(nsir_id
)
178 db_nsir
= self
.db
.get_one("nsis", {"_id": nsir_id
})
179 step
= "Getting nsilcmop={} from db".format(nsilcmop_id
)
180 db_nsilcmop
= self
.db
.get_one("nsilcmops", {"_id": nsilcmop_id
})
182 # TODO: Check if makes sense check the nsiState=NOT_INSTANTIATED when terminate
183 # CASE: Instance was terminated but there is a second request to terminate the instance
184 if db_nsir
["_admin"]["nsiState"] == "NOT_INSTANTIATED":
187 # Slice status Terminating
188 db_nsir_update
["operational-status"] = "terminating"
189 db_nsir_update
["config-status"] = "terminating"
190 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
192 # look if previous tasks is in process
193 task_name
, task_dependency
= self
.lcm_tasks
.lookfor_related("nsi", nsir_id
, nsilcmop_id
)
195 step
= db_nsilcmop_update
["detailed-status"] = \
196 "Waiting for related tasks to be completed: {}".format(task_name
)
197 self
.logger
.debug(logging_text
+ step
)
198 self
.update_db_2("nsilcmops", nsilcmop_id
, db_nsilcmop_update
)
199 _
, pending
= await asyncio
.wait(task_dependency
, timeout
=3600)
201 raise LcmException("Timeout waiting related tasks to be completed")
203 # Gets the list to keep track of network service records status in the netslice
204 nsir_admin
= db_nsir
["_admin"]
205 nsrs_detailed_list
= []
207 # Iterate over the network services operation ids to terminate NSs
208 # TODO: (future improvement) look another way check the tasks instead of keep asking
209 # -> https://docs.python.org/3/library/asyncio-task.html#waiting-primitives
210 # steps: declare ns_tasks, add task when terminate is called, await asyncio.wait(vca_task_list, timeout=300)
212 nslcmop_ids
= db_nsilcmop
["operationParams"].get("nslcmops_ids")
213 for nslcmop_id
in nslcmop_ids
:
214 nslcmop
= self
.db
.get_one("nslcmops", {"_id": nslcmop_id
})
215 nsr_id
= nslcmop
["operationParams"].get("nsInstanceId")
216 task
= asyncio
.ensure_future(self
.ns
.terminate(nsr_id
, nslcmop_id
))
217 self
.lcm_tasks
.register("ns", nsr_id
, nslcmop_id
, "ns_instantiate", task
)
219 # Wait until Network Slice is terminated
220 step
= nsir_status_detailed
= " Waiting nsi terminated. nsi_id={}".format(nsir_id
)
221 nsrs_detailed_list_old
= None
222 self
.logger
.debug(logging_text
+ step
)
224 termination_timeout
= 2 * 3600 # Two hours
225 while termination_timeout
> 0:
226 # Check ns termination status
228 nsrs_detailed_list
= []
229 for nslcmop_item
in nslcmop_ids
:
230 nslcmop
= self
.db
.get_one("nslcmops", {"_id": nslcmop_item
})
231 status
= nslcmop
["operationState"]
232 # TODO: (future improvement) other possible status: ROLLING_BACK,ROLLED_BACK
233 nsrs_detailed_list
.append({"nsrId": nslcmop
["nsInstanceId"], "status": nslcmop
["operationState"],
235 nsir_status_detailed
+ "; {}".format(nslcmop
.get("detailed-status"))})
236 if status
not in ["COMPLETED", "PARTIALLY_COMPLETED", "FAILED", "FAILED_TEMP"]:
239 if nsrs_detailed_list
!= nsrs_detailed_list_old
:
240 nsir_admin
["nsrs-detailed-list"] = nsrs_detailed_list
241 nsrs_detailed_list_old
= nsrs_detailed_list
242 db_nsir_update
["_admin"] = nsir_admin
243 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
246 step
= "Network Slice Instance is terminated. nsi_id={}".format(nsir_id
)
247 for items
in nsrs_detailed_list
:
248 if "FAILED" in items
.values():
249 raise LcmException("Error terminating NSI: {}".format(nsir_id
))
252 await asyncio
.sleep(5, loop
=self
.loop
)
253 termination_timeout
-= 5
255 if termination_timeout
<= 0:
256 raise LcmException("Timeout waiting nsi to be terminated. nsi_id={}".format(nsir_id
))
258 db_nsir_update
["operational-status"] = "terminated"
259 db_nsir_update
["config-status"] = "configured"
260 db_nsir_update
["detailed-status"] = "done"
261 db_nsilcmop_update
["operationState"] = nsilcmop_operation_state
= "COMPLETED"
262 db_nsilcmop_update
["statusEnteredTime"] = time()
263 db_nsilcmop_update
["detailed-status"] = "done"
266 except (LcmException
, DbException
) as e
:
267 self
.logger
.error(logging_text
+ "Exit Exception while '{}': {}".format(step
, e
))
269 except asyncio
.CancelledError
:
270 self
.logger
.error(logging_text
+ "Cancelled Exception while '{}'".format(step
))
271 exc
= "Operation was cancelled"
272 except Exception as e
:
273 exc
= traceback
.format_exc()
274 self
.logger
.critical(logging_text
+ "Exit Exception {} while '{}': {}".format(type(e
).__name
__, step
, e
),
279 db_nsir_update
["detailed-status"] = "ERROR {}: {}".format(step
, exc
)
280 db_nsir_update
["operational-status"] = "failed"
282 db_nsilcmop_update
["detailed-status"] = "FAILED {}: {}".format(step
, exc
)
283 db_nsilcmop_update
["operationState"] = nsilcmop_operation_state
= "FAILED"
284 db_nsilcmop_update
["statusEnteredTime"] = time()
286 db_nsir_update
["_admin.nsilcmop"] = None
287 db_nsir_update
["_admin.nsiState"] = "TERMINATED"
288 self
.update_db_2("nsis", nsir_id
, db_nsir_update
)
290 self
.update_db_2("nsilcmops", nsilcmop_id
, db_nsilcmop_update
)
292 if nsilcmop_operation_state
:
294 await self
.msg
.aiowrite("nsi", "terminated", {"nsir_id": nsir_id
, "nsilcmop_id": nsilcmop_id
,
295 "operationState": nsilcmop_operation_state
})
296 except Exception as e
:
297 self
.logger
.error(logging_text
+ "kafka_write notification Exception {}".format(e
))
298 self
.logger
.debug(logging_text
+ "Exit")
299 self
.lcm_tasks
.remove("nsi", nsir_id
, nsilcmop_id
, "nsi_terminate")