| @@ -0,0 +1,173 @@ | ||
| ''' | ||
| Created on Apr 25, 2012 | ||
| @author: vic.iglesias@eucalyptus.com | ||
| ''' | ||
|
|
||
| import pickle | ||
| import ConfigParser | ||
| import random | ||
|
|
||
| class EuPopulator(object): | ||
| ''' | ||
| This class is intended to read in a config file using ConfigParser, then create resources based on the config file | ||
| It is also able to serialize the current resources in a cloud into a file, read in that file and verify that the resources still | ||
| exist in the same way. Serialization is done with Pickle. | ||
| ''' | ||
|
|
||
|
|
||
|
|
||
| def __init__(self, eucaops, config_file = None): | ||
| ''' | ||
| Constructor for EuPopulator: | ||
| eutester A eutester object that we can use for connections | ||
| config_file Filename of the config describing what resources to populate | ||
| ''' | ||
| self.tester = eucaops | ||
| if config_file is None: | ||
| self.defaults = ConfigParser.SafeConfigParser() | ||
| ### Global | ||
| self.defaults.add_section('global') | ||
| partition = self.tester.ec2.get_all_zones()[0].name | ||
| self.defaults.set('global', 'partition', partition) | ||
|
|
||
| ### Volume | ||
| self.defaults.add_section('volumes') | ||
| self.defaults.set('volumes', 'count', '2') | ||
| self.defaults.set('volumes', 'min_size', '1') | ||
| self.defaults.set('volumes', 'max_size', '3') | ||
|
|
||
| ### Snapshot | ||
| self.defaults.add_section('snapshots') | ||
| self.defaults.set('snapshots', 'count', '2') | ||
| self.defaults.set('snapshots', 'min_size', '1') | ||
| self.defaults.set('snapshots', 'max_size', '3') | ||
| self.defaults.set('snapshots', 'delete_volumes', 'false') | ||
|
|
||
| ### Keypair | ||
| self.defaults.add_section('keypairs') | ||
| self.defaults.set('keypairs', 'count', '2') | ||
| self.defaults.set('keypairs', 'prefix', 'key-') | ||
|
|
||
| ### Groups | ||
| self.defaults.add_section('security_groups') | ||
| self.defaults.set('security_groups', 'count', '2') | ||
| self.defaults.set('security_groups', 'prefix', 'sg-') | ||
| self.defaults.set('security_groups', 'port_min', '22') | ||
| self.defaults.set('security_groups', 'port_max', '80') | ||
| self.defaults.set('security_groups', 'protocol', 'tcp') | ||
| self.defaults.set('security_groups', 'cidr', '0.0.0.0/0') | ||
|
|
||
| ### Buckets | ||
| self.defaults.add_section('buckets') | ||
| self.defaults.set('buckets', 'count', '2') | ||
| self.defaults.set('buckets', 'prefix', 'bukkit-') | ||
| self.defaults.set('buckets', 'add_keys', 'true') | ||
| self.defaults.set('buckets', 'key_count', '2') | ||
| self.defaults.set('buckets', 'key_prefix', 'key-') | ||
| self.config = self.defaults | ||
|
|
||
| else: | ||
| config = ConfigParser.SafeConfigParser() | ||
| config.read(config_file) | ||
| self.config = config | ||
|
|
||
| if self.config: | ||
| with open('populate.cfg', 'wb') as configfile: | ||
| self.config.write(configfile) | ||
| else: | ||
| raise Exception("Do not have a valid config file to use") | ||
|
|
||
| def populate(self): | ||
| ''' | ||
| Takes the config and creates each of the resources based on their parameters | ||
| ''' | ||
| for section in self.config.sections(): | ||
| if section is not "global": | ||
| try: | ||
| creation_method = getattr(EuPopulator, section) | ||
| creation_method(self) | ||
| print "Successfully created: " + section | ||
| except Exception, e: | ||
| print "Unable to bind to resource creation method for: " + section + "\n Because of " + str(e) | ||
|
|
||
| def volumes(self): | ||
| print "Creating volumes" | ||
| partition = self.config.get("global","partition") | ||
| vol_count = self.config.getint("volumes", "count") | ||
| min_size = self.config.getint("volumes", "min_size") | ||
| max_size = self.config.getint("volumes", "max_size") | ||
|
|
||
| for i in xrange(vol_count): | ||
| size = random.randint(min_size, max_size) | ||
| self.tester.create_volume(partition, size) | ||
|
|
||
|
|
||
| def snapshots(self): | ||
| print "Creating snapshots" | ||
| partition = self.config.get("global","partition") | ||
| snap_count = self.config.getint("snapshots", "count") | ||
| min_size = self.config.getint("snapshots", "min_size") | ||
| max_size = self.config.getint("snapshots", "max_size") | ||
| delete_volumes = self.config.getboolean('snapshots', 'delete_volumes') | ||
|
|
||
| for i in xrange(snap_count): | ||
| size = random.randint(min_size, max_size) | ||
| volume = self.tester.create_volume(partition, size) | ||
| self.tester.create_snapshot(volume.id) | ||
| if delete_volumes: | ||
| self.tester.delete_volume(volume) | ||
|
|
||
| def keypairs(self): | ||
| print "Creating keypairs" | ||
| key_count = self.config.getint("keypairs", "count") | ||
| prefix = self.config.get("keypairs", "prefix") | ||
|
|
||
| for i in xrange(key_count): | ||
| self.tester.add_keypair(prefix + str(i)) | ||
|
|
||
| def security_groups(self): | ||
| print "Creating security_groups" | ||
| sg_count = self.config.getint("security_groups", "count") | ||
| prefix = self.config.get("security_groups", "prefix") | ||
| port_min = self.config.getint("security_groups", "port_min") | ||
| port_max = self.config.getint("security_groups", "port_max") | ||
| cidr = self.config.get("security_groups", "cidr") | ||
| protocol = self.config.get("security_groups", "protocol") | ||
| for i in xrange(sg_count): | ||
| group = self.tester.add_group(prefix + str(i)) | ||
| self.tester.authorize_group(group, port=random.randint(port_min, port_max), protocol=protocol, cidr_ip=cidr) | ||
|
|
||
| def buckets(self): | ||
| print "Creating buckets" | ||
| bucket_count = self.config.getint('buckets', 'count') | ||
| bucket_prefix = self.config.get('buckets', 'prefix') | ||
| add_keys = self.config.getboolean('buckets', 'add_keys') | ||
| key_count = self.config.getint('buckets', 'key_count') | ||
| key_prefix = self.config.get('buckets', 'key_prefix') | ||
|
|
||
| for i in xrange(bucket_count): | ||
| bucket = self.tester.create_bucket(bucket_prefix + str(i)) | ||
| if add_keys: | ||
| for i in xrange(key_count): | ||
| self.tester.upload_object(bucket.name, key_prefix + str(i)) | ||
|
|
||
| def depopulate(self): | ||
| self.tester.cleanup_artifacts() | ||
|
|
||
|
|
||
| def serialize_resources(self, output_file="cloud_objects.dat"): | ||
| ''' | ||
| Takes a snapshot of the current resources in the system and puts them into a data structure, then pickles this struct into a file. | ||
| output_file Filename to use when outputing the serialized data, if this is None then the byte stream will be returned | ||
| ''' | ||
| self.tester.debug("Serializing current resources") | ||
| serialized = open(output_file, 'wb') | ||
| all_resources = self.tester.get_current_resources() | ||
| for type in all_resources: | ||
| for object in all_resources[type]: | ||
| print >>serialized, self.tester.get_all_attributes(object) | ||
|
|
||
|
|
||
| serialized.close() | ||
| self.tester.debug("Serialized resources can be found at: " + output_file) | ||
|
|
| @@ -0,0 +1,113 @@ | ||
| import unittest | ||
| import re | ||
| import sys | ||
| import argparse | ||
| from instancetest import InstanceBasics | ||
| from eucaops import Eucaops | ||
|
|
||
| class BFEBSBasics(InstanceBasics): | ||
|
|
||
| def RegisterImage(self): | ||
| '''Register a BFEBS snapshot''' | ||
| self.reservation = self.tester.run_instance(keypair=self.keypair.name, group=self.group.name) | ||
| self.tester.sleep(10) | ||
| bfebs_img_url = "http://192.168.7.65/bfebs-image/ag-bfebs-centos-5-i386.img" | ||
| for instance in self.reservation.instances: | ||
| self.assertTrue(self.create_attach_volume(instance, 2)) | ||
| instance.sys("curl " + bfebs_img_url + " > " + self.volume_device, timeout=800) | ||
| snapshot = self.tester.create_snapshot(self.volume.id, waitOnProgress=10) | ||
| self.assertTrue( re.search("completed", snapshot.status), "Snapshot did not complete" ) | ||
| image_id = self.tester.register_snapshot(snapshot) | ||
| self.image = self.tester.get_emi(image_id) | ||
|
|
||
| def LaunchImage(self): | ||
| '''Launch a BFEBS image''' | ||
| if self.image is None: | ||
| self.image = self.tester.get_emi(root_device_type="ebs") | ||
| self.reservation = self.tester.run_instance(self.image,keypair=self.keypair.name, group=self.group.name) | ||
| self.assertTrue( self.tester.ping(self.reservation.instances[0].public_dns_name), 'Could not ping instance') | ||
|
|
||
| def StopStart(self): | ||
| '''Launch a BFEBS instance, stop it then start it again''' | ||
| self.image = self.tester.get_emi(root_device_type="ebs") | ||
| self.reservation = self.tester.run_instance(self.image,keypair=self.keypair.name, group=self.group.name) | ||
| self.assertTrue(self.tester.stop_instances(self.reservation)) | ||
| self.assertFalse( self.tester.ping(self.reservation.instances[0].public_dns_name, poll_count=2), 'Was able to ping stopped instance') | ||
| self.assertTrue(self.tester.start_instances(self.reservation)) | ||
| self.tester.debug("Waiting 20s for instance to boot") | ||
| self.tester.sleep(20) | ||
| self.assertTrue( self.tester.ping(self.reservation.instances[0].public_dns_name, poll_count=2), 'Could not ping instance') | ||
|
|
||
| def MultipleBFEBSInstances(self): | ||
| """Run half of the available m1.small instances with a BFEBS image""" | ||
| self.image = self.tester.get_emi(root_device_type="ebs") | ||
| self.MaxSmallInstances(self.tester.get_available_vms() / 2) | ||
|
|
||
| def ChurnBFEBS(self): | ||
| """Start instances and stop them before they are running, increase time to terminate on each iteration""" | ||
| self.image = self.tester.get_emi(root_device_type="ebs") | ||
| self.Churn() | ||
|
|
||
| def StaggeredInstances(self): | ||
| '''Run a few instances concurrently''' | ||
| from multiprocessing import Process | ||
| self.failure = 0 | ||
| thread_pool = [] | ||
| queue_pool = [] | ||
| total = self.tester.get_available_vms() / 2 | ||
| for i in xrange(total): | ||
| q = Queue() | ||
| p = Process(target=self.run_testcase, args=(q)) | ||
| thread_pool.append(p) | ||
| self.tester.debug("Starting Thread " + str(i)) | ||
| p.start() | ||
| self.tester.sleep(2) | ||
| for thread in thread_pool: | ||
| thread.join() | ||
| self.assertEqual(self.failure, 0, str(self.failure) + " Tests failed out of " + str(total)) | ||
| self.failure = 0 | ||
|
|
||
| def AddressIssue(self): | ||
| self.reservation = self.tester.run_instance(self.image,keypair=self.keypair.name, group=self.group.name) | ||
| original_ip = "" | ||
| for instance in self.reservation.instances: | ||
| original_ip = instance.ip_address | ||
| self.tester.debug("Terminating instance " + str(instance)) | ||
| instance.terminate() | ||
| self.tester.sleep(1) | ||
| self.BasicInstanceChecks() | ||
|
|
||
| def run_testcase(self, queue,delay = 20, testcase="LaunchImage"): | ||
| self.tester.sleep(delay) | ||
| try: | ||
| result = unittest.TextTestRunner(verbosity=2).run(BFEBSBasics(testcase)) | ||
| except Exception, e: | ||
| queue.put(1) | ||
| raise e | ||
| if result.wasSuccessful(): | ||
| self.tester.debug("Passed test: " + testcase) | ||
| queue.put(0) | ||
| else: | ||
| self.tester.debug("Failed test: " + testcase) | ||
| queue.put(1) | ||
|
|
||
| if __name__ == "__main__": | ||
| parser = argparse.ArgumentParser(description='Basic BFEBS Cases') | ||
| parser.add_argument('--debug', dest='debug', action='store_true', default=False, | ||
| help='Capture and save euca logs') | ||
| #'--bar', nargs='*' | ||
| parser.add_argument('--cases', dest='cases', nargs='*', default= [], | ||
| help='Names of tests to run') | ||
| args = parser.parse_args() | ||
| if args.cases is []: | ||
| tests = ["RegisterImage","LaunchImage", "StopStart","MultipleBFEBSInstances","ChurnBFEBS"] | ||
| else: | ||
| ### Not ready: test3_StopStart | ||
| tests = args.cases | ||
| for test in tests: | ||
| result = unittest.TextTestRunner(verbosity=2).run(BFEBSBasics(test)) | ||
| if result.wasSuccessful(): | ||
| pass | ||
| else: | ||
| exit(1) | ||
|
|
| @@ -0,0 +1,176 @@ | ||
| #! ../share/python_lib/vic-dev/bin/python | ||
| import unittest | ||
| import time | ||
| import sys | ||
| from instancetest import InstanceBasics | ||
| from eucaops import Eucaops | ||
| import os | ||
| import re | ||
|
|
||
|
|
||
| class HAtests(InstanceBasics): | ||
| def setUp(self): | ||
| super(HAtests, self).setUp() | ||
| self.servman = self.tester.service_manager | ||
|
|
||
| def tearDown(self): | ||
| try: | ||
| self.tester.terminate_instances() | ||
| except Exception, e: | ||
| self.tester.critical("Unable to terminate all instances") | ||
|
|
||
| self.servman.start_all() | ||
|
|
||
| try: | ||
| super(HAtests, self).tearDown() | ||
| except Exception, e: | ||
| self.tester.critical("Unable to teardown group and keypair") | ||
|
|
||
| def run_testcase(self, testcase_callback,zone): | ||
| poll_count = 10 | ||
| poll_interval = 60 | ||
| while (poll_count > 0): | ||
| try: | ||
| testcase_callback(zone) | ||
| break | ||
| except Exception, e: | ||
| self.tester.debug("Attempt failed, retrying in " + str(poll_interval) ) | ||
| self.tester.sleep(poll_interval) | ||
| poll_count = poll_count - 1 | ||
| if poll_count is 0: | ||
| self.fail("Could not run an instance after " + str(poll_count) +" tries with " + str(poll_interval) + "s sleep in between") | ||
|
|
||
| def failoverService(self, service_aquisition_callback, testcase_callback, zone=None): | ||
| ### Process Take down | ||
| primary_service = service_aquisition_callback() | ||
| primary_service.stop() | ||
|
|
||
| if "clc" in primary_service.machine.components: | ||
| self.tester.debug("Switching ec2 connection to host: " + self.tester.clc.hostname) | ||
| self.tester.ec2.host = self.servman.get_enabled_clc().machine.hostname | ||
|
|
||
| if "ws" in primary_service.machine.components: | ||
| self.tester.debug("Switching walrus connection to host: " + self.tester.walrus.hostname) | ||
| self.tester.s3.DefaultHost = self.servman.get_enabled_walrus().machine.hostname | ||
|
|
||
| self.tester.setup_boto_connections() | ||
|
|
||
| self.servman.wait_for_service(primary_service) | ||
| after_failover = service_aquisition_callback() | ||
| self.tester.ec2.host = after_failover.hostname | ||
| if primary_service.hostname is after_failover.hostname: | ||
| self.fail("The enabled CLC was the same before and after the failover") | ||
|
|
||
| self.run_testcase(testcase_callback, zone) | ||
| primary_service.start() | ||
| try: | ||
| self.servman.wait_for_service(primary_service, state ="DISABLED") | ||
| except Exception, e: | ||
| self.fail("The secondary service never went to disabled") | ||
|
|
||
|
|
||
| def failoverReboot(self, service_aquisition_callback, testcase_callback, zone=None): | ||
|
|
||
| ### Reboot the current enabled component | ||
| primary_service = service_aquisition_callback() | ||
| primary_service.machine.reboot() | ||
|
|
||
| ### Change to other CLC | ||
|
|
||
| if "clc" in primary_service.machine.components: | ||
| self.tester.debug("Switching ec2 connection to host: " + self.tester.clc.hostname) | ||
| self.tester.ec2.host = self.servman.get_enabled_clc().machine.hostname | ||
|
|
||
| if "ws" in primary_service.machine.components: | ||
| self.tester.debug("Switching walrus connection to host: " + self.tester.walrus.hostname) | ||
| self.tester.s3.DefaultHost = self.servman.get_enabled_walrus().machine.hostname | ||
|
|
||
| self.tester.setup_boto_connections() | ||
|
|
||
| self.run_testcase(testcase_callback, zone) | ||
|
|
||
| after_failover = service_aquisition_callback() | ||
|
|
||
| if primary_service.hostname is after_failover.hostname: | ||
| self.fail("The enabled CLC was the same before and after the failover") | ||
|
|
||
| try: | ||
| self.servman.wait_for_service(primary_service, state ="DISABLED") | ||
| except Exception, e: | ||
| self.fail("The secondary service never went to disabled") | ||
|
|
||
| def failoverNetwork(self, service_aquisition_callback, testcase_callback, zone=None): | ||
|
|
||
| ### Reboot the current enabled component | ||
| primary_service = service_aquisition_callback() | ||
| primary_service.machine.interrupt_network() | ||
|
|
||
| if "clc" in primary_service.machine.components: | ||
| self.tester.debug("Switching ec2 connection to host: " + self.tester.clc.hostname) | ||
| self.tester.ec2.host = self.servman.get_enabled_clc().machine.hostname | ||
|
|
||
| if "ws" in primary_service.machine.components: | ||
| self.tester.debug("Switching walrus connection to host: " + self.tester.walrus.hostname) | ||
| self.tester.s3.DefaultHost = self.servman.get_enabled_walrus().machine.hostname | ||
|
|
||
| self.tester.setup_boto_connections() | ||
|
|
||
| ### Change to other CLC | ||
| self.tester.swap_clc() | ||
| self.tester.ec2.host = self.tester.clc.hostname | ||
|
|
||
| self.run_testcase(testcase_callback, zone) | ||
| try: | ||
| after_failover = self.servman.wait_for_service(primary_service) | ||
| except Exception, e: | ||
| self.fail("The primary service never went to ENABLED") | ||
|
|
||
| if primary_service.hostname is after_failover.hostname: | ||
| self.fail("The enabled CLC was the same before and after the failover") | ||
|
|
||
| try: | ||
| self.servman.wait_for_service(primary_service, state ="DISABLED") | ||
| except Exception, e: | ||
| self.fail("The secondary service never went to disabled") | ||
|
|
||
| def failoverCLC(self): | ||
| self.failoverService(self.servman.get_enabled_clc, self.MetaData) | ||
| self.failoverReboot(self.servman.get_enabled_clc, self.MetaData) | ||
| self.failoverNetwork(self.servman.get_enabled_clc, self.MetaData) | ||
|
|
||
| def failoverWalrus(self): | ||
| self.failoverService(self.servman.get_enabled_walrus, self.MetaData) | ||
|
|
||
| def failoverCC(self): | ||
| zone = self.servman.partitions.keys()[0] | ||
| self.failoverService(self.servman.partitions[zone].get_enabled_cc, self.MetaData,zone) | ||
| self.failoverReboot(self.servman.partitions[zone].get_enabled_cc, self.MetaData,zone) | ||
| self.failoverNetwork(self.servman.partitions[zone].get_enabled_cc, self.MetaData,zone) | ||
|
|
||
| def failoverSC(self): | ||
| zone = self.servman.partitions.keys()[0] | ||
| self.failoverService(self.servman.partitions[zone].get_enabled_sc, self.Reboot, zone) | ||
|
|
||
| def failoverVB(self): | ||
| zone = self.servman.partitions.keys()[0] | ||
| if len(self.servman.partitions[zone].vbs) > 1: | ||
| self.failoverService(self.servman.partitions[zone].get_enabled_vb, self.MetaData ,zone) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| import sys | ||
| ## If given command line arguments, use them as test names to launch | ||
| if (len(sys.argv) > 1): | ||
| tests = sys.argv[1:] | ||
| else: | ||
| ### Other wise launch the whole suite | ||
| #tests = ["BasicInstanceChecks","ElasticIps","MaxSmallInstances","LargestInstance","MetaData","Reboot", "Churn"] | ||
| tests = ["failoverCLC"] | ||
| for test in tests: | ||
| result = unittest.TextTestRunner(verbosity=2).run(HAtests(test)) | ||
| if result.wasSuccessful(): | ||
| pass | ||
| else: | ||
| exit(1) | ||
|
|
||
|
|
| @@ -0,0 +1,216 @@ | ||
| #!/Users/hspencer/Desktop/eutester-dev/bin/python | ||
| # | ||
| # Description: This case was developed to test the integrity of iptables upon | ||
| # deletion of security groups. Based up the arguments passed, the test | ||
| # creates at least 3 security groups and launches an instance for each one. | ||
| # Once each instance has been launched, a snapshot of iptables is taken. | ||
| # Then each instance is terminated, followed by each security group being terminated. | ||
| # Another snapshot of iptables is done. There is a comparison of iptables. | ||
| # The results are logged. | ||
| # | ||
|
|
||
| from eucaops import Eucaops | ||
| import argparse | ||
| import random | ||
| import os | ||
| import unittest | ||
| import time | ||
| import string | ||
| import re | ||
| import sys | ||
| import pprint | ||
|
|
||
| class Instances(unittest.TestCase): | ||
| def setUp(self): | ||
| self.options = options | ||
|
|
||
| ### Make sure --config_file or --credpath is provied | ||
| self.got_creds = False | ||
| while self.got_creds == False: | ||
| try: | ||
| if self.options.config_file: | ||
| self.tester = Eucaops(config_file=self.options.config_file, password=self.options.password) | ||
| elif self.options.credpath: | ||
| self.tester = Eucaops(credpath=self.options.credpath, password=self.options.password) | ||
| else: | ||
| print "\tNeed to pass either --credpath or --config_file option. Try --help for more information" | ||
| exit(1) | ||
| except Exception,e: | ||
| print str(e) | ||
| self.time.sleep(30) | ||
| continue | ||
| self.got_creds = True | ||
|
|
||
| self.tester.start_euca_logs() | ||
|
|
||
| def tearDown(self): | ||
| ### Clean up after running test case | ||
| self.tester.delete_keypair(self.keypair) | ||
| os.remove(self.keypath) | ||
| self.tester.stop_euca_logs() | ||
| self.tester.save_euca_logs() | ||
| self.keypath = None | ||
| self.keypair = None | ||
| self.tester = None | ||
| self.image = None | ||
| self.options = None | ||
| self.got_creds = None | ||
| self.time = None | ||
| self.num_vms = None | ||
| self.available = None | ||
| self.security_groups = None | ||
|
|
||
| ### Test Cases ### | ||
| def iptables_Cruft(self): | ||
| ### Launch number of instances based upon number of security groups wanting to be tested. | ||
|
|
||
| ## If specific image wants to be tested, use that; if not, use any instance-store backed image. | ||
| if (self.options.image): | ||
| self.image = self.tester.get_emi(emi=self.options.image) | ||
| else: | ||
| self.image = self.tester.get_emi(root_device_type="instance-store") | ||
|
|
||
| self.keypair = self.tester.add_keypair(self.options.prefix + "-" + str(time.time())) | ||
| self.keypath = os.curdir + "/" + self.keypair.name + ".pem" | ||
|
|
||
| ### Identify type of instance to run | ||
| if self.options.type == "random": | ||
| self.options.type = random.choice(["m1.small","c1.medium","m1.large","m1.xlarge","c1.xlarge"]) | ||
|
|
||
| ### Identify number of instances to run (i.e. number of security groups) | ||
| self.num_vms = self.tester.get_available_vms(self.options.type) | ||
|
|
||
| if self.num_vms >= self.options.number: | ||
| self.available = self.options.number | ||
| else: | ||
| self.options.type = "m1.small" | ||
| avail_vms = self.tester.get_available_vms(self.options.type) | ||
| if avail_vms < self.options.number: | ||
| self.tester.fail("Not enough m1.small vm types to run test with minimal of 3 security groups.") | ||
| else: | ||
| self.available = self.options.number | ||
|
|
||
| ### Take snapshot of iptables before creating security groups and launching instances. | ||
| self.pre_iptables = self.tester.sys("iptables-save | grep -v \"#\" | grep -v \"\:PRE\" | grep -v \"\:POST\" | grep -v \"\:INPUT\" | grep -v \"\:FORWARD\" | grep -v \"\:OUT\"") | ||
| self.assertNotEqual(len(self.pre_iptables), 0, "pre_Iptables_Snapshot failed.") | ||
|
|
||
| ### Create security group for number of security groups we want to test. | ||
| self.security_groups = [] | ||
| while self.available > 0: | ||
| ### Create unique security group and authorize SSH and PING | ||
| reservation = None | ||
| sec_group = None | ||
| sec_group = self.tester.add_group(group_name=self.options.prefix + "-" + str(time.time())) | ||
| self.assertNotEqual(len(sec_group.name), 0, "Could not create group.") | ||
| self.assertTrue(self.tester.authorize_group_by_name(group_name=sec_group.name), | ||
| "Could not authorize group for SSH") | ||
| self.assertTrue(self.tester.authorize_group_by_name(group_name=sec_group.name, port=-1, protocol="icmp" ), | ||
| "Could not authorize group for PING") | ||
| self.security_groups.append(sec_group) | ||
|
|
||
| ### Launch instance for the unique security group | ||
| try: | ||
| reservation = self.tester.run_instance(self.image,keypair=self.keypair.name, group=sec_group.name ,type=self.options.type) | ||
| except Exception, e: | ||
| self.fail("Caught an exception when running the instance: " + str(e)) | ||
|
|
||
| for instance in reservation.instances: | ||
| ### Wait for instance to run; error otherwise | ||
| self.assertTrue(self.tester.wait_for_reservation(reservation) ,'Instance did not go to running') | ||
|
|
||
| ### Ping the instance | ||
| ping_result = self.tester.ping(instance.public_dns_name) | ||
| self.assertTrue(ping_result, "Ping to instance failed.") | ||
|
|
||
| ### If test is running from Eucalyptus component, access instance and run "uname -a" | ||
| if (self.options.config_file): | ||
| uname_result = instance.sys("uname -a") | ||
| self.assertNotEqual(len(uname_result), 0, "uname -a failed.") | ||
|
|
||
| ### Decrement count of security groups and instances left to create | ||
| self.available -= 1 | ||
|
|
||
|
|
||
| ### Loop through and terminate instances | ||
| ### Grab total number of instances ran from by test case | ||
| total_reservations = self.tester.ec2.get_all_instances() | ||
| ### Terminate each instance | ||
| for reservation in total_reservations: | ||
| self.assertTrue(self.tester.terminate_instances(reservation), "Failure when terminating instance.") | ||
|
|
||
| ### Loop through and delete security groups | ||
| for group in self.security_groups: | ||
| self.assertTrue(self.tester.delete_group(group), "Failure when deleting group " + group.name) | ||
|
|
||
| ### Take snapshot of iptables after deleting security groups and launching instances. | ||
| self.post_iptables = self.tester.sys("iptables-save | grep -v \"#\" | grep -v \"\:PRE\" | grep -v \"\:POST\" | grep -v \"\:INPUT\" | grep -v \"\:FORWARD\" | grep -v \"\:OUT\"") | ||
| self.assertNotEqual(len(self.post_iptables), 0, "post_Iptables_Snapshot failed.") | ||
|
|
||
| ### Evaluate pre and post iptables outputs to see if there is a difference. | ||
| if (len(self.pre_iptables) != len(self.post_iptables)): | ||
| ## Get different lines and print them | ||
|
|
||
| iptables_diff = set(self.post_iptables) - set(self.pre_iptables) | ||
| pp = pprint.PrettyPrinter(indent=4) | ||
|
|
||
| print "\n======================================\n" | ||
| print "Diffences between iptables snapshots: " | ||
| print "PRE-IPTABLES SNAPSHOT LENGTH: " + str(len(self.pre_iptables)) | ||
| print "POST-IPTABLES SNAPSHOT LENGTH: " + str(len(self.post_iptables)) | ||
| print "\n---------------------------------------\n" | ||
| pp.pprint(list(iptables_diff)) | ||
| print "\n======================================\n" | ||
| else: | ||
| print "\n======================================\n" | ||
| print "No difference between iptables." | ||
| print "PRE-IPTABLES SNAPSHOT LENGTH: " + str(len(self.pre_iptables)) | ||
| print "POST-IPTABLES SNAPSHOT LENGTH: " + str(len(self.post_iptables)) | ||
| print "\n======================================\n" | ||
|
|
||
| def get_options(): | ||
| ### Parse args | ||
| parser = argparse.ArgumentParser(prog="iptables_security_group_test.py", | ||
| version="Test Case [iptables_security_group_test.py] Version 0.1.1", | ||
| description="Run an iterative test of operations on a cloud to test integrity of iptables \ | ||
| state upon deletion of security groups. For more information, please refer to \ | ||
| https://github.com/hspencer77/eutester/wiki/iptables_security_group_test") | ||
| parser.add_argument("-n", "--number", dest="number", type=int, | ||
| help="Number of security groups to create", default=3) | ||
| parser.add_argument("-e", "--exit", action="store_true", dest="exit_on_fail", | ||
| help="Whether or not to stop the script after a failure") | ||
| parser.add_argument("-i", "--image", dest="image", | ||
| help="Specific image to run", default=None) | ||
| parser.add_argument("-t", "--type", dest="type", | ||
| help="Type of instance to launch Default: random", default="random") | ||
| parser.add_argument( "--prefix", dest="prefix", | ||
| help="Prefix to tack on to keypairs", default="iptables-secgrp-test") | ||
| parser.add_argument("-z", "--zone", dest="zone", | ||
| help="AZ to run script against", default="PARTI00") | ||
| parser.add_argument("-u", "--user", dest="user", | ||
| help="User to run script as", default="admin") | ||
| parser.add_argument("-a", "--account", dest="account", | ||
| help="Account to run script as", default="eucalyptus") | ||
| parser.add_argument("-U", "--username", dest="username", | ||
| help="User account on physical CC machine", default="root") | ||
| parser.add_argument("-P", "--password", dest="password", | ||
| help="Password for user account on physical CC machine", default=None) | ||
| parser.add_argument("--config_file", dest="config_file", | ||
| help="Cloud config of AZ", default=None) | ||
| parser.add_argument("--credpath", dest="credpath", | ||
| help="AZ to run script against", default=None) | ||
| parser.add_argument('unittest_args', nargs='*') | ||
|
|
||
| ## Grab arguments passed via commandline | ||
| options = parser.parse_args() | ||
| sys.argv[1:] = options.unittest_args | ||
| return options | ||
|
|
||
| if __name__ == '__main__': | ||
| options = get_options() | ||
| tests = ['iptables_Cruft'] | ||
| for test in tests: | ||
| result = unittest.TextTestRunner(verbosity=2).run(Instances(test)) | ||
| if result.wasSuccessful(): | ||
| pass | ||
| else: | ||
| exit(1) |