Enable black and pylint in tox, and update code accordingly
[osm/osmclient.git] / osmclient / sol005 / vim.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 vim 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 Vim(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 = "/vim_accounts"
38 self._apiBase = "{}{}{}".format(
39 self._apiName, self._apiVersion, self._apiResource
40 )
41
42 # VIM '--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, "/vim_accounts")
48 # Wait for status for VIM instance creation/deletion
49 if isinstance(wait_time, bool):
50 wait_time = WaitForStatus.TIMEOUT_VIM_OPERATION
51 WaitForStatus.wait_for_status(
52 "VIM",
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 self._client.get_token()
64 for vim in self.list():
65 if name == vim["uuid"]:
66 return vim["uuid"]
67 for vim in self.list():
68 if name == vim["name"]:
69 return vim["uuid"]
70 return ""
71
72 def create(
73 self,
74 name,
75 vim_access,
76 config={},
77 sdn_controller=None,
78 sdn_port_mapping=None,
79 wait=False,
80 ):
81 vca_id = None
82
83 def get_vca_id(vca):
84 vca = self._client.vca.get(vca)
85 if vca is None:
86 raise NotFound("cannot find vca '{}'".format(vca))
87 return vca["_id"]
88
89 self._logger.debug("")
90 self._client.get_token()
91 if "vca" in vim_access:
92 vca_id = get_vca_id(vim_access["vca"])
93 if "vim-type" not in vim_access:
94 # 'openstack' not in vim_access['vim-type']):
95 raise Exception("vim type not provided")
96 vim_account = {}
97 vim_account["name"] = name
98 vim_account = self.update_vim_account_dict(vim_account, vim_access)
99 if vca_id:
100 vim_account["vca"] = vca_id
101 vim_config = config
102 if sdn_controller:
103 sdnc = self._client.sdnc.get(sdn_controller)
104 vim_config["sdn-controller"] = sdnc["_id"]
105 if sdn_port_mapping:
106 with open(sdn_port_mapping, "r") as f:
107 vim_config["sdn-port-mapping"] = yaml.safe_load(f.read())
108 if vim_config:
109 vim_account["config"] = vim_config
110 # vim_account['config'] = json.dumps(vim_config)
111
112 http_code, resp = self._http.post_cmd(
113 endpoint=self._apiBase, postfields_dict=vim_account
114 )
115 # print('HTTP CODE: {}'.format(http_code))
116 # print('RESP: {}'.format(resp))
117 # if http_code in (200, 201, 202, 204):
118 if resp:
119 resp = json.loads(resp)
120 if not resp or "id" not in resp:
121 raise ClientException("unexpected response from server - {}".format(resp))
122 if wait:
123 # Wait for status for VIM instance creation
124 self._wait(resp.get("id"), wait)
125 print(resp["id"])
126 # else:
127 # msg = ""
128 # if resp:
129 # try:
130 # msg = json.loads(resp)
131 # except ValueError:
132 # msg = resp
133 # raise ClientException("failed to create vim {} - {}".format(name, msg))
134
135 def update(
136 self,
137 vim_name,
138 vim_account,
139 config,
140 sdn_controller,
141 sdn_port_mapping,
142 wait=False,
143 ):
144 self._logger.debug("")
145 self._client.get_token()
146 vim = self.get(vim_name)
147 vim_id_for_wait = self._get_id_for_wait(vim_name)
148 vim_config = {}
149 if config is not None:
150 if not config and (sdn_controller or sdn_port_mapping):
151 # If config is empty (clearing config)
152 raise ClientException(
153 "clearing config is incompatible with updating SDN info"
154 )
155 vim_config = config
156 if sdn_controller == "":
157 vim_config["sdn-controller"] = None
158 vim_config["sdn-port-mapping"] = None
159 else:
160 if sdn_controller:
161 sdnc = self._client.sdnc.get(sdn_controller)
162 vim_config["sdn-controller"] = sdnc["_id"]
163 if sdn_port_mapping:
164 with open(sdn_port_mapping, "r") as f:
165 vim_config["sdn-port-mapping"] = yaml.safe_load(f.read())
166 vim_account["config"] = vim_config
167 # vim_account['config'] = json.dumps(vim_config)
168 http_code, resp = self._http.patch_cmd(
169 endpoint="{}/{}".format(self._apiBase, vim["_id"]),
170 postfields_dict=vim_account,
171 )
172 # print('HTTP CODE: {}'.format(http_code))
173 # print('RESP: {}'.format(resp))
174 # if http_code in (200, 201, 202, 204):
175 if wait:
176 # In this case, 'resp' always returns None, so 'resp['id']' cannot be used.
177 # Use the previously obtained id instead.
178 wait_id = vim_id_for_wait
179 # Wait for status for VI instance update
180 self._wait(wait_id, wait)
181 # else:
182 # pass
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 update vim {} - {}".format(vim_name, msg))
191
192 def update_vim_account_dict(self, vim_account, vim_access):
193 self._logger.debug("")
194 vim_account["vim_type"] = vim_access["vim-type"]
195 vim_account["description"] = vim_access["description"]
196 vim_account["vim_url"] = vim_access["vim-url"] or "null"
197 vim_account["vim_user"] = vim_access["vim-username"] or "null"
198 vim_account["vim_password"] = vim_access["vim-password"] or "null"
199 vim_account["vim_tenant_name"] = vim_access["vim-tenant-name"] or "null"
200 return vim_account
201
202 def get_id(self, name):
203 """Returns a VIM id from a VIM name"""
204 self._logger.debug("")
205 for vim in self.list():
206 if name == vim["name"]:
207 return vim["uuid"]
208 raise NotFound("vim {} not found".format(name))
209
210 def delete(self, vim_name, force=False, wait=False):
211 self._logger.debug("")
212 self._client.get_token()
213 vim_id = vim_name
214 if not utils.validate_uuid4(vim_name):
215 vim_id = self.get_id(vim_name)
216 querystring = ""
217 if force:
218 querystring = "?FORCE=True"
219 http_code, resp = self._http.delete_cmd(
220 "{}/{}{}".format(self._apiBase, vim_id, querystring)
221 )
222 # print('HTTP CODE: {}'.format(http_code))
223 # print('RESP: {}'.format(resp))
224 if http_code == 202:
225 if wait:
226 # When deleting an account, 'resp' may be None.
227 # In such a case, the 'id' from 'resp' cannot be used, so use 'vim_id' instead
228 wait_id = vim_id
229 if resp:
230 resp = json.loads(resp)
231 wait_id = resp.get("id")
232 # Wait for status for VIM account deletion
233 self._wait(wait_id, wait, deleteFlag=True)
234 else:
235 print("Deletion in progress")
236 elif http_code == 204:
237 print("Deleted")
238 else:
239 msg = resp or ""
240 # if resp:
241 # try:
242 # msg = json.loads(resp)
243 # except ValueError:
244 # msg = resp
245 raise ClientException("failed to delete vim {} - {}".format(vim_name, msg))
246
247 def list(self, filter=None):
248 """Returns a list of VIM accounts"""
249 self._logger.debug("")
250 self._client.get_token()
251 filter_string = ""
252 if filter:
253 filter_string = "?{}".format(filter)
254 _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string))
255 if not resp:
256 return list()
257 vim_accounts = json.loads(resp)
258 for datacenter in vim_accounts:
259 datacenter["uuid"] = datacenter.get("_id") # backward compatibility?
260 return vim_accounts
261
262 def get(self, name):
263 """Returns a VIM account based on name or id"""
264 self._logger.debug("")
265 self._client.get_token()
266 vim_id = name
267 if not utils.validate_uuid4(name):
268 vim_id = self.get_id(name)
269 try:
270 _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, vim_id))
271 if resp:
272 resp = json.loads(resp)
273 if not resp or "_id" not in resp:
274 raise ClientException("failed to get vim info: {}".format(resp))
275 return resp
276 except NotFound:
277 raise NotFound("vim '{}' not found".format(name))