Coverage for osmclient/sol005/wim.py: 14%

139 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2024-06-30 09:02 +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 wim 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 Wim(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 = "/wim_accounts" 

38 self._apiBase = "{}{}{}".format( 

39 self._apiName, self._apiVersion, self._apiResource 

40 ) 

41 

42 # WIM '--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, "/wim_accounts") 

48 # Wait for status for WIM instance creation/deletion 

49 if isinstance(wait_time, bool): 

50 wait_time = WaitForStatus.TIMEOUT_WIM_OPERATION 

51 WaitForStatus.wait_for_status( 

52 "WIM", 

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 for wim in self.list(): 

64 if name == wim["uuid"] or name == wim["name"]: 

65 return wim["uuid"] 

66 return "" 

67 

68 def create(self, name, wim_input, wim_port_mapping=None, wait=False): 

69 self._logger.debug("") 

70 self._client.get_token() 

71 if "wim_type" not in wim_input: 

72 raise Exception("wim type not provided") 

73 

74 wim_account = wim_input 

75 wim_account["name"] = name 

76 

77 wim_config = {} 

78 if "config" in wim_input and wim_input["config"] is not None: 

79 wim_config = yaml.safe_load(wim_input["config"]) 

80 if wim_port_mapping: 

81 with open(wim_port_mapping, "r") as f: 

82 wim_config["wim_port_mapping"] = yaml.safe_load(f.read()) 

83 if wim_config: 

84 wim_account["config"] = wim_config 

85 # wim_account['config'] = json.dumps(wim_config) 

86 

87 http_code, resp = self._http.post_cmd( 

88 endpoint=self._apiBase, postfields_dict=wim_account 

89 ) 

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

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

92 # if http_code in (200, 201, 202, 204): 

93 if resp: 

94 resp = json.loads(resp) 

95 if not resp or "id" not in resp: 

96 raise ClientException("unexpected response from server - {}".format(resp)) 

97 if wait: 

98 # Wait for status for WIM instance creation 

99 self._wait(resp.get("id"), wait) 

100 print(resp["id"]) 

101 # else: 

102 # msg = "" 

103 # if resp: 

104 # try: 

105 # msg = json.loads(resp) 

106 # except ValueError: 

107 # msg = resp 

108 # raise ClientException("failed to create wim {} - {}".format(name, msg)) 

109 

110 def update(self, wim_name, wim_account, wim_port_mapping=None, wait=False): 

111 self._logger.debug("") 

112 self._client.get_token() 

113 wim = self.get(wim_name) 

114 wim_id_for_wait = self._get_id_for_wait(wim_name) 

115 wim_config = {} 

116 if "config" in wim_account: 

117 if wim_account.get("config") == "" and (wim_port_mapping): 

118 raise ClientException( 

119 "clearing config is incompatible with updating SDN info" 

120 ) 

121 if wim_account.get("config") == "": 

122 wim_config = None 

123 else: 

124 wim_config = yaml.safe_load(wim_account["config"]) 

125 if wim_port_mapping: 

126 with open(wim_port_mapping, "r") as f: 

127 wim_config["wim_port_mapping"] = yaml.safe_load(f.read()) 

128 wim_account["config"] = wim_config 

129 # wim_account['config'] = json.dumps(wim_config) 

130 http_code, resp = self._http.patch_cmd( 

131 endpoint="{}/{}".format(self._apiBase, wim["_id"]), 

132 postfields_dict=wim_account, 

133 ) 

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

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

136 # if http_code in (200, 201, 202, 204): 

137 if wait: 

138 # In this case, 'resp' always returns None, so 'resp['id']' cannot be used. 

139 # Use the previously obtained id instead. 

140 wait_id = wim_id_for_wait 

141 # Wait for status for WIM instance update 

142 self._wait(wait_id, wait) 

143 # else: 

144 # pass 

145 # else: 

146 # msg = "" 

147 # if resp: 

148 # try: 

149 # msg = json.loads(resp) 

150 # except ValueError: 

151 # msg = resp 

152 # raise ClientException("failed to update wim {} - {}".format(wim_name, msg)) 

153 

154 def update_wim_account_dict(self, wim_account, wim_input): 

155 self._logger.debug("") 

156 self._logger.debug(str(wim_input)) 

157 wim_account["wim_type"] = wim_input["wim_type"] 

158 wim_account["description"] = wim_input["description"] 

159 wim_account["wim_url"] = wim_input["url"] 

160 wim_account["user"] = wim_input.get("wim-username") 

161 wim_account["password"] = wim_input.get("wim-password") 

162 return wim_account 

163 

164 def get_id(self, name): 

165 """Returns a WIM id from a WIM name""" 

166 self._logger.debug("") 

167 for wim in self.list(): 

168 if name == wim["name"]: 

169 return wim["uuid"] 

170 raise NotFound("wim {} not found".format(name)) 

171 

172 def delete(self, wim_name, force=False, wait=False): 

173 self._logger.debug("") 

174 self._client.get_token() 

175 wim_id = wim_name 

176 wim_id_for_wait = self._get_id_for_wait(wim_name) 

177 if not utils.validate_uuid4(wim_name): 

178 wim_id = self.get_id(wim_name) 

179 querystring = "" 

180 if force: 

181 querystring = "?FORCE=True" 

182 http_code, resp = self._http.delete_cmd( 

183 "{}/{}{}".format(self._apiBase, wim_id, querystring) 

184 ) 

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

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

187 # print('WIM_ID: {}'.format(wim_id)) 

188 if http_code == 202: 

189 if wait: 

190 # 'resp' may be None. 

191 # In that case, 'resp['id']' cannot be used, so use the previously obtained id instead 

192 wait_id = wim_id_for_wait 

193 if resp: 

194 resp = json.loads(resp) 

195 wait_id = resp.get("id") 

196 # Wait for status for WIM account deletion 

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

198 else: 

199 print("Deletion in progress") 

200 elif http_code == 204: 

201 print("Deleted") 

202 else: 

203 msg = resp or "" 

204 # if resp: 

205 # try: 

206 # msg = json.loads(resp) 

207 # except ValueError: 

208 # msg = resp 

209 raise ClientException("failed to delete wim {} - {}".format(wim_name, msg)) 

210 

211 def list(self, filter=None): 

212 """Returns a list of VIM accounts""" 

213 self._logger.debug("") 

214 self._client.get_token() 

215 filter_string = "" 

216 if filter: 

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

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

219 if not resp: 

220 return list() 

221 wim_accounts = [] 

222 for datacenter in json.loads(resp): 

223 wim_accounts.append( 

224 { 

225 "name": datacenter["name"], 

226 "uuid": datacenter["_id"] if "_id" in datacenter else None, 

227 } 

228 ) 

229 return wim_accounts 

230 

231 def get(self, name): 

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

233 self._logger.debug("") 

234 self._client.get_token() 

235 wim_id = name 

236 if not utils.validate_uuid4(name): 

237 wim_id = self.get_id(name) 

238 try: 

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

240 if resp: 

241 resp = json.loads(resp) 

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

243 raise ClientException("failed to get wim info: {}".format(resp)) 

244 return resp 

245 except NotFound: 

246 raise NotFound("wim '{}' not found".format(name))