d5820969eca801db45499404c0c78c17e03e091a
2 # -*- coding: utf-8 -*-
4 from juju_api
import JujuApi
5 from juju
.model
import ModelObserver
12 class VCAMonitor(ModelObserver
):
13 """Monitor state changes within the Juju Model."""
16 async def on_change(self
, delta
, old
, new
, model
):
17 """React to changes in the Juju model."""
19 db_nsr
= self
.context
['db_nsr']
20 vnf_index
= self
.context
['vnf_index']
22 nsr_lcm
= db_nsr
["_admin"]["deploy"]
23 nsr_id
= nsr_lcm
["id"]
24 application
= self
.context
['application']
26 if delta
.entity
== "unit":
27 # We only care about changes to a unit
28 if delta
.type == "add" and old
is None:
29 if new
and new
.application
== application
:
31 elif delta
.type == "change":
32 if new
and new
.application
== application
:
33 if new
.agent_status
== "idle":
34 if new
.workload_status
in ("active", "blocked"):
37 elif delta
.type == "remove" and new
is None:
38 if new
and new
.application
== application
:
42 nsr_lcm
["VCA"][vnf_index
]['operational-status'] = status
44 # TODO: Clean this up, and make it work with deletes (if we need
45 # TODO: to update the database post-delete)
46 # Figure out if we're finished configuring
47 count
= len(nsr_lcm
["VCA"])
49 for vnf_index
in nsr_lcm
["VCA"]:
50 if nsr_lcm
["VCA"][vnf_index
]['operational-status'] == "ACTIVE":
53 db_nsr
["config-status"] = "done"
55 db_nsr
["config-status"] = "configuring {}/{}".format(active
, count
)
58 self
.context
['db'].replace(
64 # self.context['db'].replace(
66 # {"id": self.context['nsr_lcm']['id']},
67 # self.context['nsr_lcm']
69 except Exception as e
:
70 # I've seen this happen when we handle a delete, because the
71 # db record is gone by the time we've finished deleting
73 print("Error updating database: ", e
)
78 def GetJujuApi(config
):
79 # Quiet logging from the websocket library. If you want to see
80 # everything sent over the wire, set this to DEBUG.
82 ws_logger
= logging
.getLogger('websockets.protocol')
83 ws_logger
.setLevel(logging
.INFO
)
85 api
= JujuApi(server
=config
['host'],
88 secret
=config
['secret'],
95 def get_vnf_unique_name(nsr_name
, vnfr_name
, member_vnf_index
):
96 """Get the unique VNF name.
97 Charm names accepts only a to z and non-consecutive - characters."""
98 name
= "{}-{}-{}".format(nsr_name
, vnfr_name
, member_vnf_index
)
103 elif not c
.isalpha():
106 return re
.sub('\-+', '-', new_name
.lower())
109 def get_initial_config(initial_config_primitive
, mgmt_ip
):
111 for primitive
in initial_config_primitive
:
112 if primitive
['name'] == 'config':
113 for parameter
in primitive
['parameter']:
114 param
= parameter
['name']
115 if parameter
['value'] == "<rw_mgmt_ip>":
116 config
[param
] = mgmt_ip
118 config
[param
] = parameter
['value']
122 async def DeployApplication(vcaconfig
, db
, db_nsr
, vnfd
,
123 vnf_index
, charm_path
):
127 Deploy a VNF configuration charm from a local directory.
128 :param dict vcaconfig: The VCA portion of the LCM Configuration
129 :param object vnfd: The VNF descriptor
131 :param int vnfd_index: The index of the vnf.
135 DeployApplication(...)
137 nsr_lcm
= db_nsr
["_admin"]["deploy"]
138 nsr_id
= db_nsr
["_id"]
141 if "proxy" in vnfd
["vnf-configuration"]["juju"]:
142 use_proxy
= vnfd
["vnf-configuration"]["juju"]["proxy"]
144 # TBD: We need this to handle a full charm
147 application
= get_vnf_unique_name(
148 db_nsr
["name"].lower().strip(),
153 api
= GetJujuApi(vcaconfig
)
156 if api
.authenticated
:
157 charm
= os
.path
.basename(charm_path
)
159 # Set the INIT state; further operational status updates
160 # will be made by the VCAMonitor
161 nsr_lcm
["VCA"][vnf_index
] = {}
162 nsr_lcm
["VCA"][vnf_index
]['operational-status'] = 'INIT'
163 nsr_lcm
["VCA"][vnf_index
]['application'] = application
165 db
.replace("nsrs", nsr_id
, db_nsr
)
167 model
= await api
.get_model()
169 'application': application
,
170 'vnf_index': vnf_index
,
175 mon
.context
= context
176 model
.add_observer(mon
)
178 await api
.deploy_application(charm
,
183 # Get and apply the initial config primitive
184 cfg
= get_initial_config(
185 vnfd
["vnf-configuration"].get(
186 "initial-config-primitive"
188 nsr_lcm
['nsr_ip'][vnf_index
]
191 await api
.apply_config(cfg
, application
)
196 async def RemoveApplication(vcaconfig
, db
, db_nsr
, vnf_index
):
198 Remove an application from the Juju Controller
200 Removed the named application and it's charm from the Juju controller.
202 :param object loop: The event loop.
203 :param str application_name: The unique name of the application.
207 RemoveApplication(loop, "ping_vnf")
208 RemoveApplication(loop, "pong_vnf")
210 nsr_id
= db_nsr
["_id"]
211 nsr_lcm
= db_nsr
["_admin"]["deploy"]
212 application
= nsr_lcm
["VCA"][vnf_index
]['application']
214 api
= GetJujuApi(vcaconfig
)
217 if api
.authenticated
:
218 model
= await api
.get_model()
220 'application': application
,
221 'vnf_index': vnf_index
,
227 mon
.context
= context
228 model
.add_observer(mon
)
230 print("VCA: Removing application {}".format(application
))
231 await api
.remove_application(application
)
232 nsr_lcm
["VCA"][vnf_index
]['application'] = None
233 db
.replace("nsrs", nsr_id
, db_nsr
)