1 |
|
# Copyright 2018 Telefonica |
2 |
|
# |
3 |
|
# All Rights Reserved. |
4 |
|
# |
5 |
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may |
6 |
|
# not use this file except in compliance with the License. You may obtain |
7 |
|
# 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, WITHOUT |
13 |
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
14 |
|
# License for the specific language governing permissions and limitations |
15 |
|
# under the License. |
16 |
|
|
17 |
1 |
""" |
18 |
|
OSM package API handling |
19 |
|
""" |
20 |
|
|
21 |
|
# from os import stat |
22 |
|
# from os.path import basename |
23 |
1 |
from osmclient.common.exceptions import ClientException |
24 |
1 |
from osmclient.common.exceptions import NotFound |
25 |
1 |
from osmclient.common import utils |
26 |
1 |
import json |
27 |
1 |
import logging |
28 |
1 |
import os.path |
29 |
|
|
30 |
|
|
31 |
1 |
class Package(object): |
32 |
1 |
def __init__(self, http=None, client=None): |
33 |
0 |
self._client = client |
34 |
0 |
self._http = http |
35 |
0 |
self._logger = logging.getLogger("osmclient") |
36 |
|
|
37 |
1 |
def get_key_val_from_pkg(self, descriptor_file): |
38 |
0 |
self._logger.debug("") |
39 |
0 |
return utils.get_key_val_from_pkg(descriptor_file) |
40 |
|
|
41 |
1 |
def _wait_for_package(self, pkg_type): |
42 |
0 |
self._logger.debug("") |
43 |
0 |
if "vnfd" in pkg_type["type"]: |
44 |
0 |
get_method = self._client.vnfd.get |
45 |
0 |
elif "nsd" in pkg_type["type"]: |
46 |
0 |
get_method = self._client.nsd.get |
47 |
|
else: |
48 |
0 |
raise ClientException("no valid package type found") |
49 |
|
|
50 |
|
# helper method to check if pkg exists |
51 |
0 |
def check_exists(func): |
52 |
0 |
self._logger.debug("") |
53 |
0 |
try: |
54 |
0 |
func() |
55 |
0 |
except NotFound: |
56 |
0 |
return False |
57 |
0 |
return True |
58 |
|
|
59 |
0 |
return utils.wait_for_value( |
60 |
|
lambda: check_exists(lambda: get_method(pkg_type["name"])) |
61 |
|
) |
62 |
|
|
63 |
1 |
def wait_for_upload(self, filename): |
64 |
|
"""wait(block) for an upload to succeed. |
65 |
|
The filename passed is assumed to be a descriptor tarball. |
66 |
|
""" |
67 |
0 |
self._logger.debug("") |
68 |
0 |
self._client.get_token() |
69 |
0 |
pkg_type = utils.get_key_val_from_pkg(filename) |
70 |
|
|
71 |
0 |
if pkg_type is None: |
72 |
0 |
raise ClientException("Cannot determine package type") |
73 |
|
|
74 |
0 |
if not self._wait_for_package(pkg_type): |
75 |
0 |
raise ClientException("package {} failed to upload".format(filename)) |
76 |
|
|
77 |
1 |
def upload(self, filename, skip_charm_build=False): |
78 |
0 |
self._logger.debug("") |
79 |
0 |
if os.path.isdir(filename): |
80 |
0 |
filename = filename.rstrip("/") |
81 |
0 |
filename = self._client.package_tool.build( |
82 |
|
filename, skip_validation=False, skip_charm_build=skip_charm_build |
83 |
|
) |
84 |
0 |
self.upload(filename) |
85 |
|
else: |
86 |
0 |
self._client.get_token() |
87 |
0 |
pkg_type = utils.get_key_val_from_pkg(filename) |
88 |
0 |
if pkg_type is None: |
89 |
0 |
raise ClientException("Cannot determine package type") |
90 |
0 |
if pkg_type["type"] == "nsd": |
91 |
0 |
endpoint = "/nsd/v1/ns_descriptors_content" |
92 |
|
else: |
93 |
0 |
endpoint = "/vnfpkgm/v1/vnf_packages_content" |
94 |
|
# endpoint = '/nsds' if pkg_type['type'] == 'nsd' else '/vnfds' |
95 |
|
# print('Endpoint: {}'.format(endpoint)) |
96 |
0 |
headers = self._client._headers |
97 |
|
|
98 |
0 |
if filename.endswith(".tar.gz"): |
99 |
0 |
headers["Content-Type"] = "application/gzip" |
100 |
|
else: |
101 |
0 |
headers["Content-Type"] = "application/zip" |
102 |
|
# headers['Content-Type'] = 'application/binary' |
103 |
|
# Next three lines are to be removed in next version |
104 |
|
# headers['Content-Filename'] = basename(filename) |
105 |
|
# file_size = stat(filename).st_size |
106 |
|
# headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size) |
107 |
0 |
headers["Content-File-MD5"] = utils.md5(filename) |
108 |
0 |
http_header = [ |
109 |
|
"{}: {}".format(key, val) for (key, val) in list(headers.items()) |
110 |
|
] |
111 |
0 |
self._http.set_http_header(http_header) |
112 |
0 |
http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename) |
113 |
|
# print('HTTP CODE: {}'.format(http_code)) |
114 |
|
# print('RESP: {}'.format(resp)) |
115 |
|
# if http_code in (200, 201, 202, 204): |
116 |
0 |
if resp: |
117 |
0 |
resp = json.loads(resp) |
118 |
0 |
if not resp or "id" not in resp: |
119 |
0 |
raise ClientException( |
120 |
|
"unexpected response from server - {}".format(resp) |
121 |
|
) |
122 |
0 |
print(resp["id"]) |
123 |
|
# else: |
124 |
|
# msg = "" |
125 |
|
# if resp: |
126 |
|
# try: |
127 |
|
# msg = json.loads(resp) |
128 |
|
# except ValueError: |
129 |
|
# msg = resp |
130 |
|
# raise ClientException("failed to upload package - {}".format(msg)) |