def Upload(files): for file in files: if not os.path.isfile(file): bpformation.output.Status('ERROR',3,"Package file '%s' not found" % file) raise(bpformation.BPFormationFatalExeption("Fatal Error")) if not bpformation.FTP_ENDPOINT: Package._GetFtpEndpoint() # TODO - alert nicely on login failure # TODO - output xfer stats if verbose ftp = ftplib.FTP(bpformation.FTP_ENDPOINT['endpoint'],bpformation.FTP_ENDPOINT['user'],bpformation.FTP_ENDPOINT['passwd']) for file in files: time_start = time.time() with open(file,'rb') as fh: file_name = re.sub(".*/","",file) ftp.storbinary("STOR %s" % (file_name),fh) bpformation.output.Status('SUCCESS',3,"%s successfully uploaded (%s seconds)" % (file_name,int(time.time()-time_start))) ftp.quit()
def ListOS(type): try: return(bpformation.web.CallScrape("POST","/blueprints/packages/GetOSList", {'osType': type}).json()['Result']) except: bpformation.output.Status('ERROR',3,"Unable to retrieve OS listi") raise(bpformation.BPFormationFatalExeption("Fatal Error"))
def Execute(ids, files, parameters, type, password, group_id, network, dns): """ parameters - dict of key/value pairs or a list of key=value pairs """ # Build list of file-based assets to exec bps = [] if files is not None and len(files): for file in files: if not os.path.isfile(file): bpformation.output.Status( 'ERROR', 3, "Blueprint json file '%s' not found" % file) # Load json with open(file) as fh: bp = json.load(fh) if 'id' not in bp['metadata']: bpformation.output.Status('ERROR', 3, "No blueprint ID in '%s'" % file) raise (bpformation.BPFormationFatalExeption("Fatal Error")) bps.append({ 'execute': bp['execute'], 'id': bp['metadata']['id'] }) # Build list of id-based assets to exec if ids is not None and len(ids): for id in ids: bps.append({'execute': {}, 'id': id}) # Build execute parameter lists # order of precedence (low to high): # o .bpformation ini file # o blueprint json file 'execute' obj # o command line args new_bps = [] for bp in bps: # Refresh latest blueprint xml r = bpformation.web.CallScrape( "GET", "/Blueprints/Designer/BlueprintXml/%s" % bp['id']) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error retrieving data (http response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) t = etree.XML(r.text) # Populate server name/id dict servers = {} for o in t.xpath("//Parameter"): if o.get("Type") == "ServerAlias": servers[o.get("Default")] = o.get("Variable").replace( ".Alias", "") # Apply defaults from config file - don't overwrite existing items. Only covers system items for key in ('type', 'password', 'group_id', 'network', 'dns'): if key in bp['execute']: continue if bpformation.config and bpformation.config.has_option( 'blueprint_execute', key): bp['execute'][key] = bpformation.config.get( 'blueprint_execute', key) # Apply system-level command line args for key in ('type', 'password', 'group_id', 'network', 'dns'): if key in vars() and vars()[key] is not None: bp['execute'][key] = vars()[key] # Apply parameter command line args if parameters is not None and isinstance(parameters, dict): for key, value in parameters.items(): bp['execute'][key] = value elif parameters is not None and len(parameters): for parameter in parameters: (key, value) = parameter.split("=", 1) bp['execute'][key] = value # If deploy-time server selection map to server.id for key, value in bp['execute'].items(): # TODO - add and to except if explicit ID already provided if re.search("\.TaskServer$", key): bp['execute'][key] = [ "${%s.ServerName}" % id for alias, id in servers.items() if alias == value ][0] # Hardcoded default DNS - this is dumb that we ask for it if 'dns' not in bp['execute'] or not len(bp['execute']['dns']): bp['execute']['dns'] = "172.17.1.26" # Confirm system parameters are all set for key in ('type', 'password', 'group_id', 'network', 'dns'): if key not in bp['execute'] or not len(bp['execute'][key]): bpformation.output.Status( 'ERROR', 3, "Missing required system parameter '%s'" % key) raise (bpformation.BPFormationFatalExeption("Fatal Error")) # TODO Confirm all blueprint parameters are set # Rename system parameters so they match what POST is expecting bp['execute']['TemplateID'] = bp['id'] bp['execute']['T3.BuildServerTask.Password'] = bp['execute'][ 'password'] bp['execute']['Confirm.T3.BuildServerTask.Password'] = bp[ 'execute']['password'] bp['execute']['T3.BuildServerTask.GroupID'] = bp['execute'][ 'group_id'] bp['execute']['T3.BuildServerTask.Network'] = bp['execute'][ 'network'] bp['execute']['T3.BuildServerTask.PrimaryDNS'] = 'Manual' bp['execute']['T3.BuildServerTask.PrimaryDNS_manual'] = bp[ 'execute']['dns'] bp['execute']['T3.BuildServerTask.SecondaryDNS'] = '' bp['execute']['T3.BuildServerTask.SecondaryDNS_manual'] = '' bp['execute']['T3.BuildServerTask.HardwareType'] = bp['execute'][ 'type'] bp['execute']['T3.BuildServerTask.AntiAffinityPoolId'] = '' bp['execute']['T3.BuildServerTask.ServiceLevel'] = 'Standard' bp['execute']['RequestID'] = '' bp['execute']['Submit'] = '' for key in ('password', 'group_id', 'network', 'dns', 'type'): del (bp['execute'][key]) new_bps.append(bp) bps = new_bps # Execute each Blueprint clc.v2.SetCredentials(bpformation.CONTROL_USER, bpformation.CONTROL_PASSWORD) results = {'servers': []} requests = [] start_time = time.time() for bp in bps: # Step 1 - customize blueprint r = bpformation.web.CallScrape("POST", "/Blueprints/Builder/Customize/%s" % bp['id'], allow_redirects=False, payload=bp['execute']) if r.status_code < 200 or r.status_code >= 400: bpformation.output.Status( 'ERROR', 3, "Error executing blueprint - step 1 customization metadata failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) # Step 2 - deploy blueprint r = bpformation.web.CallScrape("POST", r.headers['location'], allow_redirects=False, payload={ 'TemplateID': bp['id'], 'Submit': '' }) if r.status_code < 200 or r.status_code >= 400: bpformation.output.Status( 'ERROR', 3, "Error executing blueprint - step 2 submit failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) # Step 3 - queue request id request_id = re.sub(".*/(\d+).*=(.*)", r'\2-\1', r.headers['location']).lower() requests.append( clc.v2.Requests([{ 'isQueued': True, 'links': [{ 'rel': 'status', 'id': request_id }] }], alias=bpformation.web.Alias())) bpformation.output.Status( 'SUCCESS', 3, "Execution request submitted for Blueprint ID %s (request %s)" % (bp['id'], request_id)) # Wait for executing blueprints to complete # TODO - async option requests = sum(requests) requests.WaitUntilComplete() if len(requests.success_requests): #bpformation.output.Status('SUCCESS',3,"Execution completed on %s (%s seconds)" % (",".join(success_servers),int(time.time()-start_time))) bpformation.output.Status( 'SUCCESS', 3, "Execution completed on %s blueprints (%s seconds)" % (len( requests.success_requests), int(time.time() - start_time))) # Generate list of servers created try: for request in requests.success_requests: (req_loc, req_id) = request.id.split("-", 1) r = bpformation.web.CallScrape( "GET", "/Blueprints/Queue/RequestDetails/%s?location=%s" % (req_id, req_loc)) if r.status_code < 300 and r.status_code >= 200: # TODO - if multiople bps this will overwrite> Need to merge results['servers'] = re.findall( '<a href="/manage#/.+?/server/(.+?)">', r.text, re.DOTALL) bpformation.output.Status( 'SUCCESS', 3, "The following server(s) were created: %s" % (", ".join(results['servers']))) except: pass for request in requests.error_requests: (req_loc, req_id) = request.id.split("-", 1) r = bpformation.web.CallScrape( "GET", "/Blueprints/Queue/RequestDetails/%s?location=%s" % (req_id, req_loc)) if r.status_code < 300 and r.status_code >= 200: error = re.search( '<div class="module-body">.*?<pre>(\s*.Error.\s*)?(.*?)\s*</pre>', r.text, re.DOTALL).group(2) bpformation.output.Status( 'ERROR', 3, "Execution failed on %s: %s" % (request.id, error)) else: bpformation.output.Status('ERROR',3,"Execution failed on %s request ID %s (https://control.ctl.io/Blueprints/Queue/RequestDetails/%s?location=%s)" % \ (request.data['context_val'],req_id,req_id,req_loc)) if requests.error_requests: e = bpformation.BPFormationFatalExeption( "Error executing blueprint") e.error_requests = requests.error_requests raise (e) return (results)
def _PostBlueprint(bp): """Update and publish provided Blueprint objects.""" # Validate syntax and required metadata fields for key in ('description', 'name', 'visibility', 'version'): if key not in bp['metadata']: bpformation.output.Status( 'ERROR', 3, "Blueprint json missing metadata/%s" % key) raise (bpformation.BPFormationFatalExeption("Fatal Error")) # Munge version formatting if not re.search("^[\d\.]+$", bp['metadata']['version']): bpformation.output.Status( 'ERROR', 3, "Blueprint json version must contain only a dotted number representation" ) raise (bpformation.BPFormationFatalExeption("Fatal Error")) m = re.search("(.+?)\.?(.*)", bp['metadata']['version']) ver_major = int(m.group(1)) if len(m.groups(2)): ver_minor = int(m.group(2).replace(".", "")) else: ver_minor = 0 # Step 0 - Get UUID if existing if bp['metadata']['id']: r = bpformation.web.CallScrape( "GET", "/blueprints/browser/details/%s" % bp['metadata']['id']) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error creating blueprint - step 0 uuid failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) bp['metadata']['uuid'] = re.search( '/Blueprints/Browser/Clone.blueprintUUID=([a-zA-Z0-9\-]+)', r.text, re.DOTALL).group(1) r = bpformation.web.CallScrape("GET", "/blueprints/designer/metadata/%s" % bp['metadata']['uuid'], allow_redirects=False) else: bp['metadata']['uuid'] = str(uuid.uuid4()) # Step 1 - Metadata post and create Blueprint shell r = bpformation.web.CallScrape( "POST", "/blueprints/designer/metadata", allow_redirects=False, payload={ "capabilities": "", # Aligns to "tags" "companySize": 3, # 1: 1-100, 2: 101-1,000, 3: 1001-5000, 4: 5,000+ "isReseller": False, # Tied to is_managed, no-op "errors": [], # unknown "userCapabilities": "", # TODO - Custom tags "templateID": bp['metadata']['id'], "description": bp['metadata']['description'], "templateName": bp['metadata']['name'], "visibility": Blueprint.visibility_stoi[bp['metadata'] ['visibility'].lower()], "versionMajor": ver_major, "versionMinor": ver_minor, }) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error creating blueprint - step 1 metadata failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) bp['metadata']['id'] = re.search("(\d+)$", r.json()['url']).group(1) # Step 2 - Apply all tasks new_tasks = [] for task in bp['tasks']: if task['type'] == 'server': new_tasks.append( Blueprint._PostServer(bp['metadata']['id'], task)) else: bpformation.output.Status( 'ERROR', 3, "Unknown task type '%s'" % task['type']) raise (bpformation.BPFormationFatalExeption("Fatal Error")) bp['tasks'] = new_tasks # Step 3 - Publish Blueprint r = bpformation.web.CallScrape( "POST", "/Blueprints/Designer/review/%s" % bp['metadata']['id'], allow_redirects=False, payload={ "Publish": "", # unknown "DataTemplate.UUID": bp['metadata']['uuid'], "TemplateID": bp['metadata']['id'], }) # TODO Step 4 - save output? Assume needed for some kind of update if bp['metadata']['visibility'].lower() == "public": bpformation.output.Status( 'SUCCESS', 3, "CenturyLink approval needed for Public publishing. Email [email protected] for approval" ) return (bp)
def _PostTask(blueprint_id, o): """ Post to create/update add-on tasks. Must include all parameters for the server - anything not specified is "deleted". o is a server object with keys name, description, cpu, ram, template, id, and a list of tasks. o['id'] is 0 for new servers, otherwise include the uuid of the existing server to modify. """ """ Tasks appear to be preserved (unlike other attrs) on write. So since we don't want to take control state as authoritative at any time we first delete tasks. After delete we add tasks in the order specified. POST https://control.ctl.io/blueprints/designer/DeleteTask id:3710 taskId:d858c386-112e-4fae-9fd2-9129bdeaa1e8 POST https://control.ctl.io/blueprints/designer/AddTasks?id=3708 id=3708 Tasks[0].Properties[0].Value:SpecifyAtDeployment Tasks[0].Properties[0].Name:Server Tasks[0].ID:77ab3844-579d-4c8d-8955-c69a94a2ba1a Alternatly - make sure each specified task exists, then issue a reorder statement at the end? """ # Build tasks data structure # TODO - query for parameters and verify we meet requirements staged_tasks = {} staged_tasks_idx = 0 if 'tasks' in o: for task in o['tasks']: # TODO system tasks - scheduled task, delete snapshot, revert snapshot # System - add disk if task['type'] == 'disk' and task[ 'uuid'] == '22460210-b682-4138-93fd-1a95c5e4e039': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'GB' staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = task['gb'] if 'drive' in task: staged_tasks['Server.Tasks[%s].Properties[1].Name' % staged_tasks_idx] = 'Drive' staged_tasks['Server.Tasks[%s].Properties[1].Value' % staged_tasks_idx] = task['drive'] # System - reboot elif task['type'] == 'reboot' and task[ 'uuid'] == '5b949945-6981-4a81-bbcc-4ddd3d394b8d': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # System - add public NAT elif task['type'] == 'add_nat_ip' and task[ 'uuid'] == 'c000d327-3543-4d9e-ac43-e8fbce4620ab': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'FirewallOptions' staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = ",".join( task['ingress_ports']) # System - add add'l private IP elif task['type'] == 'add_ip' and task[ 'uuid'] == '9a851f50-c676-4c11-b4c8-a0a7241c1060': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # System - set ttl #elif task['type']=='ttl' and task['uuid']=='2d4d37e6-be83-461a-bfd2-b3c2ca327db5': # staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'ActivityType' # staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = 'Delete' # staged_tasks['Server.Tasks[%s].Properties[1].Name' % staged_tasks_idx] = 'TimeZone' # staged_tasks['Server.Tasks[%s].Properties[1].Value' % staged_tasks_idx] = 'UTC' # staged_tasks['Server.Tasks[%s].Properties[2].Name' % staged_tasks_idx] = 'ScheduleDate' # staged_tasks['Server.Tasks[%s].Properties[2].Value' % staged_tasks_idx] = '2015-06-06T15:35:00Z' # User package elif task['type'] == 'package': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # Add all design-time parameters try: properties_idx = 0 for key, value in task['properties'].items(): staged_tasks[ 'Server.Tasks[%s].Properties[%s].Name' % (staged_tasks_idx, properties_idx)] = key staged_tasks[ 'Server.Tasks[%s].Properties[%s].Value' % (staged_tasks_idx, properties_idx)] = value properties_idx += 1 except: pass # Unknown type/ID else: bpformation.output.Status( 'ERROR', 3, "Blueprint json server task unknown type/id '%s'" % task['type']) raise (bpformation.BPFormationFatalExeption("Fatal Error")) staged_tasks_idx += 1 # Post r = bpformation.web.CallScrape( "POST", "/blueprints/designer/SaveServer?id=%s" % blueprint_id, allow_redirects=False, payload=dict({ "Server.ID": o['id'], "Server.Template": o['template'], "Server.Name": o['name'], "Server.Description": o['description'], "Server.Processor": o['cpu'], "Server.Memory": o['ram'], }.items() + staged_tasks.items())) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error creating blueprint - step 2 add server failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) if o['id'] == 0: o['id'] = r.json()['serverID'] return (o)
def _PostServer(blueprint_id, o): """ Post to create/update server configuration. Must include all parameters for the server - anything not specified is "deleted". o is a server object with keys name, description, cpu, ram, template, id, and a list of tasks. o['id'] is 0 for new servers, otherwise include the uuid of the existing server to modify. """ # Validate core params for key in ('name', 'description', 'cpu', 'ram'): if key not in o: bpformation.output.Status( 'ERROR', 3, "Blueprint json server definition missing '%s'" % key) raise (bpformation.BPFormationFatalExeption("Fatal Error")) if 'id' not in o: o['id'] = 0 # New servers don't start with an ID if len(o['name']) == 0 or len(o['name']) > 6: bpformation.output.Status( 'ERROR', 3, "Blueprint json server name must be between 0 and six characters" ) raise (bpformation.BPFormationFatalExeption("Fatal Error")) if not re.match("^\d+$", o['cpu']) or int( o['cpu']) == 0 or int(o['cpu']) > 16: bpformation.output.Status( 'ERROR', 3, "Blueprint json server cpu must be between 1 and 16" % key) raise (bpformation.BPFormationFatalExeption("Fatal Error")) if not re.match("^\d+$", o['ram']) or int( o['ram']) == 0 or int(o['cpu']) > 128: bpformation.output.Status( 'ERROR', 3, "Blueprint json server ram must be between 1 and 128" % key) raise (bpformation.BPFormationFatalExeption("Fatal Error")) # Build tasks data structure # TODO - query for parameters and verify we meet requirements staged_tasks = {} staged_tasks_idx = 0 if 'tasks' in o: for task in o['tasks']: # TODO system tasks - scheduled task, delete snapshot, revert snapshot # System - add disk if task['type'] == 'disk' and task[ 'uuid'] == '22460210-b682-4138-93fd-1a95c5e4e039': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'GB' staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = task['gb'] if 'drive' in task: staged_tasks['Server.Tasks[%s].Properties[1].Name' % staged_tasks_idx] = 'Drive' staged_tasks['Server.Tasks[%s].Properties[1].Value' % staged_tasks_idx] = task['drive'] # System - reboot elif task['type'] == 'reboot' and task[ 'uuid'] == '5b949945-6981-4a81-bbcc-4ddd3d394b8d': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # System - add public NAT elif task['type'] == 'add_nat_ip' and task[ 'uuid'] == 'c000d327-3543-4d9e-ac43-e8fbce4620ab': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'FirewallOptions' staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = ",".join( task['ingress_ports']) # System - add add'l private IP elif task['type'] == 'add_ip' and task[ 'uuid'] == '9a851f50-c676-4c11-b4c8-a0a7241c1060': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # System - set ttl #elif task['type']=='ttl' and task['uuid']=='2d4d37e6-be83-461a-bfd2-b3c2ca327db5': # staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # staged_tasks['Server.Tasks[%s].Properties[0].Name' % staged_tasks_idx] = 'ActivityType' # staged_tasks['Server.Tasks[%s].Properties[0].Value' % staged_tasks_idx] = 'Delete' # staged_tasks['Server.Tasks[%s].Properties[1].Name' % staged_tasks_idx] = 'TimeZone' # staged_tasks['Server.Tasks[%s].Properties[1].Value' % staged_tasks_idx] = 'UTC' # staged_tasks['Server.Tasks[%s].Properties[2].Name' % staged_tasks_idx] = 'ScheduleDate' # staged_tasks['Server.Tasks[%s].Properties[2].Value' % staged_tasks_idx] = '2015-06-06T15:35:00Z' # User package elif task['type'] == 'package': staged_tasks['Server.Tasks[%s].ID' % staged_tasks_idx] = task['uuid'] # Add all design-time parameters try: properties_idx = 0 for key, value in task['properties'].items(): staged_tasks[ 'Server.Tasks[%s].Properties[%s].Name' % (staged_tasks_idx, properties_idx)] = key staged_tasks[ 'Server.Tasks[%s].Properties[%s].Value' % (staged_tasks_idx, properties_idx)] = value properties_idx += 1 except: pass # Unknown type/ID else: bpformation.output.Status( 'ERROR', 3, "Blueprint json server task unknown type/id '%s'" % task['type']) raise (bpformation.BPFormationFatalExeption("Fatal Error")) staged_tasks_idx += 1 # Post r = bpformation.web.CallScrape( "POST", "/blueprints/designer/SaveServer?id=%s" % blueprint_id, allow_redirects=False, payload=dict({ "Server.ID": o['id'], "Server.Template": o['template'], "Server.Name": o['name'], "Server.Description": o['description'], "Server.Processor": o['cpu'], "Server.Memory": o['ram'], }.items() + staged_tasks.items())) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error creating blueprint - step 2 add server failure (response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) if o['id'] == 0: o['id'] = r.json()['serverID'] return (o)
def Export(id, file=None): # Silence status output if writing to stdout if file == "-": bpformation.args.args.quiet = 999 bp = {'metadata': {}, 'tasks': [], 'execute': {}} # Blueprint metadata r = bpformation.web.CallScrape("GET", "/blueprints/browser/details/%s" % id) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error retrieving data (http response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) bp['metadata'] = { 'name': re.search('<h1 id="body-title" class="left">\s*(.+?)\s*<small>', r.text, re.DOTALL).group(1), 'owner': re.search('<small>by (.+?)</small>', r.text).group(1), 'version': re.search('<dt>version</dt>\s*<dd>\s*(.+?)\s*</dd>', r.text, re.DOTALL).group(1), 'visibility': re.search('<dt>visibility</dt>\s*<dd>\s*(.+?)\s*-', r.text, re.DOTALL).group(1), 'description': re.search('<div class="blueprint-price">.*?<p>\s*(.+?)\s*</p>', r.text, re.DOTALL).group(1), 'id': id, } # Blueprint definition r = bpformation.web.CallScrape( "GET", "/Blueprints/Designer/BlueprintXml/%s" % id) if r.status_code < 200 or r.status_code >= 300: bpformation.output.Status( 'ERROR', 3, "Error retrieving data (http response %s)" % r.status_code) raise (bpformation.BPFormationFatalExeption("Fatal Error")) t = etree.XML(r.text) for o in t.findall("Tasks/*"): try: bp['tasks'] += Blueprint._ExportProcessRoot(o) except: # Catch only our exceptions pass # Populate server name/id dict servers = {} for o in t.xpath("//Parameter"): if o.get("Type") == "ServerAlias": servers[o.get("Default")] = o.get("Variable").replace( ".Alias", "") # Populate Blueprint execute stub with script-specific vals server_names = {} for o in t.findall("UI/Group"): # system params - we don't replicate if o.get("Name") == "Build Server": continue elif o.get("Name") == "Global Blueprint Values": for param in o.findall("Parameter"): if param.get("Default"): default = param.get("Default") elif param.get("Type") in ("Option", "MultiSelect"): default = " | ".join([ opt.get("Value") for opt in param.findall("Option") ]) else: default = '' bp['execute'][param.get("Variable")] = default # Assume all other els are groups containing local package-specific variables else: for param in o.findall("Parameter"): if param.get("Default"): default = param.get("Default") elif param.get("Type") in ("Option", "MultiSelect"): default = " | ".join([ opt.get("Value") for opt in param.findall("Option") ]) elif re.search("\.TaskServer$", param.get("Variable")): default = " | ".join([o for o in servers.keys()]) else: default = '' bp['execute'][param.get("Variable")] = default # Output if file == "-": print json.dumps(bp, sort_keys=True, indent=4, separators=(',', ': ')) else: if file is None: file = "%s-%s-%s.json" % (re.sub( "[^a-zA-Z0-9\-_]", "_", bp['metadata']['name']).lower(), id, bp['metadata']['version']) bpformation.output.Status( 'SUCCESS', 3, "%s v%s exported to %s (%s tasks)" % (bp['metadata']['name'], bp['metadata']['version'], file, len(bp['tasks']))) with open(file, 'w') as fh: fh.write( json.dumps(bp, sort_keys=True, indent=4, separators=(',', ': ')))