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