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