push addional code
Change-Id: Ia427bb3460cda3a896f8faced2de69eaf3807b74
Signed-off-by: Michael Lando <ml636r@att.com>
diff --git a/openecomp-be/tools/migration/1607_to_1610.py b/openecomp-be/tools/migration/1607_to_1610.py
new file mode 100644
index 0000000..2cec48b
--- /dev/null
+++ b/openecomp-be/tools/migration/1607_to_1610.py
@@ -0,0 +1,281 @@
+#!/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, attuid=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, attuid):
+ # /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"}, attuid=attuid)
+ self.lockingUser=attuid #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"}, attuid=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, attuid=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, attuid=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, attuid, 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'] = attuid
+
+ 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, attuid):
+ """
+ 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', attuid)
+
+ 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:])
+
+
diff --git a/openecomp-be/tools/migration/README b/openecomp-be/tools/migration/README
new file mode 100644
index 0000000..7bca1f3
--- /dev/null
+++ b/openecomp-be/tools/migration/README
@@ -0,0 +1,88 @@
+Info -
+ Name: 1607 to 1610 ASDC VSP migration tool
+ Version: 4.0
+ Date: 15 Sep, 2016
+
+General -
+ This is a utility used for migration of VSP data from ASDC version 1607 to version 1610.
+ This utility will be executed post upgrade process to 1610.
+ This utility must run from the ASDC backend (BE) machine.
+
+ From version 3.0 the tool can be run several times without changing a VSP version more then once, the first time.
+ Once the VSP is "fixed" it will not be migrated by this tool.
+
+Concept -
+ Once migrating ASDC from 1607 to 1610 changes were made in the VSP load/validation.
+ In order to support these changes and force a valid HEAT file upload, the migration process should be
+ run on the existing data.
+ Not doing so will result in VSPs that will not open for update action.
+
+ The migration will run on VSPs that were upgraded from 1607 to 1610 and are not able to be retrieved.
+
+Pre ASDC upgrade requisite -
+ In order to achieve the best result from this tool users must check-in ALL VSPs.
+
+Limitations -
+
+ * Will not work if user did not create a first version of the VSP, i.e. at least one time check-in action.
+ * Once run, user must checkout a VSP, go to General and re select a license model version.
+
+
+Usage -
+
+ Note: There are default values if the script is run without arguments.
+ The values are credentials: cs0008/cs0008, with host: 127.0.0.1
+ 1607_to_1610 -h --> get help
+ 1607_to_1610 -a <username>/<password> [-ip {ip}]
+ Example:
+ using cassandra on localhost - 1607_to_1610 -a root/secret
+ using cassandra on remote host - 1607_to_1610 -a root/secert -ip 10.147.97.191
+
+ Result:
+ The migration result will be listed in a CSV file: upgradereport.csv
+ "None" is an indication that the VSP was not in a checkout status prior to the upgrade.
+
+ Exmample for a valid output:
+
+ Name: VSP-OK, Id: 9DB0E1563B22481D911ECD33989E1FDD, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP-OK was tested and does not need a migration
+ Name: VSP02-Checkout, Id: 8DF8D65535414AAAA23682E2532675E6, Vendor: OPENECOMP, locked by: cs0008, status not started
+ Server Error
+ Service VSP02-Checkout was tested and it needs a migration
+ Service VSP02 - Migration start
+ Service VSP02-Checkout is locked - forcing checkin
+ Doing new checkout
+ 200 OK Content-Type: application/json
+ Date: Thu, 08 Sep 2016 13:25:21 GMT
+ Server: Jetty(9.3.6.v20151106)
+
+ done upload
+ Doing new checkin
+ Service VSP-EMPTY - Migration end
+ Name: VSP-EMPTY, Id: D26892D2839746E18075EF49C4586320, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP-EMPTY was tested and does not need a migration
+ Name: VSP01, Id: 98F5DDFD4F684086801E86A88A0D77AB, Vendor: OPENECOMP, locked by: None, status not started
+ Server Error
+ Service VSP01 was tested and it needs a migration
+ Service VSP-EMPTY - Migration start
+ Doing new checkout
+ 200 OK Content-Type: application/json
+ Date: Thu, 08 Sep 2016 13:25:22 GMT
+ Server: Jetty(9.3.6.v20151106)
+
+ done upload
+ Doing new checkin
+ Service {0} - Migration end
+
+ Example for a case with no migration needed:
+
+ Name: VSP-OK, Id: 9DB0E1563B22481D911ECD33989E1FDD, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP-OK was tested and does not need a migration
+ Name: VSP02-Checkout, Id: 8DF8D65535414AAAA23682E2532675E6, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP02-Checkout was tested and does not need a migration
+ Name: VSP-EMPTY, Id: D26892D2839746E18075EF49C4586320, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP-EMPTY was tested and does not need a migration
+ Name: VSP01, Id: 98F5DDFD4F684086801E86A88A0D77AB, Vendor: OPENECOMP, locked by: None, status not started
+ Service VSP01 was tested and does not need a migration
+
+