3 # Copyright 2017 RIFT.IO Inc
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
20 import rift
.mano
.dts
as mano_dts
22 from . import accounts
24 from gi
.repository
import(
29 gi
.require_version('RwKeyspec', '1.0')
30 from gi
.repository
.RwKeyspec
import quoted_key
32 class ROAccountNotFound(Exception):
35 class ROAccountDtsOperdataHandler(object):
36 def __init__(self
, dts
, log
, loop
, project
):
40 self
._project
= project
47 self
._nsr
_sub
= mano_dts
.NsInstanceConfigSubscriber(
52 callback
=self
.handle_nsr
)
54 def handle_nsr(self
, nsr
, action
):
55 if action
== rwdts
.QueryAction
.CREATE
:
57 self
.ro_accounts
[nsr
.resource_orchestrator
].live_instances
+= 1
59 self
.ro_accounts
['rift'].live_instances
+= 1
60 elif action
== rwdts
.QueryAction
.DELETE
:
62 self
.ro_accounts
[nsr
.resource_orchestrator
].live_instances
-= 1
64 self
.ro_accounts
['rift'].live_instances
-= 1
67 return "D,/rw-ro-account:ro-account-state/account"
69 def get_qualified_xpath(self
, ro_account_name
):
70 if ro_account_name
is None:
71 raise Exception("Account name cannot be None")
73 return self
._project
.add_project("D,/rw-ro-account:ro-account-state/account{}".format(
74 "[name=%s]" % quoted_key(ro_account_name
))
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(
82 details
="RO account connection status success"
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
)
88 def add_ro_account(self
, account
):
89 self
.ro_accounts
[account
.name
] = account
90 account
.start_validate_ro_account(self
._loop
)
92 def delete_ro_account(self
, account_name
):
93 account
= self
.ro_accounts
[account_name
]
94 del self
.ro_accounts
[account_name
]
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
= []
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
)
107 errstr
= "RO account {} does not exist".format(ro_account_name
)
108 raise KeyError(errstr
)
110 return saved_ro_accounts
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
)
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
125 saved_accounts
= self
.get_saved_ro_accounts(ro_account_name
)
126 for account
in saved_accounts
:
127 connection_status
= account
._status
129 xpath
= self
._project
.add_project(get_xpath(account
.name
))
130 xact_info
.respond_xpath(
131 rwdts
.XactRspCode
.MORE
,
135 except Exception as e
:
136 self
._log
.warning(str(e
))
137 xact_info
.respond_xpath(rwdts
.XactRspCode
.NA
)
140 xact_info
.respond_xpath(rwdts
.XactRspCode
.ACK
)
142 xpath
= self
._project
.add_project(self
.get_xpath())
143 self
._regh
= yield from self
._dts
.register(
145 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
146 on_prepare
=on_prepare
),
147 flags
=rwdts
.Flag
.PUBLISHER
,
150 #ATTN: TODO: Should ideally wait for
151 #on_ready callback to be called.
152 self
.add_rift_ro_account()
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 ''
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
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
,
174 msg
=RwRoAccountYang
.YangData_RwProject_Project_RoAccountState_Account_InstanceRefCount(count
=instance_count
)
176 except KeyError as e
:
177 self
._log
.warning(str(e
))
178 xact_info
.respond_xpath(rwdts
.XactRspCode
.NA
)
181 xact_info
.respond_xpath(rwdts
.XactRspCode
.ACK
)
183 xpath
= self
._project
.add_project(get_xpath())
184 self
._rsic
= yield from self
._dts
.register(
186 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
187 on_prepare
=on_prepare
),
188 flags
=rwdts
.Flag
.PUBLISHER
,
192 def _register_validate_rpc(self
):
194 return "/rw-ro-account:update-ro-account-status"
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
202 if not self
._project
.rpc_check(msg
, xact_info
=xact_info
):
206 account
= self
.ro_accounts
[ro_account_name
]
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
,
213 raise ROAccountNotFound(errmsg
)
215 if ro_account_name
!= 'rift':
216 account
.start_validate_ro_account(self
._loop
)
218 xact_info
.respond_xpath(rwdts
.XactRspCode
.ACK
)
220 self
._rpc
= yield from self
._dts
.register(
222 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
223 on_prepare
=on_prepare
225 flags
=rwdts
.Flag
.PUBLISHER
,
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 ''
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
241 saved_accounts
= self
.get_saved_ro_accounts(ro_account_name
)
242 for account
in saved_accounts
:
244 if account
.name
== 'rift':
245 datacenters
= [{'name': cloud
.name
, 'datacenter_type': cloud
.account_type
}
246 for cloud
in self
._project
.cloud_accounts
]
248 datacenters
= account
._datacenters
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
,
258 except KeyError as e
:
259 self
._log
.warning(str(e
))
260 xact_info
.respond_xpath(rwdts
.XactRspCode
.NA
)
263 xact_info
.respond_xpath(rwdts
.XactRspCode
.ACK
)
265 xpath
= self
._project
.add_project(get_xpath())
266 self
._rdcp
= yield from self
._dts
.register(
268 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
269 on_prepare
=on_prepare
),
270 flags
=rwdts
.Flag
.PUBLISHER
,
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 ''
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
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
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
,
297 except KeyError as e
:
298 self
._log
.warning(str(e
))
299 xact_info
.respond_xpath(rwdts
.XactRspCode
.NA
)
302 xact_info
.respond_xpath(rwdts
.XactRspCode
.ACK
)
304 xpath
= self
._project
.add_project(get_xpath())
305 self
._rcdp
= yield from self
._dts
.register(
307 handler
=rift
.tasklets
.DTS
.RegistrationHandler(
308 on_prepare
=on_prepare
),
309 flags
=rwdts
.Flag
.PUBLISHER
,
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()
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()