/
remoteapi.py
96 lines (75 loc) · 3.44 KB
/
remoteapi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import json
from vlcp.config import defaultconfig
from vlcp.event import RoutineContainer
from vlcp.utils.webclient import WebClient, WebException
from vlcp.server.module import Module,call_api, api
from vlcp.event.event import M_
@defaultconfig
class RemoteCall(Module):
"""
Route local API calls to remote management API.
"""
# URL list for every target, should be ``{target: [url, url, ...]}``
_default_target_url_map = {}
def __init__(self,server):
super(RemoteCall,self).__init__(server)
self.app_routine = RoutineContainer(self.scheduler)
# there is no need to run this container main, so don't append it
# self.routines.append(self.app_routine)
self.wc = WebClient()
self.app_routine.main = self._main
self.routines.append(self.app_routine)
self.createAPI(api(self.call,self.app_routine))
async def _main(self):
try:
self.wc.cleanup_task(self.app_routine, 120)
await M_()
finally:
self.wc.endtask()
async def call(self,remote_module,method,timeout,params):
"""
Call remote API
:param remote_module: target name for the remote module
:param method: method name of the API
:param timeout: timeout for the call
:param params: A dictionary contains all the parameters need for the call
:return: Return result from the remote call
"""
self._logger.info("remote call remote_module %r",remote_module)
self._logger.info("remote call method %r", method)
self._logger.info("remote call kwargs %r", params)
success = False
r = None
if remote_module and remote_module in self.target_url_map:
endpoints = self.target_url_map[remote_module]
params = json.dumps(params).encode("utf-8")
for endpoint in endpoints:
url = endpoint + "/" + remote_module + "/" + method
try:
r = await self.wc.urlgetcontent(self.app_routine,
url,
params,
b'POST',
{"Content-Type":"application/json"},
tostr=True,
timeout=timeout)
except WebException as e:
# this endpoint connection error , try next url
self._logger.warning(" url (%r) post error %r , break ..",url,e)
success = False
raise
except Exception:
self._logger.warning(" url (%r) connection error , try next ..", url)
continue
else:
success = True
break
else:
self._logger.warning(" target (%r) url not existed, ignore it ",remote_module)
if not success:
raise IOError("remote call connection error !")
return json.loads(r)['result']
async def remote_api(container, targetname, name, params={}, timeout=60.0):
args = {"remote_module": targetname, "method": name, "timeout": timeout, "params": params}
return await call_api(container,"remotecall","call",params=args,timeout=timeout + 20)
remoteAPI = remote_api