Merge from OSM SO master
[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 rift.tasklets
20
21 from gi.repository import(
22 RwSdnYang,
23 RwDts as rwdts,
24 )
25
26
27 class SDNAccountNotFound(Exception):
28 pass
29
30
31 class SDNAccountDtsOperdataHandler(object):
32 def __init__(self, dts, log, loop):
33 self._dts = dts
34 self._log = log
35 self._loop = loop
36
37 self.sdn_accounts = {}
38 self._oper = None
39 self._rpc = None
40
41 def add_sdn_account(self, account):
42 self.sdn_accounts[account.name] = account
43 account.start_validate_credentials(self._loop)
44
45 def delete_sdn_account(self, account_name):
46 del self.sdn_accounts[account_name]
47
48 def get_saved_sdn_accounts(self, sdn_account_name):
49 ''' Get SDN Account corresponding to passed name, or all saved accounts if name is None'''
50 saved_sdn_accounts = []
51
52 if sdn_account_name is None or sdn_account_name == "":
53 sdn_accounts = list(self.sdn_accounts.values())
54 saved_sdn_accounts.extend(sdn_accounts)
55 elif sdn_account_name in self.sdn_accounts:
56 account = self.sdn_accounts[sdn_account_name]
57 saved_sdn_accounts.append(account)
58 else:
59 errstr = "SDN account {} does not exist".format(sdn_account_name)
60 raise KeyError(errstr)
61
62 return saved_sdn_accounts
63
64 def _register_show_status(self):
65 def get_xpath(sdn_name=None):
66 return "D,/rw-sdn:sdn/account{}/connection-status".format(
67 "[name='%s']" % sdn_name if sdn_name is not None else ''
68 )
69
70 @asyncio.coroutine
71 def on_prepare(xact_info, action, ks_path, msg):
72 self._log.debug("Got show SDN connection status request: %s", ks_path.create_string())
73 path_entry = RwSdnYang.SDNAccount.schema().keyspec_to_entry(ks_path)
74 sdn_account_name = path_entry.key00.name
75
76 try:
77 saved_accounts = self.get_saved_sdn_accounts(sdn_account_name)
78 for account in saved_accounts:
79 connection_status = account.connection_status
80 self._log.debug("Responding to SDN connection status request: %s", connection_status)
81 xact_info.respond_xpath(
82 rwdts.XactRspCode.MORE,
83 xpath=get_xpath(account.name),
84 msg=account.connection_status,
85 )
86 except KeyError as e:
87 self._log.warning(str(e))
88 xact_info.respond_xpath(rwdts.XactRspCode.NA)
89 return
90
91 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
92
93 self._oper = yield from self._dts.register(
94 xpath=get_xpath(),
95 handler=rift.tasklets.DTS.RegistrationHandler(
96 on_prepare=on_prepare),
97 flags=rwdts.Flag.PUBLISHER,
98 )
99
100 def _register_validate_rpc(self):
101 def get_xpath():
102 return "/rw-sdn:update-sdn-status"
103
104 @asyncio.coroutine
105 def on_prepare(xact_info, action, ks_path, msg):
106 if self._project and not self._project.rpc_check(msg, xact_info=xact_info):
107 return
108
109 if not msg.has_field("sdn_account"):
110 raise SDNAccountNotFound("SDN account name not provided")
111
112 sdn_account_name = msg.sdn_account
113 try:
114 account = self.sdn_accounts[sdn_account_name]
115 except KeyError:
116 raise SDNAccountNotFound("SDN account name %s not found" % sdn_account_name)
117
118 account.start_validate_credentials(self._loop)
119
120 xact_info.respond_xpath(rwdts.XactRspCode.ACK)
121
122 self._rpc = yield from self._dts.register(
123 xpath=get_xpath(),
124 handler=rift.tasklets.DTS.RegistrationHandler(
125 on_prepare=on_prepare
126 ),
127 flags=rwdts.Flag.PUBLISHER,
128 )
129
130 @asyncio.coroutine
131 def register(self):
132 yield from self._register_show_status()
133 yield from self._register_validate_rpc()
134
135 def deregister(self):
136 if self._oper:
137 self._oper.deregister()
138 self._oper = None
139
140 if self._rpc:
141 self._rpc.deregister()
142 self._rpc = None