#!/usr/bin/python import os import sys,json,datetime,time,types,httplib,re import mimetypes DEFAULT_HOST = "127.0.0.1" OPENECOMP_BE = "127.0.0.1" HOST = DEFAULT_HOST DEFAULT_PORT = "8080" DEFAULT_USERNAME = "cs0008" DEFAULT_PASSWORD = "cs0008" ONBOARD_BASE_PATH = "/onboarding-api/v1.0" VSP_LIST_PATH = "{0}/vendor-software-products".format(ONBOARD_BASE_PATH) VSP_ACTIONS_PATH = "{0}/vendor-software-products/{{vspId}}/actions".format(ONBOARD_BASE_PATH) VSP_UPLOAD_PATH = "{0}/vendor-software-products/{{vspId}}/upload".format(ONBOARD_BASE_PATH) VSP_DOWNLOAD_PATH = "{0}/vendor-software-products/{{vspId}}/downloadHeat".format(ONBOARD_BASE_PATH) VSP_GET_URL = "{0}/vendor-software-products/{{vspId}}".format(ONBOARD_BASE_PATH) def main(argv): username=DEFAULT_USERNAME password=DEFAULT_PASSWORD host=DEFAULT_HOST if not argv: print "Going to use default values" else: if argv[0].lower() == 'h' or argv[0].lower() == '-h': printHelp() return if argv[0] == '-ip': host=argv[1] else: if argv[0].lower() == '-a' and '/' not in argv[1]: print '\n>>> Error: Credentials required (username/password)\n' printHelp() return else: creds = argv[1].split('/') username = creds[0] password = creds[1] # not used try: cmdIp=argv[2] host=argv[3] except IndexError: host=DEFAULT_HOST print "Going to use user defined values" Service.server(host) webHandler=WebHandler(host=host, port=DEFAULT_PORT) response, headers = webHandler.rest(url=VSP_LIST_PATH, method='GET', data=None, userId=username) jResult = json.loads(response) jSrvices = jResult["results"] reportFileName = 'upgradereport.csv' #datetime.now() reportFile = open(reportFileName, 'w') reportFile.write(Service.header()) for jService in jSrvices: serviceName = jService["name"] vendorName = jService["vendorName"] vspId = jService["id"] status = jService["status"] if status != "Locked": lockingUser = "None" else: lockingUser = jService["lockingUser"] service = Service(serviceName=serviceName, vspId=vspId, vendorName=vendorName, lockingUser=lockingUser ) print service # Will try to GET the service res = service.Get() if res == 500: serviceMigration(service, status, username) else: print "Service {0} was tested and does not need a migration".format(serviceName) reportFile.write(service.line()) reportFile.close() def serviceMigration(service, serviceStatus, username): print "Service {0} was tested and it needs a migration".format(service.serviceName) print "Service {0} - Migration start" if serviceStatus == "Locked": print "Service {0} is locked - forcing checkin".format(service.serviceName) service.Checkin() print "Doing new checkout" service.Checkout(username) zipName = service.DownloadHeat() if not zipName: print "no heat found" service.uploadStatus = "no heat found" else: uploadResponse = service.UploadHeat(zipName) uploadResults = json.loads(uploadResponse) if uploadResults['status'] == 'Success' and uploadResults['errors'].__len__() == 0: service.uploadStatus = "Heat uploaded successfully" else: service.uploadStatus = "Heat uploaded with errors" print "Doing new checkin" service.Checkin() print "Service {0} - Migration end" def printHelp(): print("Upgrade script Help:") print("==================================") print("1607_to_1610 -h --> get help") print("1607_to_1610 -a <username>/<password> [-ip {ip}]") print("Example: 1607_to_1610 -a root/secret") class Service(object): def __init__(self, serviceName, vspId ,vendorName, lockingUser): self.serviceName = serviceName self.vspId = vspId self.vendorName = vendorName self.lockingUser = lockingUser self.webHandler = WebHandler(host=Service.serveraddress, port=DEFAULT_PORT) # Schema? self.uploadStatus = "not started" def __repr__(self): return 'Name: {0}, Id: {1}, Vendor: {2}, locked by: {3}, status {4}'.format(self.serviceName, self.vspId ,self.vendorName, self.lockingUser, self.uploadStatus) @classmethod def header(cls): return 'Name,Id,Vendor,locked-by,status\n' @classmethod def server(cls, address): cls.serveraddress=address def line(self): return '{0},{1},{2},{3},{4}\n'.format(self.serviceName, self.vspId ,self.vendorName, self.lockingUser, self.uploadStatus) def Checkout(self, userId): # /v1.0/vendor-software-products/{vspId}/actions urlpath=VSP_ACTIONS_PATH.format(vspId=self.vspId) response, headers = self.webHandler.rest( url=urlpath, method='PUT', data={"action": "Checkout"}, userId=userId) self.lockingUser=userId #we will later use this user to checkin return response def Checkin(self): # /v1.0/vendor-software-products/{vspId}/actions urlpath = VSP_ACTIONS_PATH.format(vspId=self.vspId) response, headers = self.webHandler.rest(url=urlpath, method='PUT', data={"action": "Checkin"}, userId=self.lockingUser) return response def Get(self): # /v1.0/vendor-software-products/{vspId} urlpath = VSP_GET_URL.format(vspId=self.vspId) try: response, headers = self.webHandler.rest(url=urlpath, method='GET', data=None, userId=self.lockingUser) except HttpError as e: print e.message response = e.status return response def UploadHeat(self, zipName): #/v1.0/vendor-software-products/{vspId}/upload urlpath = VSP_UPLOAD_PATH.format(vspId=self.vspId) try: fields = [] with open(zipName, 'rb') as fin: buffer = fin.read() fin.close() files = [('upload', 'heatfile.zip', buffer)] response = self.webHandler.post_multipart('HTTP', urlpath, fields, files, self.lockingUser) return response finally: print "done upload" def DownloadHeat(self): urlpath=VSP_DOWNLOAD_PATH.format(vspId=self.vspId) try: response, headers = self.webHandler.rest(url=urlpath, method='Get', data=None, userId=self.lockingUser, accept='application/octet-stream') except HttpError as e: if e.status == 404: return "" for (key, value) in headers: if key.lower() == "content-disposition": file_name = value[value.index('=')+1:] break heatsDir= os.path.join(os.path.dirname(__file__), 'heats') if not os.path.exists(heatsDir): os.makedirs(heatsDir) file_name = os.path.join(heatsDir, file_name) with open(file_name, "wb") as fout: fout.write(response) fout.close() return file_name class WebHandler(object): def __init__(self, host, port): self.host = host self.port = port def rest(self, url, method, data, userId, accept='application/json', content_type='application/json'): connection = httplib.HTTPConnection(host=self.host, port=self.port) try: headers = {'Content-Type':content_type ,'Accept':accept} headers['USER_ID'] = userId connection.request(method=method, headers=headers, body=json.dumps(data), url=url) response = connection.getresponse() if response.status not in range(200, 300): raise HttpError(status= response.status, message=response.reason) return response.read(), response.getheaders() finally: connection.close() def post_multipart(self, scheme, selector, fields, files, userId): """ Post fields and files to an http host as multipart/form-data. fields is a sequence of (name, value) elements for regular form fields. files is a sequence of (name, filename, value) elements for data to be uploaded as files Return the server's response page. """ content_type, body = self.encode_multipart_form_data(fields, files) if scheme and scheme.lower() == "http": h = httplib.HTTP(self.host, self.port) else: h = httplib.HTTPS(self.host, self.port) h.putrequest('POST', selector) h.putheader('content-type', content_type) h.putheader('content-length', str(len(body))) h.putheader('Accept', 'application/json') h.putheader('USER_ID', userId) h.endheaders() h.send(body) errcode, errmsg, headers = h.getreply() print errcode, errmsg, headers return h.file.read() def encode_multipart_form_data(self, fields, files): LIMIT = '----------lImIt_of_THE_fIle_eW_$' CRLF = '\r\n' L = [] for (key, value) in fields: L.append('--' + LIMIT) L.append('Content-Disposition: form-data; name="%s"' % key) L.append('') L.append(value) for (key, filename, value) in files: L.append('--' + LIMIT) L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename)) L.append('Content-Type: %s' % self.get_content_type(filename)) L.append('') L.append(value) L.append('--' + LIMIT + '--') L.append('') body = CRLF.join(L) content_type = 'multipart/form-data; boundary=%s' % LIMIT return content_type, body def get_content_type(self, filename): return mimetypes.guess_type(filename)[0] or 'application/octet-stream' class HttpError(Exception): def __init__(self, status, message): self.status = status self.message=message def __str__(self): return repr(self.value, self.message) if __name__ == "__main__": main(sys.argv[1:])