b2b266337f1ecdddae58a22d0627924c4b53fbb3
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_id
= self
.context
['vnf_id']
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_id
]['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_id
in nsr_lcm
["VCA"]:
50 if nsr_lcm
["VCA"][vnf_id
]['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.
81 logging
.basicConfig(level
=logging
.DEBUG
)
83 ws_logger
= logging
.getLogger('websockets.protocol')
84 ws_logger
.setLevel(logging
.INFO
)
86 api
= JujuApi(server
=config
['host'],
89 secret
=config
['secret'],
96 def get_vnf_unique_name(nsr_name
, vnfr_name
, member_vnf_index
):
97 """Get the unique VNF name.
98 Charm names accepts only a to z and non-consecutive - characters."""
99 name
= "{}-{}-{}".format(nsr_name
, vnfr_name
, member_vnf_index
)
104 elif not c
.isalpha():
107 return re
.sub('\-+', '-', new_name
.lower())
110 def get_initial_config(initial_config_primitive
, mgmt_ip
):
112 for primitive
in initial_config_primitive
:
113 if primitive
['name'] == 'config':
114 for parameter
in primitive
['parameter']:
115 param
= parameter
['name']
116 if parameter
['value'] == "<rw_mgmt_ip>":
117 config
[param
] = mgmt_ip
119 config
[param
] = parameter
['value']
123 async def DeployApplication(vcaconfig
, db
, db_nsr
, vnfd
,
124 vnfd_index
, charm_path
):
128 Deploy a VNF configuration charm from a local directory.
129 :param dict vcaconfig: The VCA portion of the LCM Configuration
130 :param object vnfd: The VNF descriptor
132 :param int vnfd_index: The index of the vnf.
136 DeployApplication(...)
138 nsr_lcm
= db_nsr
["_admin"]["deploy"]
139 nsr_id
= nsr_lcm
["id"]
142 if "proxy" in vnfd
["vnf-configuration"]["juju"]:
143 use_proxy
= vnfd
["vnf-configuration"]["juju"]["proxy"]
145 # TBD: We need this to handle a full charm
148 application
= get_vnf_unique_name(
149 db_nsr
["name"].lower().strip(),
154 api
= GetJujuApi(vcaconfig
)
157 if api
.authenticated
:
158 charm
= os
.path
.basename(charm_path
)
160 # Set the INIT state; further operational status updates
161 # will be made by the VCAMonitor
162 nsr_lcm
["VCA"][vnf_id
] = {}
163 nsr_lcm
["VCA"][vnf_id
]['operational-status'] = 'INIT'
164 nsr_lcm
["VCA"][vnf_id
]['application'] = application
166 db
.replace("nsrs", nsr_id
, db_nsr
)
168 model
= await api
.get_model()
170 'application': application
,
176 mon
.context
= context
177 model
.add_observer(mon
)
179 await api
.deploy_application(charm
,
184 # Get and apply the initial config primitive
185 cfg
= get_initial_config(
186 vnfd
["vnf-configuration"].get(
187 "initial-config-primitive"
189 nsr_lcm
['nsr_ip'][vnfd_index
]
192 await api
.apply_config(cfg
, application
)
197 async def RemoveApplication(vcaconfig
, db
, db_nsr
, vnfd
, vnfd_index
):
199 Remove an application from the Juju Controller
201 Removed the named application and it's charm from the Juju controller.
203 :param object loop: The event loop.
204 :param str application_name: The unique name of the application.
208 RemoveApplication(loop, "ping_vnf")
209 RemoveApplication(loop, "pong_vnf")
211 nsr_lcm
= db_nsr
["_admin"]["deploy"]
213 application
= nsr_lcm
["VCA"][vnf_id
]['application']
215 api
= GetJujuApi(vcaconfig
)
218 if api
.authenticated
:
219 model
= await api
.get_model()
221 'application': application
,
228 mon
.context
= context
229 model
.add_observer(mon
)
231 print("VCA: Removing application {}".format(application
))
232 await api
.remove_application(application
)