Coverage for osmclient/sol005/nsd.py: 17%

124 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2024-06-30 09:54 +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 nsd API handling 

19""" 

20 

21from osmclient.common.exceptions import NotFound 

22from osmclient.common.exceptions import ClientException 

23from osmclient.common import utils 

24import json 

25import magic 

26from os.path import basename 

27import logging 

28import os.path 

29 

30 

31class Nsd(object): 

32 def __init__(self, http=None, client=None): 

33 self._http = http 

34 self._client = client 

35 self._logger = logging.getLogger("osmclient") 

36 self._apiName = "/nsd" 

37 self._apiVersion = "/v1" 

38 self._apiResource = "/ns_descriptors" 

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

40 self._apiName, self._apiVersion, self._apiResource 

41 ) 

42 

43 def list(self, filter=None): 

44 self._logger.debug("") 

45 self._client.get_token() 

46 filter_string = "" 

47 if filter: 

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

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

50 

51 if resp: 

52 return json.loads(resp) 

53 return list() 

54 

55 def get(self, name): 

56 self._logger.debug("") 

57 self._client.get_token() 

58 if utils.validate_uuid4(name): 

59 for nsd in self.list(): 

60 if name == nsd["_id"]: 

61 return nsd 

62 else: 

63 for nsd in self.list(): 

64 if "name" in nsd and name == nsd["name"]: 

65 return nsd 

66 raise NotFound("nsd {} not found".format(name)) 

67 

68 def get_individual(self, name): 

69 self._logger.debug("") 

70 # Call to get_token not required, because will be implicitly called by get. 

71 try: 

72 nsd = self.get(name) 

73 # It is redundant, since the previous one already gets the whole nsdinfo 

74 # The only difference is that a different primitive is exercised 

75 _, resp = self._http.get2_cmd("{}/{}".format(self._apiBase, nsd["_id"])) 

76 if resp: 

77 return json.loads(resp) 

78 except NotFound: 

79 raise NotFound("nsd '{}' not found".format(name)) 

80 raise NotFound("nsd '{}' not found".format(name)) 

81 

82 def get_thing(self, name, thing, filename): 

83 self._logger.debug("") 

84 # Call to get_token not required, because will be implicitly called by get. 

85 nsd = self.get(name) 

86 headers = self._client._headers 

87 headers["Accept"] = "application/binary" 

88 http_code, resp = self._http.get2_cmd( 

89 "{}/{}/{}".format(self._apiBase, nsd["_id"], thing) 

90 ) 

91 

92 if resp: 

93 return json.loads(resp) 

94 else: 

95 msg = resp or "" 

96 raise ClientException( 

97 "failed to get {} from {} - {}".format(thing, name, msg) 

98 ) 

99 

100 def get_descriptor(self, name, filename): 

101 self._logger.debug("") 

102 self.get_thing(name, "nsd", filename) 

103 

104 def get_package(self, name, filename): 

105 self._logger.debug("") 

106 self.get_thing(name, "package_content", filename) 

107 

108 def get_artifact(self, name, artifact, filename): 

109 self._logger.debug("") 

110 self.get_thing(name, "artifacts/{}".format(artifact), filename) 

111 

112 def delete(self, name, force=False): 

113 self._logger.debug("") 

114 nsd = self.get(name) 

115 querystring = "" 

116 if force: 

117 querystring = "?FORCE=True" 

118 http_code, resp = self._http.delete_cmd( 

119 "{}/{}{}".format(self._apiBase, nsd["_id"], querystring) 

120 ) 

121 

122 if http_code == 202: 

123 print("Deletion in progress") 

124 elif http_code == 204: 

125 print("Deleted") 

126 else: 

127 msg = resp or "" 

128 raise ClientException("failed to delete nsd {} - {}".format(name, msg)) 

129 

130 def create( 

131 self, filename, overwrite=None, update_endpoint=None, skip_charm_build=False 

132 ): 

133 self._logger.debug("") 

134 if os.path.isdir(filename): 

135 filename = filename.rstrip("/") 

136 filename = self._client.package_tool.build( 

137 filename, skip_validation=False, skip_charm_build=skip_charm_build 

138 ) 

139 self.create(filename, overwrite=overwrite, update_endpoint=update_endpoint) 

140 else: 

141 self._client.get_token() 

142 mime_type = magic.from_file(filename, mime=True) 

143 if mime_type is None: 

144 raise ClientException( 

145 "Unexpected MIME type for file {}: MIME type {}".format( 

146 filename, mime_type 

147 ) 

148 ) 

149 headers = self._client._headers 

150 headers["Content-Filename"] = basename(filename) 

151 if mime_type in ["application/yaml", "text/plain", "application/json"]: 

152 headers["Content-Type"] = "text/plain" 

153 elif mime_type in ["application/gzip", "application/x-gzip"]: 

154 headers["Content-Type"] = "application/gzip" 

155 elif mime_type in ["application/zip"]: 

156 headers["Content-Type"] = "application/zip" 

157 else: 

158 raise ClientException( 

159 "Unexpected MIME type for file {}: MIME type {}".format( 

160 filename, mime_type 

161 ) 

162 ) 

163 headers["Content-File-MD5"] = utils.md5(filename) 

164 self._http.set_http_header(headers) 

165 if update_endpoint: 

166 http_code, resp = self._http.put_cmd( 

167 endpoint=update_endpoint, filename=filename 

168 ) 

169 else: 

170 ow_string = "" 

171 if overwrite: 

172 ow_string = "?{}".format(overwrite) 

173 self._apiResource = "/ns_descriptors_content" 

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

175 self._apiName, self._apiVersion, self._apiResource 

176 ) 

177 endpoint = "{}{}".format(self._apiBase, ow_string) 

178 http_code, resp = self._http.post_cmd( 

179 endpoint=endpoint, filename=filename 

180 ) 

181 

182 if http_code in (200, 201, 202): 

183 if resp: 

184 resp = json.loads(resp) 

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

186 raise ClientException( 

187 "unexpected response from server - {}".format(resp) 

188 ) 

189 print(resp["id"]) 

190 elif http_code == 204: 

191 print("Updated") 

192 

193 def update(self, name, filename): 

194 self._logger.debug("") 

195 nsd = self.get(name) 

196 endpoint = "{}/{}/nsd_content".format(self._apiBase, nsd["_id"]) 

197 self.create(filename=filename, update_endpoint=endpoint)