Fix syntax/indent errors
[osm/SO.git] / rwcm / plugins / rwconman / rift / tasklets / rwconmantasklet / jujuconf.py
1 #
2 # Copyright 2016 RIFT.IO Inc
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 import asyncio
18 import os
19 import re
20 import tempfile
21 import time
22 import yaml
23
24 import rift.mano.utils.juju_api as juju
25 from . import riftcm_config_plugin
26
27
28 # Charm service name accepts only a to z and -.
29 def get_vnf_unique_name(nsr_name, vnfr_name, member_vnf_index):
30 name = "{}-{}-{}".format(nsr_name, vnfr_name, member_vnf_index)
31 new_name = ''
32 for c in name:
33 if c.isdigit():
34 c = chr(97 + int(c))
35 elif not c.isalpha():
36 c = "-"
37 new_name += c
38 return new_name.lower()
39
40
41 class JujuConfigPlugin(riftcm_config_plugin.RiftCMConfigPluginBase):
42 """
43 Juju implementation of the riftcm_config_plugin.RiftCMConfigPluginBase
44 """
45 def __init__(self, dts, log, loop, project, account):
46 riftcm_config_plugin.RiftCMConfigPluginBase.__init__(self, dts, log, loop,
47 project, account)
48 self._name = account.name
49 self._type = 'juju'
50 self._ip_address = account.juju.ip_address
51 self._port = account.juju.port
52 self._user = account.juju.user
53 self._secret = account.juju.secret
54 self._rift_install_dir = os.environ['RIFT_INSTALL']
55 self._rift_var_root_dir = os.environ['RIFT_VAR_ROOT']
56
57 ############################################################
58 # This is wrongfully overloaded with 'juju' private data. #
59 # Really need to separate agent_vnfr from juju vnfr data. #
60 # Currently, this holds agent_vnfr, which has actual vnfr, #
61 # then this juju overloads actual vnfr with its own #
62 # dictionary elemetns (WRONG!!!) #
63 self._juju_vnfs = {}
64 ############################################################
65
66 self._tasks = {}
67 self._api = juju.JujuApi(log, loop,
68 self._ip_address, self._port,
69 self._user, self._secret)
70
71 @property
72 def name(self):
73 return self._name
74
75 @property
76 def agent_type(self):
77 return self._type
78
79 @property
80 def api(self):
81 return self._api
82
83 @property
84 def agent_data(self):
85 return dict(
86 type=self.agent_type,
87 name=self.name,
88 host=self._ip_address,
89 port=self._port,
90 user=self._user,
91 secret=self._secret
92 )
93
94 def vnfr(self, vnfr_id):
95 try:
96 vnfr = self._juju_vnfs[vnfr_id].vnfr
97 except KeyError:
98 self._log.error("jujuCA: Did not find VNFR %s in juju plugin", vnfr_id)
99 return None
100
101 return vnfr
102
103 def get_service_name(self, vnfr_id):
104 vnfr = self.vnfr(vnfr_id)
105 if vnfr and 'vnf_juju_name' in vnfr:
106 return vnfr['vnf_juju_name']
107 return None
108
109 def juju_log(self, level, name, log_str, *args):
110 if name is not None:
111 g_log_str = 'jujuCA:({}) {}'.format(name, log_str)
112 else:
113 g_log_str = 'jujuCA: {}'.format(log_str)
114 getattr(self._log, level)(g_log_str, *args)
115
116 # TBD: Do a better, similar to config manager
117 def xlate(self, tag, tags):
118 # TBD
119 if tag is None:
120 return tag
121 val = tag
122 if re.search('<.*>', tag):
123 self._log.debug("jujuCA: Xlate value %s", tag)
124 try:
125 if tag == '<rw_mgmt_ip>':
126 val = tags['rw_mgmt_ip']
127 except KeyError as e:
128 self._log.info("jujuCA: Did not get a value for tag %s, e=%s",
129 tag, e)
130 return val
131
132 @asyncio.coroutine
133 def notify_create_vlr(self, agent_nsr, agent_vnfr, vld, vlr):
134 """
135 Notification of create VL record
136 """
137 return True
138
139 @asyncio.coroutine
140 def notify_create_vnfr(self, agent_nsr, agent_vnfr):
141 """
142 Notification of create Network VNF record
143 Returns True if configured using config_agent
144 """
145 # Deploy the charm if specified for the vnf
146 self._log.debug("jujuCA: create vnfr nsr=%s vnfr=%s",
147 agent_nsr.name, agent_vnfr.name)
148 self._log.debug("jujuCA: Config = %s",
149 agent_vnfr.vnf_configuration)
150 try:
151 vnf_config = agent_vnfr.vnfr_msg.vnf_configuration
152 self._log.debug("jujuCA: vnf_configuration = %s", vnf_config)
153 if not vnf_config.has_field('juju'):
154 return False
155 charm = vnf_config.juju.charm
156 self._log.debug("jujuCA: charm = %s", charm)
157 except Exception as e:
158 self._log.Error("jujuCA: vnf_configuration error for vnfr {}: {}".
159 format(agent_vnfr.name, e))
160 return False
161
162 # Prepare unique name for this VNF
163 vnf_unique_name = get_vnf_unique_name(agent_nsr.name,
164 agent_vnfr.name,
165 agent_vnfr.member_vnf_index)
166 if vnf_unique_name in self._tasks:
167 self._log.warn("jujuCA: Service %s already deployed",
168 vnf_unique_name)
169
170 vnfr_dict = agent_vnfr.vnfr
171 vnfr_dict.update({'vnf_juju_name': vnf_unique_name,
172 'charm': charm,
173 'nsr_id': agent_nsr.id,
174 'member_vnf_index': agent_vnfr.member_vnf_index,
175 'tags': {},
176 'active': False,
177 'config': vnf_config,
178 'vnfr_name': agent_vnfr.name})
179 self._log.debug("jujuCA: Charm %s for vnf %s to be deployed as %s",
180 charm, agent_vnfr.name, vnf_unique_name)
181
182 # Find the charm directory
183 try:
184 path = os.path.join(self._rift_var_root_dir,
185 'launchpad/packages/vnfd',
186 self._project.name,
187 agent_vnfr.vnfr_msg.vnfd.id,
188 'charms/trusty',
189 charm)
190 self._log.debug("jujuCA: Charm dir is {}".format(path))
191 if not os.path.isdir(path):
192 self._log.error("jujuCA: Did not find the charm directory at {}".
193 format(path))
194 path = None
195 except Exception as e:
196 self.log.exception(e)
197 return False
198
199 if vnf_unique_name not in self._tasks:
200 self._tasks[vnf_unique_name] = {}
201
202 self._tasks[vnf_unique_name]['deploy'] = self.loop.create_task(
203 self.api.deploy_application(charm, vnf_unique_name, path=path))
204
205 self._log.debug("jujuCA: Deploying service %s",
206 vnf_unique_name)
207
208 return True
209
210 @asyncio.coroutine
211 def notify_instantiate_vnfr(self, agent_nsr, agent_vnfr):
212 """
213 Notification of Instantiate NSR with the passed nsr id
214 """
215 return True
216
217 @asyncio.coroutine
218 def notify_instantiate_vlr(self, agent_nsr, agent_vnfr, vlr):
219 """
220 Notification of Instantiate NSR with the passed nsr id
221 """
222 return True
223
224 @asyncio.coroutine
225 def notify_terminate_nsr(self, agent_nsr, agent_vnfr):
226 """
227 Notification of Terminate the network service
228 """
229 return True
230
231 @asyncio.coroutine
232 def notify_terminate_vnfr(self, agent_nsr, agent_vnfr):
233 """
234 Notification of Terminate the network service
235 """
236 self._log.debug("jujuCA: Terminate VNFr {}, current vnfrs={}".
237 format(agent_vnfr.name, self._juju_vnfs))
238 try:
239 vnfr = agent_vnfr.vnfr
240 service = vnfr['vnf_juju_name']
241
242 self._log.debug ("jujuCA: Terminating VNFr %s, %s",
243 agent_vnfr.name, service)
244 self._tasks[service]['destroy'] = self.loop.create_task(
245 self.api.remove_application(service)
246 )
247
248 del self._juju_vnfs[agent_vnfr.id]
249 self._log.debug ("jujuCA: current vnfrs={}".
250 format(self._juju_vnfs))
251 if service in self._tasks:
252 tasks = []
253 for action in self._tasks[service].keys():
254 #if self.check_task_status(service, action):
255 tasks.append(action)
256 del tasks
257 except KeyError as e:
258 self._log.debug ("jujuCA: Terminating charm service for VNFr {}, e={}".
259 format(agent_vnfr.name, e))
260 except Exception as e:
261 self._log.error("jujuCA: Exception terminating charm service for VNFR {}: {}".
262 format(agent_vnfr.name, e))
263
264 return True
265
266 @asyncio.coroutine
267 def notify_terminate_vlr(self, agent_nsr, agent_vnfr, vlr):
268 """
269 Notification of Terminate the virtual link
270 """
271 return True
272
273 def check_task_status(self, service, action):
274 #self.log.debug("jujuCA: check task status for %s, %s" % (service, action))
275 try:
276 task = self._tasks[service][action]
277 if task.done():
278 self.log.debug("jujuCA: Task for %s, %s done" % (service, action))
279 e = task.exception()
280 if e:
281 self.log.error("jujuCA: Error in task for {} and {} : {}".
282 format(service, action, e))
283 raise Exception(e)
284 r= task.result()
285 if r:
286 self.log.debug("jujuCA: Task for {} and {}, returned {}".
287 format(service, action,r))
288 return True
289 else:
290 self.log.debug("jujuCA: task {}, {} not done".
291 format(service, action))
292 return False
293 except KeyError as e:
294 self.log.error("jujuCA: KeyError for task for {} and {}: {}".
295 format(service, action, e))
296 except Exception as e:
297 self.log.error("jujuCA: Error for task for {} and {}: {}".
298 format(service, action, e))
299 raise
300 return True
301
302 @asyncio.coroutine
303 def _vnf_config_primitive(self, nsr_id, vnfr_id, primitive,
304 vnf_config=None, wait=False):
305 self._log.debug("jujuCA: VNF config primitive {} for nsr {}, "
306 "vnfr_id {}".
307 format(primitive, nsr_id, vnfr_id))
308
309 if vnf_config is None:
310 vnfr_msg = yield from self.get_vnfr(vnfr_id)
311 if vnfr_msg is None:
312 msg = "Unable to get VNFR {} through DTS".format(vnfr_id)
313 self._log.error(msg)
314 return 3, msg
315
316 vnf_config = vnfr_msg.vnf_configuration
317 self._log.debug("VNF config= %s", vnf_config.as_dict())
318
319 try:
320 service = vnfr['vnf_juju_name']
321 self._log.debug("VNF config %s", vnf_config)
322 configs = vnf_config.config_primitive
323 for config in configs:
324 if config.name == primitive.name:
325 self._log.debug("jujuCA: Found the config primitive %s",
326 config.name)
327 params = {}
328 for parameter in config.parameter:
329 val = None
330 for p in primitive.parameter:
331 if p.name == parameter.name:
332 if p.value:
333 val = self.xlate(p.value, vnfr['tags'])
334 break
335
336 if val is None:
337 val = parameter.default_value
338
339 if val is None:
340 # Check if mandatory parameter
341 if parameter.mandatory:
342 msg = "VNFR {}: Primitive {} called " \
343 "without mandatory parameter {}". \
344 format(vnfr_msg.name, config.name,
345 parameter.name)
346 self._log.error(msg)
347 return 'failed', '', msg
348
349 if val:
350 val = self.convert_value(val, parameter.data_type)
351 params.update({parameter.name: val})
352
353 rc = ''
354 exec_id = ''
355 details = ''
356 if config.name == 'config':
357 exec_id = 'config'
358 if len(params):
359 self._log.debug("jujuCA: applying config with "
360 "params {} for service {}".
361 format(params, service))
362
363 rc = yield from self.api.apply_config(params, application=service)
364
365 if rc:
366 rc = "completed"
367 self._log.debug("jujuCA: applied config {} "
368 "on {}".format(params, service))
369 else:
370 rc = 'failed'
371 details = \
372 'Failed to apply config: {}'.format(params)
373 self._log.error("jujuCA: Error applying "
374 "config {} on service {}".
375 format(params, service))
376 else:
377 self._log.warn("jujuCA: Did not find valid "
378 "parameters for config : {}".
379 format(primitive.parameter))
380 rc = "completed"
381 else:
382 self._log.debug("jujuCA: Execute action {} on "
383 "service {} with params {}".
384 format(config.name, service, params))
385
386 resp = yield from self.api.execute_action(
387 service,
388 config.name,
389 **params,
390 )
391
392 if resp:
393 if 'error' in resp:
394 details = resp['error']['message']
395 else:
396 exec_id = resp['action']['tag']
397 rc = resp['status']
398 if rc == 'failed':
399 details = resp['message']
400
401 self._log.debug("jujuCA: execute action {} on "
402 "service {} returned {}".
403 format(config.name, service, rc))
404 else:
405 self._log.error("jujuCA: error executing action "
406 "{} for {} with {}".
407 format(config.name, service,
408 params))
409 exec_id = ''
410 rc = 'failed'
411 details = "Failed to queue the action"
412 break
413
414 except KeyError as e:
415 msg = "VNF %s does not have config primitives, e=%s", \
416 vnfr_id, e
417 self._log.exception(msg)
418 raise ValueError(msg)
419
420 while wait and (rc in ['pending', 'running']):
421 self._log.debug("JujuCA: action {}, rc {}".
422 format(exec_id, rc))
423 yield from asyncio.sleep(0.2, loop=self._loop)
424 status = yield from self.api.get_action_status(exec_id)
425 rc = status['status']
426
427 return rc, exec_id, details
428
429 @asyncio.coroutine
430 def vnf_config_primitive(self, nsr_id, vnfr_id, primitive, output):
431 try:
432 vnfr = self._juju_vnfs[vnfr_id].vnfr
433 except KeyError:
434 msg = "Did not find VNFR {} in Juju plugin".format(vnfr_id)
435 self._log.debug(msg)
436 return
437
438 output.execution_status = "failed"
439 output.execution_id = ''
440 output.execution_error_details = ''
441
442 rc, exec_id, err = yield from self._vnf_config_primitive(
443 nsr_id,
444 vnfr_id,
445 primitive)
446
447 self._log.debug("VNFR {} primitive {} exec status: {}".
448 format(vnfr.name, primitive.name, rc))
449 output.execution_status = rc
450 output.execution_id = exec_id
451 output.execution_error_details = err
452
453 @asyncio.coroutine
454 def apply_config(self, agent_nsr, agent_vnfr, config, rpc_ip):
455 """ Notification on configuration of an NSR """
456 pass
457
458 @asyncio.coroutine
459 def apply_ns_config(self, agent_nsr, agent_vnfrs, rpc_ip):
460 """
461
462 ###### TBD - This really does not belong here. Looks more like NS level script ####
463 ###### apply_config should be called for a particular VNF only here ###############
464
465 Hook: Runs the user defined script. Feeds all the necessary data
466 for the script thro' yaml file.
467
468 Args:
469 rpc_ip (YangInput_Nsr_ExecNsConfigPrimitive): The input data.
470 nsr (NetworkServiceRecord): Description
471 vnfrs (dict): VNFR ID => VirtualNetworkFunctionRecord
472
473 """
474 def get_meta(agent_nsr):
475 unit_names, initial_params, vnfr_index_map = {}, {}, {}
476
477 for vnfr_id in agent_nsr.vnfr_ids:
478 juju_vnf = self._juju_vnfs[vnfr_id].vnfr
479
480 # Vnfr -> index ref
481 vnfr_index_map[vnfr_id] = juju_vnf['member_vnf_index']
482
483 # Unit name
484 unit_names[vnfr_id] = juju_vnf['vnf_juju_name']
485
486 # Flatten the data for simplicity
487 param_data = {}
488 self._log.debug("Juju Config:%s", juju_vnf['config'])
489 for primitive in juju_vnf['config'].initial_config_primitive:
490 for parameter in primitive.parameter:
491 value = self.xlate(parameter.value, juju_vnf['tags'])
492 param_data[parameter.name] = value
493
494 initial_params[vnfr_id] = param_data
495
496
497 return unit_names, initial_params, vnfr_index_map
498
499 unit_names, init_data, vnfr_index_map = get_meta(agent_nsr)
500
501 # The data consists of 4 sections
502 # 1. Account data
503 # 2. The input passed.
504 # 3. Juju unit names (keyed by vnfr ID).
505 # 4. Initial config data (keyed by vnfr ID).
506 data = dict()
507 data['config_agent'] = dict(
508 name=self._name,
509 host=self._ip_address,
510 port=self._port,
511 user=self._user,
512 secret=self._secret
513 )
514 data["rpc_ip"] = rpc_ip.as_dict()
515 data["unit_names"] = unit_names
516 data["init_config"] = init_data
517 data["vnfr_index_map"] = vnfr_index_map
518
519 tmp_file = None
520 with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
521 tmp_file.write(yaml.dump(data, default_flow_style=True)
522 .encode("UTF-8"))
523
524 self._log.debug("jujuCA: Creating a temp file: {} with input data".format(
525 tmp_file.name))
526
527 # Get the full path to the script
528 script = ''
529 if rpc_ip.user_defined_script[0] == '/':
530 # The script has full path, use as is
531 script = rpc_ip.user_defined_script
532 else:
533 script = os.path.join(self._rift_var_root_dir, 'launchpad/nsd',
534 self._project.name,
535 agent_nsr.id, 'scripts',
536 rpc_ip.user_defined_script)
537 self.log.debug("jujuCA: Checking for script in %s", script)
538 if not os.path.exists(script):
539 script = os.path.join(self._rift_install_dir, 'usr/bin', rpc_ip.user_defined_script)
540
541 cmd = "{} {}".format(rpc_ip.user_defined_script, tmp_file.name)
542 self._log.debug("jujuCA: Running the CMD: {}".format(cmd))
543
544 coro = asyncio.create_subprocess_shell(cmd, loop=self._loop,
545 stderr=asyncio.subprocess.PIPE)
546 process = yield from coro
547 err = yield from process.stderr.read()
548 task = self._loop.create_task(process.wait())
549
550 return task, err
551
552 @asyncio.coroutine
553 def apply_initial_config(self, agent_nsr, agent_vnfr):
554 """
555 Apply the initial configuration
556 Expect config directives mostly, not actions
557 Actions in initial config may not work based on charm design
558 """
559
560 try:
561 vnfr = self._juju_vnfs[agent_vnfr.id].vnfr
562 except KeyError:
563 self._log.debug("Did not find VNFR %s in Juju plugin",
564 agent_vnfr.name)
565 return False
566
567 vnfr_msg = yield from self.get_vnfr(agent_vnfr.id)
568 if vnfr_msg is None:
569 msg = "Unable to get VNFR {} ({}) through DTS". \
570 format(agent_vnfr.id, agent_vnfr.name)
571 self._log.error(msg)
572 raise RuntimeError(msg)
573
574 vnf_config = vnfr_msg.vnf_configuration
575 self._log.debug("VNFR %s config: %s", vnfr_msg.name,
576 vnf_config.as_dict())
577
578 # Sort the primitive based on the sequence number
579 primitives = sorted(vnf_config.initial_config_primitive,
580 key=lambda k: k.seq)
581 if not primitives:
582 self._log.debug("VNFR {}: No initial-config-primitive specified".
583 format(vnfr_msg.name))
584 return True
585
586 rc = yield from self.api.is_application_up(application=service)
587 if not rc:
588 return False
589
590 try:
591 if vnfr_msg.mgmt_interface.ip_address:
592 vnfr['tags'].update({'rw_mgmt_ip': vnfr_msg.mgmt_interface.ip_address})
593 self._log.debug("jujuCA:(%s) tags: %s", vnfr['vnf_juju_name'], vnfr['tags'])
594
595 for primitive in primitives:
596 self._log.debug("(%s) Initial config primitive %s",
597 vnfr['vnf_juju_name'], primitive.as_dict())
598 if primitive.config_primitive_ref:
599 # Reference to a primitive in config primitive
600 class Primitive:
601 def __init__(self, name):
602 self.name = name
603 self.value = None
604 self.parameter = []
605
606 prim = Primitive(primitive.config_primitive_ref)
607 rc, eid, err = yield from self._vnf_config_primitive(
608 agent_nsr.id,
609 agent_vnfr.id,
610 prim,
611 vnf_config,
612 wait=True)
613
614 if rc == "failed":
615 msg = "Error executing initial config primitive" \
616 " {} in VNFR {}: rc={}, stderr={}". \
617 format(prim.name, vnfr_msg.name, rc, err)
618 self._log.error(msg)
619 return False
620
621 elif rc == "pending":
622 action_ids.append(eid)
623
624 elif primitive.name:
625 config = {}
626 if primitive.name == 'config':
627 for param in primitive.parameter:
628 if vnfr['tags']:
629 val = self.xlate(param.value,
630 vnfr['tags'])
631 config.update({param.name: val})
632
633 if config:
634 self.juju_log('info', vnfr['vnf_juju_name'],
635 "Applying Initial config:%s",
636 config)
637
638 rc = yield from self.api.apply_config(
639 config,
640 application=service,
641 )
642 if rc is False:
643 self.log.error("Service {} is in error state".format(service))
644 return False
645 else:
646 # Apply any actions specified as part of initial config
647 for primitive in vnfr['config'].initial_config_primitive:
648 if primitive.name != 'config':
649 self._log.debug("jujuCA:(%s) Initial config action primitive %s",
650 vnfr['vnf_juju_name'], primitive)
651 action = primitive.name
652 params = {}
653 for param in primitive.parameter:
654 val = self.xlate(param.value, vnfr['tags'])
655 params.update({param.name: val})
656
657 self._log.info("jujuCA:(%s) Action %s with params %s",
658 vnfr['vnf_juju_name'], action, params)
659 self._log.debug("executing action")
660 resp = yield from self.api.execute_action(
661 service,
662 action,
663 **params,
664 )
665 self._log.debug("executed action")
666 if 'error' in resp:
667 self._log.error("Applying initial config on {} failed for {} with {}: {}".
668 format(vnfr['vnf_juju_name'], action, params, resp))
669 return False
670 except KeyError as e:
671 self._log.info("Juju config agent(%s): VNFR %s not managed by Juju",
672 vnfr['vnf_juju_name'], agent_vnfr.id)
673 return False
674 except Exception as e:
675 self._log.exception("jujuCA:(%s) Exception juju "
676 "apply_initial_config for VNFR {}: {}".
677 format(vnfr['vnf_juju_name'],
678 agent_vnfr.id, e))
679 return False
680
681 return True
682
683 def add_vnfr_managed(self, agent_vnfr):
684 if agent_vnfr.id not in self._juju_vnfs.keys():
685 self._log.info("juju config agent: add vnfr={}/{}".
686 format(agent_vnfr.name, agent_vnfr.id))
687 self._juju_vnfs[agent_vnfr.id] = agent_vnfr
688
689 def is_vnfr_managed(self, vnfr_id):
690 try:
691 if vnfr_id in self._juju_vnfs:
692 return True
693 except Exception as e:
694 self._log.debug("jujuCA: Is VNFR {} managed: {}".
695 format(vnfr_id, e))
696 return False
697
698 @asyncio.coroutine
699 def is_configured(self, vnfr_id):
700 try:
701 agent_vnfr = self._juju_vnfs[vnfr_id]
702 vnfr = agent_vnfr.vnfr
703 if vnfr['active']:
704 return True
705
706 vnfr = self._juju_vnfs[vnfr_id].vnfr
707 service = vnfr['vnf_juju_name']
708 resp = self.api.is_application_active(application=service)
709 self._juju_vnfs[vnfr_id]['active'] = resp
710 self._log.debug("jujuCA: Service state for {} is {}".
711 format(service, resp))
712 return resp
713
714 except KeyError:
715 self._log.debug("jujuCA: VNFR id {} not found in config agent".
716 format(vnfr_id))
717 return False
718 except Exception as e:
719 self._log.error("jujuCA: VNFR id {} is_configured: {}".
720 format(vnfr_id, e))
721 return False
722
723 @asyncio.coroutine
724 def get_config_status(self, agent_nsr, agent_vnfr):
725 """Get the configuration status for the VNF"""
726 rc = 'unknown'
727
728 try:
729 vnfr = agent_vnfr.vnfr
730 service = vnfr['vnf_juju_name']
731 except KeyError:
732 # This VNF is not managed by Juju
733 return rc
734
735 rc = 'configuring'
736
737 if not self.check_task_status(service, 'deploy'):
738 return rc
739
740 try:
741 resp = yield from self.api.get_service_status(application=service)
742 self._log.debug("jujuCA: Get service %s status? %s", service, resp)
743
744 if resp == 'error':
745 return 'error'
746 if resp == 'active':
747 return 'configured'
748 except KeyError:
749 self._log.error("jujuCA: Check unknown service %s status", service)
750 except Exception as e:
751 self._log.error("jujuCA: Caught exception when checking for service is active: %s", e)
752 self._log.exception(e)
753
754 return rc
755
756 def get_action_status(self, execution_id):
757 ''' Get the action status for an execution ID
758 *** Make sure this is NOT a asyncio coroutine function ***
759 '''
760
761 try:
762 self._log.debug("jujuCA: Get action status for {}".format(execution_id))
763 resp = self.api._get_action_status(execution_id)
764 self._log.debug("jujuCA: Action status: {}".format(resp))
765 return resp
766 except Exception as e:
767 self._log.error("jujuCA: Error fetching execution status for %s",
768 execution_id)
769 self._log.exception(e)
770 raise e
771
772 def get_service_status(self, vnfr_id):
773 '''Get the service status, used by job status handle
774 Make sure this is NOT a coroutine
775 '''
776 service = self.get_service_name(vnfr_id)
777 if service is None:
778 self._log.error("jujuCA: VNFR {} not managed by this Juju agent".
779 format(vnfr_id))
780 return None
781
782 # Delay for 3 seconds before checking as config apply takes a
783 # few seconds to transfer to the service
784 time.sleep(3)
785 return self.api._get_service_status(service=service)