5979bc02689c647f82dd335da9de6f6c3eebc77c
[osm/osmclient.git] / osmclient / sol005 / nsd.py
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 """
18 OSM nsd API handling
19 """
20
21 from osmclient.common.exceptions import NotFound
22 from osmclient.common.exceptions import ClientException
23 from osmclient.common import utils
24 import json
25 import magic
26 from os.path import basename
27 import logging
28 #from os import stat
29
30
31 class Nsd(object):
32
33 def __init__(self, http=None, client=None):
34 self._http = http
35 self._client = client
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)
42 #self._apiBase='/nsds'
43
44 def list(self, filter=None):
45 self._logger.debug("")
46 self._client.get_token()
47 filter_string = ''
48 if filter:
49 filter_string = '?{}'.format(filter)
50 _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string))
51 #print(yaml.safe_dump(resp))
52 if resp:
53 return json.loads(resp)
54 return list()
55
56 def get(self, name):
57 self._logger.debug("")
58 self._client.get_token()
59 if utils.validate_uuid4(name):
60 for nsd in self.list():
61 if name == nsd['_id']:
62 return nsd
63 else:
64 for nsd in self.list():
65 if 'name' in nsd and name == nsd['name']:
66 return nsd
67 raise NotFound("nsd {} not found".format(name))
68
69 def get_individual(self, name):
70 self._logger.debug("")
71 # Call to get_token not required, because will be implicitly called by get.
72 try:
73 nsd = self.get(name)
74 # It is redundant, since the previous one already gets the whole nsdinfo
75 # The only difference is that a different primitive is exercised
76 _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, nsd['_id']))
77 #print(yaml.safe_dump(resp))
78 if resp:
79 return json.loads(resp)
80 except NotFound:
81 raise NotFound("nsd '{}' not found".format(name))
82 raise NotFound("nsd '{}' not found".format(name))
83
84 def get_thing(self, name, thing, filename):
85 self._logger.debug("")
86 # Call to get_token not required, because will be implicitly called by get.
87 nsd = self.get(name)
88 headers = self._client._headers
89 headers['Accept'] = 'application/binary'
90 http_code, resp = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nsd['_id'], thing))
91 #print('HTTP CODE: {}'.format(http_code))
92 #print('RESP: {}'.format(resp))
93 #if http_code in (200, 201, 202, 204):
94 if resp:
95 #store in a file
96 return json.loads(resp)
97 else:
98 msg = resp or ""
99 # if resp:
100 # try:
101 # msg = json.loads(resp)
102 # except ValueError:
103 # msg = resp
104 raise ClientException("failed to get {} from {} - {}".format(thing, name, msg))
105
106 def get_descriptor(self, name, filename):
107 self._logger.debug("")
108 self.get_thing(name, 'nsd', filename)
109
110 def get_package(self, name, filename):
111 self._logger.debug("")
112 self.get_thing(name, 'package_content', filename)
113
114 def get_artifact(self, name, artifact, filename):
115 self._logger.debug("")
116 self.get_thing(name, 'artifacts/{}'.format(artifact), filename)
117
118 def delete(self, name, force=False):
119 self._logger.debug("")
120 nsd = self.get(name)
121 querystring = ''
122 if force:
123 querystring = '?FORCE=True'
124 http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase,
125 nsd['_id'], querystring))
126 #print('HTTP CODE: {}'.format(http_code))
127 #print('RESP: {}'.format(resp))
128 if http_code == 202:
129 print('Deletion in progress')
130 elif http_code == 204:
131 print('Deleted')
132 else:
133 msg = resp or ""
134 # if resp:
135 # try:
136 # msg = json.loads(resp)
137 # except ValueError:
138 # msg = resp
139 raise ClientException("failed to delete nsd {} - {}".format(name, msg))
140
141 def create(self, filename, overwrite=None, update_endpoint=None):
142 self._logger.debug("")
143 self._client.get_token()
144 mime_type = magic.from_file(filename, mime=True)
145 if mime_type is None:
146 raise ClientException(
147 "failed to guess MIME type for file '{}'".format(filename))
148 headers= self._client._headers
149 headers['Content-Filename'] = basename(filename)
150 if mime_type in ['application/yaml', 'text/plain', 'application/json']:
151 headers['Content-Type'] = 'text/plain'
152 elif mime_type in ['application/gzip', 'application/x-gzip']:
153 headers['Content-Type'] = 'application/gzip'
154 #headers['Content-Type'] = 'application/binary'
155 # Next three lines are to be removed in next version
156 #headers['Content-Filename'] = basename(filename)
157 #file_size = stat(filename).st_size
158 #headers['Content-Range'] = 'bytes 0-{}/{}'.format(file_size - 1, file_size)
159 else:
160 raise ClientException(
161 "Unexpected MIME type for file {}: MIME type {}".format(
162 filename, mime_type)
163 )
164 headers["Content-File-MD5"] = utils.md5(filename)
165 http_header = ['{}: {}'.format(key,val)
166 for (key,val) in list(headers.items())]
167 self._http.set_http_header(http_header)
168 if update_endpoint:
169 http_code, resp = self._http.put_cmd(endpoint=update_endpoint, filename=filename)
170 else:
171 ow_string = ''
172 if overwrite:
173 ow_string = '?{}'.format(overwrite)
174 self._apiResource = '/ns_descriptors_content'
175 self._apiBase = '{}{}{}'.format(self._apiName,
176 self._apiVersion, self._apiResource)
177 endpoint = '{}{}'.format(self._apiBase,ow_string)
178 http_code, resp = self._http.post_cmd(endpoint=endpoint, filename=filename)
179 #print('HTTP CODE: {}'.format(http_code))
180 #print('RESP: {}'.format(resp))
181 if http_code in (200, 201, 202):
182 if resp:
183 resp = json.loads(resp)
184 if not resp or 'id' not in resp:
185 raise ClientException('unexpected response from server - {}'.format(resp))
186 print(resp['id'])
187 elif http_code == 204:
188 print('Updated')
189 # else:
190 # msg = "Error {}".format(http_code)
191 # if resp:
192 # try:
193 # msg = "{} - {}".format(msg, json.loads(resp))
194 # except ValueError:
195 # msg = "{} - {}".format(msg, resp)
196 # raise ClientException("failed to create/update nsd - {}".format(msg))
197
198 def update(self, name, filename):
199 self._logger.debug("")
200 nsd = self.get(name)
201 endpoint = '{}/{}/nsd_content'.format(self._apiBase, nsd['_id'])
202 self.create(filename=filename, update_endpoint=endpoint)
203