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