def test_attach_detach_volume(self): """ Create a new volume, and attempt to attach it to an instance """ instance_name = "CBVolOps-{0}-{1}".format( self.provider.name, uuid.uuid4()) net, _ = helpers.create_test_network(self.provider, instance_name) test_instance = helpers.get_test_instance(self.provider, instance_name, network=net) with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( test_instance, net)): name = "CBUnitTestAttachVol-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, test_instance.zone_id) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() test_vol.attach(test_instance, '/dev/sda2') test_vol.wait_for( [VolumeState.IN_USE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) test_vol.detach() test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
def test_attach_detach_volume(self): """ Create a new volume, and attempt to attach it to an instance """ name = "cb_attachvol-{0}".format(helpers.get_uuid()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None test_instance = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(test_instance, net)): net, subnet = helpers.create_test_network(self.provider, name) test_instance = helpers.get_test_instance(self.provider, name, subnet=subnet) test_vol = self.provider.storage.volumes.create( name, 1, test_instance.zone_id) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() test_vol.attach(test_instance, '/dev/sda2') test_vol.wait_for( [VolumeState.IN_USE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) test_vol.detach() test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
def _cleanup(net, subnet, router, gateway): with helpers.cleanup_action(lambda: net.delete()): with helpers.cleanup_action(lambda: subnet.delete()): with helpers.cleanup_action(lambda: gateway.delete()): with helpers.cleanup_action(lambda: router.delete()): router.detach_subnet(subnet) router.detach_gateway(gateway)
def test_crud_vm_firewall_rules(self): name = 'cb_crudfw_rules-{0}'.format(helpers.get_uuid()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(network=net)): net, _ = helpers.create_test_network(self.provider, name) fw = None with helpers.cleanup_action(lambda: fw.delete()): fw = self.provider.security.vm_firewalls.create( name=name, description=name, network_id=net.id) def create_fw_rule(name): return fw.rules.create(direction=TrafficDirection.INBOUND, protocol='tcp', from_port=1111, to_port=1111, cidr='0.0.0.0/0') def cleanup_fw_rule(rule): rule.delete() sit.check_crud(self, fw.rules, VMFirewallRule, "cb_crudfwrule", create_fw_rule, cleanup_fw_rule, skip_name_check=True)
def test_upload_download_bucket_content_with_large_file(self): """ Creates a 6 Gig file in the temp directory, then uploads it to Swift. Once uploaded, then downloads to a new file in the temp directory and compares the two files to see if they match. """ temp_dir = tempfile.gettempdir() file_name = '6GigTest.tmp' six_gig_file = os.path.join(temp_dir, file_name) with open(six_gig_file, "wb") as out: out.truncate(6 * 1024 * 1024 * 1024) # 6 Gig... with helpers.cleanup_action(lambda: os.remove(six_gig_file)): download_file = "{0}/cbtestfile-{1}".format(temp_dir, file_name) bucket_name = "cbtestbucketlargeobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(bucket_name) with helpers.cleanup_action(lambda: test_bucket.delete()): test_obj = test_bucket.create_object(file_name) with helpers.cleanup_action(lambda: test_obj.delete()): file_uploaded = test_obj.upload_from_file(six_gig_file) self.assertTrue(file_uploaded, "Could not upload object?") with helpers.cleanup_action( lambda: os.remove(download_file)): with open(download_file, 'wb') as f: test_obj.save_content(f) self.assertTrue( filecmp.cmp(six_gig_file, download_file), "Uploaded file != downloaded")
def test_volume_properties(self): """ Test volume properties """ instance_name = "CBVolProps-{0}-{1}".format(self.provider.name, uuid.uuid4()) vol_desc = 'newvoldesc1' # Declare these variables and late binding will allow # the cleanup method access to the most current values test_instance = None net = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(test_instance, net)): net, subnet = helpers.create_test_network(self.provider, instance_name) test_instance = helpers.get_test_instance(self.provider, instance_name, subnet=subnet) name = "CBUnitTestVolProps-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, test_instance.zone_id, description=vol_desc) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() self.assertTrue( isinstance(test_vol.size, six.integer_types) and test_vol.size >= 0, "Volume.size must be a positive number, but got %s" % test_vol.size) self.assertTrue( test_vol.description is None or isinstance(test_vol.description, six.string_types), "Volume.description must be None or a string. Got: %s" % test_vol.description) self.assertIsNone(test_vol.source) self.assertIsNone(test_vol.source) self.assertIsNotNone(test_vol.create_time) self.assertIsNotNone(test_vol.zone_id) self.assertIsNone(test_vol.attachments) test_vol.attach(test_instance, '/dev/sda2') test_vol.wait_for( [VolumeState.IN_USE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) self.assertIsNotNone(test_vol.attachments) self.assertIsInstance(test_vol.attachments, AttachmentInfo) self.assertEqual(test_vol.attachments.volume, test_vol) self.assertEqual(test_vol.attachments.instance_id, test_instance.id) self.assertEqual(test_vol.attachments.device, "/dev/sda2") test_vol.detach() test_vol.name = 'newvolname1' test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) self.assertEqual(test_vol.name, 'newvolname1') self.assertEqual(test_vol.description, vol_desc) self.assertIsNone(test_vol.attachments) test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
def test_volume_properties(self): """ Test volume properties """ label = "cb-volprops-{0}".format(helpers.get_uuid()) vol_desc = 'newvoldesc1' # Declare these variables and late binding will allow # the cleanup method access to the most current values test_instance = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(test_instance)): subnet = helpers.get_or_create_default_subnet(self.provider) test_instance = helpers.get_test_instance(self.provider, label, subnet=subnet) test_vol = self.provider.storage.volumes.create( label, 1, test_instance.zone_id, description=vol_desc) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() self.assertTrue( isinstance(test_vol.size, six.integer_types) and test_vol.size >= 0, "Volume.size must be a positive number, but got %s" % test_vol.size) self.assertTrue( test_vol.description is None or isinstance(test_vol.description, six.string_types), "Volume.description must be None or a string. Got: %s" % test_vol.description) self.assertIsNone(test_vol.source) self.assertIsNone(test_vol.source) self.assertIsNotNone(test_vol.create_time) self.assertIsNotNone(test_vol.zone_id) self.assertIsNone(test_vol.attachments) test_vol.attach(test_instance, '/dev/sda2') test_vol.wait_for( [VolumeState.IN_USE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) self.assertIsNotNone(test_vol.attachments) self.assertIsInstance(test_vol.attachments, AttachmentInfo) self.assertEqual(test_vol.attachments.volume, test_vol) self.assertEqual(test_vol.attachments.instance_id, test_instance.id) if not self.provider.PROVIDER_ID == 'azure': self.assertEqual(test_vol.attachments.device, "/dev/sda2") test_vol.detach() test_vol.label = 'newvolname1' test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) self.assertEqual(test_vol.label, 'newvolname1') self.assertEqual(test_vol.description, vol_desc) self.assertIsNone(test_vol.attachments) test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
def test_network_properties(self): label = 'cb-propnetwork-{0}'.format(helpers.get_uuid()) subnet_label = 'cb-propsubnet-{0}'.format(helpers.get_uuid()) net = self.provider.networking.networks.create( label=label, cidr_block=BaseNetwork.CB_DEFAULT_IPV4RANGE) with helpers.cleanup_action(lambda: net.delete()): net.wait_till_ready() self.assertEqual( net.state, 'available', "Network in state '%s', yet should be 'available'" % net.state) sit.check_repr(self, net) self.assertIn( net.cidr_block, ['', BaseNetwork.CB_DEFAULT_IPV4RANGE], "Network CIDR %s does not contain the expected value %s." % (net.cidr_block, BaseNetwork.CB_DEFAULT_IPV4RANGE)) cidr = '10.0.20.0/24' sn = net.create_subnet(label=subnet_label, cidr_block=cidr, zone=helpers.get_provider_test_data( self.provider, 'placement')) with helpers.cleanup_action(lambda: sn.delete()): self.assertTrue( sn in net.subnets, "Subnet ID %s should be listed in network subnets %s." % (sn.id, net.subnets)) self.assertTrue( sn in self.provider.networking.subnets.list(network=net), "Subnet ID %s should be included in the subnets list %s." % (sn.id, self.provider.networking.subnets.list(net))) self.assertListEqual( net.subnets, [sn], "Network should have exactly one subnet: %s." % sn.id) self.assertEqual( net.id, sn.network_id, "Network ID %s and subnet's network id %s should be" " equal." % (net.id, sn.network_id)) self.assertEqual( net, sn.network, "Network obj %s and subnet's parent net obj %s" " should be equal." % (net, sn.network)) self.assertEqual( cidr, sn.cidr_block, "Should be exact cidr block that was requested") self.assertTrue( BaseNetwork.cidr_blocks_overlap(cidr, sn.cidr_block), "Subnet's CIDR %s should overlap the specified one %s." % (sn.cidr_block, cidr))
def test_snapshot_properties(self): """ Test snapshot properties """ label = "cb-snapprop-{0}".format(helpers.get_uuid()) test_vol = self.provider.storage.volumes.create( label, 1, helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() snap_label = "cb-snap-{0}".format(label) test_snap = test_vol.create_snapshot(label=snap_label, description=snap_label) def cleanup_snap(snap): if snap: snap.delete() snap.wait_for([SnapshotState.UNKNOWN], terminal_states=[SnapshotState.ERROR]) with helpers.cleanup_action(lambda: cleanup_snap(test_snap)): test_snap.wait_till_ready() self.assertTrue(isinstance(test_vol.size, six.integer_types)) self.assertEqual( test_snap.size, test_vol.size, "Snapshot.size must match original volume's size: %s" " but is: %s" % (test_vol.size, test_snap.size)) self.assertTrue( test_vol.description is None or isinstance(test_vol.description, six.string_types), "Snapshot.description must be None or a string. Got: %s" % test_vol.description) self.assertEqual(test_vol.id, test_snap.volume_id) self.assertIsNotNone(test_vol.create_time) test_snap.label = 'snapnewname1' test_snap.description = 'snapnewdescription1' test_snap.refresh() self.assertEqual(test_snap.label, 'snapnewname1') self.assertEqual(test_snap.description, 'snapnewdescription1') # Test volume creation from a snapshot (via VolumeService) sv_label = "cb-snapvol-{0}".format(test_snap.name) snap_vol = self.provider.storage.volumes.create( sv_label, 1, helpers.get_provider_test_data(self.provider, "placement"), snapshot=test_snap) with helpers.cleanup_action(lambda: snap_vol.delete()): snap_vol.wait_till_ready() # Test volume creation from a snapshot (via Snapshot) snap_vol2 = test_snap.create_volume( helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: snap_vol2.delete()): snap_vol2.wait_till_ready()
def test_crud_bucket_object_properties(self): """ Create a new bucket, upload some contents into the bucket, and check whether list properly detects the new content. Delete everything afterwards. """ name = "cbtestbucketobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.storage.buckets.create(name) # ensure that the bucket is empty objects = test_bucket.objects.list() self.assertEqual([], objects) with helpers.cleanup_action(lambda: test_bucket.delete()): obj_name_prefix = "hello" obj_name = obj_name_prefix + "_world.txt" obj = test_bucket.objects.create(obj_name) with helpers.cleanup_action(lambda: obj.delete()): # TODO: This is wrong. We shouldn't have to have a separate # call to upload some content before being able to delete # the content. Maybe the create_object method should accept # the file content as a parameter. obj.upload("dummy content") objs = test_bucket.objects.list() self.assertTrue( isinstance(objs[0].size, int), "Object size property needs to be a int, not {0}".format( type(objs[0].size))) self.assertTrue( datetime.strptime(objs[0].last_modified[:23], "%Y-%m-%dT%H:%M:%S.%f"), "Object's last_modified field format {0} not matching.". format(objs[0].last_modified)) # check iteration iter_objs = list(test_bucket.objects) self.assertListEqual(iter_objs, objs) obj_too = test_bucket.objects.get(obj_name) self.assertTrue( isinstance(obj_too, BucketObject), "Did not get object {0} of expected type.".format(obj_too)) prefix_filtered_list = test_bucket.objects.list( prefix=obj_name_prefix) self.assertTrue( len(objs) == len(prefix_filtered_list) == 1, 'The number of objects returned by list function, ' 'with and without a prefix, are expected to be equal, ' 'but its detected otherwise.') sit.check_delete(self, test_bucket.objects, obj)
def test_volume_properties(self): """ Test volume properties """ instance_name = "CBVolProps-{0}-{1}".format( self.provider.name, uuid.uuid4()) vol_desc = 'newvoldesc1' net, _ = helpers.create_test_network(self.provider, instance_name) test_instance = helpers.get_test_instance(self.provider, instance_name, network=net) with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( test_instance, net)): name = "CBUnitTestVolProps-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, test_instance.zone_id, description=vol_desc) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() self.assertTrue( isinstance(test_vol.size, six.integer_types) and test_vol.size >= 0, "Volume.size must be a positive number, but got %s" % test_vol.size) self.assertTrue( test_vol.description is None or isinstance(test_vol.description, six.string_types), "Volume.description must be None or a string. Got: %s" % test_vol.description) self.assertIsNone(test_vol.source) self.assertIsNone(test_vol.source) self.assertIsNotNone(test_vol.create_time) self.assertIsNotNone(test_vol.zone_id) self.assertIsNone(test_vol.attachments) test_vol.attach(test_instance, '/dev/sda2') test_vol.wait_for( [VolumeState.IN_USE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED]) self.assertIsNotNone(test_vol.attachments) self.assertIsInstance(test_vol.attachments, AttachmentInfo) self.assertEqual(test_vol.attachments.volume, test_vol) self.assertEqual(test_vol.attachments.instance_id, test_instance.id) self.assertEqual(test_vol.attachments.device, "/dev/sda2") test_vol.detach() test_vol.name = 'newvolname1' # Force a refresh before checking attachment status test_vol.refresh() self.assertEqual(test_vol.name, 'newvolname1') self.assertEqual(test_vol.description, vol_desc) self.assertIsNone(test_vol.attachments) test_vol.wait_for( [VolumeState.AVAILABLE], terminal_states=[VolumeState.ERROR, VolumeState.DELETED])
def test_crud_bucket_objects(self): """ Create a new bucket, upload some contents into the bucket, and check whether list properly detects the new content. Delete everything afterwards. """ name = "cbtestbucketobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) # ensure that the bucket is empty objects = test_bucket.list() self.assertEqual([], objects) with helpers.cleanup_action(lambda: test_bucket.delete()): obj_name = "hello_world.txt" obj = test_bucket.create_object(obj_name) self.assertTrue( obj.id in repr(obj), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") with helpers.cleanup_action(lambda: obj.delete()): # TODO: This is wrong. We shouldn't have to have a separate # call to upload some content before being able to delete # the content. Maybe the create_object method should accept # the file content as a parameter. obj.upload("dummy content") objs = test_bucket.list() # check iteration iter_objs = list(test_bucket) self.assertListEqual(iter_objs, objs) found_objs = [o for o in objs if o.name == obj_name] self.assertTrue( len(found_objs) == 1, "List bucket objects does not return the expected" " object %s" % obj_name) self.assertTrue( found_objs[0] == obj, "Objects returned by list: {0} are not as " " expected: {1}" .format(found_objs[0].id, obj.id)) objs = test_bucket.list() found_objs = [o for o in objs if o.name == obj_name] self.assertTrue( len(found_objs) == 0, "Object %s should have been deleted but still exists." % obj_name)
def test_crud_network_service(self): name = 'cbtestnetworkservice-{0}'.format(uuid.uuid4()) subnet_name = 'cbtestsubnetservice-{0}'.format(uuid.uuid4()) net = self.provider.network.create(name=name) with helpers.cleanup_action( lambda: self.provider.network.delete(network_id=net.id) ): # test list method netl = self.provider.network.list() list_netl = [n for n in netl if n.name == name] self.assertTrue( len(list_netl) == 1, "List networks does not return the expected network %s" % name) # check get get_net = self.provider.network.get(network_id=net.id) self.assertTrue( get_net == net, "Get network did not return the expected network {0}." .format(name)) # check subnet subnet = self.provider.network.create_subnet( network=net, cidr_block="10.0.0.1/24", name=subnet_name) with helpers.cleanup_action( lambda: self.provider.network.delete_subnet(subnet=subnet) ): # test list method subnetl = self.provider.network.list_subnets() list_subnetl = [n for n in subnetl if n.name == subnet_name] self.assertTrue( len(list_subnetl) == 1, "List subnets does not return the expected subnet %s" % subnet_name) subnetl = self.provider.network.list_subnets() found_subnet = [n for n in subnetl if n.name == subnet_name] self.assertTrue( len(found_subnet) == 0, "Subnet {0} should have been deleted but still exists." .format(subnet_name)) netl = self.provider.network.list() found_net = [n for n in netl if n.name == name] self.assertEqual( len(found_net), 0, "Network {0} should have been deleted but still exists." .format(name))
def test_generate_url(self): name = "cbtestbucketobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) with helpers.cleanup_action(lambda: test_bucket.delete()): obj_name = "hello_upload_download.txt" obj = test_bucket.create_object(obj_name) with helpers.cleanup_action(lambda: obj.delete()): content = b"Hello World. Generate a url." obj.upload(content) target_stream = BytesIO() obj.save_content(target_stream) url = obj.generate_url(100) self.assertEqual(requests.get(url).content, content)
def test_upload_download_bucket_content_from_file(self): name = "cbtestbucketobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) with helpers.cleanup_action(lambda: test_bucket.delete()): obj_name = "hello_upload_download.txt" obj = test_bucket.create_object(obj_name) with helpers.cleanup_action(lambda: obj.delete()): test_file = os.path.join(helpers.get_test_fixtures_folder(), 'logo.jpg') obj.upload_from_file(test_file) target_stream = BytesIO() obj.save_content(target_stream) with open(test_file, 'rb') as f: self.assertEqual(target_stream.getvalue(), f.read())
def test_vm_firewall_group_rule(self): label = 'cb-fwrule-{0}'.format(helpers.get_uuid()) # Declare these variables and late binding will allow # the cleanup method access to the most current values fw = None with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( vm_firewall=fw)): subnet = helpers.get_or_create_default_subnet(self.provider) net = subnet.network fw = self.provider.security.vm_firewalls.create( label=label, description=label, network=net.id) rule = fw.rules.create( direction=TrafficDirection.INBOUND, src_dest_fw=fw, protocol='tcp', from_port=1, to_port=65535) self.assertTrue( rule.src_dest_fw.label == fw.label, "Expected VM firewall rule label {0}. Got {1}." .format(fw.label, rule.src_dest_fw.label)) for r in fw.rules: r.delete() fw = self.provider.security.vm_firewalls.get(fw.id) # update self.assertTrue( len(list(fw.rules)) == 0, "Deleting VMFirewallRule should delete it: {0}".format( fw.rules)) fwl = self.provider.security.vm_firewalls.list() found_fw = [f for f in fwl if f.label == label] self.assertTrue( len(found_fw) == 0, "VM firewall {0} should have been deleted but still exists." .format(label))
def test_object_life_cycle(self): """ Test object life cycle methods by using a volume. """ name = "cb_objlifecycle-{0}".format(helpers.get_uuid()) test_vol = self.provider.storage.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) # Waiting for an invalid timeout should raise an exception with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=-1, interval=1) with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=1, interval=-1) # If interval < timeout, an exception should be raised with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=10, interval=20) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() # Hitting a terminal state should raise an exception with self.assertRaises(WaitStateException): test_vol.wait_for([VolumeState.ERROR], terminal_states=[VolumeState.AVAILABLE]) # Hitting the timeout should raise an exception with self.assertRaises(WaitStateException): test_vol.wait_for([VolumeState.ERROR], timeout=0, interval=0)
def test_crud_bucket_object(self): test_bucket = None def create_bucket_obj(name): obj = test_bucket.create_object(name) # TODO: This is wrong. We shouldn't have to have a separate # call to upload some content before being able to delete # the content. Maybe the create_object method should accept # the file content as a parameter. obj.upload("dummy content") return obj def cleanup_bucket_obj(bucket_obj): bucket_obj.delete() with helpers.cleanup_action(lambda: test_bucket.delete()): name = "cb-crudbucketobj-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) sit.check_crud(self, test_bucket, BucketObject, "cb_bucketobj", create_bucket_obj, cleanup_bucket_obj, skip_name_check=True)
def test_vm_firewall_rule_add_twice(self): name = 'cb_fwruletwice-{0}'.format(helpers.get_uuid()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None fw = None with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( network=net, vm_firewall=fw)): net, _ = helpers.create_test_network(self.provider, name) fw = self.provider.security.vm_firewalls.create(name=name, description=name, network_id=net.id) rule = fw.rules.create(direction=TrafficDirection.INBOUND, protocol='tcp', from_port=1111, to_port=1111, cidr='0.0.0.0/0') # attempting to add the same rule twice should succeed same_rule = fw.rules.create(direction=TrafficDirection.INBOUND, protocol='tcp', from_port=1111, to_port=1111, cidr='0.0.0.0/0') self.assertEqual(rule, same_rule)
def test_crud_instance(self): name = "CBInstCrud-{0}-{1}".format(self.provider.name, uuid.uuid4()) # Declare these variables and late binding will allow # the cleanup method access to the most current values inst = None net = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(inst, net)): net, subnet = helpers.create_test_network(self.provider, name) inst = helpers.get_test_instance(self.provider, name, subnet=subnet) all_instances = self.provider.compute.instances.list() list_instances = [i for i in all_instances if i.name == name] self.assertTrue( len(list_instances) == 1, "List instances does not return the expected instance %s" % name) # check iteration iter_instances = [ i for i in self.provider.compute.instances if i.name == name ] self.assertTrue( len(iter_instances) == 1, "Iter instances does not return the expected instance %s" % name) # check find find_instances = self.provider.compute.instances.find(name=name) self.assertTrue( len(find_instances) == 1, "Find instances does not return the expected instance %s" % name) # check non-existent find find_instances = self.provider.compute.instances.find( name="non_existent") self.assertTrue( len(find_instances) == 0, "Find() for a non-existent image returned %s" % find_instances) get_inst = self.provider.compute.instances.get(inst.id) self.assertTrue( list_instances[0] == get_inst == inst, "Objects returned by list: {0} and get: {1} are not as " " expected: {2}".format(list_instances[0].id, get_inst.id, inst.id)) self.assertTrue( list_instances[0].name == get_inst.name == inst.name, "Names returned by list: {0} and get: {1} are not as " " expected: {2}".format(list_instances[0].name, get_inst.name, inst.name)) deleted_inst = self.provider.compute.instances.get(inst.id) self.assertTrue( deleted_inst is None or deleted_inst.state in (InstanceState.TERMINATED, InstanceState.UNKNOWN), "Instance %s should have been deleted but still exists." % name)
def test_object_life_cycle(self): """ Test object life cycle methods by using a volume. """ name = "CBUnitTestLifeCycle-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) # Waiting for an invalid timeout should raise an exception with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=-1, interval=1) with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=1, interval=-1) # If interval < timeout, an exception should be raised with self.assertRaises(AssertionError): test_vol.wait_for([VolumeState.ERROR], timeout=10, interval=20) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() # Hitting a terminal state should raise an exception with self.assertRaises(WaitStateException): test_vol.wait_for([VolumeState.ERROR], terminal_states=[VolumeState.AVAILABLE]) # Hitting the timeout should raise an exception with self.assertRaises(WaitStateException): test_vol.wait_for([VolumeState.ERROR], timeout=0, interval=0)
def test_security_group_group_role(self): """Test for proper creation of a security group rule.""" name = 'cbtestsecuritygroupC-{0}'.format(uuid.uuid4()) sg = self.provider.security.security_groups.create( name=name, description=name) with helpers.cleanup_action(lambda: sg.delete()): self.assertTrue( len(sg.rules) == 0, "Expected no security group group rule. Got {0}." .format(sg.rules)) rule = sg.add_rule(src_group=sg) self.assertTrue( rule.group.name == name, "Expected security group rule name {0}. Got {1}." .format(name, rule.group.name)) for r in sg.rules: r.delete() sg = self.provider.security.security_groups.get(sg.id) # update self.assertTrue( len(sg.rules) == 0, "Deleting SecurityGroupRule should delete it: {0}".format( sg.rules)) sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists." .format(name))
def test_crud_vm_firewall_rules(self): label = 'cb-crudfw-rules-{0}'.format(helpers.get_uuid()) subnet = helpers.get_or_create_default_subnet(self.provider) net = subnet.network fw = None with helpers.cleanup_action(lambda: fw.delete()): fw = self.provider.security.vm_firewalls.create(label=label, description=label, network_id=net.id) def create_fw_rule(label): return fw.rules.create(direction=TrafficDirection.INBOUND, protocol='tcp', from_port=1111, to_port=1111, cidr='0.0.0.0/0') def cleanup_fw_rule(rule): if rule: rule.delete() sit.check_crud(self, fw.rules, VMFirewallRule, "cb-crudfwrule", create_fw_rule, cleanup_fw_rule, skip_name_check=True)
def create_instance_from_image(img): img_instance = None with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(img_instance)): img_instance = self.provider.compute.instances.create( img_inst_label, img, helpers.get_provider_test_data(self.provider, 'vm_type'), subnet=subnet, zone=helpers.get_provider_test_data( self.provider, 'placement')) img_instance.wait_till_ready() self.assertIsInstance(img_instance, Instance) self.assertEqual( img_instance.label, img_inst_label, "Instance label {0} is not equal to the expected label" " {1}".format(img_instance.label, img_inst_label)) image_id = img.id self.assertEqual( img_instance.image_id, image_id, "Image id {0} is not equal to the expected id" " {1}".format(img_instance.image_id, image_id)) self.assertIsInstance(img_instance.public_ips, list) if img_instance.public_ips: self.assertTrue( img_instance.public_ips[0], "public ip should contain a" " valid value if a list of public_ips exist") self.assertIsInstance(img_instance.private_ips, list) self.assertTrue(img_instance.private_ips[0], "private ip should" " contain a valid value")
def test_crud_snapshot(self): """ Create a new volume, create a snapshot of the volume, and check whether list_snapshots properly detects the new snapshot. Delete everything afterwards. """ name = "cb_crudsnap-{0}".format(helpers.get_uuid()) test_vol = self.provider.storage.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() def create_snap(name): return test_vol.create_snapshot(name=name, description=name) def cleanup_snap(snap): snap.delete() snap.wait_for([SnapshotState.UNKNOWN], terminal_states=[SnapshotState.ERROR]) sit.check_crud(self, self.provider.storage.snapshots, Snapshot, "cb_snap", create_snap, cleanup_snap) # Test creation of a snap via SnapshotService def create_snap2(name): return self.provider.storage.snapshots.create(name=name, volume=test_vol, description=name) if (self.provider.PROVIDER_ID == ProviderList.AWS and not isinstance(self.provider, TestMockHelperMixin)): time.sleep(15) # Or get SnapshotCreationPerVolumeRateExceeded sit.check_crud(self, self.provider.storage.snapshots, Snapshot, "cb_snaptwo", create_snap2, cleanup_snap)
def test_security_group_group_rule(self): """Test for proper creation of a security group rule.""" name = 'cbtestsecuritygroupC-{0}'.format(uuid.uuid4()) net = self.provider.network.create(name=name) sg = self.provider.security.security_groups.create(name=name, description=name, network_id=net.id) with helpers.cleanup_action(lambda: self.cleanup_sg(sg, net)): self.assertTrue( len(sg.rules) == 0, "Expected no security group group rule. Got {0}.".format( sg.rules)) rule = sg.add_rule(src_group=sg, ip_protocol='tcp', from_port=0, to_port=65535) self.assertTrue( rule.group.name == name, "Expected security group rule name {0}. Got {1}.".format( name, rule.group.name)) for r in sg.rules: r.delete() sg = self.provider.security.security_groups.get(sg.id) # update self.assertTrue( len(sg.rules) == 0, "Deleting SecurityGroupRule should delete it: {0}".format( sg.rules)) sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists.". format(name))
def test_key_pair(self): name = 'cbtestkeypairB-{0}'.format(uuid.uuid4()) kp = self.provider.security.key_pairs.create(name=name) with helpers.cleanup_action(lambda: kp.delete()): kpl = self.provider.security.key_pairs.list() found_kp = [k for k in kpl if k.name == name] self.assertTrue( len(found_kp) == 1, "List key pairs did not return the expected key {0}." .format(name)) self.assertTrue( kp.id in repr(kp), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") self.assertIsNotNone( kp.material, "KeyPair material is empty but it should not be.") self.assertTrue( kp == kp, "The same key pair should be equal to self.") json_repr = json.dumps( {"material": kp.material, "id": name, "name": name}, sort_keys=True) self.assertEqual( kp.to_json(), json_repr, "JSON key pair representation {0} does not match expected {1}" .format(kp.to_json(), json_repr)) kpl = self.provider.security.key_pairs.list() found_kp = [k for k in kpl if k.name == name] self.assertTrue( len(found_kp) == 0, "Key pair {0} should have been deleted but still exists." .format(name))
def test_crud_instance(self): name = "cb_instcrud-{0}".format(helpers.get_uuid()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None subnet = None def create_inst(name): return helpers.get_test_instance(self.provider, name, subnet=subnet) def cleanup_inst(inst): inst.terminate() inst.wait_for([InstanceState.TERMINATED, InstanceState.UNKNOWN]) def check_deleted(inst): deleted_inst = self.provider.compute.instances.get(inst.id) self.assertTrue( deleted_inst is None or deleted_inst.state in (InstanceState.TERMINATED, InstanceState.UNKNOWN), "Instance %s should have been deleted but still exists." % name) with helpers.cleanup_action( lambda: helpers.cleanup_test_resources(network=net)): net, subnet = helpers.create_test_network(self.provider, name) sit.check_crud(self, self.provider.compute.instances, Instance, "cb_instcrud", create_inst, cleanup_inst, custom_check_delete=check_deleted)
def test_floating_ip_properties(self): # Check floating IP address ip = self.provider.networking.networks.create_floating_ip() ip_id = ip.id with helpers.cleanup_action(lambda: ip.delete()): ipl = self.provider.networking.networks.floating_ips self.assertTrue( ip in ipl, "Floating IP address {0} should exist in the list {1}" .format(ip.id, ipl)) # 2016-08: address filtering not implemented in moto # empty_ipl = self.provider.network.floating_ips('dummy-net') # self.assertFalse( # empty_ipl, # "Bogus network should not have any floating IPs: {0}" # .format(empty_ipl)) self.assertIn( ip.public_ip, repr(ip), "repr(obj) should contain the address public IP value.") self.assertFalse( ip.private_ip, "Floating IP should not have a private IP value ({0})." .format(ip.private_ip)) self.assertFalse( ip.in_use(), "Newly created floating IP address should not be in use.") ipl = self.provider.networking.networks.floating_ips found_ip = [a for a in ipl if a.id == ip_id] self.assertTrue( len(found_ip) == 0, "Floating IP {0} should have been deleted but still exists." .format(ip_id))
def test_security_group_rule_add_twice(self): """Test whether adding the same rule twice succeeds.""" if isinstance(self.provider, TestMockHelperMixin): raise unittest.SkipTest( "Mock provider returns InvalidParameterValue: " "Value security_group is invalid for parameter.") name = 'CBTestSecurityGroupC-{0}'.format(uuid.uuid4()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None sg = None with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( network=net, security_group=sg)): net, _ = helpers.create_test_network(self.provider, name) sg = self.provider.security.security_groups.create( name=name, description=name, network_id=net.id) rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') # attempting to add the same rule twice should succeed same_rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') self.assertTrue( rule == same_rule, "Expected rule {0} not found in security group: {0}".format( same_rule, sg.rules))
def test_network_properties(self): name = 'cb_propnetwork-{0}'.format(helpers.get_uuid()) subnet_name = 'cb_propsubnet-{0}'.format(helpers.get_uuid()) net = self.provider.networking.networks.create( name=name, cidr_block='10.0.0.0/16') with helpers.cleanup_action(lambda: net.delete()): net.wait_till_ready() self.assertEqual( net.state, 'available', "Network in state '%s', yet should be 'available'" % net.state) sit.check_repr(self, net) self.assertIn( net.cidr_block, ['', '10.0.0.0/16'], "Network CIDR %s does not contain the expected value." % net.cidr_block) cidr = '10.0.1.0/24' sn = net.create_subnet(name=subnet_name, cidr_block=cidr, zone=helpers.get_provider_test_data( self.provider, 'placement')) with helpers.cleanup_action(lambda: sn.delete()): self.assertTrue( sn in net.subnets, "Subnet ID %s should be listed in network subnets %s." % (sn.id, net.subnets)) self.assertTrue( sn in self.provider.networking.subnets.list(network=net), "Subnet ID %s should be included in the subnets list %s." % (sn.id, self.provider.networking.subnets.list(net))) self.assertListEqual( net.subnets, [sn], "Network should have exactly one subnet: %s." % sn.id) self.assertIn( net.id, sn.network_id, "Network ID %s should be specified in the subnet's network" " id %s." % (net.id, sn.network_id)) self.assertEqual( cidr, sn.cidr_block, "Subnet's CIDR %s should match the specified one %s." % (sn.cidr_block, cidr))
def test_crud_security_group_service(self): name = 'CBTestSecurityGroupA-{0}'.format(uuid.uuid4()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None sg = None with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( network=net, security_group=sg)): net, _ = helpers.create_test_network(self.provider, name) sg = self.provider.security.security_groups.create( name=name, description=name, network_id=net.id) self.assertEqual(name, sg.description) # test list method sgl = self.provider.security.security_groups.list() found_sgl = [i for i in sgl if i.name == name] self.assertTrue( len(found_sgl) == 1, "List security groups does not return the expected group %s" % name) # check iteration found_sgl = [i for i in self.provider.security.security_groups if i.name == name] self.assertTrue( len(found_sgl) == 1, "Iter security groups does not return the expected group %s" % name) # check find find_sg = self.provider.security.security_groups.find(name=sg.name) self.assertTrue( len(find_sg) == 1, "List security groups returned {0} when expected was: {1}." .format(find_sg, sg.name)) # check get get_sg = self.provider.security.security_groups.get(sg.id) self.assertTrue( get_sg == sg, "Get SecurityGroup did not return the expected key {0}." .format(name)) self.assertTrue( sg.id in repr(sg), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists." .format(name)) no_sg = self.provider.security.security_groups.find(name='bogus_sg') self.assertTrue( len(no_sg) == 0, "Found a bogus security group?!?".format(no_sg))
def test_upload_download_bucket_content(self): name = "cbtestbucketobjs-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) with helpers.cleanup_action(lambda: test_bucket.delete()): obj_name = "hello_upload_download.txt" obj = test_bucket.create_object(obj_name) with helpers.cleanup_action(lambda: obj.delete()): content = b"Hello World. Here's some content." # TODO: Upload and download methods accept different parameter # types. Need to make this consistent - possibly provider # multiple methods like upload_from_file, from_stream etc. obj.upload(content) target_stream = BytesIO() obj.download(target_stream) self.assertEqual(target_stream.getvalue(), content)
def test_import_key_pair(self): name = 'cb-kpimport-{0}'.format(helpers.get_uuid()) public_key, _ = cb_helpers.generate_key_pair() kp = self.provider.security.key_pairs.create( name=name, public_key_material=public_key) with helpers.cleanup_action(lambda: kp.delete()): self.assertIsNone(kp.material, "Private KeyPair material should" " be None when key is imported.")
def test_security_group(self): """Test for proper creation of a security group.""" name = 'CBTestSecurityGroupB-{0}'.format(uuid.uuid4()) # Declare these variables and late binding will allow # the cleanup method access to the most current values net = None sg = None with helpers.cleanup_action(lambda: helpers.cleanup_test_resources( network=net, security_group=sg)): net, _ = helpers.create_test_network(self.provider, name) sg = self.provider.security.security_groups.create( name=name, description=name, network_id=net.id) rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') found_rule = sg.get_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') self.assertTrue( rule == found_rule, "Expected rule {0} not found in security group: {0}".format( rule, sg.rules)) object_keys = ( sg.rules[0].ip_protocol, sg.rules[0].from_port, sg.rules[0].to_port) self.assertTrue( all(str(key) in repr(sg.rules[0]) for key in object_keys), "repr(obj) should contain ip_protocol, form_port, and to_port" " so that the object can be reconstructed, but does not:" " {0}; {1}".format(sg.rules[0], object_keys)) self.assertTrue( sg == sg, "The same security groups should be equal?") self.assertFalse( sg != sg, "The same security groups should still be equal?") # json_repr = json.dumps( # {"description": name, "name": name, "id": sg.id, # "rules": # [{"from_port": 1111, "group": "", "cidr_ip": "0.0.0.0/0", # "parent": sg.id, "to_port": 1111, "ip_protocol": "tcp", # "id": sg.rules[0].id}]}, # sort_keys=True) # self.assertTrue( # sg.to_json() == json_repr, # "JSON SG representation {0} does not match expected {1}" # .format(sg.to_json(), json_repr)) sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists." .format(name))
def test_key_pair_properties(self): name = 'cb_kpprops-{0}'.format(helpers.get_uuid()) kp = self.provider.security.key_pairs.create(name=name) with helpers.cleanup_action(lambda: kp.delete()): self.assertIsNotNone( kp.material, "KeyPair material is empty but it should not be.") # get the keypair again - keypair material should now be empty kp = self.provider.security.key_pairs.get(kp.id) self.assertIsNone(kp.material, "Keypair material should now be empty")
def test_crud_security_group_service(self): name = 'cbtestsecuritygroupA-{0}'.format(uuid.uuid4()) sg = self.provider.security.security_groups.create( name=name, description=name) with helpers.cleanup_action( lambda: self.provider.security.security_groups.delete(group_id=sg.id) ): self.assertEqual(name, sg.description) # test list method sgl = self.provider.security.security_groups.list() found_sgl = [i for i in sgl if i.name == name] self.assertTrue( len(found_sgl) == 1, "List security groups does not return the expected group %s" % name) # check iteration found_sgl = [i for i in self.provider.security.security_groups if i.name == name] self.assertTrue( len(found_sgl) == 1, "Iter security groups does not return the expected group %s" % name) # check find find_sg = self.provider.security.security_groups.find(name=sg.name) self.assertTrue( len(find_sg) == 1, "List security groups returned {0} when expected was: {1}." .format(find_sg, sg.name)) # check get get_sg = self.provider.security.security_groups.get(sg.id) self.assertTrue( get_sg == sg, "Get SecurityGroup did not return the expected key {0}." .format(name)) self.assertTrue( sg.id in repr(sg), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists." .format(name)) no_sg = self.provider.security.security_groups.find(name='bogus_sg') self.assertTrue( len(no_sg) == 0, "Found a bogus security group?!?".format(no_sg))
def test_instance_properties(self): name = "CBInstProps-{0}-{1}".format( self.provider.name, uuid.uuid4()) kp = self.provider.security.key_pairs.create(name=name) sg = self.provider.security.security_groups.create( name=name, description=name) test_instance = helpers.get_test_instance(self.provider, name, keypair=kp, security_groups=[sg]) def cleanup(inst, kp, sg): inst.terminate() inst.wait_for([InstanceState.TERMINATED, InstanceState.UNKNOWN], terminal_states=[InstanceState.ERROR]) kp.delete() sg.delete() with helpers.cleanup_action(lambda: cleanup(test_instance, kp, sg)): self.assertTrue( test_instance.id in repr(test_instance), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") self.assertEqual( test_instance.name, name, "Instance name {0} is not equal to the expected name" " {1}".format(test_instance.name, name)) image_id = helpers.get_provider_test_data(self.provider, "image") self.assertEqual(test_instance.image_id, image_id, "Image id {0} is not equal to the expected id" " {1}".format(test_instance.image_id, image_id)) self.assertIsInstance(test_instance.public_ips, list) self.assertIsInstance(test_instance.private_ips, list) self.assertEqual( test_instance.key_pair_name, kp.name) self.assertIsInstance(test_instance.security_groups, list) self.assertEqual( test_instance.security_groups[0], sg) # Must have either a public or a private ip ip_private = test_instance.private_ips[0] \ if test_instance.private_ips else None ip_address = test_instance.public_ips[0] \ if test_instance.public_ips else ip_private self.assertIsNotNone( ip_address, "Instance must have either a public IP or a private IP") self.assertTrue( self._is_valid_ip(ip_address), "Instance must have a valid IP address") self.assertIsInstance(test_instance.instance_type, InstanceType)
def test_snapshot_properties(self): """ Test snapshot properties """ name = "CBTestSnapProp-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() snap_name = "CBSnapProp-{0}".format(name) test_snap = test_vol.create_snapshot(name=snap_name, description=snap_name) def cleanup_snap(snap): snap.delete() snap.wait_for( [SnapshotState.UNKNOWN], terminal_states=[SnapshotState.ERROR]) with helpers.cleanup_action(lambda: cleanup_snap(test_snap)): test_snap.wait_till_ready() self.assertTrue(isinstance(test_vol.size, six.integer_types)) self.assertEqual( test_snap.size, test_vol.size, "Snapshot.size must match original volume's size: %s" " but is: %s" % (test_vol.size, test_snap.size)) self.assertTrue( test_vol.description is None or isinstance(test_vol.description, six.string_types), "Snapshot.description must be None or a string. Got: %s" % test_vol.description) self.assertEqual(test_vol.id, test_snap.volume_id) self.assertIsNotNone(test_vol.create_time) test_snap.name = 'snapnewname1' test_snap.description = 'snapnewdescription1' test_snap.refresh() self.assertEqual(test_snap.name, 'snapnewname1') self.assertEqual(test_snap.description, 'snapnewdescription1')
def test_crud_key_pair_service(self): name = 'cbtestkeypairA-{0}'.format(uuid.uuid4()) kp = self.provider.security.key_pairs.create(name=name) with helpers.cleanup_action( lambda: self.provider.security.key_pairs.delete(key_pair_id=kp.id) ): # test list method kpl = self.provider.security.key_pairs.list() list_kpl = [i for i in kpl if i.name == name] self.assertTrue( len(list_kpl) == 1, "List key pairs does not return the expected key pair %s" % name) # check iteration iter_kpl = [i for i in self.provider.security.key_pairs if i.name == name] self.assertTrue( len(iter_kpl) == 1, "Iter key pairs does not return the expected key pair %s" % name) # check find find_kp = self.provider.security.key_pairs.find(name=name)[0] self.assertTrue( find_kp == kp, "Find key pair did not return the expected key {0}." .format(name)) # check get get_kp = self.provider.security.key_pairs.get(name) self.assertTrue( get_kp == kp, "Get key pair did not return the expected key {0}." .format(name)) recreated_kp = self.provider.security.key_pairs.create(name=name) self.assertTrue( recreated_kp == kp, "Recreating key pair did not return the expected key {0}." .format(name)) kpl = self.provider.security.key_pairs.list() found_kp = [k for k in kpl if k.name == name] self.assertTrue( len(found_kp) == 0, "Key pair {0} should have been deleted but still exists." .format(name)) no_kp = self.provider.security.key_pairs.find(name='bogus_kp') self.assertFalse( no_kp, "Found a key pair {0} that should not exist?".format(no_kp))
def test_crud_bucket(self): """ Create a new bucket, check whether the expected values are set, and delete it. """ name = "cbtestcreatebucket-{0}".format(uuid.uuid4()) test_bucket = self.provider.object_store.create(name) with helpers.cleanup_action(lambda: test_bucket.delete()): self.assertTrue( test_bucket.id in repr(test_bucket), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") buckets = self.provider.object_store.list() list_buckets = [c for c in buckets if c.name == name] self.assertTrue( len(list_buckets) == 1, "List buckets does not return the expected bucket %s" % name) # check iteration iter_buckets = [c for c in self.provider.object_store if c.name == name] self.assertTrue( len(iter_buckets) == 1, "Iter buckets does not return the expected bucket %s" % name) # check find find_buckets = self.provider.object_store.find(name=name) self.assertTrue( len(find_buckets) == 1, "Find buckets does not return the expected bucket %s" % name) get_bucket = self.provider.object_store.get( test_bucket.id) self.assertTrue( list_buckets[0] == get_bucket == test_bucket, "Objects returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_buckets[0].id, get_bucket.id, test_bucket.name)) buckets = self.provider.object_store.list() found_buckets = [c for c in buckets if c.name == name] self.assertTrue( len(found_buckets) == 0, "Bucket %s should have been deleted but still exists." % name)
def test_crud_network(self): name = 'cbtestnetwork-{0}'.format(uuid.uuid4()) subnet_name = 'cbtestsubnet-{0}'.format(uuid.uuid4()) net = self.provider.network.create(name=name) with helpers.cleanup_action( lambda: net.delete() ): net.wait_till_ready() self.assertEqual( net.refresh(), 'available', "Network in state %s , yet should be 'available'" % net.state) self.assertIn( net.id, repr(net), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not.") self.assertIn( net.cidr_block, ['', '10.0.0.0/16'], "Network CIDR %s does not contain the expected value." % net.cidr_block) cidr = '10.0.1.0/24' sn = net.create_subnet(cidr_block=cidr, name=subnet_name) with helpers.cleanup_action(lambda: sn.delete()): self.assertTrue( sn.id in [s.id for s in net.subnets()], "Subnet ID %s should be listed in network subnets %s." % (sn.id, net.subnets())) self.assertIn( net.id, sn.network_id, "Network ID %s should be specified in the subnet's network" " id %s." % (net.id, sn.network_id)) self.assertEqual( cidr, sn.cidr_block, "Subnet's CIDR %s should match the specified one %s." % ( sn.cidr_block, cidr))
def test_security_group_rule_add_twice(self): """Test whether adding the same rule twice succeeds.""" name = 'cbtestsecuritygroupB-{0}'.format(uuid.uuid4()) sg = self.provider.security.security_groups.create( name=name, description=name) with helpers.cleanup_action(lambda: sg.delete()): rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') # attempting to add the same rule twice should succeed same_rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') self.assertTrue( rule == same_rule, "Expected rule {0} not found in security group: {0}".format( same_rule, sg.rules))
def test_security_group(self): """Test for proper creation of a security group.""" name = 'cbtestsecuritygroupB-{0}'.format(uuid.uuid4()) net = self.provider.network.create(name=name) sg = self.provider.security.security_groups.create( name=name, description=name, network_id=net.id) with helpers.cleanup_action(lambda: self.cleanup_sg(sg, net)): rule = sg.add_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') found_rule = sg.get_rule(ip_protocol='tcp', from_port=1111, to_port=1111, cidr_ip='0.0.0.0/0') self.assertTrue( rule == found_rule, "Expected rule {0} not found in security group: {0}".format( rule, sg.rules)) object_keys = ( sg.rules[0].ip_protocol, sg.rules[0].from_port, sg.rules[0].to_port) self.assertTrue( all(str(key) in repr(sg.rules[0]) for key in object_keys), "repr(obj) should contain ip_protocol, form_port, and to_port" " so that the object can be reconstructed, but does not:" " {0}; {1}".format(sg.rules[0], object_keys)) self.assertTrue( sg == sg, "The same security groups should be equal?") self.assertFalse( sg != sg, "The same security groups should still be equal?") json_repr = json.dumps( {"description": name, "name": name, "id": sg.id, "rules": [{"from_port": 1111, "group": "", "cidr_ip": "0.0.0.0/0", "parent": sg.id, "to_port": 1111, "ip_protocol": "tcp", "id": sg.rules[0].id}]}, sort_keys=True) self.assertTrue( sg.to_json() == json_repr, "JSON sec group representation {0} does not match expected {1}" .format(sg.to_json(), json_repr)) sgl = self.provider.security.security_groups.list() found_sg = [g for g in sgl if g.name == name] self.assertTrue( len(found_sg) == 0, "Security group {0} should have been deleted but still exists." .format(name))
def test_crud_volume(self): """ Create a new volume, check whether the expected values are set, and delete it """ name = "CBUnitTestCreateVol-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) def cleanup_vol(vol): vol.delete() vol.wait_for([VolumeState.DELETED, VolumeState.UNKNOWN], terminal_states=[VolumeState.ERROR]) with helpers.cleanup_action(lambda: cleanup_vol(test_vol)): test_vol.wait_till_ready() self.assertTrue( test_vol.id in repr(test_vol), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") volumes = self.provider.block_store.volumes.list() list_volumes = [vol for vol in volumes if vol.name == name] self.assertTrue( len(list_volumes) == 1, "List volumes does not return the expected volume %s" % name) # check iteration iter_volumes = [vol for vol in self.provider.block_store.volumes if vol.name == name] self.assertTrue( len(iter_volumes) == 1, "Iter volumes does not return the expected volume %s" % name) # check find find_vols = self.provider.block_store.volumes.find(name=name) self.assertTrue( len(find_vols) == 1, "Find volumes does not return the expected volume %s" % name) # check non-existent find # TODO: Moto has a bug with filters causing the following test # to fail. Need to add tag based filtering support for volumes # find_vols = self.provider.block_store.volumes.find( # name="non_existent_vol") # self.assertTrue( # len(find_vols) == 0, # "Find() for a non-existent volume returned %s" % find_vols) get_vol = self.provider.block_store.volumes.get( test_vol.id) self.assertTrue( list_volumes[0] == get_vol == test_vol, "Ids returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_volumes[0].id, get_vol.id, test_vol.id)) self.assertTrue( list_volumes[0].name == get_vol.name == test_vol.name, "Names returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_volumes[0].name, get_vol.name, test_vol.name)) volumes = self.provider.block_store.volumes.list() found_volumes = [vol for vol in volumes if vol.name == name] self.assertTrue( len(found_volumes) == 0, "Volume %s should have been deleted but still exists." % name)
def test_crud_snapshot(self): """ Create a new volume, create a snapshot of the volume, and check whether list_snapshots properly detects the new snapshot. Delete everything afterwards. """ name = "CBUnitTestCreateSnap-{0}".format(uuid.uuid4()) test_vol = self.provider.block_store.volumes.create( name, 1, helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: test_vol.delete()): test_vol.wait_till_ready() snap_name = "CBSnapshot-{0}".format(name) test_snap = test_vol.create_snapshot(name=snap_name, description=snap_name) def cleanup_snap(snap): snap.delete() snap.wait_for( [SnapshotState.UNKNOWN], terminal_states=[SnapshotState.ERROR]) with helpers.cleanup_action(lambda: cleanup_snap(test_snap)): test_snap.wait_till_ready() self.assertTrue( test_snap.id in repr(test_snap), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not.") snaps = self.provider.block_store.snapshots.list() list_snaps = [snap for snap in snaps if snap.name == snap_name] self.assertTrue( len(list_snaps) == 1, "List snapshots does not return the expected volume %s" % name) # check iteration iter_snaps = [ snap for snap in self.provider.block_store.snapshots if snap.name == snap_name] self.assertTrue( len(iter_snaps) == 1, "Iter snapshots does not return the expected volume %s" % name) # check find find_snap = self.provider.block_store.snapshots.find( name=snap_name) self.assertTrue( len(find_snap) == 1, "Find snaps does not return the expected snapshot %s" % name) # check non-existent find # TODO: Moto has a bug with filters causing the following test # to fail. Need to add tag based filtering support for snaps # find_snap = self.provider.block_store.snapshots.find( # name="non_existent_snap") # self.assertTrue( # len(find_snap) == 0, # "Find() for a non-existent snap returned %s" % # find_snap) get_snap = self.provider.block_store.snapshots.get( test_snap.id) self.assertTrue( list_snaps[0] == get_snap == test_snap, "Ids returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_snaps[0].id, get_snap.id, test_snap.id)) self.assertTrue( list_snaps[0].name == get_snap.name == test_snap.name, "Names returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_snaps[0].name, get_snap.name, test_snap.name)) # Test volume creation from a snapshot (via VolumeService) sv_name = "CBUnitTestSnapVol-{0}".format(name) snap_vol = self.provider.block_store.volumes.create( sv_name, 1, helpers.get_provider_test_data(self.provider, "placement"), snapshot=test_snap) with helpers.cleanup_action(lambda: snap_vol.delete()): snap_vol.wait_till_ready() # Test volume creation from a snapshot (via Snapshot) snap_vol2 = test_snap.create_volume( helpers.get_provider_test_data(self.provider, "placement")) with helpers.cleanup_action(lambda: snap_vol2.delete()): snap_vol2.wait_till_ready() snaps = self.provider.block_store.snapshots.list() found_snaps = [snap for snap in snaps if snap.name == snap_name] self.assertTrue( len(found_snaps) == 0, "Snapshot %s should have been deleted but still exists." % snap_name) # Test creation of a snap via SnapshotService snap_too_name = "CBSnapToo-{0}".format(name) test_snap_too = self.provider.block_store.snapshots.create( name=snap_too_name, volume=test_vol, description=snap_too_name) with helpers.cleanup_action(lambda: cleanup_snap(test_snap_too)): test_snap_too.wait_till_ready() self.assertTrue( test_snap_too.id in repr(test_snap_too), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not.")
def test_block_device_mapping_attachments(self): name = "CBInstBlkAttch-{0}-{1}".format( self.provider.name, uuid.uuid4()) # test_vol = self.provider.block_store.volumes.create( # name, # 1, # helpers.get_provider_test_data(self.provider, "placement")) # with helpers.cleanup_action(lambda: test_vol.delete()): # test_vol.wait_till_ready() # test_snap = test_vol.create_snapshot(name=name, # description=name) # # def cleanup_snap(snap): # snap.delete() # snap.wait_for( # [SnapshotState.UNKNOWN], # terminal_states=[SnapshotState.ERROR]) # # with helpers.cleanup_action(lambda: cleanup_snap(test_snap)): # test_snap.wait_till_ready() lc = self.provider.compute.instances.create_launch_config() # Add a new blank volume # lc.add_volume_device(size=1, delete_on_terminate=True) # Attach an existing volume # lc.add_volume_device(size=1, source=test_vol, # delete_on_terminate=True) # Add a new volume based on a snapshot # lc.add_volume_device(size=1, source=test_snap, # delete_on_terminate=True) # Override root volume size image_id = helpers.get_provider_test_data( self.provider, "image") img = self.provider.compute.images.get(image_id) lc.add_volume_device( is_root=True, source=img, # TODO: This should be greater than the ami size or tests # will fail on actual infrastructure. Needs an image.size # method size=2, delete_on_terminate=True) # Add all available ephemeral devices instance_type_name = helpers.get_provider_test_data( self.provider, "instance_type") inst_type = self.provider.compute.instance_types.find( name=instance_type_name)[0] for _ in range(inst_type.num_ephemeral_disks): lc.add_ephemeral_device() inst = helpers.create_test_instance( self.provider, name, zone=helpers.get_provider_test_data( self.provider, 'placement'), launch_config=lc) def cleanup(instance): instance.terminate() instance.wait_for( [InstanceState.TERMINATED, InstanceState.UNKNOWN], terminal_states=[InstanceState.ERROR]) with helpers.cleanup_action(lambda: cleanup(inst)): try: inst.wait_till_ready() except WaitStateException as e: self.fail("The block device mapped launch did not " " complete successfully: %s" % e)
def test_instance_properties(self): name = "CBInstProps-{0}-{1}".format( self.provider.name, uuid.uuid4()) kp = self.provider.security.key_pairs.create(name=name) sg = self.provider.security.security_groups.create( name=name, description=name) test_instance = helpers.get_test_instance(self.provider, name, key_pair=kp, security_groups=[sg]) def cleanup(inst, kp, sg): inst.terminate() inst.wait_for([InstanceState.TERMINATED, InstanceState.UNKNOWN], terminal_states=[InstanceState.ERROR]) kp.delete() sg.delete() with helpers.cleanup_action(lambda: cleanup(test_instance, kp, sg)): self.assertTrue( test_instance.id in repr(test_instance), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not. eval(repr(obj)) == obj") self.assertEqual( test_instance.name, name, "Instance name {0} is not equal to the expected name" " {1}".format(test_instance.name, name)) image_id = helpers.get_provider_test_data(self.provider, "image") self.assertEqual(test_instance.image_id, image_id, "Image id {0} is not equal to the expected id" " {1}".format(test_instance.image_id, image_id)) self.assertIsInstance(test_instance.zone_id, six.string_types) # FIXME: Moto is not returning the instance's placement zone # find_zone = [zone for zone in # self.provider.compute.regions.current.zones # if zone.id == test_instance.zone_id] # self.assertEqual(len(find_zone), 1, # "Instance's placement zone could not be " # " found in zones list") self.assertEqual( test_instance.image_id, helpers.get_provider_test_data(self.provider, "image")) self.assertIsInstance(test_instance.public_ips, list) self.assertIsInstance(test_instance.private_ips, list) self.assertEqual( test_instance.key_pair_name, kp.name) self.assertIsInstance(test_instance.security_groups, list) self.assertEqual( test_instance.security_groups[0], sg) self.assertIsInstance(test_instance.security_group_ids, list) self.assertEqual( test_instance.security_group_ids[0], sg.id) # Must have either a public or a private ip ip_private = test_instance.private_ips[0] \ if test_instance.private_ips else None ip_address = test_instance.public_ips[0] \ if test_instance.public_ips else ip_private self.assertIsNotNone( ip_address, "Instance must have either a public IP or a private IP") self.assertTrue( self._is_valid_ip(ip_address), "Instance must have a valid IP address") self.assertIsInstance(test_instance.instance_type_id, six.string_types) itype = self.provider.compute.instance_types.get( test_instance.instance_type_id) self.assertEqual( itype, test_instance.instance_type, "Instance type {0} does not match expected type {1}".format( itype.name, test_instance.instance_type)) self.assertIsInstance(itype, InstanceType) expected_type = helpers.get_provider_test_data(self.provider, 'instance_type') self.assertEqual( itype.name, expected_type, "Instance type {0} does not match expected type {1}".format( itype.name, expected_type))
def test_create_and_list_image(self): """ Create a new image and check whether that image can be listed. This covers waiting till the image is ready, checking that the image name is the expected one and whether list_images is functional. """ instance_name = "CBImageTest-{0}-{1}".format( self.provider.name, uuid.uuid4()) test_instance = helpers.get_test_instance(self.provider, instance_name) with helpers.cleanup_action(lambda: test_instance.terminate()): name = "CBUnitTestListImg-{0}".format(uuid.uuid4()) test_image = test_instance.create_image(name) def cleanup_img(img): img.delete() img.wait_for( [MachineImageState.UNKNOWN, MachineImageState.ERROR]) with helpers.cleanup_action(lambda: cleanup_img(test_image)): test_image.wait_till_ready() self.assertTrue( test_instance.id in repr(test_instance), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not.") self.assertTrue( test_image.description is None or isinstance( test_image.description, six.string_types), "Image description must be None or a string") images = self.provider.compute.images.list() list_images = [image for image in images if image.name == name] self.assertTrue( len(list_images) == 1, "List images does not return the expected image %s" % name) # check iteration iter_images = [image for image in self.provider.compute.images if image.name == name] self.assertTrue( len(iter_images) == 1, "Iter images does not return the expected image %s" % name) # find image found_images = self.provider.compute.images.find(name=name) self.assertTrue( len(found_images) == 1, "Find images error: expected image %s but found: %s" % (name, found_images)) # check non-existent find ne_images = self.provider.compute.images.find( name="non_existent") self.assertTrue( len(ne_images) == 0, "Find() for a non-existent image returned %s" % ne_images) get_img = self.provider.compute.images.get( test_image.id) self.assertTrue( found_images[0] == iter_images[0] == get_img == test_image, "Objects returned by list: {0} and get: {1} are not as " " expected: {2}" .format(found_images[0].id, get_img.id, test_image.id)) self.assertTrue( list_images[0].name == found_images[0].name == get_img.name == test_image.name, "Names returned by list: {0}, find: {1} and get: {2} are" " not as expected: {3}" .format(list_images[0].name, found_images[0].name, get_img.name, test_image.name)) # TODO: Images take a long time to deregister on EC2. Needs # investigation images = self.provider.compute.images.list() found_images = [image for image in images if image.name == name] self.assertTrue( len(found_images) == 0, "Image %s should have been deleted but still exists." % name)
def test_crud_instance(self): name = "CBInstCrud-{0}-{1}".format( self.provider.name, uuid.uuid4()) inst = helpers.create_test_instance(self.provider, name) def cleanup_inst(instance): instance.terminate() instance.wait_for( [InstanceState.TERMINATED, InstanceState.UNKNOWN], terminal_states=[InstanceState.ERROR]) with helpers.cleanup_action(lambda: cleanup_inst(inst)): inst.wait_till_ready() all_instances = self.provider.compute.instances.list() list_instances = [i for i in all_instances if i.name == name] self.assertTrue( len(list_instances) == 1, "List instances does not return the expected instance %s" % name) # check iteration iter_instances = [i for i in self.provider.compute.instances if i.name == name] self.assertTrue( len(iter_instances) == 1, "Iter instances does not return the expected instance %s" % name) # check find find_instances = self.provider.compute.instances.find(name=name) self.assertTrue( len(find_instances) == 1, "Find instances does not return the expected instance %s" % name) # check non-existent find find_instances = self.provider.compute.instances.find( name="non_existent") self.assertTrue( len(find_instances) == 0, "Find() for a non-existent image returned %s" % find_instances) get_inst = self.provider.compute.instances.get( inst.id) self.assertTrue( list_instances[0] == get_inst == inst, "Objects returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_instances[0].id, get_inst.id, inst.id)) self.assertTrue( list_instances[0].name == get_inst.name == inst.name, "Names returned by list: {0} and get: {1} are not as " " expected: {2}" .format(list_instances[0].name, get_inst.name, inst.name)) deleted_inst = self.provider.compute.instances.get( inst.id) self.assertTrue( deleted_inst is None or deleted_inst.state in ( InstanceState.TERMINATED, InstanceState.UNKNOWN), "Instance %s should have been deleted but still exists." % name)
def test_crud_network_service(self): name = 'cbtestnetworkservice-{0}'.format(uuid.uuid4()) subnet_name = 'cbtestsubnetservice-{0}'.format(uuid.uuid4()) net = self.provider.network.create(name=name) with helpers.cleanup_action( lambda: self.provider.network.delete(network_id=net.id) ): # test list method netl = self.provider.network.list() list_netl = [n for n in netl if n.name == name] self.assertTrue( len(list_netl) == 1, "List networks does not return the expected network %s" % name) # check get get_net = self.provider.network.get(network_id=net.id) self.assertTrue( get_net == net, "Get network did not return the expected network {0}." .format(name)) # check subnet subnet = self.provider.network.subnets.create( network=net, cidr_block="10.0.0.1/24", name=subnet_name) with helpers.cleanup_action( lambda: self.provider.network.subnets.delete(subnet=subnet) ): # test list method subnetl = self.provider.network.subnets.list(network=net) list_subnetl = [n for n in subnetl if n.name == subnet_name] self.assertTrue( len(list_subnetl) == 1, "List subnets does not return the expected subnet %s" % subnet_name) # test get method sn = self.provider.network.subnets.get(subnet.id) self.assertTrue( subnet.id == sn.id, "GETting subnet should return the same subnet") subnetl = self.provider.network.subnets.list() found_subnet = [n for n in subnetl if n.name == subnet_name] self.assertTrue( len(found_subnet) == 0, "Subnet {0} should have been deleted but still exists." .format(subnet_name)) # Check floating IP address ip = self.provider.network.create_floating_ip() ip_id = ip.id with helpers.cleanup_action(lambda: ip.delete()): ipl = self.provider.network.floating_ips() self.assertTrue( ip in ipl, "Floating IP address {0} should exist in the list {1}" .format(ip.id, ipl)) # 2016-08: address filtering not implemented in moto # empty_ipl = self.provider.network.floating_ips('dummy-net') # self.assertFalse( # empty_ipl, # "Bogus network should not have any floating IPs: {0}" # .format(empty_ipl)) self.assertIn( ip.public_ip, repr(ip), "repr(obj) should contain the address public IP value.") self.assertFalse( ip.private_ip, "Floating IP should not have a private IP value ({0})." .format(ip.private_ip)) self.assertFalse( ip.in_use(), "Newly created floating IP address should not be in use.") ipl = self.provider.network.floating_ips() found_ip = [a for a in ipl if a.id == ip_id] self.assertTrue( len(found_ip) == 0, "Floating IP {0} should have been deleted but still exists." .format(ip_id)) netl = self.provider.network.list() found_net = [n for n in netl if n.name == name] self.assertEqual( len(found_net), 0, "Network {0} should have been deleted but still exists." .format(name))
def test_crud_router(self): def _cleanup(net, subnet, router): router.remove_route(subnet.id) router.detach_network() router.delete() subnet.delete() net.delete() name = 'cbtestrouter-{0}'.format(uuid.uuid4()) router = self.provider.network.create_router(name=name) net = self.provider.network.create(name=name) cidr = '10.0.1.0/24' sn = net.create_subnet(cidr_block=cidr, name=name) with helpers.cleanup_action(lambda: _cleanup(net, sn, router)): # Check basic router properties self.assertIn( router, self.provider.network.routers(), "Router {0} should exist in the router list {1}.".format( router.id, self.provider.network.routers())) self.assertIn( router.id, repr(router), "repr(obj) should contain the object id so that the object" " can be reconstructed, but does not.") self.assertEqual( router.name, name, "Router {0} name should be {1}.".format(router.name, name)) self.assertEqual( router.state, RouterState.DETACHED, "Router {0} state {1} should be {2}.".format( router.id, router.state, RouterState.DETACHED)) self.assertFalse( router.network_id, "Router {0} should not be assoc. with a network {1}".format( router.id, router.network_id)) # Check router connectivity # On OpenStack only one network is external and on AWS every # network is external, yet we need to use the one we've created?! if self.provider.PROVIDER_ID == 'openstack': for n in self.provider.network.list(): if n.external: external_net = n break else: external_net = net router.attach_network(external_net.id) router.refresh() self.assertEqual( router.network_id, external_net.id, "Router should be attached to network {0}, not {1}".format( external_net.id, router.network_id)) router.add_route(sn.id) # TODO: add a check for routes after that's been implemented routerl = self.provider.network.routers() found_router = [r for r in routerl if r.name == name] self.assertEqual( len(found_router), 0, "Router {0} should have been deleted but still exists." .format(name))