blob: 3478bcf3364834c04b8a1c882207c4fb02e058d6 [file] [log] [blame]
Chamarty4bd90252017-04-03 17:26:43 -04001
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
18import asyncio
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040019import gi
20
Chamarty4bd90252017-04-03 17:26:43 -040021import rift.tasklets
22
23from gi.repository import(
24 RwSdnYang,
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040025 RwsdnalYang,
Chamarty4bd90252017-04-03 17:26:43 -040026 RwDts as rwdts,
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040027 RwTypes,
Chamarty4bd90252017-04-03 17:26:43 -040028 )
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040029gi.require_version('RwKeyspec', '1.0')
30from gi.repository.RwKeyspec import quoted_key
Chamarty4bd90252017-04-03 17:26:43 -040031
32
33class SDNAccountNotFound(Exception):
34 pass
35
36
37class SDNAccountDtsOperdataHandler(object):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040038 def __init__(self, dts, log, loop, project):
Chamarty4bd90252017-04-03 17:26:43 -040039 self._dts = dts
40 self._log = log
41 self._loop = loop
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040042 self._project = project
Chamarty4bd90252017-04-03 17:26:43 -040043
44 self.sdn_accounts = {}
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040045 self._oper = None
46 self._rpc = None
Chamarty4bd90252017-04-03 17:26:43 -040047
48 def add_sdn_account(self, account):
49 self.sdn_accounts[account.name] = account
50 account.start_validate_credentials(self._loop)
51
52 def delete_sdn_account(self, account_name):
53 del self.sdn_accounts[account_name]
54
55 def get_saved_sdn_accounts(self, sdn_account_name):
56 ''' Get SDN Account corresponding to passed name, or all saved accounts if name is None'''
57 saved_sdn_accounts = []
58
59 if sdn_account_name is None or sdn_account_name == "":
60 sdn_accounts = list(self.sdn_accounts.values())
61 saved_sdn_accounts.extend(sdn_accounts)
62 elif sdn_account_name in self.sdn_accounts:
63 account = self.sdn_accounts[sdn_account_name]
64 saved_sdn_accounts.append(account)
65 else:
66 errstr = "SDN account {} does not exist".format(sdn_account_name)
67 raise KeyError(errstr)
68
69 return saved_sdn_accounts
70
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040071 @asyncio.coroutine
72 def create_notification(self, account):
73 xpath = "N,/rw-sdn:sdn-notif"
74 ac_status = RwSdnYang.YangNotif_RwSdn_SdnNotif()
75 ac_status.name = account.name
76 ac_status.message = account.connection_status.details
77
78 yield from self._dts.query_create(xpath, rwdts.XactFlag.ADVISE, ac_status)
79 self._log.info("Notification called by creating dts query: %s", ac_status)
80
81
82 @asyncio.coroutine
Chamarty4bd90252017-04-03 17:26:43 -040083 def _register_show_status(self):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040084 self._log.debug("Registering for show for project {}".format(self._project))
Chamarty4bd90252017-04-03 17:26:43 -040085 def get_xpath(sdn_name=None):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040086 return self._project.add_project("D,/rw-sdn:sdn/rw-sdn:account{}/rw-sdn:connection-status".
87 format(
88 "[rw-sdn:name=%s]" % quoted_key(sdn_name)
89 if sdn_name is not None else ''))
Chamarty4bd90252017-04-03 17:26:43 -040090
91 @asyncio.coroutine
92 def on_prepare(xact_info, action, ks_path, msg):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -040093 xpath = ks_path.to_xpath(RwSdnYang.get_schema())
94 self._log.debug("Got show SDN connection status request: %s", xpath)
95 path_entry = RwSdnYang.YangData_RwProject_Project_Sdn_Account.schema().keyspec_to_entry(ks_path)
Chamarty4bd90252017-04-03 17:26:43 -040096 sdn_account_name = path_entry.key00.name
97
98 try:
99 saved_accounts = self.get_saved_sdn_accounts(sdn_account_name)
100 for account in saved_accounts:
101 connection_status = account.connection_status
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400102 self._log.debug("Responding to SDN connection status request: %s",
103 connection_status)
Chamarty4bd90252017-04-03 17:26:43 -0400104 xact_info.respond_xpath(
105 rwdts.XactRspCode.MORE,
106 xpath=get_xpath(account.name),
107 msg=account.connection_status,
108 )
109 except KeyError as e:
110 self._log.warning(str(e))
111 xact_info.respond_xpath(rwdts.XactRspCode.NA)
112 return
113
114 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
115
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400116 self._oper = yield from self._dts.register(
Chamarty4bd90252017-04-03 17:26:43 -0400117 xpath=get_xpath(),
118 handler=rift.tasklets.DTS.RegistrationHandler(
119 on_prepare=on_prepare),
120 flags=rwdts.Flag.PUBLISHER,
121 )
122
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400123 @asyncio.coroutine
Chamarty4bd90252017-04-03 17:26:43 -0400124 def _register_validate_rpc(self):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400125 self._log.debug("Registering for rpc for project {}".format(self._project))
Chamarty4bd90252017-04-03 17:26:43 -0400126 def get_xpath():
127 return "/rw-sdn:update-sdn-status"
128
129 @asyncio.coroutine
130 def on_prepare(xact_info, action, ks_path, msg):
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400131 if self._project and not self._project.rpc_check(msg, xact_info=xact_info):
132 return
133
134 self._log.debug("Got update SDN connection status request: %s", msg)
135
Chamarty4bd90252017-04-03 17:26:43 -0400136 if not msg.has_field("sdn_account"):
137 raise SDNAccountNotFound("SDN account name not provided")
138
139 sdn_account_name = msg.sdn_account
140 try:
141 account = self.sdn_accounts[sdn_account_name]
142 except KeyError:
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400143 errmsg = "SDN account name %s not found" % sdn_account_name
144 self._log.error(errmsg)
145 xpath = ks_path.to_xpath(RwSdnYang.get_schema())
146 xact_info.send_error_xpath(RwTypes.RwStatus.FAILURE,
147 xpath,
148 errmsg)
149 xact_info.respond_xpath(rwdts.XactRspCode.NACK)
150 return
Chamarty4bd90252017-04-03 17:26:43 -0400151
152 account.start_validate_credentials(self._loop)
153
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400154 yield from self.create_notification(account)
155
Chamarty4bd90252017-04-03 17:26:43 -0400156 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
157
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400158 self._rpc = yield from self._dts.register(
159 xpath=get_xpath(),
160 handler=rift.tasklets.DTS.RegistrationHandler(
161 on_prepare=on_prepare
162 ),
163 flags=rwdts.Flag.PUBLISHER,
164 )
Chamarty4bd90252017-04-03 17:26:43 -0400165
166 @asyncio.coroutine
167 def register(self):
168 yield from self._register_show_status()
169 yield from self._register_validate_rpc()
Jeremy Mordkoff4870d0e2017-09-30 20:28:33 -0400170
171 def deregister(self):
172 if self._oper:
173 self._oper.deregister()
174 self._oper = None
175
176 if self._rpc:
177 self._rpc.deregister()
178 self._rpc = None