Example #1
0
def topup(machine_id,
          days,
          currency,
          host=None,
          settlement_token=None,
          refund_address=None,
          override_code=None,
          affiliate_amount=None,
          affiliate_token=None):
    """
    tops up an existing vm.
    """
    validate.machine_id(machine_id)
    validate.days(days)
    validate.currency(currency)
    validate.refund_address(refund_address)
    validate.affiliate_amount(affiliate_amount)

    topup_dict = virtual_machine_topup(machine_id=machine_id,
                                       days=days,
                                       currency=currency,
                                       refund_address=refund_address,
                                       settlement_token=settlement_token,
                                       override_code=override_code,
                                       affiliate_amount=affiliate_amount,
                                       affiliate_token=affiliate_token)
    topup_dict['machine_id'] = machine_id
    return topup_dict
Example #2
0
def ipxescript(machine_id, ipxescript, host=None):
    """
    Updates iPXE script for VM.
    """
    validate.machine_id(machine_id)
    return vmmanagement_client.ipxescript(LOCALHOST,
                                          machine_id,
                                          ipxescript=ipxescript)
Example #3
0
def exists(machine_id, host=None):
    """
    Checks if the VM exists.
    """
    output = {}
    validate.machine_id(machine_id)
    output['result'] = vmmanagement_client.exists(LOCALHOST, machine_id)
    return output
Example #4
0
def status(machine_id, host=None):
    """
    Checks if the VM is started or stopped.
    """
    output = {}
    validate.machine_id(machine_id)
    output['result'] = vmmanagement_client.status(LOCALHOST, machine_id)
    return output
def validate_options(options):
    for entry in options:
        if entry not in VALID_OPTIONS:
            raise ValueError('{} invalid option.'.format(entry))
    for entry in VALID_OPTIONS:
        if entry not in options:
            raise ValueError('{} missing option.'.format(entry))
    validate.machine_id(options['machine_id'])
    validate.expiration(options['expiration'])
    return True
def validate_options(options):
    for entry in options:
        if entry not in VALID_OPTIONS:
            raise ValueError('{} invalid option.'.format(entry))
    for entry in VALID_OPTIONS:
        if entry not in options:
            raise ValueError('{} missing option.'.format(entry))
    validate.machine_id(options['machine_id'])
    validate.memory(options['memory'])
    validate.disk(options['disk'])
    validate.cores(options['cores'])
    validate.qemuopts(options['qemuopts'])
    validate.hostaccess(options['hostaccess'])
    validate.managed(options['managed'])
    validate.expiration(options['expiration'])
    validate.ipv4(options['ipv4'])
    validate.ipv6(options['ipv6'])
    # Double check to be sure these are equivalent if nat or tor.
    validate.further_ipv4_ipv6(options['ipv4'], options['ipv6'])
    validate.bandwidth(options['bandwidth'])
    validate.organization(options['organization'])
    return True
def virtual_machine_create(machine_id,
                           days,
                           currency,
                           cores=1,
                           memory=1,
                           disk=10,
                           ipv4=False,
                           ipv6=False,
                           bandwidth=10,
                           refund_address=None,
                           organization=None,
                           override_code=None,
                           qemuopts=None,
                           managed=False,
                           hostaccess=False,
                           kvmpassthrough=False,
                           wholehost=False,
                           settlement_token=None,
                           affiliate_token=None,
                           affiliate_amount=None):
    config = get_and_validate_config()
    if not override(override_code):
        if config['draining'] is True:
            raise ValueError('Host is draining, unavailable for new builds')
    # Help prevent double buys, etc. We don't need this on topup.
    # We use os.access to facilitate working tests ran as a non-root user.
    if os.access(CREATION_DIRECTORY, os.R_OK):
        if len(os.listdir(CREATION_DIRECTORY)) != 0:
            logging.critical('VM creation already in progress???')
            raise Exception('VM creation already in progress, please retry.')
    return_data = {
        'latest_api_version': 2,
        'payment': {
            'address': None,
            'amount': 0
        },
        'refund_tx': None,
        'created': False,
        'paid': False,
        'warning': None,
        'expiration': 1,
        'txid': None
    }
    validate.machine_id(machine_id)
    validate.disk(disk)
    validate.cores(cores)
    validate.memory(memory)
    validate.qemuopts(qemuopts)
    validate.managed(managed)
    validate.hostaccess(hostaccess)
    validate.refund_address(refund_address)
    validate.currency(currency)
    validate.ipv4(ipv4)
    validate.ipv6(ipv6)
    validate.bandwidth(bandwidth)
    validate.organization(organization)
    validate.affiliate_amount(affiliate_amount)
    # settlement_token is validated in settlers.
    if virtual_machine_exists(machine_id):
        raise ValueError('machine_id is already in use.')

    if not override(override_code):
        if currency not in config['currencies']:
            # If we just send config['currencies'], we can expose settlement
            # business tokens.
            currencies = []
            for currency in config['currencies']:
                currencies.append(currency)
            msg = 'currency must be one of: {}'.format(currencies)
            raise ValueError(msg)
        if qemuopts is not None:
            message = 'qemuopts must be None unless override_code is set.'
            raise ValueError(message)
        if hostaccess is not False:
            message = 'hostaccess must be False unless override_code is set.'
            raise ValueError(message)
    else:
        return_data['paid'] = True

    if config['kvmpassthrough_whole_host_only'] is True:
        if kvmpassthrough is True:
            if wholehost is not True:
                message = 'kvmpassthrough requires wholehost.'
                raise ValueError(message)

    has_sufficient_resources(cores=cores, memory=memory, disk=disk)
    validate.days(days, zero_allowed=True)
    if days == 0:
        if not override(override_code):
            raise ValueError('days cannot be 0 without override_code.')

    # Currently has no effect over 28 days.
    max_days = config['max_days']
    if days > max_days:
        message = 'host does not allow more than {} days.'.format(max_days)
        raise ValueError(message)

    if bandwidth == 0:
        if ipv4 is not False:
            raise ValueError('bandwidth cannot be 0 without ipv4 set to False')
        if ipv6 is not False:
            raise ValueError('bandwidth cannot be 0 without ipv6 set to False')

    if ipv4 is False:
        if ipv6 is False:
            if bandwidth != 0:
                message = 'bandwidth must be 0 with ipv4 and ipv6 set to False'
                raise ValueError(message)

    if ipv4 is not False:
        if ipv4 not in config['ipv4']:
            raise ValueError('That ipv4 option is not supported.')

    if ipv6 is not False:
        if str(ipv6) not in config['ipv6']:
            raise ValueError('That ipv6 option is not supported.')

    validate.further_ipv4_ipv6(ipv4, ipv6)

    bandwidth_per_day, _ = bandwidth_calculator(bandwidth,
                                                override(override_code))

    if bandwidth_per_day != -1:
        granted_bandwidth = bandwidth_per_day * days
    else:
        granted_bandwidth = -1

    if return_data['paid'] is False:
        address = config['currencies'][currency]
        cents = cost_in_cents(days=days,
                              cores=cores,
                              memory=memory,
                              disk=disk,
                              ipv4=ipv4,
                              ipv6=ipv6,
                              bandwidth=bandwidth,
                              override=override(override_code))
        token = settlement_token
        business_token = config['settlers_business_token']
        pay = payment(machine_id,
                      currency,
                      cents,
                      address,
                      existing_txids=existing_txids(currency),
                      settlers_endpoint=config['settlers_endpoint'],
                      settlers_customer_token=token,
                      settlers_business_token=business_token,
                      monero_rpc=config['monero_rpc'],
                      affiliate_token=affiliate_token,
                      affiliate_amount=affiliate_amount)
        return_data['txid'] = pay.txid
        return_data['payment']['amount'] = pay.amount
        return_data['payment']['uri'] = pay.uri
        return_data['payment']['usd'] = pay.usd
        return_data['payment']['address'] = pay.address

        if return_data['txid'] is not None:
            return_data['paid'] = True

    expiration = days_to_expiration(days)
    creation_data = {
        'machine_id': machine_id,
        'memory': memory,
        'disk': disk,
        'cores': cores,
        'ipv4': ipv4,
        'ipv6': ipv6,
        'bandwidth': granted_bandwidth,
        'organization': organization,
        'qemuopts': qemuopts,
        'hostaccess': hostaccess,
        'managed': managed,
        'expiration': expiration,
        'currency': currency,
        'txid': [return_data['txid']]
    }
    return_data['expiration'] = expiration
    return_data['bandwidth'] = granted_bandwidth
    if return_data['paid'] is True:
        # Should we just merge this dict with return_data?
        created_dict = launch_vm_and_wait(creation_data)
        return_data['network_interfaces'] = created_dict['network_interfaces']
        return_data['sshhostname'] = created_dict['sshhostname']
        return_data['sshport'] = created_dict['sshport']
        # Only show slot if using override.
        if override(override_code):
            return_data['slot'] = created_dict['slot']
        return_data['created'] = True

    # created and paid should always be the same, True or False.
    return return_data
Example #8
0
def virtual_machine_topup(machine_id,
                          days,
                          currency,
                          refund_address=None,
                          override_code=None,
                          settlement_token=None,
                          affiliate_token=None,
                          affiliate_amount=None):
    config = get_and_validate_config()
    # We should have a draining for topups separately.
    # if config['draining'] is True:
    #     raise ValueError('Host is draining, unavailable for topups')
    if config['topup_enabled'] is False:
        raise ValueError('Host does not allow topups')

    return_data = {'latest_api_version': 2,
                   'payment': {'address': None, 'amount': 0},
                   'refund_tx': None,
                   'created': False,
                   'paid': False,
                   'warning': None,
                   'expiration': 1,
                   'txid': None}
    validate.machine_id(machine_id)
    validate.refund_address(refund_address)
    validate.currency(currency)
    validate.affiliate_amount(affiliate_amount)
    # settlement_token is validated in settlers.

    logging.info('topup request for {}'.format(machine_id))

    vm_data = hedron.virtual_machine_info(machine_id)
    if not override(override_code):
        if currency not in config['currencies']:
            msg = 'currency must be one of: {}'.format(config['currencies'])
            raise ValueError(msg)
    else:
        return_data['paid'] = True

    validate.days(days)

    if return_data['paid'] is False:
        address = config['currencies'][currency]
        # There is a bug with this, it uses the whole amount of bandwidth
        # over whatever timespan as the per-day calculation. So a 28 day server
        # at 32GiB per day will try to "pop up" at 28*32GiB per day and not
        # 32GiB per day.
        # bandwidth = vm_data['bandwidth']
        # Hack for now.
        bandwidth = 0
        cents = cost_in_cents(days=days,
                              cores=vm_data['cores'],
                              memory=vm_data['memory'],
                              disk=vm_data['disk'],
                              ipv4=vm_data['ipv4'],
                              ipv6=vm_data['ipv6'],
                              bandwidth=bandwidth)
        token = settlement_token
        business_token = config['settlers_business_token']
        pay = payment(machine_id,
                      currency,
                      cents,
                      address,
                      existing_txids=existing_txids(currency),
                      settlers_endpoint=config['settlers_endpoint'],
                      settlers_customer_token=token,
                      settlers_business_token=business_token,
                      monero_rpc=config['monero_rpc'],
                      affiliate_amount=affiliate_amount,
                      affiliate_token=affiliate_token)
        return_data['txid'] = pay.txid
        return_data['payment']['amount'] = pay.amount
        return_data['payment']['uri'] = pay.uri
        return_data['payment']['usd'] = pay.usd
        return_data['payment']['address'] = pay.address

        if return_data['txid'] is not None:
            return_data['paid'] = True

    expiration = days_to_expiration(days=days,
                                    current_expiration=vm_data['expiration'])
    topup_data = {'machine_id': machine_id,
                  'expiration': expiration,
                  'currency': currency,
                  'txid': return_data['txid']}
    return_data['expiration'] = expiration
    if return_data['paid'] is True:
        topup_vm_and_wait(topup_data)
        return_data['toppedup'] = True

    # toppedup and paid should always be the same, True or False.
    return return_data
Example #9
0
def launch(machine_id,
           currency,
           cores,
           memory,
           disk,
           ipv4,
           ipv6,
           bandwidth,
           ipxescript,
           region=None,
           operating_system=None,
           ssh_key=None,
           want_topup=False,
           host=None,
           organization=None,
           days=0,
           settlement_token=None,
           override_code=None,
           hostaccess=False,
           refund_address=None,
           qemuopts=None,
           managed=False,
           affiliate_amount=None,
           affiliate_token=None):
    """
    ssh_key and operating_system have no effect.
    """
    statsd.incr('vmmanagement_baremetal.launch')

    validate.ipv4(ipv4)
    validate.ipv6(ipv6)
    validate.bandwidth(bandwidth)
    validate.cores(cores)
    validate.disk(disk)
    validate.memory(memory)
    validate.organization(organization)
    validate.machine_id(machine_id)

    validate.ipxescript(ipxescript)
    validate.region(region)
    validate.affiliate_amount(affiliate_amount)

    validate.ssh_key(ssh_key)
    validate.operating_system(operating_system)

    validate_extra_ssh_and_os(ssh_key=ssh_key,
                              operating_system=operating_system)

    os_list = operating_systems()
    if operating_system is not None:
        if operating_system not in os_list:
            msg = 'operating_system must be one of {} on this host'
            msg = msg.format(os_list)
            raise ValueError(msg)

    if operating_system is None and ipxescript is None:
        msg = 'operating_system and ssh_key must be set, and/or ipxescript'
        raise ValueError(msg)

    if region is not None:
        raise ValueError('Only None region supported for this host.')

    def create_vm():
        create = vmmanagement_create.virtual_machine_create
        return create(machine_id=machine_id,
                      days=days,
                      memory=memory,
                      disk=disk,
                      cores=cores,
                      ipv4=ipv4,
                      ipv6=ipv6,
                      bandwidth=bandwidth,
                      currency=currency,
                      refund_address=refund_address,
                      override_code=override_code,
                      settlement_token=settlement_token,
                      qemuopts=qemuopts,
                      managed=managed,
                      organization=organization,
                      hostaccess=hostaccess,
                      affiliate_amount=affiliate_amount,
                      affiliate_token=affiliate_token)

    created_dict = create_vm()
    created_dict['cores'] = cores
    created_dict['memory'] = memory
    created_dict['disk'] = disk

    # paid and created should always be the same.
    if created_dict['paid'] is True:
        if vmmanagement_client.exists(LOCALHOST, machine_id) is not True:
            raise Exception('VM created but does not exist??')
        if ipxescript is None:
            ipxe_output = ipxe(operating_system=operating_system,
                               ssh_key=ssh_key)
            ipxescript = ipxe_output['script']
            created_dict['generated_ipxescript'] = ipxe_output['script']
            created_dict['root_password'] = ipxe_output['root_password']
        vmmanagement_client.ipxescript(LOCALHOST, machine_id, ipxescript)
        vmmanagement_client.start(LOCALHOST, machine_id)

    created_dict['host'] = host
    created_dict['machine_id'] = machine_id

    return created_dict
Example #10
0
def delete(machine_id, host=None):
    validate.machine_id(machine_id)
    logging.info('Delete request for: {}'.format(machine_id))
    raise NotImplementedError('Not implemented')
Example #11
0
def bootorder(machine_id, bootorder, host=None):
    validate.machine_id(machine_id)
    return vmmanagement_client.bootorder(hostname=LOCALHOST,
                                         machine_id=machine_id,
                                         bootorder=bootorder)
Example #12
0
def stop(machine_id, host=None):
    """
    Immediately kills the VM.
    """
    validate.machine_id(machine_id)
    return vmmanagement_client.stop(LOCALHOST, machine_id)
Example #13
0
def start(machine_id, host=None):
    """
    Boots the VM.
    """
    validate.machine_id(machine_id)
    return vmmanagement_client.start(LOCALHOST, machine_id)
Example #14
0
def info(machine_id, host=None):
    """
    Info on the VM
    """
    validate.machine_id(machine_id)
    return vmmanagement_client.info(LOCALHOST, machine_id)