update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / common / python / rift / mano / sdn / 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
21 import rift.tasklets
22
23 from gi.repository import(
24 RwSdnYang,
25 RwsdnalYang,
26 RwDts as rwdts,
27 RwTypes,
28 )
29 gi.require_version('RwKeyspec', '1.0')
30 from gi.repository.RwKeyspec import quoted_key
31
32
33 class SDNAccountNotFound(Exception):
34 pass
35
36
37 class SDNAccountDtsOperdataHandler(object):
38 def __init__(self, dts, log, loop, project):
39 self._dts = dts
40 self._log = log
41 self._loop = loop
42 self._project = project
43
44 self.sdn_accounts = {}
45 self._oper = None
46 self._rpc = None
47
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
71 @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
83 def _register_show_status(self):
84 self._log.debug("Registering for show for project {}".format(self._project))
85 def get_xpath(sdn_name=None):
86 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 ''))
90
91 @asyncio.coroutine
92 def on_prepare(xact_info, action, ks_path, msg):
93 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)
96 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
102 self._log.debug("Responding to SDN connection status request: %s",
103 connection_status)
104 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
116 self._oper = yield from self._dts.register(
117 xpath=get_xpath(),
118 handler=rift.tasklets.DTS.RegistrationHandler(
119 on_prepare=on_prepare),
120 flags=rwdts.Flag.PUBLISHER,
121 )
122
123 @asyncio.coroutine
124 def _register_validate_rpc(self):
125 self._log.debug("Registering for rpc for project {}".format(self._project))
126 def get_xpath():
127 return "/rw-sdn:update-sdn-status"
128
129 @asyncio.coroutine
130 def on_prepare(xact_info, action, ks_path, msg):
131 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
136 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:
143 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
151
152 account.start_validate_credentials(self._loop)
153
154 yield from self.create_notification(account)
155
156 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
157
158 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 )
165
166 @asyncio.coroutine
167 def register(self):
168 yield from self._register_show_status()
169 yield from self._register_validate_rpc()
170
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