update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[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 gi
23 import tempfile
24
25 from gi.repository import (
26 RwDts as rwdts,
27 RwPkgMgmtYang)
28 import rift.tasklets
29 import rift.mano.dts as mano_dts
30
31 from . import downloader as pkg_downloader
32
33 # Shortcuts
34 RPC_PKG_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_GetPackageEndpoint
35 RPC_SCHEMA_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_GetPackageSchema
36 RPC_PACKAGE_ADD_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageFileAdd
37 RPC_PACKAGE_DELETE_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageFileDelete
38 RPC_PACKAGE_COPY_ENDPOINT = RwPkgMgmtYang.YangOutput_RwPkgMgmt_PackageCopy
39
40
41 class EndpointDiscoveryRpcHandler(mano_dts.AbstractRpcHandler):
42 """RPC handler to generate the endpoint for the Package manager."""
43
44 def __init__(self, log, dts, loop, proxy):
45 """
46 Args:
47 proxy: Any impl of .proxy.AbstractPackageManagerProxy
48 """
49 super().__init__(log, dts, loop)
50 self.proxy = proxy
51
52 @property
53 def xpath(self):
54 return "/rw-pkg-mgmt:get-package-endpoint"
55
56 @asyncio.coroutine
57 def callback(self, ks_path, msg):
58 """Forwards the request to proxy.
59 """
60
61 url = yield from self.proxy.endpoint(
62 msg.package_type if msg.has_field('package_type') else "",
63 msg.package_id,
64 msg.project_name if msg.has_field('project_name') else None)
65
66 rpc_op = RPC_PKG_ENDPOINT.from_dict({"endpoint": url})
67
68 return rpc_op
69
70
71 class SchemaRpcHandler(mano_dts.AbstractRpcHandler):
72 """RPC handler to generate the schema for the packages.
73 """
74 def __init__(self, log, dts, loop, proxy):
75 """
76 Args:
77 proxy: Any impl of .proxy.AbstractPackageManagerProxy
78 """
79 super().__init__(log, dts, loop)
80 self.proxy = proxy
81
82 @property
83 def xpath(self):
84 return "/rw-pkg-mgmt:get-package-schema"
85
86 @asyncio.coroutine
87 def callback(self, ks_path, msg):
88
89 package_type = msg.package_type.lower()
90 schema = yield from self.proxy.schema(msg.package_type)
91
92 rpc_op = RPC_SCHEMA_ENDPOINT()
93 for dirname in schema:
94 rpc_op.schema.append(dirname)
95
96 return rpc_op
97
98
99 class PackageOperationsRpcHandler(mano_dts.AbstractRpcHandler):
100 """File add RPC
101
102 Steps:
103 1. For a request, we schedule a download in the background
104 2. We register the downloader to a publisher to push out the download status
105 Note: The publisher starts the download automatically.
106 3. Return a tracking ID for the client to monitor the entire status
107
108 """
109 def __init__(self, log, dts, loop, proxy, tasklet):
110 """
111 Args:
112 proxy: Any impl of .proxy.AbstractPackageManagerProxy
113 publisher: Instance of tasklet to find the DownloadStatusPublisher
114 for a specific project
115 """
116 super().__init__(log, dts, loop)
117 self.proxy = proxy
118 self.tasklet = tasklet
119
120 @property
121 def xpath(self):
122 return "/rw-pkg-mgmt:package-file-add"
123
124 def get_publisher(self, msg):
125 try:
126 proj = self.tasklet.projects[msg.project_name]
127 except Exception as e:
128 err = "Project or project name not found {}: {}". \
129 format(msg.as_dict(), e)
130 self.log.error (err)
131 raise Exception (err)
132
133 return proj.job_handler
134
135 @asyncio.coroutine
136 def callback(self, ks_path, msg):
137 publisher = self.get_publisher(msg)
138
139 if not msg.external_url:
140 # For now we will only support External URL download
141 raise Exception ("No download URL provided")
142
143 # Create a tmp file to download the url
144 # We first store the data in temp and post download finish
145 # we move the file to actual location.
146 _, filename = tempfile.mkstemp()
147
148 auth = None
149 if msg.username is not None:
150 auth = (msg.username, msg.password)
151
152 url_downloader = pkg_downloader.PackageFileDownloader.from_rpc_input(
153 msg,
154 auth=auth,
155 file_obj=filename,
156 proxy=self.proxy,
157 log=self.log,
158 project=msg.project_name)
159
160 download_id = yield from publisher.register_downloader(url_downloader)
161
162 rpc_op = RPC_PACKAGE_ADD_ENDPOINT.from_dict({"task_id": download_id})
163
164 return rpc_op
165
166 class PackageCopyOperationsRpcHandler(mano_dts.AbstractRpcHandler):
167 def __init__(self, log, dts, loop, project, proxy, publisher):
168 """
169 Args:
170 proxy: Any impl of .proxy.AbstractPackageManagerProxy
171 publisher: CopyStatusPublisher object
172 """
173 super().__init__(log, dts, loop, project)
174 self.proxy = proxy
175 self.publisher = publisher
176
177 @property
178 def xpath(self):
179 return "/rw-pkg-mgmt:package-copy"
180
181 @asyncio.coroutine
182 def callback(self, ks_path, msg):
183 import uuid
184 copier = pkg_downloader.PackageFileCopier.from_rpc_input(msg, self.project, proxy=self.proxy, log=self.log)
185
186 transaction_id, dest_package_id = yield from self.publisher.register_copier(copier)
187 rpc_op = RPC_PACKAGE_COPY_ENDPOINT.from_dict({
188 "transaction_id":transaction_id,
189 "package_id":dest_package_id,
190 "package_type":msg.package_type})
191
192 return rpc_op
193
194 class PackageDeleteOperationsRpcHandler(mano_dts.AbstractRpcHandler):
195 def __init__(self, log, dts, loop, proxy):
196 """
197 Args:
198 proxy: Any impl of .proxy.AbstractPackageManagerProxy
199 """
200 super().__init__(log, dts, loop)
201 self.proxy = proxy
202
203 @property
204 def xpath(self):
205 return "/rw-pkg-mgmt:package-file-delete"
206
207 @asyncio.coroutine
208 def callback(self, ks_path, msg):
209
210 rpc_op = RPC_PACKAGE_DELETE_ENDPOINT.from_dict({"status": str(True)})
211
212 try:
213 package_file_type = msg.vnfd_file_type.lower() \
214 if msg.package_type == 'VNFD' else msg.nsd_file_type.lower()
215 self.proxy.package_file_delete(
216 msg.package_type,
217 msg.package_id,
218 msg.package_path,
219 package_file_type,
220 msg.project_name,
221 )
222 except Exception as e:
223 self.log.exception(e)
224 rpc_op.status = str(False)
225 rpc_op.error_trace = str(e)
226
227 return rpc_op