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
33 def __init__(self
, http
=None, client
=None):
36 self
._logger
= logging
.getLogger('osmclient')
37 self
._apiName
= '/nsd'
38 self
._apiVersion
= '/v1'
39 self
._apiResource
= '/ns_descriptors'
40 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
41 self
._apiVersion
, self
._apiResource
)
43 def list(self
, filter=None):
44 self
._logger
.debug("")
45 self
._client
.get_token()
48 filter_string
= '?{}'.format(filter)
49 _
, resp
= self
._http
.get2_cmd('{}{}'.format(self
._apiBase
, filter_string
))
51 return json
.loads(resp
)
55 self
._logger
.debug("")
56 self
._client
.get_token()
57 if utils
.validate_uuid4(name
):
58 for nsd
in self
.list():
59 if name
== nsd
['_id']:
62 for nsd
in self
.list():
63 if 'name' in nsd
and name
== nsd
['name']:
65 raise NotFound("nsd {} not found".format(name
))
67 def get_individual(self
, name
):
68 self
._logger
.debug("")
69 # Call to get_token not required, because will be implicitly called by get.
72 # It is redundant, since the previous one already gets the whole nsdinfo
73 # The only difference is that a different primitive is exercised
74 _
, resp
= self
._http
.get2_cmd('{}/{}'.format(self
._apiBase
, nsd
['_id']))
76 return json
.loads(resp
)
78 raise NotFound("nsd '{}' not found".format(name
))
79 raise NotFound("nsd '{}' not found".format(name
))
81 def get_thing(self
, name
, thing
, filename
):
82 self
._logger
.debug("")
83 # Call to get_token not required, because will be implicitly called by get.
85 headers
= self
._client
._headers
86 headers
['Accept'] = 'application/binary'
87 http_code
, resp
= self
._http
.get2_cmd('{}/{}/{}'.format(self
._apiBase
, nsd
['_id'], thing
))
89 return json
.loads(resp
)
93 raise ClientException("failed to get {} from {} - {}".format(thing
, name
, msg
))
95 def get_descriptor(self
, name
, filename
):
96 self
._logger
.debug("")
97 self
.get_thing(name
, 'nsd', filename
)
99 def get_package(self
, name
, filename
):
100 self
._logger
.debug("")
101 self
.get_thing(name
, 'package_content', filename
)
103 def get_artifact(self
, name
, artifact
, filename
):
104 self
._logger
.debug("")
105 self
.get_thing(name
, 'artifacts/{}'.format(artifact
), filename
)
107 def delete(self
, name
, force
=False):
108 self
._logger
.debug("")
112 querystring
= '?FORCE=True'
113 http_code
, resp
= self
._http
.delete_cmd('{}/{}{}'.format(self
._apiBase
,
114 nsd
['_id'], querystring
))
117 print('Deletion in progress')
118 elif http_code
== 204:
122 raise ClientException("failed to delete nsd {} - {}".format(name
, msg
))
124 def create(self
, filename
, overwrite
=None, update_endpoint
=None, skip_charm_build
=False):
125 self
._logger
.debug("")
126 if os
.path
.isdir(filename
):
127 filename
= filename
.rstrip('/')
128 filename
= self
._client
.package_tool
.build(filename
, skip_validation
=False,
129 skip_charm_build
=skip_charm_build
)
130 self
.create(filename
, overwrite
=overwrite
, update_endpoint
=update_endpoint
)
132 self
._client
.get_token()
133 mime_type
= magic
.from_file(filename
, mime
=True)
134 if mime_type
is None:
135 raise ClientException(
136 "Unexpected MIME type for file {}: MIME type {}".format(
139 headers
= self
._client
._headers
141 headers
['Content-Filename'] = basename(filename
)
142 if mime_type
in ['application/yaml', 'text/plain', 'application/json']:
143 headers
['Content-Type'] = 'text/plain'
144 elif mime_type
in ['application/gzip', 'application/x-gzip']:
145 headers
['Content-Type'] = 'application/gzip'
147 raise ClientException(
148 "Unexpected MIME type for file {}: MIME type {}".format(
151 headers
["Content-File-MD5"] = utils
.md5(filename
)
152 http_header
= ['{}: {}'.format(key
, val
)
153 for (key
, val
) in list(headers
.items())]
154 self
._http
.set_http_header(http_header
)
156 http_code
, resp
= self
._http
.put_cmd(endpoint
=update_endpoint
, filename
=filename
)
160 ow_string
= '?{}'.format(overwrite
)
161 self
._apiResource
= '/ns_descriptors_content'
162 self
._apiBase
= '{}{}{}'.format(self
._apiName
,
163 self
._apiVersion
, self
._apiResource
)
164 endpoint
= '{}{}'.format(self
._apiBase
, ow_string
)
165 http_code
, resp
= self
._http
.post_cmd(endpoint
=endpoint
, filename
=filename
)
167 if http_code
in (200, 201, 202):
169 resp
= json
.loads(resp
)
170 if not resp
or 'id' not in resp
:
171 raise ClientException('unexpected response from server - {}'.format(resp
))
173 elif http_code
== 204:
176 def update(self
, name
, filename
):
177 self
._logger
.debug("")
179 endpoint
= '{}/{}/nsd_content'.format(self
._apiBase
, nsd
['_id'])
180 self
.create(filename
=filename
, update_endpoint
=endpoint
)