1 # Copyright 2018 Telefonica
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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
21 from osmclient
.common
.exceptions
import NotFound
22 from osmclient
.common
.exceptions
import ClientException
23 from osmclient
.common
import utils
26 from os
.path
import basename
34 def __init__(self
, http
=None, client
=None):
37 self
._logger
= logging
.getLogger('osmclient')
38 self
._apiName
= '/vnfpkgm'
39 self
._apiVersion
= '/v1'
40 self
._apiResource
= '/vnf_packages'
41 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
42 self
._apiVersion
, self
._apiResource
)
43 #self._apiBase='/vnfds'
45 def list(self
, filter=None):
46 self
._logger
.debug("")
47 self
._client
.get_token()
50 filter_string
= '?{}'.format(filter)
51 _
, resp
= self
._http
.get2_cmd('{}{}'.format(self
._apiBase
,filter_string
))
53 return json
.loads(resp
)
57 self
._logger
.debug("")
58 self
._client
.get_token()
59 if utils
.validate_uuid4(name
):
60 for vnfd
in self
.list():
61 if name
== vnfd
['_id']:
64 for vnfd
in self
.list():
65 if 'name' in vnfd
and name
== vnfd
['name']:
67 raise NotFound("vnfd {} not found".format(name
))
69 def get_individual(self
, name
):
70 self
._logger
.debug("")
72 # It is redundant, since the previous one already gets the whole vnfpkginfo
73 # The only difference is that a different primitive is exercised
75 _
, resp
= self
._http
.get2_cmd('{}/{}'.format(self
._apiBase
, vnfd
['_id']))
76 #print(yaml.safe_dump(resp))
78 return json
.loads(resp
)
80 raise NotFound("vnfd '{}' not found".format(name
))
81 raise NotFound("vnfd '{}' not found".format(name
))
83 def get_thing(self
, name
, thing
, filename
):
84 self
._logger
.debug("")
86 headers
= self
._client
._headers
87 headers
['Accept'] = 'application/binary'
88 http_code
, resp
= self
._http
.get2_cmd('{}/{}/{}'.format(self
._apiBase
, vnfd
['_id'], thing
))
89 #print('HTTP CODE: {}'.format(http_code))
90 #print('RESP: {}'.format(resp))
91 #if http_code in (200, 201, 202, 204):
94 return json
.loads(resp
)
99 # msg = json.loads(resp)
102 # raise ClientException("failed to get {} from {} - {}".format(thing, name, msg))
104 def get_descriptor(self
, name
, filename
):
105 self
._logger
.debug("")
106 self
.get_thing(name
, 'vnfd', filename
)
108 def get_package(self
, name
, filename
):
109 self
._logger
.debug("")
110 self
.get_thing(name
, 'package_content', filename
)
112 def get_artifact(self
, name
, artifact
, filename
):
113 self
._logger
.debug("")
114 self
.get_thing(name
, 'artifacts/{}'.format(artifact
), filename
)
116 def delete(self
, name
, force
=False):
117 self
._logger
.debug("")
118 self
._client
.get_token()
119 vnfd
= self
.get(name
)
122 querystring
= '?FORCE=True'
123 http_code
, resp
= self
._http
.delete_cmd('{}/{}{}'.format(self
._apiBase
,
124 vnfd
['_id'], querystring
))
125 #print('HTTP CODE: {}'.format(http_code))
126 #print('RESP: {}'.format(resp))
128 print('Deletion in progress')
129 elif http_code
== 204:
135 # msg = json.loads(resp)
138 raise ClientException("failed to delete vnfd {} - {}".format(name
, msg
))
140 def create(self
, filename
, overwrite
=None, update_endpoint
=None, skip_charm_build
=False):
141 self
._logger
.debug("")
142 if os
.path
.isdir(filename
):
143 filename
= filename
.rstrip('/')
144 filename
= self
._client
.package_tool
.build(filename
, skip_validation
=False, skip_charm_build
=skip_charm_build
)
145 print('Uploading package {}'.format(filename
))
146 self
.create(filename
, overwrite
=overwrite
, update_endpoint
=update_endpoint
)
148 self
._client
.get_token()
149 mime_type
= magic
.from_file(filename
, mime
=True)
150 if mime_type
is None:
151 raise ClientException(
152 "Unexpected MIME type for file {}: MIME type {}".format(
155 headers
= self
._client
._headers
156 headers
['Content-Filename'] = basename(filename
)
157 if mime_type
in ['application/yaml', 'text/plain', 'application/json']:
158 headers
['Content-Type'] = 'text/plain'
159 elif mime_type
in ['application/gzip', 'application/x-gzip']:
160 headers
['Content-Type'] = 'application/gzip'
161 #headers['Content-Type'] = 'application/binary'
162 # Next three lines are to be removed in next version
163 #headers['Content-Filename'] = basename(filename)
164 #file_size = stat(filename).st_size
165 #headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size)
167 raise ClientException(
168 "Unexpected MIME type for file {}: MIME type {}".format(
171 headers
["Content-File-MD5"] = utils
.md5(filename
)
172 http_header
= ['{}: {}'.format(key
,val
)
173 for (key
,val
) in list(headers
.items())]
174 self
._http
.set_http_header(http_header
)
176 http_code
, resp
= self
._http
.put_cmd(endpoint
=update_endpoint
, filename
=filename
)
180 ow_string
= '?{}'.format(overwrite
)
181 self
._apiResource
= '/vnf_packages_content'
182 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
183 self
._apiVersion
, self
._apiResource
)
184 endpoint
= '{}{}'.format(self
._apiBase
,ow_string
)
185 http_code
, resp
= self
._http
.post_cmd(endpoint
=endpoint
, filename
=filename
)
186 #print('HTTP CODE: {}'.format(http_code))
187 #print('RESP: {}'.format(resp))
188 if http_code
in (200, 201, 202):
190 resp
= json
.loads(resp
)
191 if not resp
or 'id' not in resp
:
192 raise ClientException('unexpected response from server: '.format(resp
))
194 elif http_code
== 204:
197 # msg = "Error {}".format(http_code)
200 # msg = "{} - {}".format(msg, json.loads(resp))
202 # msg = "{} - {}".format(msg, resp)
203 # raise ClientException("failed to create/update vnfd - {}".format(msg))
205 def update(self
, name
, filename
):
206 self
._logger
.debug("")
207 self
._client
.get_token()
208 vnfd
= self
.get(name
)
209 endpoint
= '{}/{}/package_content'.format(self
._apiBase
, vnfd
['_id'])
210 self
.create(filename
=filename
, update_endpoint
=endpoint
)