Coverage for osmclient/sol005/vim.py: 12%

160 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2024-06-29 09:50 +0000

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""" 

18OSM vim API handling 

19""" 

20 

21from osmclient.common import utils 

22from osmclient.common import wait as WaitForStatus 

23from osmclient.common.exceptions import ClientException 

24from osmclient.common.exceptions import NotFound 

25import yaml 

26import json 

27import logging 

28 

29 

30class 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 if "prometheus-config" in vim_access: 

201 vim_account["prometheus-config"] = vim_access["prometheus-config"] 

202 return vim_account 

203 

204 def get_id(self, name): 

205 """Returns a VIM id from a VIM name""" 

206 self._logger.debug("") 

207 for vim in self.list(): 

208 if name == vim["name"]: 

209 return vim["uuid"] 

210 raise NotFound("vim {} not found".format(name)) 

211 

212 def delete(self, vim_name, force=False, wait=False): 

213 self._logger.debug("") 

214 self._client.get_token() 

215 vim_id = vim_name 

216 if not utils.validate_uuid4(vim_name): 

217 vim_id = self.get_id(vim_name) 

218 querystring = "" 

219 if force: 

220 querystring = "?FORCE=True" 

221 http_code, resp = self._http.delete_cmd( 

222 "{}/{}{}".format(self._apiBase, vim_id, querystring) 

223 ) 

224 # print('HTTP CODE: {}'.format(http_code)) 

225 # print('RESP: {}'.format(resp)) 

226 if http_code == 202: 

227 if wait: 

228 # When deleting an account, 'resp' may be None. 

229 # In such a case, the 'id' from 'resp' cannot be used, so use 'vim_id' instead 

230 wait_id = vim_id 

231 if resp: 

232 resp = json.loads(resp) 

233 wait_id = resp.get("id") 

234 # Wait for status for VIM account deletion 

235 self._wait(wait_id, wait, deleteFlag=True) 

236 else: 

237 print("Deletion in progress") 

238 elif http_code == 204: 

239 print("Deleted") 

240 else: 

241 msg = resp or "" 

242 # if resp: 

243 # try: 

244 # msg = json.loads(resp) 

245 # except ValueError: 

246 # msg = resp 

247 raise ClientException("failed to delete vim {} - {}".format(vim_name, msg)) 

248 

249 def list(self, filter=None): 

250 """Returns a list of VIM accounts""" 

251 self._logger.debug("") 

252 self._client.get_token() 

253 filter_string = "" 

254 if filter: 

255 filter_string = "?{}".format(filter) 

256 _, resp = self._http.get2_cmd("{}{}".format(self._apiBase, filter_string)) 

257 if not resp: 

258 return list() 

259 vim_accounts = json.loads(resp) 

260 for datacenter in vim_accounts: 

261 datacenter["uuid"] = datacenter.get("_id") # backward compatibility? 

262 return vim_accounts 

263 

264 def get(self, name): 

265 """Returns a VIM account based on name or id""" 

266 self._logger.debug("") 

267 self._client.get_token() 

268 vim_id = name 

269 if not utils.validate_uuid4(name): 

270 vim_id = self.get_id(name) 

271 try: 

272 _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, vim_id)) 

273 if resp: 

274 resp = json.loads(resp) 

275 if not resp or "_id" not in resp: 

276 raise ClientException("failed to get vim info: {}".format(resp)) 

277 return resp 

278 except NotFound: 

279 raise NotFound("vim '{}' not found".format(name))