Use of PATCH method instead of PUT for projects
[osm/osmclient.git] / osmclient / sol005 / wim.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 wim API handling
19 """
20
21 from osmclient.common import utils
22 from osmclient.common import wait as WaitForStatus
23 from osmclient.common.exceptions import ClientException
24 from osmclient.common.exceptions import NotFound
25 import yaml
26 import json
27
28
29 class Wim(object):
30 def __init__(self, http=None, client=None):
31 self._http = http
32 self._client = client
33 self._apiName = '/admin'
34 self._apiVersion = '/v1'
35 self._apiResource = '/wim_accounts'
36 self._apiBase = '{}{}{}'.format(self._apiName,
37 self._apiVersion, self._apiResource)
38
39 # WIM '--wait' option
40 def _wait(self, id, deleteFlag=False):
41 self._client.get_token()
42 # Endpoint to get operation status
43 apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/wim_accounts')
44 # Wait for status for WIM instance creation/deletion
45 WaitForStatus.wait_for_status(
46 'WIM',
47 str(id),
48 WaitForStatus.TIMEOUT_WIM_OPERATION,
49 apiUrlStatus,
50 self._http.get2_cmd,
51 deleteFlag=deleteFlag)
52
53 def _get_id_for_wait(self, name):
54 # Returns id of name, or the id itself if given as argument
55 for wim in self.list():
56 if name == wim['uuid']:
57 return wim['uuid']
58 for wim in self.list():
59 if name == wim['name']:
60 return wim['uuid']
61 return ''
62
63 def create(self, name, wim_input, wim_port_mapping=None, wait=False):
64 self._client.get_token()
65 if 'wim_type' not in wim_input:
66 raise Exception("wim type not provided")
67
68 wim_account = wim_input
69 wim_account["name"] = name
70
71 wim_config = {}
72 if 'config' in wim_input and wim_input['config'] is not None:
73 wim_config = yaml.safe_load(wim_input['config'])
74 if wim_port_mapping:
75 with open(wim_port_mapping, 'r') as f:
76 wim_config['wim_port_mapping'] = yaml.safe_load(f.read())
77 if wim_config:
78 wim_account['config'] = wim_config
79 #wim_account['config'] = json.dumps(wim_config)
80
81 http_code, resp = self._http.post_cmd(endpoint=self._apiBase,
82 postfields_dict=wim_account)
83 #print('HTTP CODE: {}'.format(http_code))
84 #print('RESP: {}'.format(resp))
85 if http_code in (200, 201, 202, 204):
86 if resp:
87 resp = json.loads(resp)
88 if not resp or 'id' not in resp:
89 raise ClientException('unexpected response from server - {}'.format(
90 resp))
91 if wait:
92 # Wait for status for WIM instance creation
93 self._wait(resp.get('id'))
94 print(resp['id'])
95 else:
96 msg = ""
97 if resp:
98 try:
99 msg = json.loads(resp)
100 except ValueError:
101 msg = resp
102 raise ClientException("failed to create wim {} - {}".format(name, msg))
103
104 def update(self, wim_name, wim_account, wim_port_mapping=None, wait=False):
105 self._client.get_token()
106 wim = self.get(wim_name)
107 wim_id_for_wait = self._get_id_for_wait(wim_name)
108 wim_config = {}
109 if 'config' in wim_account:
110 if wim_account.get('config')=="" and (wim_port_mapping):
111 raise ClientException("clearing config is incompatible with updating SDN info")
112 if wim_account.get('config')=="":
113 wim_config = None
114 else:
115 wim_config = yaml.safe_load(wim_account['config'])
116 if wim_port_mapping:
117 with open(wim_port_mapping, 'r') as f:
118 wim_config['wim_port_mapping'] = yaml.safe_load(f.read())
119 wim_account['config'] = wim_config
120 #wim_account['config'] = json.dumps(wim_config)
121 http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,wim['_id']),
122 postfields_dict=wim_account)
123 #print('HTTP CODE: {}'.format(http_code))
124 #print('RESP: {}'.format(resp))
125 if http_code in (200, 201, 202, 204):
126 if wait:
127 # In this case, 'resp' always returns None, so 'resp['id']' cannot be used.
128 # Use the previously obtained id instead.
129 wait_id = wim_id_for_wait
130 # Wait for status for WIM instance update
131 self._wait(wait_id)
132 else:
133 pass
134 else:
135 msg = ""
136 if resp:
137 try:
138 msg = json.loads(resp)
139 except ValueError:
140 msg = resp
141 raise ClientException("failed to update wim {} - {}".format(wim_name, msg))
142
143 def update_wim_account_dict(self, wim_account, wim_input):
144 print(wim_input)
145 wim_account['wim_type'] = wim_input['wim_type']
146 wim_account['description'] = wim_input['description']
147 wim_account['wim_url'] = wim_input['url']
148 wim_account['user'] = wim_input.get('wim-username')
149 wim_account['password'] = wim_input.get('wim-password')
150 return wim_account
151
152 def get_id(self, name):
153 """Returns a WIM id from a WIM name
154 """
155 for wim in self.list():
156 if name == wim['name']:
157 return wim['uuid']
158 raise NotFound("wim {} not found".format(name))
159
160 def delete(self, wim_name, force=False, wait=False):
161 self._client.get_token()
162 wim_id = wim_name
163 wim_id_for_wait = self._get_id_for_wait(wim_name)
164 if not utils.validate_uuid4(wim_name):
165 wim_id = self.get_id(wim_name)
166 querystring = ''
167 if force:
168 querystring = '?FORCE=True'
169 http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase,
170 wim_id, querystring))
171 # print('HTTP CODE: {}'.format(http_code))
172 # print('RESP: {}'.format(resp))
173 # print('WIM_ID: {}'.format(wim_id))
174 if http_code == 202:
175 if wait:
176 # 'resp' may be None.
177 # In that case, 'resp['id']' cannot be used, so use the previously obtained id instead
178 wait_id = wim_id_for_wait
179 if resp:
180 resp = json.loads(resp)
181 wait_id = resp.get('id')
182 # Wait for status for WIM account deletion
183 self._wait(wait_id, deleteFlag=True)
184 else:
185 print('Deletion in progress')
186 elif http_code == 204:
187 print('Deleted')
188 else:
189 msg = ""
190 if resp:
191 try:
192 msg = json.loads(resp)
193 except ValueError:
194 msg = resp
195 raise ClientException("failed to delete wim {} - {}".format(wim_name, msg))
196
197 def list(self, filter=None):
198 """Returns a list of VIM accounts
199 """
200 self._client.get_token()
201 filter_string = ''
202 if filter:
203 filter_string = '?{}'.format(filter)
204 resp = self._http.get_cmd('{}{}'.format(self._apiBase,filter_string))
205 if not resp:
206 return list()
207 wim_accounts = []
208 for datacenter in resp:
209 wim_accounts.append({"name": datacenter['name'], "uuid": datacenter['_id']
210 if '_id' in datacenter else None})
211 return wim_accounts
212
213 def get(self, name):
214 """Returns a VIM account based on name or id
215 """
216 self._client.get_token()
217 wim_id = name
218 if not utils.validate_uuid4(name):
219 wim_id = self.get_id(name)
220 resp = self._http.get_cmd('{}/{}'.format(self._apiBase,wim_id))
221 if not resp or '_id' not in resp:
222 raise ClientException('failed to get wim info: '.format(
223 resp))
224 else:
225 return resp
226 raise NotFound("wim {} not found".format(name))