diff --git a/SoftLayer/CLI/metadata.py b/SoftLayer/CLI/metadata.py index 1d25ee38b..3cc3e384d 100644 --- a/SoftLayer/CLI/metadata.py +++ b/SoftLayer/CLI/metadata.py @@ -36,8 +36,8 @@ \b Examples : %s -""" % ('*'+'\n*'.join(META_CHOICES), - 'slcli metadata '+'\nslcli metadata '.join(META_CHOICES)) +""" % ('*' + '\n*'.join(META_CHOICES), + 'slcli metadata ' + '\nslcli metadata '.join(META_CHOICES)) @click.command(help=HELP, diff --git a/SoftLayer/CLI/virt/capacity/create_guest.py b/SoftLayer/CLI/virt/capacity/create_guest.py index 854fe3f94..4b8a983a6 100644 --- a/SoftLayer/CLI/virt/capacity/create_guest.py +++ b/SoftLayer/CLI/virt/capacity/create_guest.py @@ -36,8 +36,7 @@ def cli(env, **args): """Allows for creating a virtual guest in a reserved capacity.""" create_args = _parse_create_args(env.client, args) - if args.get('ipv6'): - create_args['ipv6'] = True + create_args['primary_disk'] = args.get('primary_disk') manager = CapacityManager(env.client) capacity_id = args.get('capacity_id') diff --git a/SoftLayer/CLI/virt/create.py b/SoftLayer/CLI/virt/create.py index 79af92585..3ee44b3a0 100644 --- a/SoftLayer/CLI/virt/create.py +++ b/SoftLayer/CLI/virt/create.py @@ -73,15 +73,25 @@ def _parse_create_args(client, args): """ data = { "hourly": args.get('billing', 'hourly') == 'hourly', - "domain": args['domain'], - "hostname": args['hostname'], - "private": args.get('private', None), - "dedicated": args.get('dedicated', None), - "disks": args['disk'], "cpus": args.get('cpu', None), + "ipv6": args.get('ipv6', None), + "disks": args.get('disk', None), + "os_code": args.get('os', None), "memory": args.get('memory', None), "flavor": args.get('flavor', None), - "boot_mode": args.get('boot_mode', None) + "domain": args.get('domain', None), + "host_id": args.get('host_id', None), + "private": args.get('private', None), + "hostname": args.get('hostname', None), + "nic_speed": args.get('network', None), + "boot_mode": args.get('boot_mode', None), + "dedicated": args.get('dedicated', None), + "post_uri": args.get('postinstall', None), + "datacenter": args.get('datacenter', None), + "public_vlan": args.get('vlan_public', None), + "private_vlan": args.get('vlan_private', None), + "public_subnet": args.get('subnet_public', None), + "private_subnet": args.get('subnet_private', None), } # The primary disk is included in the flavor and the local_disk flag is not needed @@ -91,33 +101,20 @@ def _parse_create_args(client, args): else: data['local_disk'] = not args.get('san') - if args.get('os'): - data['os_code'] = args['os'] - if args.get('image'): if args.get('image').isdigit(): image_mgr = SoftLayer.ImageManager(client) - image_details = image_mgr.get_image(args.get('image'), - mask="id,globalIdentifier") + image_details = image_mgr.get_image(args.get('image'), mask="id,globalIdentifier") data['image_id'] = image_details['globalIdentifier'] else: data['image_id'] = args['image'] - if args.get('datacenter'): - data['datacenter'] = args['datacenter'] - - if args.get('network'): - data['nic_speed'] = args.get('network') - if args.get('userdata'): data['userdata'] = args['userdata'] elif args.get('userfile'): with open(args['userfile'], 'r') as userfile: data['userdata'] = userfile.read() - if args.get('postinstall'): - data['post_uri'] = args.get('postinstall') - # Get the SSH keys if args.get('key'): keys = [] @@ -127,16 +124,6 @@ def _parse_create_args(client, args): keys.append(key_id) data['ssh_keys'] = keys - if args.get('vlan_public'): - data['public_vlan'] = args['vlan_public'] - - if args.get('vlan_private'): - data['private_vlan'] = args['vlan_private'] - - data['public_subnet'] = args.get('subnet_public', None) - - data['private_subnet'] = args.get('subnet_private', None) - if args.get('public_security_group'): pub_groups = args.get('public_security_group') data['public_security_groups'] = [group for group in pub_groups] @@ -145,7 +132,7 @@ def _parse_create_args(client, args): priv_groups = args.get('private_security_group') data['private_security_groups'] = [group for group in priv_groups] - if args.get('tag'): + if args.get('tag', False): data['tags'] = ','.join(args['tag']) if args.get('host_id'): @@ -155,200 +142,127 @@ def _parse_create_args(client, args): @click.command(epilog="See 'slcli vs create-options' for valid options") -@click.option('--hostname', '-H', - help="Host portion of the FQDN", - required=True, - prompt=True) -@click.option('--domain', '-D', - help="Domain portion of the FQDN", - required=True, - prompt=True) -@click.option('--cpu', '-c', - help="Number of CPU cores (not available with flavors)", - type=click.INT) -@click.option('--memory', '-m', - help="Memory in mebibytes (not available with flavors)", - type=virt.MEM_TYPE) -@click.option('--flavor', '-f', - help="Public Virtual Server flavor key name", - type=click.STRING) -@click.option('--datacenter', '-d', - help="Datacenter shortname", - required=True, - prompt=True) -@click.option('--os', '-o', - help="OS install code. Tip: you can specify _LATEST") -@click.option('--image', - help="Image ID. See: 'slcli image list' for reference") -@click.option('--boot-mode', - help="Specify the mode to boot the OS in. Supported modes are HVM and PV.", - type=click.STRING) -@click.option('--billing', - type=click.Choice(['hourly', 'monthly']), - default='hourly', - show_default=True, +@click.option('--hostname', '-H', required=True, prompt=True, help="Host portion of the FQDN") +@click.option('--domain', '-D', required=True, prompt=True, help="Domain portion of the FQDN") +@click.option('--cpu', '-c', type=click.INT, help="Number of CPU cores (not available with flavors)") +@click.option('--memory', '-m', type=virt.MEM_TYPE, help="Memory in mebibytes (not available with flavors)") +@click.option('--flavor', '-f', type=click.STRING, help="Public Virtual Server flavor key name") +@click.option('--datacenter', '-d', required=True, prompt=True, help="Datacenter shortname") +@click.option('--os', '-o', help="OS install code. Tip: you can specify _LATEST") +@click.option('--image', help="Image ID. See: 'slcli image list' for reference") +@click.option('--boot-mode', type=click.STRING, + help="Specify the mode to boot the OS in. Supported modes are HVM and PV.") +@click.option('--billing', type=click.Choice(['hourly', 'monthly']), default='hourly', show_default=True, help="Billing rate") -@click.option('--dedicated/--public', - is_flag=True, - help="Create a Dedicated Virtual Server") -@click.option('--host-id', - type=click.INT, - help="Host Id to provision a Dedicated Host Virtual Server onto") -@click.option('--san', - is_flag=True, - help="Use SAN storage instead of local disk.") -@click.option('--test', - is_flag=True, - help="Do not actually create the virtual server") -@click.option('--export', - type=click.Path(writable=True, resolve_path=True), +@click.option('--dedicated/--public', is_flag=True, help="Create a Dedicated Virtual Server") +@click.option('--host-id', type=click.INT, help="Host Id to provision a Dedicated Host Virtual Server onto") +@click.option('--san', is_flag=True, help="Use SAN storage instead of local disk.") +@click.option('--test', is_flag=True, help="Do not actually create the virtual server") +@click.option('--export', type=click.Path(writable=True, resolve_path=True), help="Exports options to a template file") @click.option('--postinstall', '-i', help="Post-install script to download") -@helpers.multi_option('--key', '-k', - help="SSH keys to add to the root user") +@helpers.multi_option('--key', '-k', help="SSH keys to add to the root user") @helpers.multi_option('--disk', help="Disk sizes") -@click.option('--private', - is_flag=True, +@click.option('--private', is_flag=True, help="Forces the VS to only have access the private network") -@click.option('--like', - is_eager=True, - callback=_update_with_like_args, +@click.option('--like', is_eager=True, callback=_update_with_like_args, help="Use the configuration from an existing VS") @click.option('--network', '-n', help="Network port speed in Mbps") @helpers.multi_option('--tag', '-g', help="Tags to add to the instance") -@click.option('--template', '-t', - is_eager=True, - callback=template.TemplateCallback(list_args=['disk', - 'key', - 'tag']), +@click.option('--template', '-t', is_eager=True, + callback=template.TemplateCallback(list_args=['disk', 'key', 'tag']), help="A template file that defaults the command-line options", type=click.Path(exists=True, readable=True, resolve_path=True)) @click.option('--userdata', '-u', help="User defined metadata string") -@click.option('--userfile', '-F', - help="Read userdata from file", - type=click.Path(exists=True, readable=True, resolve_path=True)) -@click.option('--vlan-public', - help="The ID of the public VLAN on which you want the virtual " - "server placed", - type=click.INT) -@click.option('--vlan-private', - help="The ID of the private VLAN on which you want the virtual " - "server placed", - type=click.INT) -@click.option('--subnet-public', - help="The ID of the public SUBNET on which you want the virtual server placed", - type=click.INT) -@click.option('--subnet-private', - help="The ID of the private SUBNET on which you want the virtual server placed", - type=click.INT) -@helpers.multi_option('--public-security-group', - '-S', - help=('Security group ID to associate with ' - 'the public interface')) -@helpers.multi_option('--private-security-group', - '-s', - help=('Security group ID to associate with ' - 'the private interface')) -@click.option('--wait', - type=click.INT, - help="Wait until VS is finished provisioning for up to X " - "seconds before returning") +@click.option('--userfile', '-F', type=click.Path(exists=True, readable=True, resolve_path=True), + help="Read userdata from file") +@click.option('--vlan-public', type=click.INT, + help="The ID of the public VLAN on which you want the virtual server placed") +@click.option('--vlan-private', type=click.INT, + help="The ID of the private VLAN on which you want the virtual server placed") +@click.option('--subnet-public', type=click.INT, + help="The ID of the public SUBNET on which you want the virtual server placed") +@click.option('--subnet-private', type=click.INT, + help="The ID of the private SUBNET on which you want the virtual server placed") +@helpers.multi_option('--public-security-group', '-S', + help=('Security group ID to associate with the public interface')) +@helpers.multi_option('--private-security-group', '-s', + help=('Security group ID to associate with the private interface')) +@click.option('--wait', type=click.INT, + help="Wait until VS is finished provisioning for up to X seconds before returning") +@click.option('--ipv6', is_flag=True, help="Adds an IPv6 address to this guest") @environment.pass_env def cli(env, **args): """Order/create virtual servers.""" + vsi = SoftLayer.VSManager(env.client) _validate_args(env, args) - - # Do not create a virtual server with test or export - do_create = not (args['export'] or args['test']) - - table = formatting.Table(['Item', 'cost']) - table.align['Item'] = 'r' - table.align['cost'] = 'r' - data = _parse_create_args(env.client, args) - - output = [] - if args.get('test'): - result = vsi.verify_create_instance(**data) - - if result['presetId']: - ordering_mgr = SoftLayer.OrderingManager(env.client) - item_prices = ordering_mgr.get_item_prices(result['packageId']) - preset_prices = ordering_mgr.get_preset_prices(result['presetId']) - search_keys = ["guest_core", "ram"] - for price in preset_prices['prices']: - if price['item']['itemCategory']['categoryCode'] in search_keys: - item_key_name = price['item']['keyName'] - _add_item_prices(item_key_name, item_prices, result) - - table = _build_receipt_table(result['prices'], args.get('billing')) - - output.append(table) - output.append(formatting.FormattedItem( - None, - ' -- ! Prices reflected here are retail and do not ' - 'take account level discounts and are not guaranteed.')) - - if args['export']: - export_file = args.pop('export') - template.export_to_template(export_file, args, - exclude=['wait', 'test']) - env.fout('Successfully exported options to a template file.') + create_args = _parse_create_args(env.client, args) + test = args.get('test', False) + do_create = not (args.get('export') or test) if do_create: if not (env.skip_confirmations or formatting.confirm( "This action will incur charges on your account. Continue?")): raise exceptions.CLIAbort('Aborting virtual server order.') - result = vsi.create_instance(**data) + if args.get('export'): + export_file = args.pop('export') + template.export_to_template(export_file, args, exclude=['wait', 'test']) + env.fout('Successfully exported options to a template file.') + + else: + result = vsi.order_guest(create_args, test) + output = _build_receipt_table(result, args.get('billing'), test) - table = formatting.KeyValueTable(['name', 'value']) - table.align['name'] = 'r' - table.align['value'] = 'l' - table.add_row(['id', result['id']]) - table.add_row(['created', result['createDate']]) - table.add_row(['guid', result['globalIdentifier']]) - output.append(table) + if do_create: + env.fout(_build_guest_table(result)) + env.fout(output) if args.get('wait'): - ready = vsi.wait_for_ready(result['id'], args.get('wait') or 1) - table.add_row(['ready', ready]) + virtual_guests = utils.lookup(result, 'orderDetails', 'virtualGuests') + guest_id = virtual_guests[0]['id'] + click.secho("Waiting for %s to finish provisioning..." % guest_id, fg='green') + ready = vsi.wait_for_ready(guest_id, args.get('wait') or 1) if ready is False: env.out(env.fmt(output)) raise exceptions.CLIHalt(code=1) - env.fout(output) - - -def _add_item_prices(item_key_name, item_prices, result): - """Add the flavor item prices to the rest o the items prices""" - for item in item_prices: - if item_key_name == item['item']['keyName']: - if 'pricingLocationGroup' in item: - for location in item['pricingLocationGroup']['locations']: - if result['location'] == str(location['id']): - result['prices'].append(item) - -def _build_receipt_table(prices, billing="hourly"): +def _build_receipt_table(result, billing="hourly", test=False): """Retrieve the total recurring fee of the items prices""" - total = 0.000 - table = formatting.Table(['Cost', 'Item']) + title = "OrderId: %s" % (result.get('orderId', 'No order placed')) + table = formatting.Table(['Cost', 'Description'], title=title) table.align['Cost'] = 'r' - table.align['Item'] = 'l' - for price in prices: + table.align['Description'] = 'l' + total = 0.000 + if test: + prices = result['prices'] + else: + prices = result['orderDetails']['prices'] + + for item in prices: rate = 0.000 if billing == "hourly": - rate += float(price.get('hourlyRecurringFee', 0.000)) + rate += float(item.get('hourlyRecurringFee', 0.000)) else: - rate += float(price.get('recurringFee', 0.000)) + rate += float(item.get('recurringFee', 0.000)) total += rate - - table.add_row(["%.3f" % rate, price['item']['description']]) + table.add_row([rate, item['item']['description']]) table.add_row(["%.3f" % total, "Total %s cost" % billing]) return table +def _build_guest_table(result): + table = formatting.Table(['ID', 'FQDN', 'guid', 'Order Date']) + table.align['name'] = 'r' + table.align['value'] = 'l' + virtual_guests = utils.lookup(result, 'orderDetails', 'virtualGuests') + for guest in virtual_guests: + table.add_row([guest['id'], guest['fullyQualifiedDomainName'], guest['globalIdentifier'], result['orderDate']]) + return table + + def _validate_args(env, args): """Raises an ArgumentError if the given arguments are not valid.""" @@ -378,8 +292,6 @@ def _validate_args(env, args): '[-o | --os] not allowed with [--image]') while not any([args['os'], args['image']]): - args['os'] = env.input("Operating System Code", - default="", - show_default=False) + args['os'] = env.input("Operating System Code", default="", show_default=False) if not args['os']: args['image'] = env.input("Image", default="", show_default=False) diff --git a/SoftLayer/CLI/virt/upgrade.py b/SoftLayer/CLI/virt/upgrade.py index 039e7cbfc..463fc077e 100644 --- a/SoftLayer/CLI/virt/upgrade.py +++ b/SoftLayer/CLI/virt/upgrade.py @@ -16,13 +16,12 @@ completed. However for Network, no reboot is required.""") @click.argument('identifier') @click.option('--cpu', type=click.INT, help="Number of CPU cores") -@click.option('--private', - is_flag=True, +@click.option('--private', is_flag=True, help="CPU core will be on a dedicated host server.") @click.option('--memory', type=virt.MEM_TYPE, help="Memory in megabytes") @click.option('--network', type=click.INT, help="Network port speed in Mbps") -@click.option('--flavor', type=click.STRING, help="Flavor keyName\n" - "Do not use --memory, --cpu or --private, if you are using flavors") +@click.option('--flavor', type=click.STRING, + help="Flavor keyName\nDo not use --memory, --cpu or --private, if you are using flavors") @environment.pass_env def cli(env, identifier, cpu, private, memory, network, flavor): """Upgrade a virtual server.""" @@ -30,26 +29,17 @@ def cli(env, identifier, cpu, private, memory, network, flavor): vsi = SoftLayer.VSManager(env.client) if not any([cpu, memory, network, flavor]): - raise exceptions.ArgumentError( - "Must provide [--cpu], [--memory], [--network], or [--flavor] to upgrade") + raise exceptions.ArgumentError("Must provide [--cpu], [--memory], [--network], or [--flavor] to upgrade") if private and not cpu: - raise exceptions.ArgumentError( - "Must specify [--cpu] when using [--private]") + raise exceptions.ArgumentError("Must specify [--cpu] when using [--private]") vs_id = helpers.resolve_id(vsi.resolve_ids, identifier, 'VS') - if not (env.skip_confirmations or formatting.confirm( - "This action will incur charges on your account. " - "Continue?")): + if not (env.skip_confirmations or formatting.confirm("This action will incur charges on your account. Continue?")): raise exceptions.CLIAbort('Aborted') if memory: memory = int(memory / 1024) - if not vsi.upgrade(vs_id, - cpus=cpu, - memory=memory, - nic_speed=network, - public=not private, - preset=flavor): + if not vsi.upgrade(vs_id, cpus=cpu, memory=memory, nic_speed=network, public=not private, preset=flavor): raise exceptions.CLIAbort('VS Upgrade Failed') diff --git a/SoftLayer/fixtures/SoftLayer_Product_Order.py b/SoftLayer/fixtures/SoftLayer_Product_Order.py index 5be637c9b..3774f63a8 100644 --- a/SoftLayer/fixtures/SoftLayer_Product_Order.py +++ b/SoftLayer/fixtures/SoftLayer_Product_Order.py @@ -13,7 +13,29 @@ 'setupFee': '1', 'item': {'id': 1, 'description': 'this is a thing'}, }]} -placeOrder = verifyOrder +placeOrder = { + 'orderId': 1234, + 'orderDate': '2013-08-01 15:23:45', + 'orderDetails': { + 'prices': [{ + 'id': 1, + 'laborFee': '2', + 'oneTimeFee': '2', + 'oneTimeFeeTax': '.1', + 'quantity': 1, + 'recurringFee': '2', + 'recurringFeeTax': '.1', + 'hourlyRecurringFee': '2', + 'setupFee': '1', + 'item': {'id': 1, 'description': 'this is a thing'}, + }], + 'virtualGuests': [{ + 'id': 1234567, + 'globalIdentifier': '1a2b3c-1701', + 'fullyQualifiedDomainName': 'test.guest.com' + }] + } +} # Reserved Capacity Stuff @@ -75,7 +97,9 @@ 'id': 1, 'description': 'B1.1x2 (1 Year ''Term)', 'keyName': 'B1_1X2_1_YEAR_TERM', - } + }, + 'hourlyRecurringFee': 1.0, + 'recurringFee': 2.0 } ] } diff --git a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py index 69a1b95e6..c01fd17a8 100644 --- a/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py +++ b/SoftLayer/fixtures/SoftLayer_Virtual_Guest.py @@ -533,7 +533,16 @@ setUserMetadata = ['meta'] reloadOperatingSystem = 'OK' setTags = True -createArchiveTransaction = {} +createArchiveTransaction = { + 'createDate': '2018-12-10T17:29:18-06:00', + 'elapsedSeconds': 0, + 'guestId': 12345678, + 'hardwareId': None, + 'id': 12345, + 'modifyDate': '2018-12-10T17:29:18-06:00', + 'statusChangeDate': '2018-12-10T17:29:18-06:00' +} + executeRescueLayer = True getUpgradeItemPrices = [ diff --git a/SoftLayer/managers/vs.py b/SoftLayer/managers/vs.py index dbbaa98c4..785ad3834 100644 --- a/SoftLayer/managers/vs.py +++ b/SoftLayer/managers/vs.py @@ -18,8 +18,7 @@ LOGGER = logging.getLogger(__name__) - -# pylint: disable=no-self-use +# pylint: disable=no-self-use,too-many-lines class VSManager(utils.IdentifierMixin, object): @@ -664,12 +663,10 @@ def change_port_speed(self, instance_id, public, speed): A port speed of 0 will disable the interface. """ if public: - return self.client.call('Virtual_Guest', - 'setPublicNetworkInterfaceSpeed', + return self.client.call('Virtual_Guest', 'setPublicNetworkInterfaceSpeed', speed, id=instance_id) else: - return self.client.call('Virtual_Guest', - 'setPrivateNetworkInterfaceSpeed', + return self.client.call('Virtual_Guest', 'setPrivateNetworkInterfaceSpeed', speed, id=instance_id) def _get_ids_from_hostname(self, hostname): @@ -784,10 +781,7 @@ def capture(self, instance_id, name, additional_disks=False, notes=None): continue # We never want swap devices - type_name = utils.lookup(block_device, - 'diskImage', - 'type', - 'keyName') + type_name = utils.lookup(block_device, 'diskImage', 'type', 'keyName') if type_name == 'SWAP': continue @@ -804,8 +798,7 @@ def capture(self, instance_id, name, additional_disks=False, notes=None): return self.guest.createArchiveTransaction( name, disks_to_capture, notes, id=instance_id) - def upgrade(self, instance_id, cpus=None, memory=None, - nic_speed=None, public=True, preset=None): + def upgrade(self, instance_id, cpus=None, memory=None, nic_speed=None, public=True, preset=None): """Upgrades a VS instance. Example:: @@ -832,17 +825,16 @@ def upgrade(self, instance_id, cpus=None, memory=None, data = {'nic_speed': nic_speed} if cpus is not None and preset is not None: - raise exceptions.SoftLayerError("Do not use cpu, private and memory if you are using flavors") + raise ValueError("Do not use cpu, private and memory if you are using flavors") data['cpus'] = cpus if memory is not None and preset is not None: - raise exceptions.SoftLayerError("Do not use memory, private or cpu if you are using flavors") + raise ValueError("Do not use memory, private or cpu if you are using flavors") data['memory'] = memory maintenance_window = datetime.datetime.now(utils.UTC()) order = { - 'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_' - 'Upgrade', + 'complexType': 'SoftLayer_Container_Product_Order_Virtual_Guest_Upgrade', 'properties': [{ 'name': 'MAINTENANCE_WINDOW', 'value': maintenance_window.strftime("%Y-%m-%d %H:%M:%S%z") @@ -874,6 +866,59 @@ def upgrade(self, instance_id, cpus=None, memory=None, return True return False + def order_guest(self, guest_object, test=False): + """Uses Product_Order::placeOrder to create a virtual guest. + + Useful when creating a virtual guest with options not supported by Virtual_Guest::createObject + specifically ipv6 support. + + :param dictionary guest_object: See SoftLayer.CLI.virt.create._parse_create_args + + Example:: + new_vsi = { + 'domain': u'test01.labs.sftlyr.ws', + 'hostname': u'minion05', + 'datacenter': u'hkg02', + 'flavor': 'BL1_1X2X100' + 'dedicated': False, + 'private': False, + 'os_code' : u'UBUNTU_LATEST', + 'hourly': True, + 'ssh_keys': [1234], + 'disks': ('100','25'), + 'local_disk': True, + 'tags': 'test, pleaseCancel', + 'public_security_groups': [12, 15], + 'ipv6': True + } + + vsi = mgr.order_guest(new_vsi) + # vsi will have the newly created vsi receipt. + # vsi['orderDetails']['virtualGuests'] will be an array of created Guests + print vsi + """ + tags = guest_object.pop('tags', None) + template = self.verify_create_instance(**guest_object) + + if guest_object.get('ipv6'): + ipv6_price = self.ordering_manager.get_price_id_list('PUBLIC_CLOUD_SERVER', ['1_IPV6_ADDRESS']) + template['prices'].append({'id': ipv6_price[0]}) + + # Notice this is `userdata` from the cli, but we send it in as `userData` + if guest_object.get('userdata'): + # SL_Virtual_Guest::generateOrderTemplate() doesn't respect userData, so we need to add it ourself + template['virtualGuests'][0]['userData'] = [{"value": guest_object.get('userdata')}] + + if test: + result = self.client.call('Product_Order', 'verifyOrder', template) + else: + result = self.client.call('Product_Order', 'placeOrder', template) + if tags is not None: + virtual_guests = utils.lookup(result, 'orderDetails', 'virtualGuests') + for guest in virtual_guests: + self.set_tags(tags, guest_id=guest['id']) + return result + def _get_package_items(self): """Following Method gets all the item ids related to VS. diff --git a/SoftLayer/utils.py b/SoftLayer/utils.py index 131c681f1..96efac342 100644 --- a/SoftLayer/utils.py +++ b/SoftLayer/utils.py @@ -121,8 +121,8 @@ def query_filter_date(start, end): return { 'operation': 'betweenDate', 'options': [ - {'name': 'startDate', 'value': [startdate+' 0:0:0']}, - {'name': 'endDate', 'value': [enddate+' 0:0:0']} + {'name': 'startDate', 'value': [startdate + ' 0:0:0']}, + {'name': 'endDate', 'value': [enddate + ' 0:0:0']} ] } diff --git a/tests/CLI/modules/subnet_tests.py b/tests/CLI/modules/subnet_tests.py index 72825e0f9..eaa0b1d99 100644 --- a/tests/CLI/modules/subnet_tests.py +++ b/tests/CLI/modules/subnet_tests.py @@ -37,5 +37,5 @@ def test_detail(self): json.loads(result.output)) def test_list(self): - result = self.run_command(['subnet', 'list']) + result = self.run_command(['subnet', 'list']) self.assert_no_fail(result) diff --git a/tests/CLI/modules/vs/__init__.py b/tests/CLI/modules/vs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/CLI/modules/vs_capacity_tests.py b/tests/CLI/modules/vs/vs_capacity_tests.py similarity index 98% rename from tests/CLI/modules/vs_capacity_tests.py rename to tests/CLI/modules/vs/vs_capacity_tests.py index 922bf2118..3dafee347 100644 --- a/tests/CLI/modules/vs_capacity_tests.py +++ b/tests/CLI/modules/vs/vs_capacity_tests.py @@ -1,5 +1,5 @@ """ - SoftLayer.tests.CLI.modules.vs_capacity_tests + SoftLayer.tests.CLI.modules.vs.vs_capacity_tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :license: MIT, see LICENSE for more details. diff --git a/tests/CLI/modules/vs/vs_create_tests.py b/tests/CLI/modules/vs/vs_create_tests.py new file mode 100644 index 000000000..61fe1cee5 --- /dev/null +++ b/tests/CLI/modules/vs/vs_create_tests.py @@ -0,0 +1,611 @@ +""" + SoftLayer.tests.CLI.modules.vs.vs_create_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. +""" +import mock +import sys +import tempfile + +from SoftLayer.fixtures import SoftLayer_Product_Package as SoftLayer_Product_Package +from SoftLayer import testing + + +class VirtCreateTests(testing.TestCase): + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05', + '--tag=dev', + '--tag=green']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + + args = ({'datacenter': {'name': 'dal05'}, + 'domain': 'example.com', + 'hourlyBillingFlag': True, + 'localDiskFlag': True, + 'maxMemory': 1024, + 'hostname': 'host', + 'startCpus': 2, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'networkComponents': [{'maxSpeed': '100'}], + 'supplementalCreateObjectOptions': {'bootMode': None}},) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_vlan_subnet(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--memory=1', + '--billing=hourly', + '--datacenter=dal05', + '--vlan-private=577940', + '--subnet-private=478700', + '--vlan-public=1639255', + '--subnet-public=297614', + '--tag=dev', + '--tag=green']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + args = ({ + 'startCpus': 2, + 'maxMemory': 1024, + 'hostname': 'host', + 'domain': 'example.com', + 'localDiskFlag': True, + 'hourlyBillingFlag': True, + 'supplementalCreateObjectOptions': {'bootMode': None}, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'datacenter': {'name': 'dal05'}, + 'primaryBackendNetworkComponent': { + 'networkVlan': { + 'id': 577940, + 'primarySubnet': {'id': 478700} + } + }, + 'primaryNetworkComponent': { + 'networkVlan': { + 'id': 1639255, + 'primarySubnet': {'id': 297614} + } + } + },) + + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_wait_ready(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + "provisionDate": "2018-06-10T12:00:00-05:00", + "id": 100 + } + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05', + '--wait=1']) + + self.assert_no_fail(result) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_wait_not_ready(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + "ready": False, + "guid": "1a2b3c-1701", + "id": 100, + "created": "2018-06-10 12:00:00" + } + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05', + '--wait=1']) + + self.assertEqual(result.exit_code, 1) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_integer_image_id(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--image=12345', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_integer_image_guid(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--image=aaaa1111bbbb2222', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + args = ({ + 'startCpus': 2, + 'maxMemory': 1024, + 'hostname': 'host', + 'domain': 'example.com', + 'localDiskFlag': True, + 'hourlyBillingFlag': True, + 'supplementalCreateObjectOptions': {'bootMode': None}, + 'blockDeviceTemplateGroup': {'globalIdentifier': 'aaaa1111bbbb2222'}, + 'datacenter': {'name': 'dal05'}, + 'networkComponents': [{'maxSpeed': '100'}] + },) + + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_flavor(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--network=100', + '--billing=hourly', + '--datacenter=dal05', + '--flavor=B1_1X2X25']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + args = ({'datacenter': {'name': 'dal05'}, + 'domain': 'example.com', + 'hourlyBillingFlag': True, + 'hostname': 'host', + 'startCpus': None, + 'maxMemory': None, + 'localDiskFlag': None, + 'supplementalCreateObjectOptions': { + 'bootMode': None, + 'flavorKeyName': 'B1_1X2X25'}, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'networkComponents': [{'maxSpeed': '100'}]},) + + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_flavor_and_memory(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--network=100', + '--datacenter=TEST00', + '--flavor=BL_1X2X25', + '--memory=2048MB']) + + self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_dedicated_and_flavor(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--network=100', + '--datacenter=TEST00', + '--dedicated', + '--flavor=BL_1X2X25']) + + self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_hostid_and_flavor(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--network=100', + '--datacenter=dal05', + '--host-id=100', + '--flavor=BL_1X2X25']) + + self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_flavor_and_cpu(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--network=100', + '--datacenter=TEST00', + '--flavor=BL_1X2X25', + '--cpu=2']) + + self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_host_id(self, confirm_mock): + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--cpu=2', + '--domain=example.com', + '--hostname=host', + '--os=UBUNTU_LATEST', + '--memory=1', + '--network=100', + '--billing=hourly', + '--datacenter=dal05', + '--dedicated', + '--host-id=123']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + args = ({ + 'startCpus': 2, + 'maxMemory': 1024, + 'hostname': 'host', + 'domain': 'example.com', + 'localDiskFlag': True, + 'hourlyBillingFlag': True, + 'supplementalCreateObjectOptions': { + 'bootMode': None + }, + 'dedicatedHost': { + 'id': 123 + }, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'datacenter': { + 'name': 'dal05' + }, + 'networkComponents': [ + { + 'maxSpeed': '100' + } + ] + },) + + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_like(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + 'hostname': 'vs-test-like', + 'domain': 'test.sftlyr.ws', + 'maxCpu': 2, + 'maxMemory': 1024, + 'datacenter': {'name': 'dal05'}, + 'networkComponents': [{'maxSpeed': 100}], + 'dedicatedAccountHostOnlyFlag': False, + 'privateNetworkOnlyFlag': False, + 'billingItem': {'orderItem': {'preset': {}}}, + 'operatingSystem': {'softwareLicense': { + 'softwareDescription': {'referenceCode': 'UBUNTU_LATEST'} + }}, + 'hourlyBillingFlag': False, + 'localDiskFlag': True, + 'userData': {} + } + + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--like=123', + '--san', + '--billing=hourly']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + + args = ({'datacenter': {'name': 'dal05'}, + 'domain': 'test.sftlyr.ws', + 'hourlyBillingFlag': True, + 'hostname': 'vs-test-like', + 'startCpus': 2, + 'maxMemory': 1024, + 'localDiskFlag': False, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'networkComponents': [{'maxSpeed': 100}], + 'supplementalCreateObjectOptions': {'bootMode': None}},) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_like_tags(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + 'hostname': 'vs-test-like', + 'domain': 'test.sftlyr.ws', + 'maxCpu': 2, + 'maxMemory': 1024, + 'datacenter': {'name': 'dal05'}, + 'networkComponents': [{'maxSpeed': 100}], + 'dedicatedAccountHostOnlyFlag': False, + 'privateNetworkOnlyFlag': False, + 'billingItem': {'orderItem': {'preset': {}}}, + 'operatingSystem': {'softwareLicense': { + 'softwareDescription': {'referenceCode': 'UBUNTU_LATEST'} + }}, + 'hourlyBillingFlag': False, + 'localDiskFlag': True, + 'userData': {}, + 'tagReferences': [{'tag': {'name': 'production'}}], + } + + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--like=123', + '--san', + '--billing=hourly']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + _args = ('production',) + self.assert_called_with('SoftLayer_Virtual_Guest', 'setTags', identifier=1234567, args=_args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_like_image(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + 'hostname': 'vs-test-like', + 'domain': 'test.sftlyr.ws', + 'maxCpu': 2, + 'maxMemory': 1024, + 'datacenter': {'name': 'dal05'}, + 'networkComponents': [{'maxSpeed': 100}], + 'dedicatedAccountHostOnlyFlag': False, + 'privateNetworkOnlyFlag': False, + 'billingItem': {'orderItem': {'preset': {}}}, + 'blockDeviceTemplateGroup': {'globalIdentifier': 'aaa1xxx1122233'}, + 'hourlyBillingFlag': False, + 'localDiskFlag': True, + 'userData': {}, + } + + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', + '--like=123', + '--san', + '--billing=hourly']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + args = ({'datacenter': {'name': 'dal05'}, + 'domain': 'test.sftlyr.ws', + 'hourlyBillingFlag': True, + 'hostname': 'vs-test-like', + 'startCpus': 2, + 'maxMemory': 1024, + 'localDiskFlag': False, + 'blockDeviceTemplateGroup': {'globalIdentifier': 'aaa1xxx1122233'}, + 'networkComponents': [{'maxSpeed': 100}], + 'supplementalCreateObjectOptions': {'bootMode': None}},) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_like_flavor(self, confirm_mock): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') + mock.return_value = { + 'hostname': 'vs-test-like', + 'domain': 'test.sftlyr.ws', + 'maxCpu': 2, + 'maxMemory': 1024, + 'datacenter': {'name': 'dal05'}, + 'networkComponents': [{'maxSpeed': 100}], + 'dedicatedAccountHostOnlyFlag': False, + 'privateNetworkOnlyFlag': False, + 'billingItem': {'orderItem': {'preset': {'keyName': 'B1_1X2X25'}}}, + 'operatingSystem': {'softwareLicense': { + 'softwareDescription': {'referenceCode': 'UBUNTU_LATEST'} + }}, + 'hourlyBillingFlag': True, + 'localDiskFlag': False, + 'userData': {} + } + + confirm_mock.return_value = True + result = self.run_command(['vs', 'create', '--like=123']) + + self.assert_no_fail(result) + self.assertIn('"guid": "1a2b3c-1701"', result.output) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + + args = ({'datacenter': {'name': 'dal05'}, + 'domain': 'test.sftlyr.ws', + 'hourlyBillingFlag': True, + 'hostname': 'vs-test-like', + 'startCpus': None, + 'maxMemory': None, + 'localDiskFlag': None, + 'supplementalCreateObjectOptions': { + 'bootMode': None, + 'flavorKeyName': 'B1_1X2X25'}, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'networkComponents': [{'maxSpeed': 100}]},) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_vs_test(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', + '--domain', 'TESTING', '--cpu', '1', + '--memory', '2048MB', '--datacenter', + 'TEST00', '--os', 'UBUNTU_LATEST']) + + self.assertEqual(result.exit_code, 0) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_vs_flavor_test(self, confirm_mock): + confirm_mock.return_value = True + + result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST']) + + self.assert_no_fail(result) + self.assertEqual(result.exit_code, 0) + + def test_create_vs_bad_memory(self): + result = self.run_command(['vs', 'create', '--hostname', 'TEST', + '--domain', 'TESTING', '--cpu', '1', + '--memory', '2034MB', '--flavor', + 'UBUNTU', '--datacenter', 'TEST00']) + + self.assertEqual(result.exit_code, 2) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_ipv6(self, confirm_mock): + amock = self.set_mock('SoftLayer_Product_Package', 'getItems') + amock.return_value = SoftLayer_Product_Package.getItems_1_IPV6_ADDRESS + result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST', '--ipv6']) + + self.assert_no_fail(result) + self.assertEqual(result.exit_code, 0) + self.assert_called_with('SoftLayer_Product_Order', 'verifyOrder') + args = ({ + 'startCpus': None, + 'maxMemory': None, + 'hostname': 'TEST', + 'domain': 'TESTING', + 'localDiskFlag': None, + 'hourlyBillingFlag': True, + 'supplementalCreateObjectOptions': { + 'bootMode': None, + 'flavorKeyName': 'B1_2X8X25' + }, + 'operatingSystemReferenceCode': 'UBUNTU_LATEST', + 'datacenter': { + 'name': 'TEST00' + } + }, + ) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate', args=args) + self.assertEqual([], self.calls('SoftLayer_Virtual_Guest', 'setTags')) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_ipv6_no_test(self, confirm_mock): + confirm_mock.return_value = True + amock = self.set_mock('SoftLayer_Product_Package', 'getItems') + amock.return_value = SoftLayer_Product_Package.getItems_1_IPV6_ADDRESS + result = self.run_command(['vs', 'create', '--hostname', 'TEST', + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST', '--ipv6']) + + self.assert_no_fail(result) + self.assertEqual(result.exit_code, 0) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + self.assertEqual([], self.calls('SoftLayer_Virtual_Guest', 'setTags')) + + @mock.patch('SoftLayer.CLI.formatting.no_going_back') + def test_create_with_ipv6_no_prices(self, confirm_mock): + """Test makes sure create fails if ipv6 price cannot be found. + + Since its hard to test if the price ids gets added to placeOrder call, + this test juse makes sure that code block isn't being skipped + """ + result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST', + '--ipv6']) + self.assertEqual(result.exit_code, 1) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_vs_no_confirm(self, confirm_mock): + confirm_mock.return_value = False + + result = self.run_command(['vs', 'create', '--hostname', 'TEST', + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST']) + + self.assertEqual(result.exit_code, 2) + + def test_create_vs_export(self): + if(sys.platform.startswith("win")): + self.skipTest("Test doesn't work in Windows") + with tempfile.NamedTemporaryFile() as config_file: + result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--export', config_file.name, + '--domain', 'TESTING', '--flavor', 'B1_2X8X25', + '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST']) + self.assert_no_fail(result) + self.assertTrue('Successfully exported options to a template file.' + in result.output) + contents = config_file.read().decode("utf-8") + self.assertIn('hostname=TEST', contents) + self.assertIn('flavor=B1_2X8X25', contents) + + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_create_with_userdata(self, confirm_mock): + result = self.run_command(['vs', 'create', '--hostname', 'TEST', '--domain', 'TESTING', + '--flavor', 'B1_2X8X25', '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST', + '--userdata', 'This is my user data ok']) + self.assert_no_fail(result) + expected_guest = [ + { + 'domain': 'test.local', + 'hostname': 'test', + 'userData': [{'value': 'This is my user data ok'}] + } + ] + # Returns a list of API calls that hit SL_Product_Order::placeOrder + api_call = self.calls('SoftLayer_Product_Order', 'placeOrder') + # Doing this because the placeOrder args are huge and mostly not needed to test + self.assertEqual(api_call[0].args[0]['virtualGuests'], expected_guest) diff --git a/tests/CLI/modules/vs_tests.py b/tests/CLI/modules/vs/vs_tests.py similarity index 61% rename from tests/CLI/modules/vs_tests.py rename to tests/CLI/modules/vs/vs_tests.py index d22fcddc1..ce1bb9d73 100644 --- a/tests/CLI/modules/vs_tests.py +++ b/tests/CLI/modules/vs/vs_tests.py @@ -302,397 +302,6 @@ def test_create_options(self): 'os (DEBIAN)': 'DEBIAN_7_64', 'os (UBUNTU)': 'UBUNTU_12_64'}) - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--memory=1', - '--network=100', - '--billing=hourly', - '--datacenter=dal05', - '--tag=dev', - '--tag=green']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({'datacenter': {'name': 'dal05'}, - 'domain': 'example.com', - 'hourlyBillingFlag': True, - 'localDiskFlag': True, - 'maxMemory': 1024, - 'hostname': 'host', - 'startCpus': 2, - 'operatingSystemReferenceCode': 'UBUNTU_LATEST', - 'networkComponents': [{'maxSpeed': '100'}], - 'supplementalCreateObjectOptions': {'bootMode': None}},) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_vlan_subnet(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--memory=1', - '--billing=hourly', - '--datacenter=dal05', - '--vlan-private=577940', - '--subnet-private=478700', - '--vlan-public=1639255', - '--subnet-public=297614', - '--tag=dev', - '--tag=green']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_wait_ready(self, confirm_mock): - mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') - mock.return_value = { - "provisionDate": "2018-06-10T12:00:00-05:00", - "id": 100 - } - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--memory=1', - '--network=100', - '--billing=hourly', - '--datacenter=dal05', - '--wait=1']) - - self.assert_no_fail(result) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_wait_not_ready(self, confirm_mock): - mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') - mock.return_value = { - "ready": False, - "guid": "1a2b3c-1701", - "id": 100, - "created": "2018-06-10 12:00:00" - } - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--memory=1', - '--network=100', - '--billing=hourly', - '--datacenter=dal05', - '--wait=1']) - - self.assertEqual(result.exit_code, 1) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_integer_image_id(self, confirm_mock): - confirm_mock.return_value = True - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--image=12345', - '--memory=1', - '--network=100', - '--billing=hourly', - '--datacenter=dal05']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({ - 'datacenter': {'name': 'dal05'}, - 'domain': 'example.com', - 'hourlyBillingFlag': True, - 'localDiskFlag': True, - 'maxMemory': 1024, - 'hostname': 'host', - 'startCpus': 2, - 'blockDeviceTemplateGroup': { - 'globalIdentifier': '0B5DEAF4-643D-46CA-A695-CECBE8832C9D', - }, - 'networkComponents': [{'maxSpeed': '100'}], - 'supplementalCreateObjectOptions': {'bootMode': None} - },) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_flavor(self, confirm_mock): - confirm_mock.return_value = True - result = self.run_command(['vs', 'create', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--network=100', - '--billing=hourly', - '--datacenter=dal05', - '--flavor=B1_1X2X25']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({'datacenter': {'name': 'dal05'}, - 'domain': 'example.com', - 'hourlyBillingFlag': True, - 'hostname': 'host', - 'startCpus': None, - 'maxMemory': None, - 'localDiskFlag': None, - 'supplementalCreateObjectOptions': { - 'bootMode': None, - 'flavorKeyName': 'B1_1X2X25'}, - 'operatingSystemReferenceCode': 'UBUNTU_LATEST', - 'networkComponents': [{'maxSpeed': '100'}]},) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_flavor_and_memory(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--network=100', - '--datacenter=TEST00', - '--flavor=BL_1X2X25', - '--memory=2048MB']) - - self.assertEqual(result.exit_code, 2) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_dedicated_and_flavor(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--network=100', - '--datacenter=TEST00', - '--dedicated', - '--flavor=BL_1X2X25']) - - self.assertEqual(result.exit_code, 2) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_hostid_and_flavor(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--network=100', - '--datacenter=dal05', - '--host-id=100', - '--flavor=BL_1X2X25']) - - self.assertEqual(result.exit_code, 2) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_flavor_and_cpu(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--network=100', - '--datacenter=TEST00', - '--flavor=BL_1X2X25', - '--cpu=2']) - - self.assertEqual(result.exit_code, 2) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_with_host_id(self, confirm_mock): - confirm_mock.return_value = True - result = self.run_command(['vs', 'create', - '--cpu=2', - '--domain=example.com', - '--hostname=host', - '--os=UBUNTU_LATEST', - '--memory=1', - '--network=100', - '--billing=hourly', - '--datacenter=dal05', - '--dedicated', - '--host-id=123']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({'datacenter': {'name': 'dal05'}, - 'domain': 'example.com', - 'hourlyBillingFlag': True, - 'localDiskFlag': True, - 'maxMemory': 1024, - 'hostname': 'host', - 'startCpus': 2, - 'operatingSystemReferenceCode': 'UBUNTU_LATEST', - 'networkComponents': [{'maxSpeed': '100'}], - 'dedicatedHost': {'id': 123}, - 'supplementalCreateObjectOptions': {'bootMode': None}},) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_like(self, confirm_mock): - mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') - mock.return_value = { - 'hostname': 'vs-test-like', - 'domain': 'test.sftlyr.ws', - 'maxCpu': 2, - 'maxMemory': 1024, - 'datacenter': {'name': 'dal05'}, - 'networkComponents': [{'maxSpeed': 100}], - 'dedicatedAccountHostOnlyFlag': False, - 'privateNetworkOnlyFlag': False, - 'billingItem': {'orderItem': {'preset': {}}}, - 'operatingSystem': {'softwareLicense': { - 'softwareDescription': {'referenceCode': 'UBUNTU_LATEST'} - }}, - 'hourlyBillingFlag': False, - 'localDiskFlag': True, - 'userData': {} - } - - confirm_mock.return_value = True - result = self.run_command(['vs', 'create', - '--like=123', - '--san', - '--billing=hourly']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({'datacenter': {'name': 'dal05'}, - 'domain': 'test.sftlyr.ws', - 'hourlyBillingFlag': True, - 'hostname': 'vs-test-like', - 'startCpus': 2, - 'maxMemory': 1024, - 'localDiskFlag': False, - 'operatingSystemReferenceCode': 'UBUNTU_LATEST', - 'networkComponents': [{'maxSpeed': 100}], - 'supplementalCreateObjectOptions': {'bootMode': None}},) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_like_flavor(self, confirm_mock): - mock = self.set_mock('SoftLayer_Virtual_Guest', 'getObject') - mock.return_value = { - 'hostname': 'vs-test-like', - 'domain': 'test.sftlyr.ws', - 'maxCpu': 2, - 'maxMemory': 1024, - 'datacenter': {'name': 'dal05'}, - 'networkComponents': [{'maxSpeed': 100}], - 'dedicatedAccountHostOnlyFlag': False, - 'privateNetworkOnlyFlag': False, - 'billingItem': {'orderItem': {'preset': {'keyName': 'B1_1X2X25'}}}, - 'operatingSystem': {'softwareLicense': { - 'softwareDescription': {'referenceCode': 'UBUNTU_LATEST'} - }}, - 'hourlyBillingFlag': True, - 'localDiskFlag': False, - 'userData': {} - } - - confirm_mock.return_value = True - result = self.run_command(['vs', 'create', '--like=123']) - - self.assert_no_fail(result) - self.assertEqual(json.loads(result.output), - {'guid': '1a2b3c-1701', - 'id': 100, - 'created': '2013-08-01 15:23:45'}) - - args = ({'datacenter': {'name': 'dal05'}, - 'domain': 'test.sftlyr.ws', - 'hourlyBillingFlag': True, - 'hostname': 'vs-test-like', - 'startCpus': None, - 'maxMemory': None, - 'localDiskFlag': None, - 'supplementalCreateObjectOptions': { - 'bootMode': None, - 'flavorKeyName': 'B1_1X2X25'}, - 'operatingSystemReferenceCode': 'UBUNTU_LATEST', - 'networkComponents': [{'maxSpeed': 100}]},) - self.assert_called_with('SoftLayer_Virtual_Guest', 'createObject', - args=args) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_vs_test(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', - '--domain', 'TESTING', '--cpu', '1', - '--memory', '2048MB', '--datacenter', - 'TEST00', '--os', 'UBUNTU_LATEST']) - - self.assertEqual(result.exit_code, 0) - - @mock.patch('SoftLayer.CLI.formatting.confirm') - def test_create_vs_flavor_test(self, confirm_mock): - confirm_mock.return_value = True - - result = self.run_command(['vs', 'create', '--test', '--hostname', 'TEST', - '--domain', 'TESTING', '--flavor', 'B1_2X8X25', - '--datacenter', 'TEST00', '--os', 'UBUNTU_LATEST']) - - self.assert_no_fail(result) - self.assertEqual(result.exit_code, 0) - - def test_create_vs_bad_memory(self): - result = self.run_command(['vs', 'create', '--hostname', 'TEST', - '--domain', 'TESTING', '--cpu', '1', - '--memory', '2034MB', '--flavor', - 'UBUNTU', '--datacenter', 'TEST00']) - - self.assertEqual(result.exit_code, 2) - @mock.patch('SoftLayer.CLI.formatting.confirm') def test_dns_sync_both(self, confirm_mock): confirm_mock.return_value = True @@ -924,10 +533,13 @@ def test_upgrade_with_flavor(self, confirm_mock): self.assertIn({'id': 100}, order_container['virtualGuests']) self.assertEqual(order_container['virtualGuests'], [{'id': 100}]) - def test_upgrade_with_cpu_memory_and_flavor(self): + @mock.patch('SoftLayer.CLI.formatting.confirm') + def test_upgrade_with_cpu_memory_and_flavor(self, confirm_mock): + confirm_mock.return_value = True result = self.run_command(['vs', 'upgrade', '100', '--cpu=4', '--memory=1024', '--flavor=M1_64X512X100']) - self.assertEqual("Do not use cpu, private and memory if you are using flavors", str(result.exception)) + self.assertEqual(result.exit_code, 1) + self.assertIsInstance(result.exception, ValueError) def test_edit(self): result = self.run_command(['vs', 'edit', @@ -1042,3 +654,9 @@ def test_cancel_no_confirm(self, confirm_mock): result = self.run_command(['vs', 'cancel', '100']) self.assertEqual(result.exit_code, 2) + + def test_vs_capture(self): + + result = self.run_command(['vs', 'capture', '100', '--name', 'TestName']) + self.assert_no_fail(result) + self.assert_called_with('SoftLayer_Virtual_Guest', 'createArchiveTransaction', identifier=100) diff --git a/tests/managers/network_tests.py b/tests/managers/network_tests.py index 7a84bebae..e78b91f1a 100644 --- a/tests/managers/network_tests.py +++ b/tests/managers/network_tests.py @@ -92,7 +92,7 @@ def test_add_subnet_for_ipv4(self): version=4, test_order=False) - self.assertEqual(fixtures.SoftLayer_Product_Order.verifyOrder, result) + self.assertEqual(fixtures.SoftLayer_Product_Order.placeOrder, result) result = self.network.add_subnet('global', test_order=True) diff --git a/tests/managers/vs/__init__.py b/tests/managers/vs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/managers/vs_capacity_tests.py b/tests/managers/vs/vs_capacity_tests.py similarity index 98% rename from tests/managers/vs_capacity_tests.py rename to tests/managers/vs/vs_capacity_tests.py index 43db16afb..751b31753 100644 --- a/tests/managers/vs_capacity_tests.py +++ b/tests/managers/vs/vs_capacity_tests.py @@ -1,5 +1,5 @@ """ - SoftLayer.tests.managers.vs_capacity_tests + SoftLayer.tests.managers.vs.vs_capacity_tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :license: MIT, see LICENSE for more details. @@ -13,7 +13,7 @@ from SoftLayer import testing -class VSCapacityTests(testing.TestCase): +class VSManagerCapacityTests(testing.TestCase): def set_up(self): self.manager = SoftLayer.CapacityManager(self.client) diff --git a/tests/managers/vs/vs_order_tests.py b/tests/managers/vs/vs_order_tests.py new file mode 100644 index 000000000..12750224d --- /dev/null +++ b/tests/managers/vs/vs_order_tests.py @@ -0,0 +1,175 @@ +""" + SoftLayer.tests.managers.vs.vs_order_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + These tests deal with ordering in the VS manager. + :license: MIT, see LICENSE for more details. + +""" +import mock + +import SoftLayer +from SoftLayer import fixtures +from SoftLayer import testing + + +class VSOrderTests(testing.TestCase): + + def set_up(self): + self.vs = SoftLayer.VSManager(self.client) + + @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') + def test_create_verify(self, create_dict): + create_dict.return_value = {'test': 1, 'verify': 1} + + self.vs.verify_create_instance(test=1, verify=1, tags=['test', 'tags']) + + create_dict.assert_called_once_with(test=1, verify=1) + self.assert_called_with('SoftLayer_Virtual_Guest', + 'generateOrderTemplate', + args=({'test': 1, 'verify': 1},)) + + def test_upgrade(self): + # test single upgrade + result = self.vs.upgrade(1, cpus=4, public=False) + + self.assertEqual(result, True) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertEqual(order_container['prices'], [{'id': 1007}]) + self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + + def test_upgrade_blank(self): + # Now test a blank upgrade + result = self.vs.upgrade(1) + + self.assertEqual(result, False) + self.assertEqual(self.calls('SoftLayer_Product_Order', 'placeOrder'), + []) + + def test_upgrade_full(self): + # Testing all parameters Upgrade + result = self.vs.upgrade(1, + cpus=4, + memory=2, + nic_speed=1000, + public=True) + + self.assertEqual(result, True) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertIn({'id': 1144}, order_container['prices']) + self.assertIn({'id': 1133}, order_container['prices']) + self.assertIn({'id': 1122}, order_container['prices']) + self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + + def test_upgrade_with_flavor(self): + # Testing Upgrade with parameter preset + result = self.vs.upgrade(1, + preset="M1_64X512X100", + nic_speed=1000, + public=True) + + self.assertEqual(result, True) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertEqual(799, order_container['presetId']) + self.assertIn({'id': 1}, order_container['virtualGuests']) + self.assertIn({'id': 1122}, order_container['prices']) + self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + + def test_upgrade_dedicated_host_instance(self): + mock = self.set_mock('SoftLayer_Virtual_Guest', 'getUpgradeItemPrices') + mock.return_value = fixtures.SoftLayer_Virtual_Guest.DEDICATED_GET_UPGRADE_ITEM_PRICES + + # test single upgrade + result = self.vs.upgrade(1, cpus=4, public=False) + + self.assertEqual(result, True) + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] + order_container = call.args[0] + self.assertEqual(order_container['prices'], [{'id': 115566}]) + self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) + + def test_get_item_id_for_upgrade(self): + item_id = 0 + package_items = self.client['Product_Package'].getItems(id=46) + for item in package_items: + if ((item['prices'][0]['categories'][0]['id'] == 3) + and (item.get('capacity') == '2')): + item_id = item['prices'][0]['id'] + break + self.assertEqual(1133, item_id) + + def test_get_package_items(self): + self.vs._get_package_items() + self.assert_called_with('SoftLayer_Product_Package', 'getItems') + + def test_get_price_id_for_upgrade(self): + package_items = self.vs._get_package_items() + + price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, + option='cpus', + value='4') + self.assertEqual(1144, price_id) + + def test_get_price_id_for_upgrade_skips_location_price(self): + package_items = self.vs._get_package_items() + + price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, + option='cpus', + value='55') + self.assertEqual(None, price_id) + + def test_get_price_id_for_upgrade_finds_nic_price(self): + package_items = self.vs._get_package_items() + + price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, + option='memory', + value='2') + self.assertEqual(1133, price_id) + + def test_get_price_id_for_upgrade_finds_memory_price(self): + package_items = self.vs._get_package_items() + + price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, + option='nic_speed', + value='1000') + self.assertEqual(1122, price_id) + + @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') + def test_order_guest(self, create_dict): + create_dict.return_value = {'test': 1, 'verify': 1} + guest = {'test': 1, 'verify': 1, 'tags': ['First']} + result = self.vs.order_guest(guest, test=False) + create_dict.assert_called_once_with(test=1, verify=1) + self.assertEqual(1234, result['orderId']) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate') + self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') + self.assert_called_with('SoftLayer_Virtual_Guest', 'setTags', identifier=1234567) + + @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') + def test_order_guest_verify(self, create_dict): + create_dict.return_value = {'test': 1, 'verify': 1} + guest = {'test': 1, 'verify': 1, 'tags': ['First']} + result = self.vs.order_guest(guest, test=True) + create_dict.assert_called_once_with(test=1, verify=1) + self.assertEqual(1234, result['orderId']) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate') + self.assert_called_with('SoftLayer_Product_Order', 'verifyOrder') + + @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') + def test_order_guest_ipv6(self, create_dict): + amock = self.set_mock('SoftLayer_Product_Package', 'getItems') + amock.return_value = fixtures.SoftLayer_Product_Package.getItems_1_IPV6_ADDRESS + create_dict.return_value = {'test': 1, 'verify': 1} + guest = {'test': 1, 'verify': 1, 'tags': ['First'], 'ipv6': True} + result = self.vs.order_guest(guest, test=True) + self.assertEqual(1234, result['orderId']) + self.assert_called_with('SoftLayer_Virtual_Guest', 'generateOrderTemplate') + self.assert_called_with('SoftLayer_Product_Package', 'getItems', identifier=200) + self.assert_called_with('SoftLayer_Product_Order', 'verifyOrder') diff --git a/tests/managers/vs_tests.py b/tests/managers/vs/vs_tests.py similarity index 69% rename from tests/managers/vs_tests.py rename to tests/managers/vs/vs_tests.py index c24124dd6..f13c3e7b9 100644 --- a/tests/managers/vs_tests.py +++ b/tests/managers/vs/vs_tests.py @@ -1,5 +1,5 @@ """ - SoftLayer.tests.managers.vs_tests + SoftLayer.tests.managers.vs.vs_tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :license: MIT, see LICENSE for more details. @@ -16,8 +16,7 @@ class VSTests(testing.TestCase): def set_up(self): - self.vs = SoftLayer.VSManager(self.client, - SoftLayer.OrderingManager(self.client)) + self.vs = SoftLayer.VSManager(self.client, SoftLayer.OrderingManager(self.client)) def test_list_instances(self): results = self.vs.list_instances(hourly=True, monthly=True) @@ -156,17 +155,6 @@ def test_reload_instance_with_new_os(self): args=args, identifier=1) - @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') - def test_create_verify(self, create_dict): - create_dict.return_value = {'test': 1, 'verify': 1} - - self.vs.verify_create_instance(test=1, verify=1, tags=['test', 'tags']) - - create_dict.assert_called_once_with(test=1, verify=1) - self.assert_called_with('SoftLayer_Virtual_Guest', - 'generateOrderTemplate', - args=({'test': 1, 'verify': 1},)) - @mock.patch('SoftLayer.managers.vs.VSManager._generate_create_dict') def test_create_instance(self, create_dict): create_dict.return_value = {'test': 1, 'verify': 1} @@ -842,266 +830,3 @@ def test_capture_additional_disks(self): 'createArchiveTransaction', args=args, identifier=1) - - def test_upgrade(self): - # test single upgrade - result = self.vs.upgrade(1, cpus=4, public=False) - - self.assertEqual(result, True) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') - call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] - order_container = call.args[0] - self.assertEqual(order_container['prices'], [{'id': 1007}]) - self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) - - def test_upgrade_blank(self): - # Now test a blank upgrade - result = self.vs.upgrade(1) - - self.assertEqual(result, False) - self.assertEqual(self.calls('SoftLayer_Product_Order', 'placeOrder'), - []) - - def test_upgrade_full(self): - # Testing all parameters Upgrade - result = self.vs.upgrade(1, - cpus=4, - memory=2, - nic_speed=1000, - public=True) - - self.assertEqual(result, True) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') - call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] - order_container = call.args[0] - self.assertIn({'id': 1144}, order_container['prices']) - self.assertIn({'id': 1133}, order_container['prices']) - self.assertIn({'id': 1122}, order_container['prices']) - self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) - - def test_upgrade_with_flavor(self): - # Testing Upgrade with parameter preset - result = self.vs.upgrade(1, - preset="M1_64X512X100", - nic_speed=1000, - public=True) - - self.assertEqual(result, True) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') - call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] - order_container = call.args[0] - self.assertEqual(799, order_container['presetId']) - self.assertIn({'id': 1}, order_container['virtualGuests']) - self.assertIn({'id': 1122}, order_container['prices']) - self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) - - def test_upgrade_dedicated_host_instance(self): - mock = self.set_mock('SoftLayer_Virtual_Guest', 'getUpgradeItemPrices') - mock.return_value = fixtures.SoftLayer_Virtual_Guest.DEDICATED_GET_UPGRADE_ITEM_PRICES - - # test single upgrade - result = self.vs.upgrade(1, cpus=4, public=False) - - self.assertEqual(result, True) - self.assert_called_with('SoftLayer_Product_Order', 'placeOrder') - call = self.calls('SoftLayer_Product_Order', 'placeOrder')[0] - order_container = call.args[0] - self.assertEqual(order_container['prices'], [{'id': 115566}]) - self.assertEqual(order_container['virtualGuests'], [{'id': 1}]) - - def test_get_item_id_for_upgrade(self): - item_id = 0 - package_items = self.client['Product_Package'].getItems(id=46) - for item in package_items: - if ((item['prices'][0]['categories'][0]['id'] == 3) - and (item.get('capacity') == '2')): - item_id = item['prices'][0]['id'] - break - self.assertEqual(1133, item_id) - - def test_get_package_items(self): - self.vs._get_package_items() - self.assert_called_with('SoftLayer_Product_Package', 'getItems') - - def test_get_price_id_for_upgrade(self): - package_items = self.vs._get_package_items() - - price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, - option='cpus', - value='4') - self.assertEqual(1144, price_id) - - def test_get_price_id_for_upgrade_skips_location_price(self): - package_items = self.vs._get_package_items() - - price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, - option='cpus', - value='55') - self.assertEqual(None, price_id) - - def test_get_price_id_for_upgrade_finds_nic_price(self): - package_items = self.vs._get_package_items() - - price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, - option='memory', - value='2') - self.assertEqual(1133, price_id) - - def test_get_price_id_for_upgrade_finds_memory_price(self): - package_items = self.vs._get_package_items() - - price_id = self.vs._get_price_id_for_upgrade(package_items=package_items, - option='nic_speed', - value='1000') - self.assertEqual(1122, price_id) - - -class VSWaitReadyGoTests(testing.TestCase): - - def set_up(self): - self.client = mock.MagicMock() - self.vs = SoftLayer.VSManager(self.client) - self.guestObject = self.client['Virtual_Guest'].getObject - - @mock.patch('SoftLayer.managers.vs.VSManager.wait_for_ready') - def test_wait_interface(self, ready): - # verify interface to wait_for_ready is intact - self.vs.wait_for_transaction(1, 1) - ready.assert_called_once_with(1, 1, delay=10, pending=True) - - def test_active_not_provisioned(self): - # active transaction and no provision date should be false - self.guestObject.return_value = {'activeTransaction': {'id': 1}} - value = self.vs.wait_for_ready(1, 0) - self.assertFalse(value) - - def test_active_and_provisiondate(self): - # active transaction and provision date should be True - self.guestObject.side_effect = [ - {'activeTransaction': {'id': 1}, - 'provisionDate': 'aaa'}, - ] - value = self.vs.wait_for_ready(1, 1) - self.assertTrue(value) - - @mock.patch('time.sleep') - @mock.patch('time.time') - def test_active_provision_pending(self, _now, _sleep): - _now.side_effect = [0, 0, 1, 1, 2, 2] - # active transaction and provision date - # and pending should be false - self.guestObject.return_value = {'activeTransaction': {'id': 2}, 'provisionDate': 'aaa'} - - value = self.vs.wait_for_ready(instance_id=1, limit=1, delay=1, pending=True) - _sleep.assert_has_calls([mock.call(0)]) - self.assertFalse(value) - - def test_reload_no_pending(self): - # reload complete, maintance transactions - self.guestObject.return_value = { - 'activeTransaction': {'id': 2}, - 'provisionDate': 'aaa', - 'lastOperatingSystemReload': {'id': 1}, - } - - value = self.vs.wait_for_ready(1, 1) - self.assertTrue(value) - - @mock.patch('time.sleep') - @mock.patch('time.time') - def test_reload_pending(self, _now, _sleep): - _now.side_effect = [0, 0, 1, 1, 2, 2] - # reload complete, pending maintance transactions - self.guestObject.return_value = {'activeTransaction': {'id': 2}, - 'provisionDate': 'aaa', - 'lastOperatingSystemReload': {'id': 1}} - value = self.vs.wait_for_ready(instance_id=1, limit=1, delay=1, pending=True) - _sleep.assert_has_calls([mock.call(0)]) - self.assertFalse(value) - - @mock.patch('time.sleep') - def test_ready_iter_once_incomplete(self, _sleep): - # no iteration, false - self.guestObject.return_value = {'activeTransaction': {'id': 1}} - value = self.vs.wait_for_ready(1, 0, delay=1) - self.assertFalse(value) - _sleep.assert_has_calls([mock.call(0)]) - - @mock.patch('time.sleep') - def test_iter_once_complete(self, _sleep): - # no iteration, true - self.guestObject.return_value = {'provisionDate': 'aaa'} - value = self.vs.wait_for_ready(1, 1, delay=1) - self.assertTrue(value) - self.assertFalse(_sleep.called) - - @mock.patch('time.sleep') - def test_iter_four_complete(self, _sleep): - # test 4 iterations with positive match - self.guestObject.side_effect = [ - {'activeTransaction': {'id': 1}}, - {'activeTransaction': {'id': 1}}, - {'activeTransaction': {'id': 1}}, - {'provisionDate': 'aaa'}, - ] - - value = self.vs.wait_for_ready(1, 4, delay=1) - self.assertTrue(value) - _sleep.assert_has_calls([mock.call(1), mock.call(1), mock.call(1)]) - self.guestObject.assert_has_calls([ - mock.call(id=1, mask=mock.ANY), mock.call(id=1, mask=mock.ANY), - mock.call(id=1, mask=mock.ANY), mock.call(id=1, mask=mock.ANY), - ]) - - @mock.patch('time.time') - @mock.patch('time.sleep') - def test_iter_two_incomplete(self, _sleep, _time): - # test 2 iterations, with no matches - self.guestObject.side_effect = [ - {'activeTransaction': {'id': 1}}, - {'activeTransaction': {'id': 1}}, - {'activeTransaction': {'id': 1}}, - {'provisionDate': 'aaa'} - ] - # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. - _time.side_effect = [0, 1, 2, 3, 4, 5, 6] - value = self.vs.wait_for_ready(1, 2, delay=1) - self.assertFalse(value) - _sleep.assert_has_calls([mock.call(1), mock.call(0)]) - self.guestObject.assert_has_calls([ - mock.call(id=1, mask=mock.ANY), - mock.call(id=1, mask=mock.ANY), - ]) - - @mock.patch('time.time') - @mock.patch('time.sleep') - def test_iter_20_incomplete(self, _sleep, _time): - """Wait for up to 20 seconds (sleeping for 10 seconds) for a server.""" - self.guestObject.return_value = {'activeTransaction': {'id': 1}} - # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. - _time.side_effect = [0, 0, 10, 10, 20, 20, 50, 60] - value = self.vs.wait_for_ready(1, 20, delay=10) - self.assertFalse(value) - self.guestObject.assert_has_calls([mock.call(id=1, mask=mock.ANY)]) - - _sleep.assert_has_calls([mock.call(10)]) - - @mock.patch('SoftLayer.decoration.sleep') - @mock.patch('SoftLayer.transports.FixtureTransport.__call__') - @mock.patch('time.time') - @mock.patch('time.sleep') - def test_exception_from_api(self, _sleep, _time, _vs, _dsleep): - """Tests escalating scale back when an excaption is thrown""" - _dsleep.return_value = False - - self.guestObject.side_effect = [ - exceptions.TransportError(104, "Its broken"), - {'activeTransaction': {'id': 1}}, - {'provisionDate': 'aaa'} - ] - # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. - _time.side_effect = [0, 1, 2, 3, 4] - value = self.vs.wait_for_ready(1, 20, delay=1) - _sleep.assert_called_once() - _dsleep.assert_called_once() - self.assertTrue(value) diff --git a/tests/managers/vs/vs_waiting_for_ready_tests.py b/tests/managers/vs/vs_waiting_for_ready_tests.py new file mode 100644 index 000000000..802b945fd --- /dev/null +++ b/tests/managers/vs/vs_waiting_for_ready_tests.py @@ -0,0 +1,163 @@ +""" + SoftLayer.tests.managers.vs.vs_waiting_for_ready_tests + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :license: MIT, see LICENSE for more details. + +""" +import mock + +import SoftLayer +from SoftLayer import exceptions +from SoftLayer import testing + + +class VSWaitReadyGoTests(testing.TestCase): + + def set_up(self): + self.client = mock.MagicMock() + self.vs = SoftLayer.VSManager(self.client) + self.guestObject = self.client['Virtual_Guest'].getObject + + @mock.patch('SoftLayer.managers.vs.VSManager.wait_for_ready') + def test_wait_interface(self, ready): + # verify interface to wait_for_ready is intact + self.vs.wait_for_transaction(1, 1) + ready.assert_called_once_with(1, 1, delay=10, pending=True) + + def test_active_not_provisioned(self): + # active transaction and no provision date should be false + self.guestObject.return_value = {'activeTransaction': {'id': 1}} + value = self.vs.wait_for_ready(1, 0) + self.assertFalse(value) + + def test_active_and_provisiondate(self): + # active transaction and provision date should be True + self.guestObject.side_effect = [ + {'activeTransaction': {'id': 1}, + 'provisionDate': 'aaa'}, + ] + value = self.vs.wait_for_ready(1, 1) + self.assertTrue(value) + + @mock.patch('time.sleep') + @mock.patch('time.time') + def test_active_provision_pending(self, _now, _sleep): + _now.side_effect = [0, 0, 1, 1, 2, 2] + # active transaction and provision date + # and pending should be false + self.guestObject.return_value = {'activeTransaction': {'id': 2}, 'provisionDate': 'aaa'} + + value = self.vs.wait_for_ready(instance_id=1, limit=1, delay=1, pending=True) + _sleep.assert_has_calls([mock.call(0)]) + self.assertFalse(value) + + def test_reload_no_pending(self): + # reload complete, maintance transactions + self.guestObject.return_value = { + 'activeTransaction': {'id': 2}, + 'provisionDate': 'aaa', + 'lastOperatingSystemReload': {'id': 1}, + } + + value = self.vs.wait_for_ready(1, 1) + self.assertTrue(value) + + @mock.patch('time.sleep') + @mock.patch('time.time') + def test_reload_pending(self, _now, _sleep): + _now.side_effect = [0, 0, 1, 1, 2, 2] + # reload complete, pending maintance transactions + self.guestObject.return_value = {'activeTransaction': {'id': 2}, + 'provisionDate': 'aaa', + 'lastOperatingSystemReload': {'id': 1}} + value = self.vs.wait_for_ready(instance_id=1, limit=1, delay=1, pending=True) + _sleep.assert_has_calls([mock.call(0)]) + self.assertFalse(value) + + @mock.patch('time.sleep') + def test_ready_iter_once_incomplete(self, _sleep): + # no iteration, false + self.guestObject.return_value = {'activeTransaction': {'id': 1}} + value = self.vs.wait_for_ready(1, 0, delay=1) + self.assertFalse(value) + _sleep.assert_has_calls([mock.call(0)]) + + @mock.patch('time.sleep') + def test_iter_once_complete(self, _sleep): + # no iteration, true + self.guestObject.return_value = {'provisionDate': 'aaa'} + value = self.vs.wait_for_ready(1, 1, delay=1) + self.assertTrue(value) + self.assertFalse(_sleep.called) + + @mock.patch('time.sleep') + def test_iter_four_complete(self, _sleep): + # test 4 iterations with positive match + self.guestObject.side_effect = [ + {'activeTransaction': {'id': 1}}, + {'activeTransaction': {'id': 1}}, + {'activeTransaction': {'id': 1}}, + {'provisionDate': 'aaa'}, + ] + + value = self.vs.wait_for_ready(1, 4, delay=1) + self.assertTrue(value) + _sleep.assert_has_calls([mock.call(1), mock.call(1), mock.call(1)]) + self.guestObject.assert_has_calls([ + mock.call(id=1, mask=mock.ANY), mock.call(id=1, mask=mock.ANY), + mock.call(id=1, mask=mock.ANY), mock.call(id=1, mask=mock.ANY), + ]) + + @mock.patch('time.time') + @mock.patch('time.sleep') + def test_iter_two_incomplete(self, _sleep, _time): + # test 2 iterations, with no matches + self.guestObject.side_effect = [ + {'activeTransaction': {'id': 1}}, + {'activeTransaction': {'id': 1}}, + {'activeTransaction': {'id': 1}}, + {'provisionDate': 'aaa'} + ] + # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. + _time.side_effect = [0, 1, 2, 3, 4, 5, 6] + value = self.vs.wait_for_ready(1, 2, delay=1) + self.assertFalse(value) + _sleep.assert_has_calls([mock.call(1), mock.call(0)]) + self.guestObject.assert_has_calls([ + mock.call(id=1, mask=mock.ANY), + mock.call(id=1, mask=mock.ANY), + ]) + + @mock.patch('time.time') + @mock.patch('time.sleep') + def test_iter_20_incomplete(self, _sleep, _time): + """Wait for up to 20 seconds (sleeping for 10 seconds) for a server.""" + self.guestObject.return_value = {'activeTransaction': {'id': 1}} + # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. + _time.side_effect = [0, 0, 10, 10, 20, 20, 50, 60] + value = self.vs.wait_for_ready(1, 20, delay=10) + self.assertFalse(value) + self.guestObject.assert_has_calls([mock.call(id=1, mask=mock.ANY)]) + + _sleep.assert_has_calls([mock.call(10)]) + + @mock.patch('SoftLayer.decoration.sleep') + @mock.patch('SoftLayer.transports.FixtureTransport.__call__') + @mock.patch('time.time') + @mock.patch('time.sleep') + def test_exception_from_api(self, _sleep, _time, _vs, _dsleep): + """Tests escalating scale back when an excaption is thrown""" + _dsleep.return_value = False + + self.guestObject.side_effect = [ + exceptions.TransportError(104, "Its broken"), + {'activeTransaction': {'id': 1}}, + {'provisionDate': 'aaa'} + ] + # logging calls time.time as of pytest3.3, not sure if there is a better way of getting around that. + _time.side_effect = [0, 1, 2, 3, 4] + value = self.vs.wait_for_ready(1, 20, delay=1) + _sleep.assert_called_once() + _dsleep.assert_called_once() + self.assertTrue(value)