1 # Copyright 2018 Telefonica
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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
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
31 def __init__(self
, http
=None, client
=None):
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
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(
57 deleteFlag
=deleteFlag
,
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"]:
67 for vim
in self
.list():
68 if name
== vim
["name"]:
73 self
, name
, vim_access
, sdn_controller
=None, sdn_port_mapping
=None, wait
=False
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")
82 vim_account
["name"] = name
83 vim_account
= self
.update_vim_account_dict(vim_account
, vim_access
)
86 if "config" in vim_access
and vim_access
["config"] is not None:
87 vim_config
= yaml
.safe_load(vim_access
["config"])
89 sdnc
= self
._client
.sdnc
.get(sdn_controller
)
90 vim_config
["sdn-controller"] = sdnc
["_id"]
92 with
open(sdn_port_mapping
, "r") as f
:
93 vim_config
["sdn-port-mapping"] = yaml
.safe_load(f
.read())
95 vim_account
["config"] = vim_config
96 # vim_account['config'] = json.dumps(vim_config)
98 http_code
, resp
= self
._http
.post_cmd(
99 endpoint
=self
._apiBase
, postfields_dict
=vim_account
101 # print('HTTP CODE: {}'.format(http_code))
102 # print('RESP: {}'.format(resp))
103 # if http_code in (200, 201, 202, 204):
105 resp
= json
.loads(resp
)
106 if not resp
or "id" not in resp
:
107 raise ClientException("unexpected response from server - {}".format(resp
))
109 # Wait for status for VIM instance creation
110 self
._wait
(resp
.get("id"), wait
)
116 # msg = json.loads(resp)
119 # raise ClientException("failed to create vim {} - {}".format(name, msg))
122 self
, vim_name
, vim_account
, sdn_controller
, sdn_port_mapping
, wait
=False
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
)
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"
134 if vim_account
.get("config") == "":
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
143 sdnc
= self
._client
.sdnc
.get(sdn_controller
)
144 vim_config
["sdn-controller"] = sdnc
["_id"]
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
,
154 # print('HTTP CODE: {}'.format(http_code))
155 # print('RESP: {}'.format(resp))
156 # if http_code in (200, 201, 202, 204):
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
)
169 # msg = json.loads(resp)
172 # raise ClientException("failed to update vim {} - {}".format(vim_name, msg))
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"]
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"]:
190 raise NotFound("vim {} not found".format(name
))
192 def delete(self
, vim_name
, force
=False, wait
=False):
193 self
._logger
.debug("")
194 self
._client
.get_token()
196 if not utils
.validate_uuid4(vim_name
):
197 vim_id
= self
.get_id(vim_name
)
200 querystring
= "?FORCE=True"
201 http_code
, resp
= self
._http
.delete_cmd(
202 "{}/{}{}".format(self
._apiBase
, vim_id
, querystring
)
204 # print('HTTP CODE: {}'.format(http_code))
205 # print('RESP: {}'.format(resp))
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
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)
217 print("Deletion in progress")
218 elif http_code
== 204:
224 # msg = json.loads(resp)
227 raise ClientException("failed to delete vim {} - {}".format(vim_name
, msg
))
229 def list(self
, filter=None):
230 """Returns a list of VIM accounts"""
231 self
._logger
.debug("")
232 self
._client
.get_token()
235 filter_string
= "?{}".format(filter)
236 _
, resp
= self
._http
.get2_cmd("{}{}".format(self
._apiBase
, filter_string
))
239 vim_accounts
= json
.loads(resp
)
240 for datacenter
in vim_accounts
:
241 datacenter
["uuid"] = datacenter
.get("_id") # backward compatibility?
245 """Returns a VIM account based on name or id"""
246 self
._logger
.debug("")
247 self
._client
.get_token()
249 if not utils
.validate_uuid4(name
):
250 vim_id
= self
.get_id(name
)
252 _
, resp
= self
._http
.get2_cmd("{}/{}".format(self
._apiBase
, vim_id
))
254 resp
= json
.loads(resp
)
255 if not resp
or "_id" not in resp
:
256 raise ClientException("failed to get vim info: {}".format(resp
))
259 raise NotFound("vim '{}' not found".format(name
))