def _create_machine_gce(conn, key_name, private_key, public_key, machine_name, image, size, location, cloud_init): """Create a machine in GCE. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') metadata = { # 'startup-script': script, 'sshKeys': 'user:%s' % key} # metadata for ssh user, ssh key and script to deploy if cloud_init: metadata['startup-script'] = cloud_init try: node = conn.create_node( name=machine_name, image=image, size=size, location=location, ex_metadata=metadata ) except Exception as e: raise MachineCreationError( "Google Compute Engine, got exception %s" % e, e) return node
def _create_machine_linode(conn, key_name, private_key, public_key, machine_name, image, size, location): """Create a machine in Linode. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ auth = NodeAuthSSHKey(public_key) with get_temp_file(private_key) as tmp_key_path: try: node = conn.create_node( name=machine_name, image=image, size=size, location=location, auth=auth, ssh_key=tmp_key_path, ex_private=True ) except Exception as e: raise MachineCreationError("Linode, got exception %s" % e, e) return node
def _create_machine_docker(conn, machine_name, image, script=None, public_key=None, docker_env={}, docker_command=None, tty_attach=True, docker_port_bindings={}, docker_exposed_ports={}): """Create a machine in docker. """ try: if public_key: environment = ['PUBLIC_KEY=%s' % public_key.strip()] else: environment = [] if docker_env: # docker_env is a dict, and we must convert it ot be in the form: # [ "key=value", "key=value"...] docker_environment = ["%s=%s" % (key, value) for key, value in docker_env.iteritems()] environment += docker_environment node = conn.create_node( name=machine_name, image=image, command=docker_command, environment=environment, tty=tty_attach, ports=docker_exposed_ports, port_bindings=docker_port_bindings, ) except Exception as e: raise MachineCreationError("Docker, got exception %s" % e, e) return node
def _create_machine_softlayer(conn, key_name, private_key, public_key, machine_name, image, size, location, bare_metal, cloud_init, hourly, softlayer_backend_vlan_id): """Create a machine in Softlayer. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = str(public_key).replace('\n', '') try: server_key = '' keys = conn.list_key_pairs() for k in keys: if key == k.key: server_key = k.id break if not server_key: server_key = conn.create_key_pair(machine_name, key) server_key = server_key.id except: server_key = conn.create_key_pair( 'mistio' + str(random.randint(1, 100000)), key ) server_key = server_key.id if '.' in machine_name: domain = '.'.join(machine_name.split('.')[1:]) name = machine_name.split('.')[0] else: domain = None name = machine_name # FIXME: SoftLayer allows only bash/script, no actual cloud-init # Also need to upload this on a public https url... if cloud_init: postInstallScriptUri = '' else: postInstallScriptUri = None try: node = conn.create_node( name=name, ex_domain=domain, image=image, size=size, location=location, sshKeys=server_key, bare_metal=bare_metal, postInstallScriptUri=postInstallScriptUri, ex_hourly=hourly, ex_backend_vlan=softlayer_backend_vlan_id ) except Exception as e: raise MachineCreationError("Softlayer, got exception %s" % e, e) return node
def _create_machine_azure(conn, key_name, private_key, public_key, machine_name, image, size, location, cloud_init, cloud_service_name, azure_port_bindings): """Create a machine Azure. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ public_key.replace('\n', '') port_bindings = [] if azure_port_bindings and type(azure_port_bindings) in [str, unicode]: # we receive something like: http tcp 80:80, smtp tcp 25:25, # https tcp 443:443 # and transform it to [{'name':'http', 'protocol': 'tcp', # 'local_port': 80, 'port': 80}, # {'name':'smtp', 'protocol': 'tcp', 'local_port': 25, 'port': 25}] for port_binding in azure_port_bindings.split(','): try: port_dict = port_binding.split() port_name = port_dict[0] protocol = port_dict[1] ports = port_dict[2] local_port = ports.split(':')[0] port = ports.split(':')[1] binding = {'name': port_name, 'protocol': protocol, 'local_port': local_port, 'port': port} port_bindings.append(binding) except: pass try: node = conn.create_node( name=machine_name, size=size, image=image, location=location, ex_cloud_service_name=cloud_service_name, endpoint_ports=port_bindings, custom_data=base64.b64encode(cloud_init) ) except Exception as e: try: # try to get the message only out of the XML response msg = re.search(r"(<Message>)(.*?)(</Message>)", e.value) if not msg: msg = re.search(r"(Message: ')(.*?)(', Body)", e.value) if msg: msg = msg.group(2) except: msg = e raise MachineCreationError('Azure, got exception %s' % msg) return node
def _create_machine_openstack(conn, private_key, public_key, machine_name, image, size, location, networks, user_data): """Create a machine in Openstack. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = str(public_key).replace('\n', '') try: server_key = '' keys = conn.ex_list_keypairs() for k in keys: if key == k.public_key: server_key = k.name break if not server_key: server_key = conn.ex_import_keypair_from_string(name=machine_name, key_material=key) server_key = server_key.name except: server_key = conn.ex_import_keypair_from_string( name='mistio' + str(random.randint(1, 100000)), key_material=key) server_key = server_key.name # select the right OpenStack network object available_networks = conn.ex_list_networks() try: chosen_networks = [] for net in available_networks: if net.id in networks: chosen_networks.append(net) except: chosen_networks = [] with get_temp_file(private_key) as tmp_key_path: try: node = conn.create_node( name=machine_name, image=image, size=size, location=location, ssh_key=tmp_key_path, ssh_alternate_usernames=['ec2-user', 'ubuntu'], max_tries=1, ex_keyname=server_key, networks=chosen_networks, ex_userdata=user_data) except Exception as e: raise MachineCreationError("OpenStack, got exception %s" % e, e) return node
def _create_machine_packet(conn, public_key, machine_name, image, size, location, cloud_init, project_id=None): """Create a machine in Packet.net. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') try: conn.create_key_pair('mistio', key) except: # key exists and will be deployed pass # if project_id is not specified, use the project for which the driver # has been initiated. If driver hasn't been initiated with a project, # then use the first one from the projects ex_project_id = None if not project_id: if conn.project_id: ex_project_id = conn.project_id else: try: ex_project_id = conn.projects[0].id except IndexError: raise BadRequestError( "You don't have any projects on packet.net" ) else: for project_obj in conn.projects: if project_id in [project_obj.name, project_obj.id]: ex_project_id = project_obj.id break if not ex_project_id: raise BadRequestError("Project id is invalid") try: node = conn.create_node( name=machine_name, size=size, image=image, location=location, ex_project_id=ex_project_id, cloud_init=cloud_init ) except Exception as e: raise MachineCreationError("Packet.net, got exception %s" % e, e) return node
def _create_machine_ec2(conn, key_name, private_key, public_key, machine_name, image, size, location, user_data): """Create a machine in Amazon EC2. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ with get_temp_file(public_key) as tmp_key_path: try: # create keypair with key name and pub key conn.ex_import_keypair(name=key_name, keyfile=tmp_key_path) except: # get existing key with that pub key try: keypair = conn.ex_find_or_import_keypair_by_key_material( pubkey=public_key ) key_name = keypair['keyName'] except Exception as exc: raise CloudUnavailableError("Failed to import key") # create security group name = config.EC2_SECURITYGROUP.get('name', '') description = config.EC2_SECURITYGROUP.get('description', '') try: log.info("Attempting to create security group") conn.ex_create_security_group(name=name, description=description) conn.ex_authorize_security_group_permissive(name=name) except Exception as exc: if 'Duplicate' in exc.message: log.info('Security group already exists, not doing anything.') else: raise InternalServerError("Couldn't create security group", exc) try: node = conn.create_node( name=machine_name, image=image, size=size, location=location, max_tries=1, ex_keyname=key_name, ex_securitygroup=config.EC2_SECURITYGROUP['name'], ex_userdata=user_data ) except Exception as e: raise MachineCreationError("EC2, got exception %s" % e, e) return node
def _create_machine_vcloud(conn, machine_name, image, size, public_key, networks): """Create a machine vCloud. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') # we have the option to pass a guest customisation # script as ex_vm_script. We'll pass # the ssh key there deploy_script = NamedTemporaryFile(delete=False) deploy_script.write( 'mkdir -p ~/.ssh && echo "%s" >> ~/.ssh/authorized_keys ' '&& chmod -R 700 ~/.ssh/' % key) deploy_script.close() # select the right network object ex_network = None try: if networks: network = networks[0] available_networks = conn.ex_list_networks() available_networks_ids = [net.id for net in available_networks] if network in available_networks_ids: ex_network = network except: pass try: node = conn.create_node( name=machine_name, image=image, size=size, ex_vm_script=deploy_script.name, ex_vm_network=ex_network, ex_vm_fence='bridged', ex_vm_ipmode='DHCP' ) except Exception as e: raise MachineCreationError("vCloud, got exception %s" % e, e) return node
def _create_machine_onapp(conn, public_key, machine_name, image, size_ram, size_cpu, size_disk_primary, size_disk_swap, boot, build, cpu_priority, cpu_sockets, cpu_threads, port_speed, location, networks, hypervisor_group_id): """Create a machine in OnApp. """ if public_key: # get user_id, push ssh key. This will be deployed on the new server try: res = conn.ex_list_profile_info() user_id = res['id'] conn.create_key_pair(user_id, public_key) except: pass boot = 1 if boot else 0 build = 1 if build else 0 try: node = conn.create_node( machine_name, str(size_ram), str(size_cpu), cpu_priority, machine_name, image.id, str(size_disk_primary), str(size_disk_swap), ex_required_virtual_machine_build=build, ex_required_ip_address_assignment=1, ex_required_virtual_machine_startup=boot, ex_cpu_sockets=cpu_sockets, ex_cpu_threads=cpu_threads, ex_hypervisor_group_id=hypervisor_group_id, ex_primary_network_group_id=networks, rate_limit=port_speed ) except Exception as e: raise MachineCreationError("OnApp, got exception %s" % e, e) return node
def _create_machine_vultr(conn, public_key, machine_name, image, size, location, cloud_init): """Create a machine in Vultr. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') try: server_key = '' keys = conn.ex_list_ssh_keys() for k in keys: if key == k.ssh_key.replace('\n', ''): server_key = k break if not server_key: server_key = conn.ex_create_ssh_key(machine_name, key) except: server_key = conn.ex_create_ssh_key('mistio' + str( random.randint(1, 100000)), key) try: server_key = server_key.id except: pass try: node = conn.create_node( name=machine_name, size=size, image=image, location=location, ssh_key=[server_key], userdata=cloud_init ) except Exception as e: raise MachineCreationError("Vultr, got exception %s" % e, e) return node
def _create_machine_rackspace(conn, public_key, machine_name, image, size, location, user_data): """Create a machine in Rackspace. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = str(public_key).replace('\n', '') try: server_key = '' keys = conn.ex_list_keypairs() for k in keys: if key == k.public_key: server_key = k.name break if not server_key: server_key = conn.ex_import_keypair_from_string(name=machine_name, key_material=key) server_key = server_key.name except: try: server_key = conn.ex_import_keypair_from_string( name='mistio' + str(random.randint(1, 100000)), key_material=key) server_key = server_key.name except AttributeError: # RackspaceFirstGenNodeDriver based on OpenStack_1_0_NodeDriver # has no support for keys. So don't break here, since # create_node won't include it anyway server_key = None try: node = conn.create_node(name=machine_name, image=image, size=size, location=location, ex_keyname=server_key, ex_userdata=user_data) return node except Exception as e: raise MachineCreationError("Rackspace, got exception %r" % e, exc=e)
def _create_machine_libvirt(conn, machine_name, disk_size, ram, cpu, image, disk_path, networks, public_key, cloud_init): """Create a machine in Libvirt. """ try: node = conn.create_node( name=machine_name, disk_size=disk_size, ram=ram, cpu=cpu, image=image, disk_path=disk_path, networks=networks, public_key=public_key, cloud_init=cloud_init ) except Exception as e: raise MachineCreationError("KVM, got exception %s" % e, e) return node
def _create_machine_hostvirtual(conn, public_key, machine_name, image, size, location): """Create a machine in HostVirtual. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') auth = NodeAuthSSHKey(pubkey=key) try: node = conn.create_node( name=machine_name, image=image, size=size, auth=auth, location=location ) except Exception as e: raise MachineCreationError("HostVirtual, got exception %s" % e, e) return node
def add_machine(request): """ Tags: machines --- Add a machine to an OtherServer/Libvirt Cloud. READ permission required on cloud. EDIT permission required on cloud. READ permission required on key. --- cloud: in: path required: true type: string machine_hostname: type: string required: true operating_system: type: string machine_name: type: string machine_key: type: string machine_user: type: string machine_port: type: string remote_desktop_port: type: string monitoring: type: boolean images_location: type: string """ cloud_id = request.matchdict.get('cloud') auth_context = auth_context_from_request(request) try: cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None) except Cloud.DoesNotExist: raise NotFoundError('Cloud does not exist') if cloud.ctl.provider not in ['libvirt', 'bare_metal']: raise MistNotImplementedError() params = params_from_request(request) machine_hostname = params.get('machine_hostname') if not machine_hostname: raise RequiredParameterMissingError("machine_hostname") operating_system = params.get('operating_system', '') machine_name = params.get('machine_name', '') machine_key = params.get('machine_key', '') machine_user = params.get('machine_user', '') machine_port = params.get('machine_port', 22) remote_desktop_port = params.get('remote_desktop_port', '') images_location = params.get('images_location', '') monitoring = params.get('monitoring', False) job_id = params.get('job_id') if not job_id: job = 'add_machine' job_id = uuid.uuid4().hex else: job = None auth_context.check_perm("cloud", "read", cloud_id) auth_context.check_perm("cloud", "edit", cloud_id) if machine_key: auth_context.check_perm("key", "read", machine_key) log.info('Adding host machine %s on cloud %s' % (machine_name, cloud_id)) try: machine = cloud.ctl.add_machine(host=machine_hostname, ssh_user=machine_user, ssh_port=machine_port, ssh_key=machine_key, name=machine_name, os_type=operating_system, rdp_port=remote_desktop_port, images_location=images_location) except Exception as e: raise MachineCreationError("Adding host got exception %r" % e, exc=e) # Enable monitoring if monitoring: monitor = enable_monitoring( auth_context.owner, cloud.id, machine.machine_id, no_ssh=not (machine.os_type == 'unix' and KeyMachineAssociation.objects(machine=machine))) ret = { 'id': machine.id, 'name': machine.name, 'extra': {}, 'public_ips': machine.public_ips, 'private_ips': machine.private_ips, 'job_id': job_id, 'job': job } if monitoring: ret.update({'monitoring': monitor}) return ret
def _create_machine_digital_ocean(conn, key_name, private_key, public_key, machine_name, image, size, location, user_data): """Create a machine in Digital Ocean. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ key = public_key.replace('\n', '') # on API v1 list keys returns only ids, without actual public keys # So the check fails. If there's already a key with the same pub key, # create key call will fail! try: server_key = '' keys = conn.ex_list_ssh_keys() for k in keys: if key == k.pub_key: server_key = k break if not server_key: server_key = conn.ex_create_ssh_key(machine_name, key) except: try: server_key = conn.ex_create_ssh_key('mistio' + str( random.randint(1, 100000)), key) except: # on API v1 if we can't create that key, means that key is already # on our account. Since we don't know the id, we pass all the ids server_keys = [str(k.id) for k in keys] if not server_key: ex_ssh_key_ids = server_keys else: ex_ssh_key_ids = [str(server_key.id)] # check if location allows the private_networking setting private_networking = False try: locations = conn.list_locations() for loc in locations: if loc.id == location.id: if 'private_networking' in loc.extra: private_networking = True break except: # do not break if this fails for some reason pass with get_temp_file(private_key) as tmp_key_path: try: node = conn.create_node( name=machine_name, image=image, size=size, ex_ssh_key_ids=ex_ssh_key_ids, location=location, ssh_key=tmp_key_path, private_networking=private_networking, user_data=user_data ) except Exception as e: raise MachineCreationError( "Digital Ocean, got exception %s" % e, e ) return node
def add_machine(request): """ Tags: machines --- Add a machine to an OtherServer Cloud. This works for bare_metal clouds. --- cloud: in: path required: true type: string machine_ip: type: string required: true operating_system: type: string machine_name: type: string machine_key: type: string machine_user: type: string machine_port: type: string remote_desktop_port: type: string monitoring: type: boolean """ cloud_id = request.matchdict.get('cloud') params = params_from_request(request) machine_ip = params.get('machine_ip') if not machine_ip: raise RequiredParameterMissingError("machine_ip") operating_system = params.get('operating_system', '') machine_name = params.get('machine_name', '') machine_key = params.get('machine_key', '') machine_user = params.get('machine_user', '') machine_port = params.get('machine_port', '') remote_desktop_port = params.get('remote_desktop_port', '') monitoring = params.get('monitoring', '') job_id = params.get('job_id') if not job_id: job = 'add_machine' job_id = uuid.uuid4().hex else: job = None auth_context = auth_context_from_request(request) auth_context.check_perm("cloud", "read", cloud_id) if machine_key: auth_context.check_perm("key", "read", machine_key) try: Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None) except Cloud.DoesNotExist: raise NotFoundError('Cloud does not exist') log.info('Adding bare metal machine %s on cloud %s' % (machine_name, cloud_id)) cloud = Cloud.objects.get(owner=auth_context.owner, id=cloud_id, deleted=None) try: machine = cloud.ctl.add_machine(machine_name, host=machine_ip, ssh_user=machine_user, ssh_port=machine_port, ssh_key=machine_key, os_type=operating_system, rdp_port=remote_desktop_port, fail_on_error=True) except Exception as e: raise MachineCreationError("OtherServer, got exception %r" % e, exc=e) # Enable monitoring if monitoring: monitor = enable_monitoring( auth_context.owner, cloud.id, machine.machine_id, no_ssh=not (machine.os_type == 'unix' and KeyMachineAssociation.objects(machine=machine))) ret = { 'id': machine.id, 'name': machine.name, 'extra': {}, 'public_ips': machine.public_ips, 'private_ips': machine.private_ips, 'job_id': job_id, 'job': job } if monitoring: ret.update({'monitoring': monitor}) return ret
def _create_machine_nephoscale(conn, key_name, private_key, public_key, machine_name, image, size, location, ips): """Create a machine in Nephoscale. Here there is no checking done, all parameters are expected to be sanitized by create_machine. """ machine_name = machine_name[:64].replace(' ', '-') # name in NephoScale must start with a letter, can contain mixed # alpha-numeric characters, hyphen ('-') and underscore ('_') # characters, cannot exceed 64 characters, and can end with a # letter or a number." # Hostname must start with a letter, can contain mixed alpha-numeric # characters and the hyphen ('-') character, cannot exceed 15 characters, # and can end with a letter or a number. key = public_key.replace('\n', '') # NephoScale has 2 keys that need be specified, console and ssh key # get the id of the ssh key if it exists, otherwise add the key try: server_key = '' keys = conn.ex_list_keypairs(ssh=True, key_group=1) for k in keys: if key == k.public_key: server_key = k.id break if not server_key: server_key = conn.ex_create_keypair(machine_name, public_key=key) except: server_key = conn.ex_create_keypair( 'mistio' + str(random.randint(1, 100000)), public_key=key ) # mist.api does not support console key add through the wizzard. # Try to add one try: console_key = conn.ex_create_keypair( 'mistio' + str(random.randint(1, 100000)), key_group=4 ) except: console_keys = conn.ex_list_keypairs(key_group=4) if console_keys: console_key = console_keys[0].id if size.name and size.name.startswith('D'): baremetal = True else: baremetal = False with get_temp_file(private_key) as tmp_key_path: try: node = conn.create_node( name=machine_name, hostname=machine_name[:15], image=image, size=size, zone=location.id, server_key=server_key, console_key=console_key, ssh_key=tmp_key_path, baremetal=baremetal, ips=ips ) except Exception as e: raise MachineCreationError("Nephoscale, got exception %s" % e, e) return node