Merge from OSM SO master
[osm/SO.git] / rwlaunchpad / plugins / rwpkgmgr / rift / tasklets / rwpkgmgr / rpc.py
1 #
2 # Copyright 2016 RIFT.IO Inc
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # Author(s): Varun Prasad
17 # Creation Date: 09/25/2016
18 #
19
20 import abc
21 import asyncio
22 import tempfile
23
24 from gi.repository import (
25 RwDts as rwdts,
26 RwPkgMgmtYang)
27 import rift.tasklets
28 import rift.mano.dts as mano_dts
29
30 from . import downloader as pkg_downloader
31
32 # Shortcuts
33 RPC_PKG_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_GetPackageEndpoint
34 RPC_SCHEMA_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_GetPackageSchema
35 RPC_PACKAGE_ADD_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageFileAdd
36 RPC_PACKAGE_DELETE_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageFileDelete
37 RPC_PACKAGE_COPY_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageCopy
38
39
40 class EndpointDiscoveryRpcHandler(mano_dts.AbstractRpcHandler):
41 """RPC handler to generate the endpoint for the Package manager."""
42
43 def __init__(self, log, dts, loop, proxy):
44 """
45 Args:
46 proxy: Any impl of .proxy.AbstractPackageManagerProxy
47 """
48 super().__init__(log, dts, loop)
49 self.proxy = proxy
50
51 @property
52 def xpath(self):
53 return "/rw-pkg-mgmt:get-package-endpoint"
54
55 @asyncio.coroutine
56 def callback(self, ks_path, msg):
57 """Forwards the request to proxy.
58 """
59 url = yield from self.proxy.endpoint(
60 msg.package_type,
61 msg.package_id)
62
63 rpc_op = RPC_PKG_ENDPOINT.from_dict({"endpoint": url})
64
65 return rpc_op
66
67
68 class SchemaRpcHandler(mano_dts.AbstractRpcHandler):
69 """RPC handler to generate the schema for the packages.
70 """
71 def __init__(self, log, dts, loop, project, proxy):
72 """
73 Args:
74 proxy: Any impl of .proxy.AbstractPackageManagerProxy
75 """
76 super().__init__(log, dts, loop, project)
77 self.proxy = proxy
78
79 @property
80 def xpath(self):
81 return "/rw-pkg-mgmt:get-package-schema"
82
83 @asyncio.coroutine
84 def callback(self, ks_path, msg):
85
86 package_type = msg.package_type.lower()
87 schema = yield from self.proxy.schema(msg.package_type)
88
89 rpc_op = RPC_SCHEMA_ENDPOINT()
90 for dirname in schema:
91 rpc_op.schema.append(dirname)
92
93 return rpc_op
94
95
96 class PackageOperationsRpcHandler(mano_dts.AbstractRpcHandler):
97 """File add RPC
98
99 Steps:
100 1. For a request, we schedule a download in the background
101 2. We register the downloader to a publisher to push out the download status
102 Note: The publisher starts the download automatically.
103 3. Return a tracking ID for the client to monitor the entire status
104
105 """
106 def __init__(self, log, dts, loop, proxy, tasklet):
107 """
108 Args:
109 proxy: Any impl of .proxy.AbstractPackageManagerProxy
110 publisher: Instance of tasklet to find the DownloadStatusPublisher
111 for a specific project
112 """
113 super().__init__(log, dts, loop)
114 self.proxy = proxy
115 self.tasklet = tasklet
116
117 @property
118 def xpath(self):
119 return "/rw-pkg-mgmt:package-file-add"
120
121 def get_publisher(self, msg):
122 try:
123 proj = self.tasklet.projects[msg.project_name]
124 except Exception as e:
125 err = "Project or project name not found {}: {}". \
126 format(msg.as_dict(), e)
127 self.log.error (err)
128 raise Exception (err)
129
130 return proj.job_handler
131
132 @asyncio.coroutine
133 def callback(self, ks_path, msg):
134 publisher = self.get_publisher(msg)
135
136 if not msg.external_url:
137 # For now we will only support External URL download
138 raise Exception ("No download URL provided")
139
140 # Create a tmp file to download the url
141 # We first store the data in temp and post download finish
142 # we move the file to actual location.
143 _, filename = tempfile.mkstemp()
144
145 auth = None
146 if msg.username is not None:
147 auth = (msg.username, msg.password)
148
149 url_downloader = pkg_downloader.PackageFileDownloader.from_rpc_input(
150 msg,
151 auth=auth,
152 file_obj=filename,
153 proxy=self.proxy,
154 log=self.log)
155
156 download_id = yield from publisher.register_downloader(url_downloader)
157
158 rpc_op = RPC_PACKAGE_ADD_ENDPOINT.from_dict({"task_id": download_id})
159
160 return rpc_op
161
162 class PackageCopyOperationsRpcHandler(mano_dts.AbstractRpcHandler):
163 def __init__(self, log, dts, loop, project, proxy, publisher):
164 """
165 Args:
166 proxy: Any impl of .proxy.AbstractPackageManagerProxy
167 publisher: CopyStatusPublisher object
168 """
169 super().__init__(log, dts, loop, project)
170 self.proxy = proxy
171 self.publisher = publisher
172
173 @property
174 def xpath(self):
175 return "/rw-pkg-mgmt:package-copy"
176
177 @asyncio.coroutine
178 def callback(self, ks_path, msg):
179 import uuid
180 copier = pkg_downloader.PackageFileCopier.from_rpc_input(msg, proxy=self.proxy, log=self.log)
181
182 transaction_id, dest_package_id = yield from self.publisher.register_copier(copier)
183 rpc_op = RPC_PACKAGE_COPY_ENDPOINT.from_dict({
184 "transaction_id":transaction_id,
185 "package_id":dest_package_id,
186 "package_type":msg.package_type})
187
188 return rpc_op
189
190 class PackageDeleteOperationsRpcHandler(mano_dts.AbstractRpcHandler):
191 def __init__(self, log, dts, loop, proxy):
192 """
193 Args:
194 proxy: Any impl of .proxy.AbstractPackageManagerProxy
195 """
196 super().__init__(log, dts, loop)
197 self.proxy = proxy
198
199 @property
200 def xpath(self):
201 return "/rw-pkg-mgmt:package-file-delete"
202
203 @asyncio.coroutine
204 def callback(self, ks_path, msg):
205
206 rpc_op = RPC_PACKAGE_DELETE_ENDPOINT.from_dict({"status": str(True)})
207
208 try:
209 self.proxy.package_file_delete(
210 msg.package_type,
211 msg.package_id,
212 msg.package_path)
213 except Exception as e:
214 self.log.exception(e)
215 rpc_op.status = str(False)
216 rpc_op.error_trace = str(e)
217
218 return rpc_op