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
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)
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
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
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
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
def delete(machine_id, host=None): validate.machine_id(machine_id) logging.info('Delete request for: {}'.format(machine_id)) raise NotImplementedError('Not implemented')
def bootorder(machine_id, bootorder, host=None): validate.machine_id(machine_id) return vmmanagement_client.bootorder(hostname=LOCALHOST, machine_id=machine_id, bootorder=bootorder)
def stop(machine_id, host=None): """ Immediately kills the VM. """ validate.machine_id(machine_id) return vmmanagement_client.stop(LOCALHOST, machine_id)
def start(machine_id, host=None): """ Boots the VM. """ validate.machine_id(machine_id) return vmmanagement_client.start(LOCALHOST, machine_id)
def info(machine_id, host=None): """ Info on the VM """ validate.machine_id(machine_id) return vmmanagement_client.info(LOCALHOST, machine_id)