c9249d061e028887d715138879f73bb21bb55057
[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(
39 self._apiName, self._apiVersion, self._apiResource
40 )
41
42 # WIM '--wait' option
43 def _wait(self, id, wait_time, 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 if isinstance(wait_time, bool):
50 wait_time = WaitForStatus.TIMEOUT_WIM_OPERATION
51 WaitForStatus.wait_for_status(
52 "WIM",
53 str(id),
54 wait_time,
55 apiUrlStatus,
56 self._http.get2_cmd,
57 deleteFlag=deleteFlag,
58 )
59
60 def _get_id_for_wait(self, name):
61 """Returns id of name, or the id itself if given as argument"""
62 self._logger.debug("")
63 for wim in self.list():
64 if name == wim["uuid"] or 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(
88 endpoint=self._apiBase, postfields_dict=wim_account
89 )
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 ClientException("unexpected response from server - {}".format(resp))
97 if wait:
98 # Wait for status for WIM instance creation
99 self._wait(resp.get("id"), wait)
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(
119 "clearing config is incompatible with updating SDN info"
120 )
121 if wim_account.get("config") == "":
122 wim_config = None
123 else:
124 wim_config = yaml.safe_load(wim_account["config"])
125 if wim_port_mapping:
126 with open(wim_port_mapping, "r") as f:
127 wim_config["wim_port_mapping"] = yaml.safe_load(f.read())
128 wim_account["config"] = wim_config
129 # wim_account['config'] = json.dumps(wim_config)
130 http_code, resp = self._http.patch_cmd(
131 endpoint="{}/{}".format(self._apiBase, wim["_id"]),
132 postfields_dict=wim_account,
133 )
134 # print('HTTP CODE: {}'.format(http_code))
135 # print('RESP: {}'.format(resp))
136 # if http_code in (200, 201, 202, 204):
137 if wait:
138 # In this case, 'resp' always returns None, so 'resp['id']' cannot be used.
139 # Use the previously obtained id instead.
140 wait_id = wim_id_for_wait
141 # Wait for status for WIM instance update
142 self._wait(wait_id, wait)
143 # else:
144 # pass
145 # else:
146 # msg = ""
147 # if resp:
148 # try:
149 # msg = json.loads(resp)
150 # except ValueError:
151 # msg = resp
152 # raise ClientException("failed to update wim {} - {}".format(wim_name, msg))
153
154 def update_wim_account_dict(self, wim_account, wim_input):
155 self._logger.debug("")
156 self._logger.debug(str(wim_input))
157 wim_account["wim_type"] = wim_input["wim_type"]
158 wim_account["description"] = wim_input["description"]
159 wim_account["wim_url"] = wim_input["url"]
160 wim_account["user"] = wim_input.get("wim-username")
161 wim_account["password"] = wim_input.get("wim-password")
162 return wim_account
163
164 def get_id(self, name):
165 """Returns a WIM id from a WIM name"""
166 self._logger.debug("")
167 for wim in self.list():
168 if name == wim["name"]:
169 return wim["uuid"]
170 raise NotFound("wim {} not found".format(name))
171
172 def delete(self, wim_name, force=False, wait=False):
173 self._logger.debug("")
174 self._client.get_token()
175 wim_id = wim_name
176 wim_id_for_wait = self._get_id_for_wait(wim_name)
177 if not utils.validate_uuid4(wim_name):
178 wim_id = self.get_id(wim_name)
179 querystring = ""
180 if force:
181 querystring = "?FORCE=True"
182 http_code, resp = self._http.delete_cmd(
183 "{}/{}{}".format(self._apiBase, wim_id, querystring)
184 )
185 # print('HTTP CODE: {}'.format(http_code))
186 # print('RESP: {}'.format(resp))
187 # print('WIM_ID: {}'.format(wim_id))
188 if http_code == 202:
189 if wait:
190 # 'resp' may be None.
191 # In that case, 'resp['id']' cannot be used, so use the previously obtained id instead
192 wait_id = wim_id_for_wait
193 if resp:
194 resp = json.loads(resp)
195 wait_id = resp.get("id")
196 # Wait for status for WIM account deletion
197 self._wait(wait_id, wait, deleteFlag=True)
198 else:
199 print("Deletion in progress")
200 elif http_code == 204:
201 print("Deleted")
202 else:
203 msg = resp or ""
204 # if resp:
205 # try:
206 # msg = json.loads(resp)
207 # except ValueError:
208 # msg = resp
209 raise ClientException("failed to delete wim {} - {}".format(wim_name, msg))
210
211 def list(self, filter=None):
212 """Returns a list of VIM accounts"""
213 self._logger.debug("")
214 self._client.get_token()
215 filter_string = ""
216 if filter:
217 filter_string = "?{}".format(filter)
218 _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string))
219 if not resp:
220 return list()
221 wim_accounts = []
222 for datacenter in json.loads(resp):
223 wim_accounts.append(
224 {
225 "name": datacenter["name"],
226 "uuid": datacenter["_id"] if "_id" in datacenter else None,
227 }
228 )
229 return wim_accounts
230
231 def get(self, name):
232 """Returns a VIM account based on name or id"""
233 self._logger.debug("")
234 self._client.get_token()
235 wim_id = name
236 if not utils.validate_uuid4(name):
237 wim_id = self.get_id(name)
238 try:
239 _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, wim_id))
240 if resp:
241 resp = json.loads(resp)
242 if not resp or "_id" not in resp:
243 raise ClientException("failed to get wim info: {}".format(resp))
244 return resp
245 except NotFound:
246 raise NotFound("wim '{}' not found".format(name))