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