def create(fco_api, *args, **kwargs): ctx.logger.info('starting server creation') # Ease of access _rp = ctx.instance.runtime_properties _np = ctx.node.properties # Check if existing server is to be used if _np[PROP_USE_EXISTING]: server = get_resource(fco_api, _np[PROP_RESOURCE_ID, RT.SERVER]) if not server.nics: raise Exception('No NICs attached to server') _rp[RPROP_UUID] = server.resourceUUID _rp[RPROP_DISKS] = [d.resourceUUID for d in server.disks] _rp[RPROP_NIC] = server.nics[0].resourceUUID _rp[RPROP_NICS] = [n.resourceUUID for n in server.nics] _rp[RPROP_IP] = server.nics[0].ipAddresses[0].ipAddress _rp[RPROP_USER] = server.initialUser _rp[RPROP_PASS] = server.initialPassword return (_rp[RPROP_UUID], _rp[RPROP_IP], _rp[RPROP_USER], _rp[RPROP_PASS]) # Get configuration image = get_resource(fco_api, _np[PROP_IMAGE], RT.IMAGE) if _np[PROP_IMAGE]: vdc = get_resource(fco_api, _np[PROP_VDC], RT.VDC) else: vdc = None network = get_resource(fco_api, _np[PROP_NET], RT.NETWORK) server_po = get_resource(fco_api, _np[PROP_SERVER_PO], RT.PRODUCTOFFER) manager_key = get_resource(fco_api, _np[PROP_MANAGER_KEY], RT.SSHKEY) cpu_count = _np[PROP_CPU_COUNT] ram_amount = _np[PROP_RAM_AMOUNT] public_keys = _np[PROP_PUBLIC_KEYS] or [] private_keys = _np[PROP_PRIVATE_KEYS] or [] # Verify existence of private keys missing_keys = set() bad_permission_keys = set() key_contents = {} for key in private_keys: try: key_contents[key] = ctx.get_resource(os.path.expanduser(key)) except NonRecoverableError as e: if 'HttpException: 404' in str(e): missing_keys.add(key) elif 'HttpException: 403' in str(e): bad_permission_keys.add(key) else: raise if missing_keys or bad_permission_keys: raise Exception('Missing private keys: {}\nBad permission keys: {}' .format(missing_keys, bad_permission_keys)) # Generate missing configuration image_uuid = image.resourceUUID if vdc is not None: cluster_uuid = vdc.clusterUUID vdc_uuid = vdc.resourceUUID else: cluster_uuid = image.clusterUUID vdc_uuid = image.vdcUUID network_uuid = network.resourceUUID network_type = network.networkType server_po_uuid = server_po.resourceUUID manager_key_uuid = manager_key.resourceUUID # TODO: better way of determining suitable disk boot_disk_po_uuid = get_resource(fco_api, '{} GB Storage Disk'.format(image.size), RT.PRODUCTOFFER).resourceUUID ctx.logger.info('Configuration: \n' 'image_uuid: %s\n' 'cluster_uuid: %s\n' 'vdc_uuid: %s\n' 'network_uuid: %s\n' 'server_po_uuid: %s\n' 'manager_key_uuid: %s\n' 'boot_disk_po_uuid: %s', image_uuid, cluster_uuid, vdc_uuid, network_uuid, server_po_uuid, manager_key_uuid, boot_disk_po_uuid) # Create server server_name = '{}{}_{}'.format(ctx.bootstrap_context.resources_prefix, ctx.deployment.id, ctx.instance.id) try: server_uuid = _rp[RPROP_UUID] except KeyError: # key_obj = get_resource(fco_api, key_uuid, RT.SSHKEY) # keys = SSHKey.REQUIRED_ATTRIBS.copy() # keys.add('resourceUUID') # submit_key = {} # for k in keys: # try: # submit_key[k] = getattr(manager_key, k) # except AttributeError: # submit_key[k] = None server_uuid = create_server(fco_api, server_po_uuid, image_uuid, cluster_uuid, vdc_uuid, cpu_count, ram_amount, boot_disk_po_uuid, [manager_key], server_name) _rp[RPROP_UUID] = server_uuid ctx.logger.info('server_uuid: %s', server_uuid) server = get_resource(fco_api, server_uuid, RT.SERVER) server_nics = [nic.resourceUUID for nic in server.nics] server_keys = [key.resourceUUID for key in server.sshkeys] # Wait for server to be active if not wait_for_state(fco_api, server_uuid, enums.ResourceState.ACTIVE, RT.SERVER): raise Exception('Server failed to prepare in time!') ctx.logger.info('Server ACTIVE') # Add keys new_keys = set() for key in public_keys: if key not in server_keys: key_uuid = create_ssh_key(fco_api, key, server_name + ' Key') attach_ssh_key(fco_api, server_uuid, key_uuid) new_keys.add(key_uuid) ctx.logger.info('Keys attached: %s', new_keys) # Create NIC try: nic_uuid = _rp[RPROP_NIC] except KeyError: nic_uuid = create_nic(fco_api, cluster_uuid, network_type, network_uuid, vdc_uuid, server_name + ' NIC') if not wait_for_state(fco_api, nic_uuid, enums.ResourceState.ACTIVE, RT.NIC): raise Exception('NIC failed to create in time!') _rp[RPROP_NIC] = nic_uuid ctx.logger.info('nic_uuid: %s', nic_uuid) # Stop server if started if get_server_status(fco_api, server_uuid) != enums.ServerStatus.STOPPED: if not stop_server(fco_api, server_uuid): raise Exception('Stopping server failed to complete in time!') ctx.logger.info('Server STOPPED') # Attach NIC if nic_uuid not in server_nics: job_uuid = attach_nic(fco_api, server_uuid, nic_uuid, 1).resourceUUID cond = cobjects.Job.status == enums.JobStatus.SUCCESSFUL if not wait_for_cond(fco_api, job_uuid, cond, RT.JOB): raise Exception('Attaching NIC failed to complete in time!') ctx.logger.info('NICs attached') else: ctx.logger.info('NICs already attached') # Start server if not started if get_server_status(fco_api, server_uuid) == enums.ServerStatus.STOPPED: if not start_server(fco_api, server_uuid): raise Exception('Running server failed to complete in time!') ctx.logger.info('Server RUNNING') nic = get_resource(fco_api, nic_uuid, RT.NIC) server_ip = nic.ipAddresses[0].ipAddress server_port = 22 ctx.logger.info('Server READY') username = server.initialUser password = server.initialPassword ssh_attempts = -1 ssh_delay = 3 # Fabric test while ssh_attempts: ctx.logger.info('Attempting to SSH ({})'.format(ssh_attempts)) try: with settings(host_string=server_po_uuid, user=username, password=password, disable_known_hosts=True, abort_exception=Exception): run('mkdir ~/.ssh') run('chmod 0700 ~/.ssh') for key, key_content in key_contents.items(): remote = os.path.join('~', '.ssh', os.path.basename(key)) run('echo \'{}\' > {}'.format(key_content, remote)) run('chmod 0600 ' + remote) ctx.logger.info('Done') break except Exception as e: ctx.logger.info(e) ssh_attempts -= 1 else: raise Exception('Failed to provision keys in time') # # Spur test # while ssh_attempts: # ctx.logger.info('Attempting to SSH ({})'.format(ssh_attempts)) # shell = spur.SshShell( # hostname=server_ip, # port=server_port, # username=username, # password=password, # shell_type=spur.ssh.ShellTypes.minimal, # missing_host_key=spur.ssh.MissingHostKey.accept # ) # with shell: # try: # ctx.logger.info('Creating & chmoding .ssh') # shell.run(['mkdir', '~/.ssh']) # shell.run(['chmod', '0700', '~/.ssh']) # for key, key_content in key_contents.items(): # ctx.logger.info('Adding private key: ' + remote) # remote = os.path.join('~', '.ssh', os.path.basename(key)) # shell.run(['echo', "'{}'".format(key_content), '>', # remote]) # shell.run(['chmod', '0600', remote]) # except spur.ssh.ConnectionError as e: # if e.original_error[0] not in {errno.ECONNREFUSED, # errno.EHOSTUNREACH}: # raise # sleep(ssh_delay) # ssh_attempts -= 1 # else: # raise Exception('Failed to provision keys in time') # # Provision private keys # ssh = SSHClient() # call(['ssh-keygen', '-R', server_ip]) # ssh.set_missing_host_key_policy(AutoAddPolicy()) # # while ssh_attempts: # try: # ctx.logger.info('Attempting to SSH ({})'.format(ssh_attempts)) # ctx.logger.info('SSH Connection details: {}'.format( # ((server_ip, server_port, username, password, ssh_delay)))) # ssh.connect(server_ip, server_port, username, password, # timeout=ssh_delay, look_for_keys=False) # ctx.logger.info('SSH connection established') # break # except socket.timeout: # ssh_attempts -= 1 # except socket.error as e: # if e[0] not in {errno.ECONNREFUSED, errno.EHOSTUNREACH}: # ctx.logger.info('SSH connection failed: %s', e[0]) # raise # sleep(ssh_delay) # ssh_attempts -= 1 # else: # raise Exception('Failed to provision keys in time') # ssh.exec_command('mkdir ~/.ssh') # ssh.exec_command('chmod 0700 ~/.ssh') # for key, key_content in key_contents.items(): # remote = os.path.join('~', '.ssh', os.path.basename(key)) # ssh.exec_command('echo \'{}\' > {}'.format(key_content, remote)) # ssh.exec_command('chmod 0600 ' + remote) _rp[RPROP_UUID] = server_uuid _rp[RPROP_IP] = server_ip _rp[RPROP_USER] = username _rp[RPROP_PASS] = password server = get_resource(fco_api, server_uuid, RT.SERVER) _rp[RPROP_DISKS] = [d.resourceUUID for d in server.disks] _rp[RPROP_NICS] = [n.resourceUUID for n in server.nics] ctx.logger.info('Server IP: ' + server_ip) ctx.logger.info('Server User: '******'Server Password: ' + password) return server_uuid, server_ip, username, password
def create(fco_api, *args, **kwargs): ctx.logger.info("starting server creation") # Ease of access _rp = ctx.instance.runtime_properties _np = ProviderProperties(ctx) # Check if existing server is to be used if _np[PROP_USE_EXISTING]: server = get_resource(fco_api, _np[PROP_RESOURCE_ID], RT.SERVER) if not server.nics: raise Exception("No NICs attached to server") _rp[RPROP_UUID] = server.resourceUUID _rp[RPROP_NIC] = server.nics[0].resourceUUID _rp[RPROP_IP] = server.nics[0].ipAddresses[0].ipAddress _rp[RPROP_USER] = server.initialUser _rp[RPROP_PASS] = server.initialPassword return (_rp[RPROP_UUID], _rp[RPROP_IP], _rp[RPROP_USER], _rp[RPROP_PASS]) # Image image = get_resource(fco_api, _np[PROP_IMAGE], RT.IMAGE) image_uuid = image.resourceUUID # VDC/Cluster if _np[PROP_VDC]: vdc = get_resource(fco_api, _np[PROP_VDC], RT.VDC) vdc_uuid = vdc.resourceUUID cluster_uuid = vdc.clusterUUID else: vdc_uuid = image.vdcUUID cluster_uuid = image.clusterUUID # Boot disk if _np[PROP_DISK]: boot_disk_po_id = _np[PROP_DISK] else: boot_disk_po_id = "{} GB Storage Disk".format(image.size) boot_disk_po_uuid = get_resource(fco_api, boot_disk_po_id, RT.PRODUCTOFFER).resourceUUID # Network if _np[PROP_NET]: network = get_resource(fco_api, _np[PROP_NET], RT.NETWORK) else: cond = ( (cobjects.Network.vdcUUID == vdc_uuid) & (cobjects.Network.networkType == enums.NetworkType.IP) & (cobjects.Network.resourceState == enums.ResourceState.ACTIVE) ) try: network = list_resource(fco_api, cond, resource_type=RT.NETWORK)[0] except KeyError: raise Exception("No matching network found") network_uuid = network.resourceUUID network_type = network.networkType # Server product offer server_po = get_resource(fco_api, _np[PROP_SERVER_PO], RT.PRODUCTOFFER) server_po_uuid = server_po.resourceUUID cpu_count = _np[PROP_CPU_COUNT] ram_amount = _np[PROP_RAM_AMOUNT] # Manager key if _np[PROP_AGENT_KEY]: ctx.logger.info("Agent key: %s", _np[PROP_AGENT_KEY]) try: agent_key = get_resource(fco_api, _np[PROP_AGENT_KEY], RT.SSHKEY) agent_key_uuid = agent_key.resourceUUID except (ConflictingResourceError, NoResourceError): agent_key_uuid = None else: agent_key_uuid = None # Log configuration ctx.logger.info( "Configuration: \n" "image_uuid: %s\n" "cluster_uuid: %s\n" "vdc_uuid: %s\n" "network_uuid: %s\n" "server_po_uuid: %s\n" "boot_disk_po_uuid: %s\n" "manager_key_uuid: %s", image_uuid, cluster_uuid, vdc_uuid, network_uuid, server_po_uuid, boot_disk_po_uuid, agent_key_uuid, ) # Create server server_name = "{}{}_{}".format(ctx.bootstrap_context.resources_prefix, ctx.deployment.id, ctx.instance.id) try: server_uuid = _rp[RPROP_UUID] except KeyError: if agent_key_uuid: keys = [agent_key_uuid] else: keys = [] server_uuid = create_server( fco_api, server_po_uuid, image_uuid, cluster_uuid, vdc_uuid, cpu_count, ram_amount, boot_disk_po_uuid, keys, server_name, ) _rp[RPROP_UUID] = server_uuid ctx.logger.info("server_uuid: %s", server_uuid) # Wait for server to be active if not wait_for_state(fco_api, server_uuid, enums.ResourceState.ACTIVE, RT.SERVER): raise Exception("Server failed to prepare in time!") ctx.logger.info("Server ACTIVE") # Create NIC try: nic_uuid = _rp[RPROP_NIC] except KeyError: nic_uuid = create_nic(fco_api, cluster_uuid, network_type, network_uuid, vdc_uuid, server_name + " NIC") if not wait_for_state(fco_api, nic_uuid, enums.ResourceState.ACTIVE, RT.NIC): raise Exception("NIC failed to create in time!") _rp[RPROP_NIC] = nic_uuid ctx.logger.info("nic_uuid: %s", nic_uuid) server = get_resource(fco_api, server_uuid, RT.SERVER) # Attach NIC if nic_uuid not in [nic.resourceUUID for nic in server.nics]: job_uuid = attach_nic(fco_api, server_uuid, nic_uuid, 1).resourceUUID cond = cobjects.Job.status == enums.JobStatus.SUCCESSFUL if not wait_for_cond(fco_api, job_uuid, cond, RT.JOB): raise Exception("Attaching NIC failed to complete in time!") ctx.logger.info("NICs attached") else: ctx.logger.info("NICs already attached") nic = get_resource(fco_api, nic_uuid, RT.NIC) server_ip = nic.ipAddresses[0].ipAddress username = server.initialUser password = server.initialPassword # FIXME: Firewall template should not be baked in, but this should get us # through tests. firewall_template = "24a0f4d4-46dc-3561-b102-2c93b656c18a" # Apply firewall template job = apply_firewall_template(fco_api, firewall_template, server_ip) cond = cobjects.Job.status == enums.JobStatus.SUCCESSFUL if not wait_for_cond(fco_api, job.resourceUUID, cond, RT.JOB): raise Exception("Applying firewall template failed.") ctx.logger.info("Firewall template applied.") # Attach ssh key job1 = attach_ssh_key(fco_api, server_uuid, agent_key_uuid) cond1 = cobjects.Job.status == enums.JobStatus.SUCCESSFUL if not wait_for_cond(fco_api, job1.resourceUUID, cond1, RT.JOB): raise Exception("Adding SSH key failed.") ctx.logger.info("SSH key {} attached.".format(agent_key_uuid)) _rp[RPROP_UUID] = server_uuid _rp[RPROP_IP] = server_ip _rp[RPROP_USER] = username _rp[RPROP_PASS] = password ctx.logger.info("Server IP: " + server_ip) ctx.logger.info("Server User: "******"Server Password: " + password) return server_uuid, server_ip, username, password