def launch_instance(compute, compartment, test_id, availability_domain, subnet, public_key): # print('Launching instance') request = oci.core.models.LaunchInstanceDetails() request.availability_domain = availability_domain request.compartment_id = compartment request.display_name = 'pythonsdk_tutorial_instance_' + test_id # Oracle-Linux-7.3-2017.03.03-0 request.image_id = util.oracle_linux_image() request.shape = 'VM.Standard1.1' request.subnet_id = subnet.id request.metadata = {'ssh_authorized_keys': public_key} response = compute.launch_instance(request) assert response.status == 200 assert 'PROVISIONING' == response.data.lifecycle_state response = compute.get_instance(response.data.id) instance = test_config_container.do_wait(compute, response, 'lifecycle_state', 'RUNNING', max_wait_seconds=300).data assert 'RUNNING' == instance.lifecycle_state return instance
def launch_instance(compute, compartment, test_id, availability_domain, subnet, public_key): print('Launching instance') request = oci.core.models.LaunchInstanceDetails() request.availability_domain = availability_domain request.compartment_id = compartment request.display_name = 'pythonsdk_tutorial_instance_' + test_id # Oracle-Linux-7.3-2017.03.03-0 request.image_id = util.oracle_linux_image() request.shape = 'VM.Standard1.1' request.subnet_id = subnet.id request.metadata = {'ssh_authorized_keys': public_key} response = compute.launch_instance(request) assert response.status == 200 assert 'PROVISIONING' == response.data.lifecycle_state response = compute.get_instance(response.data.id) instance = test_config_container.do_wait( compute, response, 'lifecycle_state', 'RUNNING', max_wait_seconds=300 ).data assert 'RUNNING' == instance.lifecycle_state return instance
def subtest_launch_instance_merges_user_data_file_param_with_metadata( self): instance_name = util.random_name('cli_test_instance_options') image_id = util.oracle_linux_image() shape = 'VM.Standard1.2' hostname_label = util.random_name('bminstance', insert_underscore=False) launch_instance_result = util.invoke_command([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--hostname-label', hostname_label + "4", '--user-data-file', USER_DATA_FILE, '--metadata', util.remove_outer_quotes(oci_cli_compute.compute_cli_extended. compute_instance_launch_metadata_example) ]) util.validate_response(launch_instance_result, expect_etag=True) temp_instance_ocid = util.find_id_in_response( launch_instance_result.output) self.instance_ocids.append(temp_instance_ocid) response = json.loads(launch_instance_result.output) instance_metadata = response['data']['metadata'] assert instance_metadata['user_data'] assert instance_metadata['ssh_authorized_keys'] self.delete_instance(temp_instance_ocid)
def subtest_instance_operations(self): instance_name = util.random_name('cli_test_instance') fault_domain = 'FAULT-DOMAIN-1' image_id = util.oracle_linux_image() shape = 'VM.Standard1.1' result = self.invoke( ['compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--fault-domain', fault_domain, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--metadata', util.remove_outer_quotes(oci_cli_compute.compute_cli_extended.compute_instance_launch_metadata_example)]) self.instance_ocid = util.find_id_in_response(result.output) util.validate_response(result, expect_etag=True) util.wait_until(['compute', 'instance', 'get', '--instance-id', self.instance_ocid], 'RUNNING', max_wait_seconds=600) result = self.invoke(['compute', 'instance', 'list', '--compartment-id', util.COMPARTMENT_ID]) util.validate_response(result) # list with compartment shortcut result = self.invoke(['compute', 'instance', 'list', '-c', util.COMPARTMENT_ID]) util.validate_response(result) instance_name = instance_name + "_updated" result = self.invoke(['compute', 'instance', 'update', '--instance-id', self.instance_ocid, '--display-name', instance_name]) util.validate_response(result, expect_etag=True) result = self.invoke(['compute', 'instance', 'get', '--instance-id', self.instance_ocid]) util.validate_response(result, expect_etag=True) result = self.invoke( ['compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name + "_2", '--fault-domain', fault_domain, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--metadata', util.remove_outer_quotes(oci_cli_compute.compute_cli_extended.compute_instance_launch_metadata_example), '--wait-for-state', 'RUNNING', '--max-wait-seconds', '20', '--wait-interval-seconds', '5']) self.instance_ocid_2 = util.find_id_in_response(result.output[result.output.index('{'):]) assert result.exit_code != 0
def subtest_launch_instance_ssh_authorized_keys_in_param_and_in_metadata_throws_error(self): instance_name = util.random_name('cli_test_instance_options') image_id = util.oracle_linux_image() shape = 'VM.Standard1.2' hostname_label = util.random_name('bminstance', insert_underscore=False) launch_instance_result = util.invoke_command( ['compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--hostname-label', hostname_label + "2", '--ssh-authorized-keys-file', util.SSH_AUTHORIZED_KEYS_FILE, '--metadata', util.remove_outer_quotes(oci_cli_compute.compute_cli_extended.compute_instance_launch_metadata_example)]) assert launch_instance_result.exit_code != 0
def subtest_launch_instance_user_data_in_param_and_in_metadata_throws_error( self): instance_name = util.random_name('cli_test_instance_options') image_id = util.oracle_linux_image() shape = 'VM.Standard1.2' hostname_label = util.random_name('bminstance', insert_underscore=False) metadata = """{"user_data": "IyEvYmluL2Jhc2gKCm1rZGlyIC90bXAvbXlkaXIKdG91Y2ggL3RtcC9teWRpci9teXR4dC50eHQ="}""" launch_instance_result = util.invoke_command([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--hostname-label', hostname_label, '--user-data-file', USER_DATA_FILE, '--metadata', metadata ]) assert launch_instance_result.exit_code != 0
def test_boot_volume_clone_backup(network_resources): with test_config_container.create_vcr(cassette_library_dir=CASSETTE_LIBRARY_DIR).use_cassette('boot_volume_test_boot_volume_clone_backup.yml'): boot_volume_id = None instance_ocid = None backup_boot_volume_id = None cloned_boot_volume_id = None backup_id = None try: instance_name = util.random_name('boot_vol_instance') image_id = util.oracle_linux_image() shape = 'VM.Standard1.1' hostname_label = util.random_name('bootvolinst', insert_underscore=False) boot_volume_size_in_gbs = '51' result = invoke([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', network_resources[1], '--image-id', image_id, '--shape', shape, '--hostname-label', hostname_label, '--boot-volume-size-in-gbs', boot_volume_size_in_gbs, '--wait-for-state', 'RUNNING', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS ]) util.validate_response(result, json_response_expected=False) instance_data = util.get_json_from_mixed_string(result.output)['data'] instance_ocid = instance_data['id'] assert 'image' == instance_data['source-details']['source-type'] assert image_id == instance_data['source-details']['image-id'] result = invoke([ 'compute', 'boot-volume-attachment', 'list', '-c', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--instance-id', instance_data['id'] ]) util.validate_response(result) parsed_result = json.loads(result.output) assert len(parsed_result['data']) == 1 boot_volume_id = parsed_result['data'][0]['boot-volume-id'] result = invoke([ 'bv', 'boot-volume', 'get', '--boot-volume-id', boot_volume_id ]) util.validate_response(result) parsed_result = json.loads(result.output) boot_volume_size_in_gbs = parsed_result['data']['size-in-gbs'] assert boot_volume_size_in_gbs == int(boot_volume_size_in_gbs) result = invoke([ 'compute', 'instance', 'terminate', '--instance-id', instance_ocid, '--wait-for-state', 'TERMINATED', '--preserve-boot-volume', 'true', '--force' ]) util.validate_response(result, json_response_expected=False) instance_ocid = None # Since we preserved the volume it should still be available result = invoke(['bv', 'boot-volume', 'get', '--boot-volume-id', boot_volume_id]) util.validate_response(result) parsed_result = json.loads(result.output) assert util.availability_domain() == parsed_result['data']['availability-domain'] assert 'AVAILABLE' == parsed_result['data']['lifecycle-state'] assert image_id == parsed_result['data']['image-id'] size_in_gbs = int(parsed_result['data']['size-in-gbs']) new_size_in_gbs = size_in_gbs + 10 # Resize boot volume to new_size_in_gbs result = invoke(['bv', 'boot-volume', 'update', '--boot-volume-id', boot_volume_id, '--size-in-gbs', str(new_size_in_gbs), '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_response(result, json_response_expected=False) # Since we preserved the volume it should still be available result = invoke(['bv', 'boot-volume', 'get', '--boot-volume-id', boot_volume_id]) util.validate_response(result) parsed_result = json.loads(result.output) assert 'AVAILABLE' == parsed_result['data']['lifecycle-state'] assert new_size_in_gbs == int(parsed_result['data']['size-in-gbs']) # Take a backup result = invoke(['bv', 'boot-volume-backup', 'create', '--boot-volume-id', boot_volume_id, '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_response(result, json_response_expected=False) parsed_result = util.get_json_from_mixed_string(result.output) assert boot_volume_id == parsed_result['data']['boot-volume-id'] assert image_id == parsed_result['data']['image-id'] assert 'AVAILABLE' == parsed_result['data']['lifecycle-state'] backup_id = parsed_result['data']['id'] # Boot Volume Create Error cases # Error 1: No option specified result = invoke(['bv', 'boot-volume', 'create', '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) assert "An empty boot volume cannot be created. Please specify either --boot-volume-backup-id, --source-boot-volume-id or --source-volume-replica-id" in result.output # Error 2: Both options specified result = invoke(['bv', 'boot-volume', 'create', '--source-boot-volume-id', boot_volume_id[0], '--boot-volume-backup-id', boot_volume_id[0], '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) assert "You can only specify one of either --source-boot-volume-id, --boot-volume-backup-id or --source-volume-replica-id option" in result.output # Clone the boot volume (Error 1: Invalid Boot Volume ID) result = invoke(['bv', 'boot-volume', 'create', '--source-boot-volume-id', boot_volume_id[0], '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_service_error(result, error_message="InvalidParameter") backup_policy_ids = get_backup_policy_ids() create_new_size_in_gbs = new_size_in_gbs + 10 # Clone the boot volume with bronze backup policy and larger size result = invoke(['bv', 'boot-volume', 'create', '--source-boot-volume-id', boot_volume_id, '--backup-policy-id', backup_policy_ids["bronze"], '--wait-for-state', 'AVAILABLE', '--size-in-gbs', str(create_new_size_in_gbs), '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_response(result, json_response_expected=False) parsed_result = util.get_json_from_mixed_string(result.output) assert util.availability_domain() == parsed_result['data']['availability-domain'] assert 'AVAILABLE' == parsed_result['data']['lifecycle-state'] assert image_id == parsed_result['data']['image-id'] assert create_new_size_in_gbs == int(parsed_result['data']['size-in-gbs']) cloned_boot_volume_id = parsed_result['data']['id'] # Verify the backup policy result = invoke(['bv', 'volume-backup-policy-assignment', 'get-volume-backup-policy-asset-assignment', '--asset-id', cloned_boot_volume_id]) util.validate_response(result) parsed_result = json.loads(result.output) backup_policy_assignment_id = parsed_result["data"][0]["id"] assert parsed_result["data"][0]["policy-id"] == backup_policy_ids["bronze"] # Remove backup policy result = invoke(['bv', 'volume-backup-policy-assignment', 'delete', '--policy-assignment-id', backup_policy_assignment_id, '--force']) util.validate_response(result) # Change backup policy to silver result = invoke(['bv', 'volume-backup-policy-assignment', 'create', '--asset-id', cloned_boot_volume_id, '--policy-id', backup_policy_ids['silver']]) util.validate_response(result) parsed_result = json.loads(result.output) backup_policy_assignment_id = parsed_result["data"]["id"] assert parsed_result["data"]["policy-id"] == backup_policy_ids["silver"] # Remove the backup policy result = invoke(['bv', 'volume-backup-policy-assignment', 'delete', '--policy-assignment-id', backup_policy_assignment_id, '--force']) util.validate_response(result) # We can now launch an instance using that boot volume result = invoke([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', network_resources[1], '--shape', shape, '--hostname-label', hostname_label, '--source-boot-volume-id', cloned_boot_volume_id, '--wait-for-state', 'RUNNING', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS ]) util.validate_response(result, json_response_expected=False) instance_data = util.get_json_from_mixed_string(result.output)['data'] instance_ocid = instance_data['id'] assert 'bootVolume' == instance_data['source-details']['source-type'] assert cloned_boot_volume_id == instance_data['source-details']['boot-volume-id'] clean_up_instances(instance_ocid) cloned_boot_volume_id = None instance_ocid = None # Delete existing boot volume clean_up_boot_volume(boot_volume_id) boot_volume_id = None # Create boot volume from backup (Error 1: Invalid Backup Volume ID) result = invoke(['bv', 'boot-volume', 'create', '--boot-volume-backup-id', backup_id[0], '--availability-domain', util.availability_domain(), '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_service_error(result, error_message="InvalidParameter") # Create boot volume from backup (Error 2: Availability domain not specified) result = invoke(['bv', 'boot-volume', 'create', '--boot-volume-backup-id', backup_id, '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) assert "An availability domain must be specified when restoring a boot volume from backup" in result.output # Create boot volume from backup result = invoke(['bv', 'boot-volume', 'create', '--boot-volume-backup-id', backup_id, '--availability-domain', util.availability_domain(), '--wait-for-state', 'AVAILABLE', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS]) util.validate_response(result, json_response_expected=False) parsed_result = util.get_json_from_mixed_string(result.output) assert util.availability_domain() == parsed_result['data']['availability-domain'] assert 'AVAILABLE' == parsed_result['data']['lifecycle-state'] assert image_id == parsed_result['data']['image-id'] backup_boot_volume_id = parsed_result['data']['id'] # We can now launch an instance using that boot volume result = invoke([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', network_resources[1], '--shape', shape, '--hostname-label', hostname_label, '--source-boot-volume-id', backup_boot_volume_id, '--wait-for-state', 'RUNNING', '--wait-interval-seconds', util.WAIT_INTERVAL_SECONDS ]) util.validate_response(result, json_response_expected=False) instance_data = util.get_json_from_mixed_string(result.output)['data'] instance_ocid = instance_data['id'] assert 'bootVolume' == instance_data['source-details']['source-type'] assert backup_boot_volume_id == instance_data['source-details']['boot-volume-id'] clean_up_instances(instance_ocid) backup_boot_volume_id = None instance_ocid = None finally: clean_up_instances(instance_ocid) clean_up_boot_volume(boot_volume_id) clean_up_boot_volume(cloned_boot_volume_id) clean_up_boot_volume(backup_boot_volume_id) clean_up_boot_volume_backup(backup_id)
def subtest_subnet_secondary_ip_operations(self): self.set_up_vcn_and_subnet("10.0.0.0/16") available_ip_addresses = self.get_ip_addresses_from_cidr("10.0.0.0/16") # First we need to launch two instances and get their VNICs. We get two instances # so that we can move the secondary private IP around. The instances need to be # in the same subnet for the secondary private IP address moves to be valid image_id = util.oracle_linux_image() shape = 'VM.Standard1.1' first_instance_name = util.random_name('cli_test_instance') result = self.invoke([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', first_instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape ]) self.first_instance_id = util.find_id_in_response(result.output) second_instance_name = util.random_name('cli_test_instance') result = self.invoke([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', second_instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape ]) self.second_instance_id = util.find_id_in_response(result.output) util.wait_until([ 'compute', 'instance', 'get', '--instance-id', self.first_instance_id ], 'RUNNING', max_wait_seconds=600) util.wait_until([ 'compute', 'instance', 'get', '--instance-id', self.second_instance_id ], 'RUNNING', max_wait_seconds=600) vnics_on_instance_result = self.invoke([ 'compute', 'instance', 'list-vnics', '--instance-id', self.first_instance_id ]) vnics = json.loads(vnics_on_instance_result.output) first_vnic_id = vnics['data'][0]['id'] first_vnic_primary_private_ip = vnics['data'][0]['private-ip'] # So we don't try and re-use the IP address unintentionally available_ip_addresses.remove(first_vnic_primary_private_ip) vnics_on_instance_result = self.invoke([ 'compute', 'instance', 'list-vnics', '--instance-id', self.second_instance_id ]) vnics = json.loads(vnics_on_instance_result.output) second_vnic_id = vnics['data'][0]['id'] second_vnic_primary_private_ip = vnics['data'][0]['private-ip'] available_ip_addresses.remove(second_vnic_primary_private_ip) # Running the assign command against a non-existent VNIC fails fudged_vnic_id = self.fudge_ocid(first_vnic_id) result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', fudged_vnic_id ]) self.assertNotEqual(0, result.exit_code) assert 'Either VNIC with ID {} does not exist or you are not authorized to access it.'.format( fudged_vnic_id) in result.output # Most basic call with VNIC only - in this case we assign the IP automatically result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', first_vnic_id ]) first_secondary_private_ip_data = json.loads(result.output)['data'] first_secondary_private_ip_id = first_secondary_private_ip_data['id'] first_secondary_private_ip_address = first_secondary_private_ip_data[ 'ip-address'] available_ip_addresses.remove(first_secondary_private_ip_address) # Assign a new secondary IP with all parameters given second_secondary_private_ip_address = available_ip_addresses.pop() result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', first_vnic_id, '--ip-address', second_secondary_private_ip_address, '--display-name', 'My second secondary', '--hostname-label', 'secondary-1', # The --unassign-if-already-assigned should not have an impact as the IP address doesn't exist '--unassign-if-already-assigned' ]) second_secondary_private_ip_data = json.loads(result.output)['data'] second_secondary_private_ip_id = second_secondary_private_ip_data['id'] self.assertEqual(second_secondary_private_ip_address, second_secondary_private_ip_data['ip-address']) # Checkpoint by listing the private IPs. Our created secondaries should be there result = self.invoke( ['network', 'private-ip', 'list', '--vnic-id', first_vnic_id]) private_ips = json.loads(result.output)['data'] self.assertEqual(3, len(private_ips)) self.find_private_ip_and_do_assertions( private_ips, first_secondary_private_ip_id, first_secondary_private_ip_address, None, None) self.find_private_ip_and_do_assertions( private_ips, second_secondary_private_ip_id, second_secondary_private_ip_address, 'My second secondary', 'secondary-1') # Trying to assign the same private IP to the same VNIC is a no-op result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', first_vnic_id, '--ip-address', first_secondary_private_ip_address ]) assert 'Taking no action as IP address {} is already assigned to VNIC {}'.format( first_secondary_private_ip_address, first_vnic_id) in result.output # Trying to move a primary IP fails result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', first_vnic_id, '--ip-address', second_vnic_primary_private_ip, '--unassign-if-already-assigned' ]) self.assertNotEqual(0, result.exit_code) result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', first_vnic_primary_private_ip, '--unassign-if-already-assigned' ]) self.assertNotEqual(0, result.exit_code) # Trying to move an existing IP address without saying "unassign" fails result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', first_secondary_private_ip_address ]) target_message = 'IP address {} is already assigned to a different VNIC: {}. To reassign it, re-run this command with the --unassign-if-already-assigned option'.format( first_secondary_private_ip_address, first_vnic_id) assert target_message in result.output self.assertNotEqual(0, result.exit_code) # Move the secondary IP and also update some information result = self.invoke([ 'network', 'vnic', 'assign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', first_secondary_private_ip_address, '--display-name', 'My first secondary', '--hostname-label', 'moved-first-secondary-1', '--unassign-if-already-assigned' ]) private_ip_data_after_move = json.loads(result.output)['data'] self.assertEqual(first_secondary_private_ip_id, private_ip_data_after_move['id']) self.assertEqual(first_secondary_private_ip_address, private_ip_data_after_move['ip-address']) self.assertEqual('My first secondary', private_ip_data_after_move['display-name']) self.assertEqual('moved-first-secondary-1', private_ip_data_after_move['hostname-label']) # List each VNIC - we expect 2 results per list call (1 x primary private and 1 x secondary private per VNIC) after moving stuff around result = self.invoke( ['network', 'private-ip', 'list', '--vnic-id', first_vnic_id]) private_ips = json.loads(result.output)['data'] self.assertEqual(2, len(private_ips)) self.ensure_private_ip_record_not_present( private_ips, first_secondary_private_ip_id) self.find_private_ip_and_do_assertions( private_ips, second_secondary_private_ip_id, second_secondary_private_ip_address, 'My second secondary', 'secondary-1') result = self.invoke( ['network', 'private-ip', 'list', '--vnic-id', second_vnic_id]) private_ips = json.loads(result.output)['data'] self.assertEqual(2, len(private_ips)) self.ensure_private_ip_record_not_present( private_ips, second_secondary_private_ip_id) self.find_private_ip_and_do_assertions( private_ips, first_secondary_private_ip_id, first_secondary_private_ip_address, 'My first secondary', 'moved-first-secondary-1') # Listing by subnet should give us 4 records (2 x primary private and 2 x secondary private) as it queries across all VNICs in the subnet result = self.invoke( ['network', 'private-ip', 'list', '--subnet-id', self.subnet_ocid]) private_ips = json.loads(result.output)['data'] self.assertEqual(4, len(private_ips)) self.find_private_ip_and_do_assertions( private_ips, first_secondary_private_ip_id, first_secondary_private_ip_address, 'My first secondary', 'moved-first-secondary-1') self.find_private_ip_and_do_assertions( private_ips, second_secondary_private_ip_id, second_secondary_private_ip_address, 'My second secondary', 'secondary-1') # Update the display name and hostname result = self.invoke([ 'network', 'private-ip', 'update', '--private-ip-id', second_secondary_private_ip_id, '--display-name', 'batman display name', '--hostname-label', 'batman-secondary-1' ]) updated_private_ip_info = json.loads(result.output)['data'] self.assertEqual(second_secondary_private_ip_id, updated_private_ip_info['id']) self.assertEqual(second_secondary_private_ip_address, updated_private_ip_info['ip-address']) self.assertEqual(first_vnic_id, updated_private_ip_info['vnic-id']) self.assertEqual('batman display name', updated_private_ip_info['display-name']) self.assertEqual('batman-secondary-1', updated_private_ip_info['hostname-label']) # Do a get and confirm the information which we receive result = self.invoke([ 'network', 'private-ip', 'get', '--private-ip-id', second_secondary_private_ip_id ]) private_ip_info_from_get = json.loads(result.output)['data'] self.assertEqual(second_secondary_private_ip_id, private_ip_info_from_get['id']) self.assertEqual(second_secondary_private_ip_address, private_ip_info_from_get['ip-address']) self.assertEqual(first_vnic_id, private_ip_info_from_get['vnic-id']) self.assertEqual('batman display name', private_ip_info_from_get['display-name']) self.assertEqual('batman-secondary-1', private_ip_info_from_get['hostname-label']) # Running the unassign command against a non-existent VNIC fails # Listing by VNIC should give us one record (the primary private IP) per call result = self.invoke([ 'network', 'vnic', 'unassign-private-ip', '--vnic-id', fudged_vnic_id, '--ip-address', second_secondary_private_ip_address ]) self.assertNotEqual(0, result.exit_code) # The error message from the service is not being sent correctly to the CLI. The Error code is correct. # This needs to be investigated # assert 'Either VNIC with ID {} does not exist or you are not authorized to access it.'.format(fudged_vnic_id) in result.output # Unassigning an IP address not in the VNIC fails result = self.invoke([ 'network', 'vnic', 'unassign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', second_secondary_private_ip_address ]) assert 'IP address {} was not found on VNIC {}'.format( second_secondary_private_ip_address, second_vnic_id) in result.output self.assertNotEqual(0, result.exit_code) # Unassigning a primary private IP address is not supported result = self.invoke([ 'network', 'vnic', 'unassign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', second_vnic_primary_private_ip ]) assert 'Taking no action as {} is the primary private IP on VNIC {}'.format( second_vnic_primary_private_ip, second_vnic_id) in result.output self.assertNotEqual(0, result.exit_code) # Unassign a secondary private IP result = self.invoke([ 'network', 'vnic', 'unassign-private-ip', '--vnic-id', second_vnic_id, '--ip-address', first_secondary_private_ip_address ]) assert 'Unassigned IP address {} from VNIC {}'.format( first_secondary_private_ip_address, second_vnic_id) in result.output # Delete a secondary private IP (by its OCID) result = self.invoke([ 'network', 'private-ip', 'delete', '--private-ip-id', second_secondary_private_ip_id, '--force' ]) self.assertEqual(0, result.exit_code) # Listing by VNIC should give us one record (the primary private IP) per call result = self.invoke( ['network', 'private-ip', 'list', '--vnic-id', first_vnic_id]) private_ips = json.loads(result.output)['data'] self.assertEqual(1, len(private_ips)) self.assertTrue(private_ips[0]['is-primary']) result = self.invoke( ['network', 'private-ip', 'list', '--vnic-id', second_vnic_id]) private_ips = json.loads(result.output)['data'] self.assertEqual(1, len(private_ips)) self.assertTrue(private_ips[0]['is-primary']) # Listing by subnet should give us two records (the primary private IP for each VNIC) result = self.invoke( ['network', 'private-ip', 'list', '--subnet-id', self.subnet_ocid]) private_ips = json.loads(result.output)['data'] self.assertEqual(2, len(private_ips)) self.assertTrue(private_ips[0]['is-primary']) self.assertTrue(private_ips[1]['is-primary'])
def subtest_launch_instance_ipxe_script_file_and_extended_metadata(self): instance_name = util.random_name('cli_test_instance_options') image_id = util.oracle_linux_image() shape = 'VM.Standard1.2' hostname_label = util.random_name('bminstance', insert_underscore=False) vnic_display_name = 'vnic_display_name' private_ip = '10.0.0.15' assign_public_ip = 'true' extended_metadata = '{"a": "1", "b": {"c": "3", "d": {}}}' launch_instance_result = util.invoke_command([ 'compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape, '--ipxe-script-file', IPXE_SCRIPT_FILE, '--hostname-label', hostname_label + "1", '--private-ip', private_ip, '--assign-public-ip', assign_public_ip, '--vnic-display-name', vnic_display_name, '--extended-metadata', extended_metadata ]) temp_instance_ocid = util.find_id_in_response( launch_instance_result.output) self.instance_ocids.append(temp_instance_ocid) util.validate_response(launch_instance_result, expect_etag=True) extended_metadata_result = json.loads( launch_instance_result.output)['data']['extended-metadata'] assert extended_metadata_result['a'] == '1' assert extended_metadata_result['b']['c'] == '3' # This can be in ATTACHING state for some time try: util.wait_until([ 'compute', 'vnic-attachment', 'list', '--compartment-id', util.COMPARTMENT_ID, '--instance-id', temp_instance_ocid ], 'ATTACHED', max_wait_seconds=60, item_index_in_list_response=0) except Exception: try: # If it is ATTACHING we will consider it good enough util.wait_until([ 'compute', 'vnic-attachment', 'list', '--compartment-id', util.COMPARTMENT_ID, '--instance-id', temp_instance_ocid ], 'ATTACHING', max_wait_seconds=30, item_index_in_list_response=0) except Exception: # If it is not ATTACHING, double check that it didn't go to ATTACHED util.wait_until([ 'compute', 'vnic-attachment', 'list', '--compartment-id', util.COMPARTMENT_ID, '--instance-id', temp_instance_ocid ], 'ATTACHED', max_wait_seconds=30, item_index_in_list_response=0) # get vnic attachments for given instance list_vnics_result = util.invoke_command([ 'compute', 'vnic-attachment', 'list', '--compartment-id', util.COMPARTMENT_ID, '--instance-id', temp_instance_ocid ]) vnic_id = json.loads(list_vnics_result.output)['data'][0]['vnic-id'] # get full data for vnic attached to new instance (which includes hostname-label) get_vnic_result = util.invoke_command( ['network', 'vnic', 'get', '--vnic-id', vnic_id]) vnic = json.loads(get_vnic_result.output)['data'] assert vnic['hostname-label'] == hostname_label + "1" assert vnic['display-name'] == vnic_display_name assert vnic['public-ip'] content = None with open(IPXE_SCRIPT_FILE, mode='r') as file: content = file.read() assert 'ipxe-script' in launch_instance_result.output # Just look at the first few characters. Once we hit a line break the formatting will differ. assert content[:5] in launch_instance_result.output self.delete_instance(temp_instance_ocid)
def set_up_resources(self): # Grab the Object Storage namespace result = self.invoke(['os', 'ns', 'get']) self.object_storage_namespace = json.loads(result.output)['data'] # Create a bucket print("Creating bucket") self.bucket_name = util.random_name('CliImageImportExport') result = self.invoke( ['os', 'bucket', 'create', '--compartment-id', util.COMPARTMENT_ID, '--namespace', self.object_storage_namespace, '--name', self.bucket_name]) util.validate_response(result, expect_etag=True) # Create a VCN print("Creating VCN") vcn_name = util.random_name('cli_test_compute_vcn') result = self.invoke( ['network', 'vcn', 'create', '--compartment-id', util.COMPARTMENT_ID, '--display-name', vcn_name, '--dns-label', 'clivcn', '--cidr-block', '10.0.0.0/16']) util.validate_response(result, expect_etag=True) self.vcn_ocid = util.find_id_in_response(result.output) util.wait_until(['network', 'vcn', 'get', '--vcn-id', self.vcn_ocid], 'AVAILABLE', max_wait_seconds=300) # Create a subnet print("Creating subnet") subnet_name = util.random_name('cli_test_compute_subnet') result = self.invoke( ['network', 'subnet', 'create', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', subnet_name, '--dns-label', 'clisubnet', '--vcn-id', self.vcn_ocid, '--cidr-block', '10.0.0.0/16', ]) util.validate_response(result, expect_etag=True) self.subnet_ocid = util.find_id_in_response(result.output) util.wait_until(['network', 'subnet', 'get', '--subnet-id', self.subnet_ocid], 'AVAILABLE', max_wait_seconds=300) # Create an instance image_id = util.oracle_linux_image() shape = 'VM.Standard1.1' instance_name = util.random_name('cli_test_instance') print("Creating instance " + instance_name) result = self.invoke( ['compute', 'instance', 'launch', '--compartment-id', util.COMPARTMENT_ID, '--availability-domain', util.availability_domain(), '--display-name', instance_name, '--subnet-id', self.subnet_ocid, '--image-id', image_id, '--shape', shape]) util.validate_response(result, expect_etag=True) self.instance_id = util.find_id_in_response(result.output) util.wait_until(['compute', 'instance', 'get', '--instance-id', self.instance_id], 'RUNNING', max_wait_seconds=600) # Export an image from the instance to use in tests print("Exporting image") result = self.invoke( ['compute', 'image', 'create', '--compartment-id', util.COMPARTMENT_ID, '--instance-id', self.instance_id]) util.validate_response(result, expect_etag=True) self.custom_image_id = util.find_id_in_response(result.output) util.wait_until(['compute', 'image', 'get', '--image-id', self.custom_image_id], 'AVAILABLE', max_wait_seconds=3600)