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