Reformats code on NSD and VNFD clients and fixes small validation bug on VNFD create...
[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 import os.path
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
43 def list(self, filter=None):
44 self._logger.debug("")
45 self._client.get_token()
46 filter_string = ''
47 if filter:
48 filter_string = '?{}'.format(filter)
49 _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase, filter_string))
50
51 if resp:
52 return json.loads(resp)
53 return list()
54
55 def get(self, name):
56 self._logger.debug("")
57 self._client.get_token()
58 if utils.validate_uuid4(name):
59 for nsd in self.list():
60 if name == nsd['_id']:
61 return nsd
62 else:
63 for nsd in self.list():
64 if 'name' in nsd and name == nsd['name']:
65 return nsd
66 raise NotFound("nsd {} not found".format(name))
67
68 def get_individual(self, name):
69 self._logger.debug("")
70 # Call to get_token not required, because will be implicitly called by get.
71 try:
72 nsd = self.get(name)
73 # It is redundant, since the previous one already gets the whole nsdinfo
74 # The only difference is that a different primitive is exercised
75 _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase, nsd['_id']))
76 if resp:
77 return json.loads(resp)
78 except NotFound:
79 raise NotFound("nsd '{}' not found".format(name))
80 raise NotFound("nsd '{}' not found".format(name))
81
82 def get_thing(self, name, thing, filename):
83 self._logger.debug("")
84 # Call to get_token not required, because will be implicitly called by get.
85 nsd = self.get(name)
86 headers = self._client._headers
87 headers['Accept'] = 'application/binary'
88 http_code, resp = self._http.get2_cmd('{}/{}/{}'.format(self._apiBase, nsd['_id'], thing))
89
90 if resp:
91 return json.loads(resp)
92 else:
93 msg = resp or ""
94 raise ClientException("failed to get {} from {} - {}".format(thing, name, msg))
95
96 def get_descriptor(self, name, filename):
97 self._logger.debug("")
98 self.get_thing(name, 'nsd', filename)
99
100 def get_package(self, name, filename):
101 self._logger.debug("")
102 self.get_thing(name, 'package_content', filename)
103
104 def get_artifact(self, name, artifact, filename):
105 self._logger.debug("")
106 self.get_thing(name, 'artifacts/{}'.format(artifact), filename)
107
108 def delete(self, name, force=False):
109 self._logger.debug("")
110 nsd = self.get(name)
111 querystring = ''
112 if force:
113 querystring = '?FORCE=True'
114 http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase,
115 nsd['_id'], querystring))
116
117 if http_code == 202:
118 print('Deletion in progress')
119 elif http_code == 204:
120 print('Deleted')
121 else:
122 msg = resp or ""
123 raise ClientException("failed to delete nsd {} - {}".format(name, msg))
124
125 def create(self, filename, overwrite=None, update_endpoint=None, skip_charm_build=False):
126 self._logger.debug("")
127 if os.path.isdir(filename):
128 filename = filename.rstrip('/')
129 filename = self._client.package_tool.build(filename, skip_validation=False,
130 skip_charm_build=skip_charm_build)
131 self.create(filename, overwrite=overwrite, update_endpoint=update_endpoint)
132 else:
133 self._client.get_token()
134 mime_type = magic.from_file(filename, mime=True)
135 if mime_type is None:
136 raise ClientException(
137 "Unexpected MIME type for file {}: MIME type {}".format(
138 filename, mime_type)
139 )
140 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'
146 else:
147 raise ClientException(
148 "Unexpected MIME type for file {}: MIME type {}".format(
149 filename, mime_type)
150 )
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)
155 if update_endpoint:
156 http_code, resp = self._http.put_cmd(endpoint=update_endpoint, filename=filename)
157 else:
158 ow_string = ''
159 if overwrite:
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)
166
167 if http_code in (200, 201, 202):
168 if resp:
169 resp = json.loads(resp)
170 if not resp or 'id' not in resp:
171 raise ClientException('unexpected response from server - {}'.format(resp))
172 print(resp['id'])
173 elif http_code == 204:
174 print('Updated')
175
176 def update(self, name, filename):
177 self._logger.debug("")
178 nsd = self.get(name)
179 endpoint = '{}/{}/nsd_content'.format(self._apiBase, nsd['_id'])
180 self.create(filename=filename, update_endpoint=endpoint)