blob: f46cb3a4b8ff0bd98bd0c12086938d3b4494a692 [file] [log] [blame]
Michael Landof5f13c42017-02-19 12:35:04 +02001#!/usr/bin/python
2import os
3import sys,json,datetime,time,types,httplib,re
4import mimetypes
5
6DEFAULT_HOST = "127.0.0.1"
7OPENECOMP_BE = "127.0.0.1"
8
9HOST = DEFAULT_HOST
10DEFAULT_PORT = "8080"
11DEFAULT_USERNAME = "cs0008"
12DEFAULT_PASSWORD = "cs0008"
13
14ONBOARD_BASE_PATH = "/onboarding-api/v1.0"
15VSP_LIST_PATH = "{0}/vendor-software-products".format(ONBOARD_BASE_PATH)
16VSP_ACTIONS_PATH = "{0}/vendor-software-products/{{vspId}}/actions".format(ONBOARD_BASE_PATH)
17VSP_UPLOAD_PATH = "{0}/vendor-software-products/{{vspId}}/upload".format(ONBOARD_BASE_PATH)
18VSP_DOWNLOAD_PATH = "{0}/vendor-software-products/{{vspId}}/downloadHeat".format(ONBOARD_BASE_PATH)
19VSP_GET_URL = "{0}/vendor-software-products/{{vspId}}".format(ONBOARD_BASE_PATH)
20
21def main(argv):
22 username=DEFAULT_USERNAME
23 password=DEFAULT_PASSWORD
24 host=DEFAULT_HOST
25
26 if not argv:
27 print "Going to use default values"
28 else:
29 if argv[0].lower() == 'h' or argv[0].lower() == '-h':
30 printHelp()
31 return
32
33 if argv[0] == '-ip':
34 host=argv[1]
35 else:
36 if argv[0].lower() == '-a' and '/' not in argv[1]:
37 print '\n>>> Error: Credentials required (username/password)\n'
38 printHelp()
39 return
40
41 else:
42 creds = argv[1].split('/')
43 username = creds[0]
44 password = creds[1] # not used
45
46 try:
47 cmdIp=argv[2]
48 host=argv[3]
49 except IndexError:
50 host=DEFAULT_HOST
51 print "Going to use user defined values"
52 Service.server(host)
53
54 webHandler=WebHandler(host=host, port=DEFAULT_PORT)
AviZi280f8012017-06-09 02:39:56 +030055 response, headers = webHandler.rest(url=VSP_LIST_PATH, method='GET', data=None, userId=username)
Michael Landof5f13c42017-02-19 12:35:04 +020056 jResult = json.loads(response)
57 jSrvices = jResult["results"]
58 reportFileName = 'upgradereport.csv' #datetime.now()
59 reportFile = open(reportFileName, 'w')
60 reportFile.write(Service.header())
61
62 for jService in jSrvices:
63 serviceName = jService["name"]
64 vendorName = jService["vendorName"]
65 vspId = jService["id"]
66 status = jService["status"]
67 if status != "Locked":
68 lockingUser = "None"
69 else:
70 lockingUser = jService["lockingUser"]
71
72 service = Service(serviceName=serviceName, vspId=vspId, vendorName=vendorName, lockingUser=lockingUser )
73 print service
74 # Will try to GET the service
75 res = service.Get()
76 if res == 500:
77 serviceMigration(service, status, username)
78 else:
79 print "Service {0} was tested and does not need a migration".format(serviceName)
80
81 reportFile.write(service.line())
82 reportFile.close()
83
84
85def serviceMigration(service, serviceStatus, username):
86 print "Service {0} was tested and it needs a migration".format(service.serviceName)
87 print "Service {0} - Migration start"
88 if serviceStatus == "Locked":
89 print "Service {0} is locked - forcing checkin".format(service.serviceName)
90 service.Checkin()
91 print "Doing new checkout"
92 service.Checkout(username)
93
94 zipName = service.DownloadHeat()
95 if not zipName:
96 print "no heat found"
97 service.uploadStatus = "no heat found"
98 else:
99 uploadResponse = service.UploadHeat(zipName)
100 uploadResults = json.loads(uploadResponse)
101 if uploadResults['status'] == 'Success' and uploadResults['errors'].__len__() == 0:
102 service.uploadStatus = "Heat uploaded successfully"
103 else:
104 service.uploadStatus = "Heat uploaded with errors"
105 print "Doing new checkin"
106 service.Checkin()
107
108 print "Service {0} - Migration end"
109
110
111def printHelp():
112 print("Upgrade script Help:")
113 print("==================================")
114 print("1607_to_1610 -h --> get help")
115 print("1607_to_1610 -a <username>/<password> [-ip {ip}]")
116 print("Example: 1607_to_1610 -a root/secret")
117
118class Service(object):
119 def __init__(self, serviceName, vspId ,vendorName, lockingUser):
120 self.serviceName = serviceName
121 self.vspId = vspId
122 self.vendorName = vendorName
123 self.lockingUser = lockingUser
124 self.webHandler = WebHandler(host=Service.serveraddress, port=DEFAULT_PORT) # Schema?
125 self.uploadStatus = "not started"
126
127 def __repr__(self):
128 return 'Name: {0}, Id: {1}, Vendor: {2}, locked by: {3}, status {4}'.format(self.serviceName, self.vspId ,self.vendorName, self.lockingUser, self.uploadStatus)
129 @classmethod
130 def header(cls):
131 return 'Name,Id,Vendor,locked-by,status\n'
132
133 @classmethod
134 def server(cls, address):
135 cls.serveraddress=address
136
137 def line(self):
138 return '{0},{1},{2},{3},{4}\n'.format(self.serviceName, self.vspId ,self.vendorName, self.lockingUser, self.uploadStatus)
139
AviZi280f8012017-06-09 02:39:56 +0300140 def Checkout(self, userId):
Michael Landof5f13c42017-02-19 12:35:04 +0200141 # /v1.0/vendor-software-products/{vspId}/actions
142 urlpath=VSP_ACTIONS_PATH.format(vspId=self.vspId)
AviZi280f8012017-06-09 02:39:56 +0300143 response, headers = self.webHandler.rest( url=urlpath, method='PUT', data={"action": "Checkout"}, userId=userId)
144 self.lockingUser=userId #we will later use this user to checkin
Michael Landof5f13c42017-02-19 12:35:04 +0200145 return response
146
147 def Checkin(self):
148 # /v1.0/vendor-software-products/{vspId}/actions
149 urlpath = VSP_ACTIONS_PATH.format(vspId=self.vspId)
AviZi280f8012017-06-09 02:39:56 +0300150 response, headers = self.webHandler.rest(url=urlpath, method='PUT', data={"action": "Checkin"}, userId=self.lockingUser)
Michael Landof5f13c42017-02-19 12:35:04 +0200151 return response
152
153 def Get(self):
154 # /v1.0/vendor-software-products/{vspId}
155 urlpath = VSP_GET_URL.format(vspId=self.vspId)
156 try:
AviZi280f8012017-06-09 02:39:56 +0300157 response, headers = self.webHandler.rest(url=urlpath, method='GET', data=None, userId=self.lockingUser)
Michael Landof5f13c42017-02-19 12:35:04 +0200158 except HttpError as e:
159 print e.message
160 response = e.status
161 return response
162
163 def UploadHeat(self, zipName):
164 #/v1.0/vendor-software-products/{vspId}/upload
165 urlpath = VSP_UPLOAD_PATH.format(vspId=self.vspId)
166 try:
167 fields = []
168 with open(zipName, 'rb') as fin:
169 buffer = fin.read()
170 fin.close()
171 files = [('upload', 'heatfile.zip', buffer)]
172 response = self.webHandler.post_multipart('HTTP', urlpath, fields, files, self.lockingUser)
173
174 return response
175 finally:
176 print "done upload"
177
178 def DownloadHeat(self):
179 urlpath=VSP_DOWNLOAD_PATH.format(vspId=self.vspId)
180 try:
AviZi280f8012017-06-09 02:39:56 +0300181 response, headers = self.webHandler.rest(url=urlpath, method='Get', data=None, userId=self.lockingUser, accept='application/octet-stream')
Michael Landof5f13c42017-02-19 12:35:04 +0200182 except HttpError as e:
183 if e.status == 404:
184 return ""
185
186 for (key, value) in headers:
187 if key.lower() == "content-disposition":
188 file_name = value[value.index('=')+1:]
189 break
190 heatsDir= os.path.join(os.path.dirname(__file__), 'heats')
191 if not os.path.exists(heatsDir):
192 os.makedirs(heatsDir)
193 file_name = os.path.join(heatsDir, file_name)
194 with open(file_name, "wb") as fout:
195 fout.write(response)
196 fout.close()
197
198 return file_name
199
200
201
202class WebHandler(object):
203 def __init__(self, host, port):
204 self.host = host
205 self.port = port
206
AviZi280f8012017-06-09 02:39:56 +0300207 def rest(self, url, method, data, userId, accept='application/json', content_type='application/json'):
Michael Landof5f13c42017-02-19 12:35:04 +0200208 connection = httplib.HTTPConnection(host=self.host, port=self.port)
209
210 try:
211 headers = {'Content-Type':content_type ,'Accept':accept}
AviZi280f8012017-06-09 02:39:56 +0300212 headers['USER_ID'] = userId
Michael Landof5f13c42017-02-19 12:35:04 +0200213
214 connection.request(method=method, headers=headers, body=json.dumps(data), url=url)
215 response = connection.getresponse()
216 if response.status not in range(200, 300):
217 raise HttpError(status= response.status, message=response.reason)
218
219 return response.read(), response.getheaders()
220 finally:
221 connection.close()
222
AviZi280f8012017-06-09 02:39:56 +0300223 def post_multipart(self, scheme, selector, fields, files, userId):
Michael Landof5f13c42017-02-19 12:35:04 +0200224 """
225 Post fields and files to an http host as multipart/form-data.
226 fields is a sequence of (name, value) elements for regular form fields.
227 files is a sequence of (name, filename, value) elements for data to be uploaded as files
228 Return the server's response page.
229 """
230 content_type, body = self.encode_multipart_form_data(fields, files)
231 if scheme and scheme.lower() == "http":
232 h = httplib.HTTP(self.host, self.port)
233 else:
234 h = httplib.HTTPS(self.host, self.port)
235 h.putrequest('POST', selector)
236 h.putheader('content-type', content_type)
237 h.putheader('content-length', str(len(body)))
238 h.putheader('Accept', 'application/json')
AviZi280f8012017-06-09 02:39:56 +0300239 h.putheader('USER_ID', userId)
Michael Landof5f13c42017-02-19 12:35:04 +0200240
241 h.endheaders()
242 h.send(body)
243 errcode, errmsg, headers = h.getreply()
244 print errcode, errmsg, headers
245 return h.file.read()
246
247 def encode_multipart_form_data(self, fields, files):
248 LIMIT = '----------lImIt_of_THE_fIle_eW_$'
249 CRLF = '\r\n'
250 L = []
251 for (key, value) in fields:
252 L.append('--' + LIMIT)
253 L.append('Content-Disposition: form-data; name="%s"' % key)
254 L.append('')
255 L.append(value)
256 for (key, filename, value) in files:
257 L.append('--' + LIMIT)
258 L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
259 L.append('Content-Type: %s' % self.get_content_type(filename))
260 L.append('')
261 L.append(value)
262 L.append('--' + LIMIT + '--')
263 L.append('')
264 body = CRLF.join(L)
265 content_type = 'multipart/form-data; boundary=%s' % LIMIT
266 return content_type, body
267
268 def get_content_type(self, filename):
269 return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
270
271class HttpError(Exception):
272 def __init__(self, status, message):
273 self.status = status
274 self.message=message
275 def __str__(self):
276 return repr(self.value, self.message)
277
278if __name__ == "__main__":
279 main(sys.argv[1:])
280
281