update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / common / python / rift / mano / ro_account / operdata.py
1
2 #
3 # Copyright 2017 RIFT.IO Inc
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17
18 import asyncio
19 import gi
20 import rift.mano.dts as mano_dts
21 import rift.tasklets
22 from . import accounts
23
24 from gi.repository import(
25 RwRoAccountYang,
26 RwDts as rwdts,
27 RwTypes,
28 )
29 gi.require_version('RwKeyspec', '1.0')
30 from gi.repository.RwKeyspec import quoted_key
31
32 class ROAccountNotFound(Exception):
33 pass
34
35 class ROAccountDtsOperdataHandler(object):
36 def __init__(self, dts, log, loop, project):
37 self._dts = dts
38 self._log = log
39 self._loop = loop
40 self._project = project
41
42 self._regh = None
43 self._rpc = None
44 self._rsic = None
45 self._rdcp = None
46 self.ro_accounts = {}
47 self._nsr_sub = mano_dts.NsInstanceConfigSubscriber(
48 self._log,
49 self._dts,
50 self._loop,
51 self._project,
52 callback=self.handle_nsr)
53
54 def handle_nsr(self, nsr, action):
55 if action == rwdts.QueryAction.CREATE:
56 try:
57 self.ro_accounts[nsr.resource_orchestrator].live_instances += 1
58 except KeyError as e:
59 self.ro_accounts['rift'].live_instances += 1
60 elif action == rwdts.QueryAction.DELETE:
61 try:
62 self.ro_accounts[nsr.resource_orchestrator].live_instances -= 1
63 except KeyError as e:
64 self.ro_accounts['rift'].live_instances -= 1
65
66 def get_xpath(self):
67 return "D,/rw-ro-account:ro-account-state/account"
68
69 def get_qualified_xpath(self, ro_account_name):
70 if ro_account_name is None:
71 raise Exception("Account name cannot be None")
72
73 return self._project.add_project("D,/rw-ro-account:ro-account-state/account{}".format(
74 "[name=%s]" % quoted_key(ro_account_name))
75 )
76
77 def add_rift_ro_account(self):
78 rift_acc = accounts.ROAccount()
79 rift_acc._name = 'rift'
80 rift_acc._status = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account_ConnectionStatus(
81 status="success",
82 details="RO account connection status success"
83 )
84 self.ro_accounts[rift_acc.name] = rift_acc
85 rift_acc_state = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account(name=rift_acc.name)
86 self._regh.create_element(self.get_qualified_xpath(rift_acc.name), rift_acc_state)
87
88 def add_ro_account(self, account):
89 self.ro_accounts[account.name] = account
90 account.start_validate_ro_account(self._loop)
91
92 def delete_ro_account(self, account_name):
93 account = self.ro_accounts[account_name]
94 del self.ro_accounts[account_name]
95
96 def get_saved_ro_accounts(self, ro_account_name):
97 ''' Get RO Account corresponding to passed name, or all saved accounts if name is None'''
98 saved_ro_accounts = []
99
100 if ro_account_name is None or ro_account_name == "":
101 ro_accounts = list(self.ro_accounts.values())
102 saved_ro_accounts.extend(ro_accounts)
103 elif ro_account_name in self.ro_accounts:
104 account = self.ro_accounts[ro_account_name]
105 saved_ro_accounts.append(account)
106 else:
107 errstr = "RO account {} does not exist".format(ro_account_name)
108 raise KeyError(errstr)
109
110 return saved_ro_accounts
111
112 @asyncio.coroutine
113 def _register_show_status(self):
114 def get_xpath(ro_account_name):
115 return "D,/rw-ro-account:ro-account-state/account{}/connection-status".format(
116 "[name=%s]" % quoted_key(ro_account_name)
117 )
118
119 @asyncio.coroutine
120 def on_prepare(xact_info, action, ks_path, msg):
121 path_entry = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account.schema().keyspec_to_entry(ks_path)
122 ro_account_name = path_entry.key00.name
123
124 try:
125 saved_accounts = self.get_saved_ro_accounts(ro_account_name)
126 for account in saved_accounts:
127 connection_status = account._status
128
129 xpath = self._project.add_project(get_xpath(account.name))
130 xact_info.respond_xpath(
131 rwdts.XactRspCode.MORE,
132 xpath=xpath,
133 msg=account._status,
134 )
135 except Exception as e:
136 self._log.warning(str(e))
137 xact_info.respond_xpath(rwdts.XactRspCode.NA)
138 return
139
140 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
141
142 xpath = self._project.add_project(self.get_xpath())
143 self._regh = yield from self._dts.register(
144 xpath=xpath,
145 handler=rift.tasklets.DTS.RegistrationHandler(
146 on_prepare=on_prepare),
147 flags=rwdts.Flag.PUBLISHER,
148 )
149
150 #ATTN: TODO: Should ideally wait for
151 #on_ready callback to be called.
152 self.add_rift_ro_account()
153
154 @asyncio.coroutine
155 def _register_show_instance_count(self):
156 def get_xpath(ro_account_name=None):
157 return "D,/rw-ro-account:ro-account-state/account{}/instance-ref-count".format(
158 "[name=%s]" % quoted_key(ro_account_name) if ro_account_name is not None else ''
159 )
160
161 @asyncio.coroutine
162 def on_prepare(xact_info, action, ks_path, msg):
163 path_entry = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account.schema().keyspec_to_entry(ks_path)
164 ro_account_name = path_entry.key00.name
165
166 try:
167 saved_accounts = self.get_saved_ro_accounts(ro_account_name)
168 for account in saved_accounts:
169 instance_count = account.live_instances
170 xpath = self._project.add_project(get_xpath(account.name))
171 xact_info.respond_xpath(
172 rwdts.XactRspCode.MORE,
173 xpath=xpath,
174 msg=RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account_InstanceRefCount(count=instance_count)
175 )
176 except KeyError as e:
177 self._log.warning(str(e))
178 xact_info.respond_xpath(rwdts.XactRspCode.NA)
179 return
180
181 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
182
183 xpath = self._project.add_project(get_xpath())
184 self._rsic = yield from self._dts.register(
185 xpath=xpath,
186 handler=rift.tasklets.DTS.RegistrationHandler(
187 on_prepare=on_prepare),
188 flags=rwdts.Flag.PUBLISHER,
189 )
190
191 @asyncio.coroutine
192 def _register_validate_rpc(self):
193 def get_xpath():
194 return "/rw-ro-account:update-ro-account-status"
195
196 @asyncio.coroutine
197 def on_prepare(xact_info, action, ks_path, msg):
198 if not msg.has_field("ro_account"):
199 raise ROAccountNotFound("RO account name not provided")
200 ro_account_name = msg.ro_account
201
202 if not self._project.rpc_check(msg, xact_info=xact_info):
203 return
204
205 try:
206 account = self.ro_accounts[ro_account_name]
207 except KeyError:
208 errmsg = "RO account name {} not found in project {}". \
209 format(ro_account_name, self._project.name)
210 xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
211 get_xpath(),
212 errmsg)
213 raise ROAccountNotFound(errmsg)
214
215 if ro_account_name != 'rift':
216 account.start_validate_ro_account(self._loop)
217
218 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
219
220 self._rpc = yield from self._dts.register(
221 xpath=get_xpath(),
222 handler=rift.tasklets.DTS.RegistrationHandler(
223 on_prepare=on_prepare
224 ),
225 flags=rwdts.Flag.PUBLISHER,
226 )
227
228 @asyncio.coroutine
229 def _register_data_center_publisher(self):
230 def get_xpath(ro_account_name=None):
231 return "D,/rw-ro-account:ro-account-state/account{}/datacenters".format(
232 "[name=%s]" % quoted_key(ro_account_name) if ro_account_name is not None else ''
233 )
234
235 @asyncio.coroutine
236 def on_prepare(xact_info, action, ks_path, msg):
237 path_entry = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account.schema().keyspec_to_entry(ks_path)
238 ro_account_name = path_entry.key00.name
239
240 try:
241 saved_accounts = self.get_saved_ro_accounts(ro_account_name)
242 for account in saved_accounts:
243 datacenters = []
244 if account.name == 'rift':
245 datacenters = [{'name': cloud.name, 'datacenter_type': cloud.account_type}
246 for cloud in self._project.cloud_accounts]
247 else :
248 datacenters = account._datacenters
249
250 response = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account_Datacenters()
251 response.from_dict({'datacenters': datacenters})
252 xpath = self._project.add_project(get_xpath(account.name))
253 xact_info.respond_xpath(
254 rwdts.XactRspCode.MORE,
255 xpath=xpath,
256 msg=response
257 )
258 except KeyError as e:
259 self._log.warning(str(e))
260 xact_info.respond_xpath(rwdts.XactRspCode.NA)
261 return
262
263 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
264
265 xpath = self._project.add_project(get_xpath())
266 self._rdcp = yield from self._dts.register(
267 xpath=xpath,
268 handler=rift.tasklets.DTS.RegistrationHandler(
269 on_prepare=on_prepare),
270 flags=rwdts.Flag.PUBLISHER,
271 )
272
273 @asyncio.coroutine
274 def _register_config_data_publisher(self):
275 def get_xpath(ro_account_name=None):
276 return "D,/rw-ro-account:ro-account-state/account{}/config-data".format(
277 "[name=%s]" % quoted_key(ro_account_name) if ro_account_name is not None else ''
278 )
279
280 @asyncio.coroutine
281 def on_prepare(xact_info, action, ks_path, msg):
282 path_entry = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account.schema().keyspec_to_entry(ks_path)
283 ro_account_name = path_entry.key00.name
284
285 try:
286 saved_accounts = self.get_saved_ro_accounts(ro_account_name)
287 for account in saved_accounts:
288 ro_acct_type = account.ro_acccount_type
289
290 response = RwRoAccountYang.YangData_RwProject_Project_RoAccountState_Account_ConfigData(ro_account_type=ro_acct_type)
291 xpath = self._project.add_project(get_xpath(account.name))
292 xact_info.respond_xpath(
293 rwdts.XactRspCode.MORE,
294 xpath=xpath,
295 msg=response
296 )
297 except KeyError as e:
298 self._log.warning(str(e))
299 xact_info.respond_xpath(rwdts.XactRspCode.NA)
300 return
301
302 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
303
304 xpath = self._project.add_project(get_xpath())
305 self._rcdp = yield from self._dts.register(
306 xpath=xpath,
307 handler=rift.tasklets.DTS.RegistrationHandler(
308 on_prepare=on_prepare),
309 flags=rwdts.Flag.PUBLISHER,
310 )
311
312 @asyncio.coroutine
313 def register(self):
314 self._log.debug("Register RO account for project %s", self._project.name)
315 yield from self._register_show_status()
316 yield from self._register_validate_rpc()
317 yield from self._register_show_instance_count()
318 yield from self._register_data_center_publisher()
319 yield from self._register_config_data_publisher()
320 yield from self._nsr_sub.register()
321
322 def deregister(self):
323 self._log.debug("De-register RO account for project %s", self._project.name)
324 self._rpc.deregister()
325 self._regh.deregister()
326 self._rsic.deregister()
327 self._rdcp.deregister()
328 self._rcdp.deregister()
329 self._nsr_sub.deregister()