diff --git a/contrib/boto_v6/__init__.py b/contrib/boto_v6/__init__.py deleted file mode 100644 index 9fec157f178d..000000000000 --- a/contrib/boto_v6/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/ -# Copyright (c) 2010, Eucalyptus Systems, Inc. -# All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, dis- -# tribute, sublicense, and/or sell copies of the Software, and to permit -# persons to whom the Software is furnished to do so, subject to the fol- -# lowing conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- -# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -def connect_ec2(aws_access_key_id=None, aws_secret_access_key=None, **kwargs): - """ - :type aws_access_key_id: string - :param aws_access_key_id: Your AWS Access Key ID - - :type aws_secret_access_key: string - :param aws_secret_access_key: Your AWS Secret Access Key - - :rtype: :class:`boto.ec2.connection.EC2Connection` - :return: A connection to Amazon's EC2 - """ - from boto_v6.ec2.connection import EC2ConnectionV6 - return EC2ConnectionV6(aws_access_key_id, aws_secret_access_key, **kwargs) diff --git a/contrib/boto_v6/ec2/__init__.py b/contrib/boto_v6/ec2/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/contrib/boto_v6/ec2/connection.py b/contrib/boto_v6/ec2/connection.py deleted file mode 100644 index 4cec65ad8368..000000000000 --- a/contrib/boto_v6/ec2/connection.py +++ /dev/null @@ -1,141 +0,0 @@ -''' -Created on 2010/12/20 - -@author: Nachi Ueno -''' -import base64 -import boto -import boto.ec2 -import boto.ec2.securitygroup as securitygroup -from boto_v6.ec2.instance import ReservationV6 - - -class EC2ConnectionV6(boto.ec2.EC2Connection): - ''' - EC2Connection for OpenStack IPV6 mode - ''' - def get_all_instances(self, instance_ids=None, filters=None): - """ - Retrieve all the instances associated with your account. - - :type instance_ids: list - :param instance_ids: A list of strings of instance IDs - - :type filters: dict - :param filters: Optional filters that can be used to limit - the results returned. Filters are provided - in the form of a dictionary consisting of - filter names as the key and filter values - as the value. The set of allowable filter - names/values is dependent on the request - being performed. Check the EC2 API guide - for details. - - :rtype: list - :return: A list of :class:`boto.ec2.instance.Reservation` - """ - params = {} - if instance_ids: - self.build_list_params(params, instance_ids, 'InstanceId') - if filters: - self.build_filter_params(params, filters) - return self.get_list('DescribeInstancesV6', params, - [('item', ReservationV6)]) - - def run_instances(self, image_id, min_count=1, max_count=1, - key_name=None, security_groups=None, - user_data=None, addressing_type=None, - instance_type='m1.small', placement=None, - kernel_id=None, ramdisk_id=None, - monitoring_enabled=False, subnet_id=None, - block_device_map=None): - """ - Runs an image on EC2. - - :type image_id: string - :param image_id: The ID of the image to run - - :type min_count: int - :param min_count: The minimum number of instances to launch - - :type max_count: int - :param max_count: The maximum number of instances to launch - - :type key_name: string - :param key_name: The name of the key pair with which to - launch instances - - :type security_groups: list of strings - :param security_groups: The names of the security groups with - which to associate instances - - :type user_data: string - :param user_data: The user data passed to the launched instances - - :type instance_type: string - :param instance_type: The type of instance to run - (m1.small, m1.large, m1.xlarge) - - :type placement: string - :param placement: The availability zone in which to launch - the instances - - :type kernel_id: string - :param kernel_id: The ID of the kernel with which to - launch the instances - - :type ramdisk_id: string - :param ramdisk_id: The ID of the RAM disk with which to - launch the instances - - :type monitoring_enabled: bool - :param monitoring_enabled: Enable CloudWatch monitoring - on the instance. - - :type subnet_id: string - :param subnet_id: The subnet ID within which to launch - the instances for VPC. - - :type block_device_map: - :class:`boto.ec2.blockdevicemapping.BlockDeviceMapping` - :param block_device_map: A BlockDeviceMapping data structure - describing the EBS volumes associated - with the Image. - - :rtype: Reservation - :return: The :class:`boto.ec2.instance.ReservationV6` - associated with the request for machines - """ - params = {'ImageId': image_id, - 'MinCount': min_count, - 'MaxCount': max_count} - if key_name: - params['KeyName'] = key_name - if security_groups: - l = [] - for group in security_groups: - if isinstance(group, securitygroup.SecurityGroup): - l.append(group.name) - else: - l.append(group) - self.build_list_params(params, l, 'SecurityGroup') - if user_data: - params['UserData'] = base64.b64encode(user_data) - if addressing_type: - params['AddressingType'] = addressing_type - if instance_type: - params['InstanceType'] = instance_type - if placement: - params['Placement.AvailabilityZone'] = placement - if kernel_id: - params['KernelId'] = kernel_id - if ramdisk_id: - params['RamdiskId'] = ramdisk_id - if monitoring_enabled: - params['Monitoring.Enabled'] = 'true' - if subnet_id: - params['SubnetId'] = subnet_id - if block_device_map: - block_device_map.build_list_params(params) - return self.get_object('RunInstances', params, - ReservationV6, verb='POST') diff --git a/contrib/boto_v6/ec2/instance.py b/contrib/boto_v6/ec2/instance.py deleted file mode 100644 index 6f088c67e73a..000000000000 --- a/contrib/boto_v6/ec2/instance.py +++ /dev/null @@ -1,34 +0,0 @@ -''' -Created on 2010/12/20 - -@author: Nachi Ueno -''' -from boto.ec2 import instance -from boto import resultset - - -class ReservationV6(instance.Reservation): - def startElement(self, name, attrs, connection): - if name == 'instancesSet': - self.instances = resultset.ResultSet([('item', InstanceV6)]) - return self.instances - elif name == 'groupSet': - self.groups = resultset.ResultSet([('item', instance.Group)]) - return self.groups - else: - return None - - -class InstanceV6(instance.Instance): - def __init__(self, connection=None): - instance.Instance.__init__(self, connection) - self.dns_name_v6 = None - - def endElement(self, name, value, connection): - instance.Instance.endElement(self, name, value, connection) - if name == 'dnsNameV6': - self.dns_name_v6 = value - - def _update(self, updated): - self.__dict__.update(updated.__dict__) - self.dns_name_v6 = updated.dns_name_v6 diff --git a/smoketests/__init__.py b/smoketests/__init__.py deleted file mode 100644 index 67609d4249f0..000000000000 --- a/smoketests/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -:mod:`smoketests` -- Nova Integration "Smoke" Tests -===================================================== - -.. automodule:: nova.volume - :platform: Unix -""" diff --git a/smoketests/base.py b/smoketests/base.py deleted file mode 100644 index c3b2be131181..000000000000 --- a/smoketests/base.py +++ /dev/null @@ -1,201 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import boto -from boto.ec2 import regioninfo -import commands -import httplib -import os -import paramiko -import sys -import time -import unittest - -from smoketests import flags - -SUITE_NAMES = '[image, instance, volume]' -FLAGS = flags.FLAGS -flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES) -flags.DEFINE_integer('ssh_tries', 3, 'Numer of times to try ssh') - - -class SmokeTestCase(unittest.TestCase): - def connect_ssh(self, ip, key_name): - key = paramiko.RSAKey.from_private_key_file('/tmp/%s.pem' % key_name) - tries = 0 - while(True): - try: - client = paramiko.SSHClient() - client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - client.connect(ip, username='root', pkey=key, timeout=5) - return client - except (paramiko.AuthenticationException, paramiko.SSHException): - tries += 1 - if tries == FLAGS.ssh_tries: - raise - - def can_ping(self, ip, command="ping"): - """Attempt to ping the specified IP, and give up after 1 second.""" - - # NOTE(devcamcar): ping timeout flag is different in OSX. - if sys.platform == 'darwin': - timeout_flag = 't' - else: - timeout_flag = 'w' - - status, output = commands.getstatusoutput('%s -c1 -%s1 %s' % - (command, timeout_flag, ip)) - return status == 0 - - def wait_for_running(self, instance, tries=60, wait=1): - """Wait for instance to be running.""" - for x in xrange(tries): - instance.update() - if instance.state.startswith('running'): - return True - time.sleep(wait) - else: - return False - - def wait_for_deleted(self, instance, tries=60, wait=1): - """Wait for instance to be deleted.""" - for x in xrange(tries): - try: - #NOTE(dprince): raises exception when instance id disappears - instance.update(validate=True) - except ValueError: - return True - time.sleep(wait) - else: - return False - - def wait_for_ping(self, ip, command="ping", tries=120): - """Wait for ip to be pingable.""" - for x in xrange(tries): - if self.can_ping(ip, command): - return True - else: - return False - - def wait_for_ssh(self, ip, key_name, tries=30, wait=5): - """Wait for ip to be sshable.""" - for x in xrange(tries): - try: - conn = self.connect_ssh(ip, key_name) - conn.close() - except Exception: - time.sleep(wait) - else: - return True - else: - return False - - def connection_for_env(self, **kwargs): - """ - Returns a boto ec2 connection for the current environment. - """ - access_key = os.getenv('EC2_ACCESS_KEY') - secret_key = os.getenv('EC2_SECRET_KEY') - clc_url = os.getenv('EC2_URL') - - if not access_key or not secret_key or not clc_url: - raise Exception('Missing EC2 environment variables. Please source ' - 'the appropriate novarc file before running this ' - 'test.') - - parts = self.split_clc_url(clc_url) - if FLAGS.use_ipv6: - return boto_v6.connect_ec2(aws_access_key_id=access_key, - aws_secret_access_key=secret_key, - is_secure=parts['is_secure'], - region=regioninfo.RegionInfo(None, - 'nova', - parts['ip']), - port=parts['port'], - path='/services/Cloud', - **kwargs) - - return boto.connect_ec2(aws_access_key_id=access_key, - aws_secret_access_key=secret_key, - is_secure=parts['is_secure'], - region=regioninfo.RegionInfo(None, - 'nova', - parts['ip']), - port=parts['port'], - path='/services/Cloud', - **kwargs) - - def split_clc_url(self, clc_url): - """Splits a cloud controller endpoint url.""" - parts = httplib.urlsplit(clc_url) - is_secure = parts.scheme == 'https' - ip, port = parts.netloc.split(':') - return {'ip': ip, 'port': int(port), 'is_secure': is_secure} - - def create_key_pair(self, conn, key_name): - try: - os.remove('/tmp/%s.pem' % key_name) - except Exception: - pass - key = conn.create_key_pair(key_name) - key.save('/tmp/') - return key - - def delete_key_pair(self, conn, key_name): - conn.delete_key_pair(key_name) - try: - os.remove('/tmp/%s.pem' % key_name) - except Exception: - pass - - def bundle_image(self, image, tempdir='/tmp', kernel=False): - cmd = 'euca-bundle-image -i %s -d %s' % (image, tempdir) - if kernel: - cmd += ' --kernel true' - status, output = commands.getstatusoutput(cmd) - if status != 0: - raise Exception(output) - return True - - def upload_image(self, bucket_name, image, tempdir='/tmp'): - cmd = 'euca-upload-bundle -b ' - cmd += '%s -m %s/%s.manifest.xml' % (bucket_name, tempdir, image) - status, output = commands.getstatusoutput(cmd) - if status != 0: - raise Exception(output) - return True - - def delete_bundle_bucket(self, bucket_name): - cmd = 'euca-delete-bundle --clear -b %s' % (bucket_name) - status, output = commands.getstatusoutput(cmd) - if status != 0: - raise Exception(output) - return True - - -TEST_DATA = {} -if FLAGS.use_ipv6: - global boto_v6 - boto_v6 = __import__('boto_v6') - - -class UserSmokeTestCase(SmokeTestCase): - def setUp(self): - global TEST_DATA - self.conn = self.connection_for_env() - self.data = TEST_DATA diff --git a/smoketests/flags.py b/smoketests/flags.py deleted file mode 100644 index 472e76409015..000000000000 --- a/smoketests/flags.py +++ /dev/null @@ -1,39 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Package-level global flags are defined here, the rest are defined -where they're used. -""" - - -from gflags import * # noqa - -# This keeps pylint from barfing on the imports -FLAGS = FLAGS -DEFINE_string = DEFINE_string -DEFINE_integer = DEFINE_integer -DEFINE_bool = DEFINE_bool - -# __GLOBAL FLAGS ONLY__ -# Define any app-specific flags in their own files, docs at: -# http://code.google.com/p/python-gflags/source/browse/trunk/gflags.py#39 - -DEFINE_string('region', 'nova', 'Region to use') -DEFINE_string('test_image', 'ami-tty', 'Image to use for launch tests') -DEFINE_bool('use_ipv6', False, 'use the ipv6 or not') diff --git a/smoketests/proxy.sh b/smoketests/proxy.sh deleted file mode 100755 index b9057fe9dec6..000000000000 --- a/smoketests/proxy.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -# This is a simple shell script that uses netcat to set up a proxy to the -# metadata server on port 80 and to a google ip on port 8080. This is meant -# to be passed in by a script to an instance via user data, so that -# automatic testing of network connectivity can be performed. - -# Example usage: -# euca-run-instances -t m1.tiny -f proxy.sh ami-tty - -mkfifo backpipe1 -mkfifo backpipe2 - -if nc -h 2>&1 | grep -i openbsd -then - NC_LISTEN="nc -l" -else - NC_LISTEN="nc -l -p" -fi - -# NOTE(vish): proxy metadata on port 80 -while true; do - $NC_LISTEN 80 0backpipe1 -done & - -# NOTE(vish): proxy google on port 8080 -while true; do - $NC_LISTEN 8080 0backpipe2 -done & diff --git a/smoketests/public_network_smoketests.py b/smoketests/public_network_smoketests.py deleted file mode 100644 index ef6582770438..000000000000 --- a/smoketests/public_network_smoketests.py +++ /dev/null @@ -1,180 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import commands -import os -import random -import sys -import time - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - -from smoketests import base -from smoketests import flags - -#Note that this test should run from -#public network (outside of private network segments) -#Please set EC2_URL correctly -#You should use admin account in this test - -FLAGS = flags.FLAGS - -TEST_PREFIX = 'test%s' % int(random.random() * 1000000) -TEST_BUCKET = '%s_bucket' % TEST_PREFIX -TEST_KEY = '%s_key' % TEST_PREFIX -TEST_KEY2 = '%s_key2' % TEST_PREFIX -TEST_DATA = {} - - -class InstanceTestsFromPublic(base.UserSmokeTestCase): - def test_001_can_create_keypair(self): - key = self.create_key_pair(self.conn, TEST_KEY) - self.assertEqual(key.name, TEST_KEY) - - def test_002_security_group(self): - security_group_name = "".join(random.choice("sdiuisudfsdcnpaqwertasd") - for x in range(random.randint(4, 8))) - group = self.conn.create_security_group(security_group_name, - 'test group') - group.connection = self.conn - group.authorize('tcp', 22, 22, '0.0.0.0/0') - if FLAGS.use_ipv6: - group.authorize('tcp', 22, 22, '::/0') - - reservation = self.conn.run_instances(FLAGS.test_image, - key_name=TEST_KEY, - security_groups=[security_group_name], - instance_type='m1.tiny') - self.data['security_group_name'] = security_group_name - self.data['group'] = group - self.data['instance_id'] = reservation.instances[0].id - - def test_003_instance_with_group_runs_within_60_seconds(self): - reservations = self.conn.get_all_instances([self.data['instance_id']]) - instance = reservations[0].instances[0] - # allow 60 seconds to exit pending with IP - for x in xrange(60): - instance.update() - if instance.state == u'running': - break - time.sleep(1) - else: - self.fail('instance failed to start') - ip = reservations[0].instances[0].private_ip_address - self.assertFalse(ip == '0.0.0.0') - self.data['private_ip'] = ip - if FLAGS.use_ipv6: - ipv6 = reservations[0].instances[0].dns_name_v6 - self.assertFalse(ipv6 is None) - self.data['ip_v6'] = ipv6 - - def test_004_can_ssh_to_ipv6(self): - if FLAGS.use_ipv6: - for x in xrange(20): - try: - conn = self.connect_ssh( - self.data['ip_v6'], TEST_KEY) - conn.close() - except Exception: - time.sleep(1) - else: - break - else: - self.fail('could not ssh to instance') - - def test_012_can_create_instance_with_keypair(self): - if 'instance_id' in self.data: - self.conn.terminate_instances([self.data['instance_id']]) - reservation = self.conn.run_instances(FLAGS.test_image, - key_name=TEST_KEY, - instance_type='m1.tiny') - self.assertEqual(len(reservation.instances), 1) - self.data['instance_id'] = reservation.instances[0].id - - def test_013_instance_runs_within_60_seconds(self): - reservations = self.conn.get_all_instances([self.data['instance_id']]) - instance = reservations[0].instances[0] - # allow 60 seconds to exit pending with IP - for x in xrange(60): - instance.update() - if instance.state == u'running': - break - time.sleep(1) - else: - self.fail('instance failed to start') - ip = reservations[0].instances[0].private_ip_address - self.assertFalse(ip == '0.0.0.0') - self.data['private_ip'] = ip - if FLAGS.use_ipv6: - ipv6 = reservations[0].instances[0].dns_name_v6 - self.assertFalse(ipv6 is None) - self.data['ip_v6'] = ipv6 - - def test_014_can_not_ping_private_ip(self): - for x in xrange(4): - # ping waits for 1 second - status, output = commands.getstatusoutput( - 'ping -c1 %s' % self.data['private_ip']) - if status == 0: - self.fail('can ping private ip from public network') - if FLAGS.use_ipv6: - status, output = commands.getstatusoutput( - 'ping6 -c1 %s' % self.data['ip_v6']) - if status == 0: - self.fail('can ping ipv6 from public network') - else: - pass - - def test_015_can_not_ssh_to_private_ip(self): - for x in xrange(1): - try: - conn = self.connect_ssh(self.data['private_ip'], TEST_KEY) - conn.close() - except Exception: - time.sleep(1) - else: - self.fail('can ssh for ipv4 address from public network') - - if FLAGS.use_ipv6: - for x in xrange(1): - try: - conn = self.connect_ssh( - self.data['ip_v6'], TEST_KEY) - conn.close() - except Exception: - time.sleep(1) - else: - self.fail('can ssh for ipv6 address from public network') - - def test_999_tearDown(self): - self.delete_key_pair(self.conn, TEST_KEY) - security_group_name = self.data['security_group_name'] - group = self.data['group'] - if group: - group.revoke('tcp', 22, 22, '0.0.0.0/0') - if FLAGS.use_ipv6: - group.revoke('tcp', 22, 22, '::/0') - self.conn.delete_security_group(security_group_name) - if 'instance_id' in self.data: - self.conn.terminate_instances([self.data['instance_id']]) diff --git a/smoketests/random.image b/smoketests/random.image deleted file mode 100644 index f2c0c30bbc73..000000000000 Binary files a/smoketests/random.image and /dev/null differ diff --git a/smoketests/random.kernel b/smoketests/random.kernel deleted file mode 100644 index 01a6284dd785..000000000000 Binary files a/smoketests/random.kernel and /dev/null differ diff --git a/smoketests/requirements.txt b/smoketests/requirements.txt deleted file mode 100644 index b942b507ceb2..000000000000 --- a/smoketests/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -python-gflags diff --git a/smoketests/run_tests.py b/smoketests/run_tests.py deleted file mode 100644 index e8caff4c77d1..000000000000 --- a/smoketests/run_tests.py +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Colorizer Code is borrowed from Twisted: -# Copyright (c) 2001-2010 Twisted Matrix Laboratories. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -"""Unittest runner for Nova. - -To run all tests - python run_tests.py - -To run a single test: - python run_tests.py test_compute:ComputeTestCase.test_run_terminate - -To run a single test module: - python run_tests.py test_compute - - or - - python run_tests.py api.test_wsgi - -""" - -from __future__ import print_function - -import os -import sys -import unittest - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - - -from nose import config -from nose import core -from nose import result - -from smoketests import flags - -from nova.openstack.common.gettextutils import _ - -FLAGS = flags.FLAGS - - -class _AnsiColorizer(object): - """ - A colorizer is an object that loosely wraps around a stream, allowing - callers to write text to the stream in a particular color. - - Colorizer classes must implement C{supported()} and C{write(text, color)}. - """ - _colors = dict(black=30, red=31, green=32, yellow=33, - blue=34, magenta=35, cyan=36, white=37) - - def __init__(self, stream): - self.stream = stream - - def supported(cls, stream=sys.stdout): - """ - A class method that returns True if the current platform supports - coloring terminal output using this method. Returns False otherwise. - """ - if not stream.isatty(): - return False # auto color only on TTYs - try: - import curses - except ImportError: - return False - else: - try: - try: - return curses.tigetnum("colors") > 2 - except curses.error: - curses.setupterm() - return curses.tigetnum("colors") > 2 - except Exception: - raise - # guess false in case of error - return False - supported = classmethod(supported) - - def write(self, text, color): - """ - Write the given text to the stream in the given color. - - @param text: Text to be written to the stream. - - @param color: A string label for a color. e.g. 'red', 'white'. - """ - color = self._colors[color] - self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) - - -class _Win32Colorizer(object): - """ - See _AnsiColorizer docstring. - """ - def __init__(self, stream): - from win32console import FOREGROUND_BLUE - from win32console import FOREGROUND_GREEN - from win32console import FOREGROUND_INTENSITY - from win32console import FOREGROUND_RED - from win32console import GetStdHandle - from win32console import STD_OUTPUT_HANDLE - - red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, - FOREGROUND_BLUE, FOREGROUND_INTENSITY) - self.stream = stream - self.screenBuffer = GetStdHandle(STD_OUTPUT_HANDLE) - self._colors = { - 'normal': red | green | blue, - 'red': red | bold, - 'green': green | bold, - 'blue': blue | bold, - 'yellow': red | green | bold, - 'magenta': red | blue | bold, - 'cyan': green | blue | bold, - 'white': red | green | blue | bold - } - - def supported(cls, stream=sys.stdout): - try: - import win32console - screenBuffer = win32console.GetStdHandle( - win32console.STD_OUTPUT_HANDLE) - except ImportError: - return False - import pywintypes - try: - screenBuffer.SetConsoleTextAttribute( - win32console.FOREGROUND_RED | - win32console.FOREGROUND_GREEN | - win32console.FOREGROUND_BLUE) - except pywintypes.error: - return False - else: - return True - supported = classmethod(supported) - - def write(self, text, color): - color = self._colors[color] - self.screenBuffer.SetConsoleTextAttribute(color) - self.stream.write(text) - self.screenBuffer.SetConsoleTextAttribute(self._colors['normal']) - - -class _NullColorizer(object): - """ - See _AnsiColorizer docstring. - """ - def __init__(self, stream): - self.stream = stream - - def supported(cls, stream=sys.stdout): - return True - supported = classmethod(supported) - - def write(self, text, color): - self.stream.write(text) - - -class NovaTestResult(result.TextTestResult): - def __init__(self, *args, **kw): - result.TextTestResult.__init__(self, *args, **kw) - self._last_case = None - self.colorizer = None - # NOTE(vish): reset stdout for the terminal check - stdout = sys.stdout - sys.stdout = sys.__stdout__ - for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: - if colorizer.supported(): - self.colorizer = colorizer(self.stream) - break - sys.stdout = stdout - - def getDescription(self, test): - return str(test) - - # NOTE(vish): copied from unittest with edit to add color - def addSuccess(self, test): - unittest.TestResult.addSuccess(self, test) - if self.showAll: - self.colorizer.write("OK", 'green') - self.stream.writeln() - elif self.dots: - self.stream.write('.') - self.stream.flush() - - # NOTE(vish): copied from unittest with edit to add color - def addFailure(self, test, err): - unittest.TestResult.addFailure(self, test, err) - if self.showAll: - self.colorizer.write("FAIL", 'red') - self.stream.writeln() - elif self.dots: - self.stream.write('F') - self.stream.flush() - - # NOTE(vish): copied from nose with edit to add color - def addError(self, test, err): - """Overrides normal addError to add support for - errorClasses. If the exception is a registered class, the - error will be added to the list for that class, not errors. - """ - stream = getattr(self, 'stream', None) - ec, ev, tb = err - try: - exc_info = self._exc_info_to_string(err, test) - except TypeError: - # 2.3 compat - exc_info = self._exc_info_to_string(err) - for cls, (storage, label, isfail) in self.errorClasses.items(): - if result.isclass(ec) and issubclass(ec, cls): - if isfail: - test.passed = False - storage.append((test, exc_info)) - # Might get patched into a streamless result - if stream is not None: - if self.showAll: - message = [label] - detail = result._exception_detail(err[1]) - if detail: - message.append(detail) - stream.writeln(": ".join(message)) - elif self.dots: - stream.write(label[:1]) - return - self.errors.append((test, exc_info)) - test.passed = False - if stream is not None: - if self.showAll: - self.colorizer.write("ERROR", 'red') - self.stream.writeln() - elif self.dots: - stream.write('E') - - def startTest(self, test): - unittest.TestResult.startTest(self, test) - current_case = test.test.__class__.__name__ - - if self.showAll: - if current_case != self._last_case: - self.stream.writeln(current_case) - self._last_case = current_case - - self.stream.write( - ' %s' % str(test.test._testMethodName).ljust(60)) - self.stream.flush() - - -class NovaTestRunner(core.TextTestRunner): - def _makeResult(self): - return NovaTestResult(self.stream, - self.descriptions, - self.verbosity, - self.config) - - -if __name__ == '__main__': - if not os.getenv('EC2_ACCESS_KEY'): - print(_('Missing EC2 environment variables. Please ' - 'source the appropriate novarc file before ' - 'running this test.')) - sys.exit(1) - - argv = FLAGS(sys.argv) - testdir = os.path.abspath("./") - c = config.Config(stream=sys.stdout, - env=os.environ, - verbosity=3, - workingDir=testdir, - plugins=core.DefaultPluginManager()) - - runner = NovaTestRunner(stream=c.stream, - verbosity=c.verbosity, - config=c) - sys.exit(not core.run(config=c, testRunner=runner, argv=argv)) diff --git a/smoketests/test_netadmin.py b/smoketests/test_netadmin.py deleted file mode 100644 index d1254234e345..000000000000 --- a/smoketests/test_netadmin.py +++ /dev/null @@ -1,203 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import commands -import os -import random -import sys -import time - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - -from smoketests import base -from smoketests import flags - - -FLAGS = flags.FLAGS - -TEST_PREFIX = 'test%s' % int(random.random() * 1000000) -TEST_BUCKET = '%s_bucket' % TEST_PREFIX -TEST_KEY = '%s_key' % TEST_PREFIX -TEST_GROUP = '%s_group' % TEST_PREFIX - - -class AddressTests(base.UserSmokeTestCase): - def test_000_setUp(self): - self.create_key_pair(self.conn, TEST_KEY) - reservation = self.conn.run_instances(FLAGS.test_image, - instance_type='m1.tiny', - key_name=TEST_KEY) - self.data['instance'] = reservation.instances[0] - if not self.wait_for_running(self.data['instance']): - self.fail('instance failed to start') - self.data['instance'].update() - if not self.wait_for_ping(self.data['instance'].private_ip_address): - self.fail('could not ping instance') - if not self.wait_for_ssh(self.data['instance'].private_ip_address, - TEST_KEY): - self.fail('could not ssh to instance') - - def test_001_can_allocate_floating_ip(self): - result = self.conn.allocate_address() - self.assertTrue(hasattr(result, 'public_ip')) - self.data['public_ip'] = result.public_ip - - def test_002_can_associate_ip_with_instance(self): - result = self.conn.associate_address(self.data['instance'].id, - self.data['public_ip']) - self.assertTrue(result) - - def test_003_can_ssh_with_public_ip(self): - ssh_authorized = False - groups = self.conn.get_all_security_groups(['default']) - for rule in groups[0].rules: - if (rule.ip_protocol == 'tcp' and - int(rule.from_port) <= 22 and - int(rule.to_port) >= 22): - ssh_authorized = True - break - if not ssh_authorized: - self.conn.authorize_security_group('default', - ip_protocol='tcp', - from_port=22, - to_port=22) - try: - if not self.wait_for_ssh(self.data['public_ip'], TEST_KEY): - self.fail('could not ssh to public ip') - finally: - if not ssh_authorized: - self.conn.revoke_security_group('default', - ip_protocol='tcp', - from_port=22, - to_port=22) - - def test_004_can_disassociate_ip_from_instance(self): - result = self.conn.disassociate_address(self.data['public_ip']) - self.assertTrue(result) - - def test_005_can_deallocate_floating_ip(self): - result = self.conn.release_address(self.data['public_ip']) - self.assertTrue(result) - - def test_999_tearDown(self): - self.delete_key_pair(self.conn, TEST_KEY) - self.conn.terminate_instances([self.data['instance'].id]) - - -class SecurityGroupTests(base.UserSmokeTestCase): - - def __get_metadata_item(self, category): - id_url = "latest/meta-data/%s" % category - options = "-f -s --max-time 1" - command = "curl %s %s/%s" % (options, self.data['public_ip'], id_url) - status, output = commands.getstatusoutput(command) - value = output.strip() - if status > 0: - return False - return value - - def __public_instance_is_accessible(self): - instance_id = self.__get_metadata_item('instance-id') - if not instance_id: - return False - if instance_id != self.data['instance'].id: - raise Exception("Wrong instance id. Expected: %s, Got: %s" % - (self.data['instance'].id, instance_id)) - return True - - def test_001_can_create_security_group(self): - self.conn.create_security_group(TEST_GROUP, description='test') - - groups = self.conn.get_all_security_groups() - self.assertTrue(TEST_GROUP in [group.name for group in groups]) - - def test_002_can_launch_instance_in_security_group(self): - with open("proxy.sh") as f: - user_data = f.read() - self.create_key_pair(self.conn, TEST_KEY) - reservation = self.conn.run_instances(FLAGS.test_image, - key_name=TEST_KEY, - security_groups=[TEST_GROUP], - user_data=user_data, - instance_type='m1.tiny') - - self.data['instance'] = reservation.instances[0] - if not self.wait_for_running(self.data['instance']): - self.fail('instance failed to start') - self.data['instance'].update() - - def test_003_can_authorize_security_group_ingress(self): - self.assertTrue(self.conn.authorize_security_group(TEST_GROUP, - ip_protocol='tcp', - from_port=80, - to_port=80)) - - def test_004_can_access_metadata_over_public_ip(self): - result = self.conn.allocate_address() - self.assertTrue(hasattr(result, 'public_ip')) - self.data['public_ip'] = result.public_ip - - result = self.conn.associate_address(self.data['instance'].id, - self.data['public_ip']) - start_time = time.time() - while not self.__public_instance_is_accessible(): - # 1 minute to launch - if time.time() - start_time > 60: - raise Exception("Timeout") - time.sleep(1) - - def test_005_validate_metadata(self): - instance = self.data['instance'] - start_time = time.time() - instance_type = False - while not instance_type: - instance_type = self.__get_metadata_item('instance-type') - # 10 seconds to restart proxy - if time.time() - start_time > 10: - raise Exception("Timeout") - time.sleep(1) - self.assertEqual(instance.instance_type, instance_type) - #FIXME(dprince): validate more metadata here - - def test_006_can_revoke_security_group_ingress(self): - self.assertTrue(self.conn.revoke_security_group(TEST_GROUP, - ip_protocol='tcp', - from_port=80, - to_port=80)) - start_time = time.time() - while self.__public_instance_is_accessible(): - # 1 minute to teardown - if time.time() - start_time > 60: - raise Exception("Timeout") - time.sleep(1) - - def test_999_tearDown(self): - self.conn.disassociate_address(self.data['public_ip']) - self.conn.delete_key_pair(TEST_KEY) - self.conn.terminate_instances([self.data['instance'].id]) - self.wait_for_deleted(self.data['instance']) - self.conn.delete_security_group(TEST_GROUP) - groups = self.conn.get_all_security_groups() - self.assertFalse(TEST_GROUP in [group.name for group in groups]) - self.assertTrue(self.conn.release_address(self.data['public_ip'])) diff --git a/smoketests/test_sysadmin.py b/smoketests/test_sysadmin.py deleted file mode 100644 index e3c58ea31a1a..000000000000 --- a/smoketests/test_sysadmin.py +++ /dev/null @@ -1,337 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import random -import shutil -import sys -import tempfile -import time - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - -from smoketests import base -from smoketests import flags - -FLAGS = flags.FLAGS -flags.DEFINE_string('bundle_kernel', 'random.kernel', - 'Local kernel file to use for bundling tests') -flags.DEFINE_string('bundle_image', 'random.image', - 'Local image file to use for bundling tests') - -TEST_PREFIX = 'test%s' % int(random.random() * 1000000) -TEST_BUCKET = '%s_bucket' % TEST_PREFIX -TEST_KEY = '%s_key' % TEST_PREFIX -TEST_GROUP = '%s_group' % TEST_PREFIX - - -class ImageTests(base.UserSmokeTestCase): - def test_001_can_bundle_image(self): - self.data['tempdir'] = tempfile.mkdtemp() - self.assertTrue(self.bundle_image(FLAGS.bundle_image, - self.data['tempdir'])) - - def test_002_can_upload_image(self): - try: - self.assertTrue(self.upload_image(TEST_BUCKET, - FLAGS.bundle_image, - self.data['tempdir'])) - finally: - if os.path.exists(self.data['tempdir']): - shutil.rmtree(self.data['tempdir']) - - def test_003_can_register_image(self): - image_id = self.conn.register_image('%s/%s.manifest.xml' % - (TEST_BUCKET, FLAGS.bundle_image)) - self.assertTrue(image_id is not None) - self.data['image_id'] = image_id - - def test_004_can_bundle_kernel(self): - self.assertTrue(self.bundle_image(FLAGS.bundle_kernel, kernel=True)) - - def test_005_can_upload_kernel(self): - self.assertTrue(self.upload_image(TEST_BUCKET, FLAGS.bundle_kernel)) - - def test_006_can_register_kernel(self): - kernel_id = self.conn.register_image('%s/%s.manifest.xml' % - (TEST_BUCKET, FLAGS.bundle_kernel)) - self.assertTrue(kernel_id is not None) - self.data['kernel_id'] = kernel_id - - def test_007_images_are_available_within_10_seconds(self): - for i in xrange(10): - image = self.conn.get_image(self.data['image_id']) - if image and image.state == 'available': - break - time.sleep(1) - else: - self.assertTrue(False) # wasn't available within 10 seconds - self.assertTrue(image.type == 'machine') - - for i in xrange(10): - kernel = self.conn.get_image(self.data['kernel_id']) - if kernel and kernel.state == 'available': - break - time.sleep(1) - else: - self.assertTrue(False) # wasn't available within 10 seconds - self.assertTrue(kernel.type == 'kernel') - - def test_008_can_describe_image_attribute(self): - attrs = self.conn.get_image_attribute(self.data['image_id'], - 'launchPermission') - self.assertTrue(attrs.name, 'launch_permission') - - def test_009_can_add_image_launch_permission(self): - image = self.conn.get_image(self.data['image_id']) - self.assertEqual(image.id, self.data['image_id']) - self.assertEqual(image.is_public, False) - self.conn.modify_image_attribute(image_id=self.data['image_id'], - operation='add', - attribute='launchPermission', - groups='all') - image = self.conn.get_image(self.data['image_id']) - self.assertEqual(image.id, self.data['image_id']) - self.assertEqual(image.is_public, True) - - def test_010_can_see_launch_permission(self): - attrs = self.conn.get_image_attribute(self.data['image_id'], - 'launchPermission') - self.assertEqual(attrs.name, 'launch_permission') - self.assertEqual(attrs.attrs['groups'][0], 'all') - - def test_011_can_remove_image_launch_permission(self): - image = self.conn.get_image(self.data['image_id']) - self.assertEqual(image.id, self.data['image_id']) - self.assertEqual(image.is_public, True) - self.conn.modify_image_attribute(image_id=self.data['image_id'], - operation='remove', - attribute='launchPermission', - groups='all') - image = self.conn.get_image(self.data['image_id']) - self.assertEqual(image.id, self.data['image_id']) - self.assertEqual(image.is_public, False) - - def test_012_private_image_shows_in_list(self): - images = self.conn.get_all_images() - image_ids = [image.id for image in images] - self.assertTrue(self.data['image_id'] in image_ids) - - def test_013_user_can_deregister_kernel(self): - self.assertTrue(self.conn.deregister_image(self.data['kernel_id'])) - - def test_014_can_deregister_image(self): - self.assertTrue(self.conn.deregister_image(self.data['image_id'])) - - def test_015_can_delete_bundle(self): - self.assertTrue(self.delete_bundle_bucket(TEST_BUCKET)) - - -class InstanceTests(base.UserSmokeTestCase): - def test_001_can_create_keypair(self): - key = self.create_key_pair(self.conn, TEST_KEY) - self.assertEqual(key.name, TEST_KEY) - - def test_002_can_create_instance_with_keypair(self): - reservation = self.conn.run_instances(FLAGS.test_image, - key_name=TEST_KEY, - instance_type='m1.tiny') - self.assertEqual(len(reservation.instances), 1) - self.data['instance'] = reservation.instances[0] - - def test_003_instance_runs_within_60_seconds(self): - # allow 60 seconds to exit pending with IP - if not self.wait_for_running(self.data['instance']): - self.fail('instance failed to start') - self.data['instance'].update() - ip = self.data['instance'].private_ip_address - self.assertFalse(ip == '0.0.0.0') - if FLAGS.use_ipv6: - ipv6 = self.data['instance'].dns_name_v6 - self.assertFalse(ipv6 is None) - - def test_004_can_ping_private_ip(self): - if not self.wait_for_ping(self.data['instance'].private_ip_address): - self.fail('could not ping instance') - - if FLAGS.use_ipv6: - if not self.wait_for_ping(self.data['instance'].dns_name_v6, - "ping6"): - self.fail('could not ping instance v6') - - def test_005_can_ssh_to_private_ip(self): - if not self.wait_for_ssh(self.data['instance'].private_ip_address, - TEST_KEY): - self.fail('could not ssh to instance') - - if FLAGS.use_ipv6: - if not self.wait_for_ssh(self.data['instance'].dns_name_v6, - TEST_KEY): - self.fail('could not ssh to instance v6') - - def test_999_tearDown(self): - self.delete_key_pair(self.conn, TEST_KEY) - self.conn.terminate_instances([self.data['instance'].id]) - - -class VolumeTests(base.UserSmokeTestCase): - def setUp(self): - super(VolumeTests, self).setUp() - self.device = '/dev/vdb' - - def test_000_setUp(self): - self.create_key_pair(self.conn, TEST_KEY) - reservation = self.conn.run_instances(FLAGS.test_image, - instance_type='m1.tiny', - key_name=TEST_KEY) - self.data['instance'] = reservation.instances[0] - if not self.wait_for_running(self.data['instance']): - self.fail('instance failed to start') - self.data['instance'].update() - if not self.wait_for_ping(self.data['instance'].private_ip_address): - self.fail('could not ping instance') - if not self.wait_for_ssh(self.data['instance'].private_ip_address, - TEST_KEY): - self.fail('could not ssh to instance') - - def test_001_can_create_volume(self): - volume = self.conn.create_volume(1, 'nova') - self.assertEqual(volume.size, 1) - self.data['volume'] = volume - # Give network time to find volume. - time.sleep(5) - - def test_002_can_attach_volume(self): - volume = self.data['volume'] - - for x in xrange(10): - volume.update() - if volume.status.startswith('available'): - break - time.sleep(1) - else: - self.fail('cannot attach volume with state %s' % volume.status) - - # Give volume some time to be ready. - time.sleep(5) - volume.attach(self.data['instance'].id, self.device) - - # wait - for x in xrange(10): - volume.update() - if volume.status.startswith('in-use'): - break - time.sleep(1) - else: - self.fail('volume never got to in use') - - self.assertTrue(volume.status.startswith('in-use')) - - def test_003_can_mount_volume(self): - ip = self.data['instance'].private_ip_address - conn = self.connect_ssh(ip, TEST_KEY) - - # NOTE(dprince): give some time for volume to show up in partitions - stdin, stdout, stderr = conn.exec_command( - 'COUNT="0";' - 'until cat /proc/partitions | grep "%s\\$"; do ' - '[ "$COUNT" -eq "60" ] && exit 1;' - 'COUNT=$(( $COUNT + 1 ));' - 'sleep 1; ' - 'done' - % self.device.rpartition('/')[2]) - out = stdout.read() - if not out.strip().endswith(self.device.rpartition('/')[2]): - self.fail('Timeout waiting for volume partition in instance. %s %s' - % (out, stderr.read())) - - # NOTE(vish): this will create a dev for images that don't have - # udev rules - stdin, stdout, stderr = conn.exec_command( - 'grep %s /proc/partitions | ' - '`awk \'{print "mknod /dev/"\\$4" b "\\$1" "\\$2}\'`' - % self.device.rpartition('/')[2]) - exec_list = [] - exec_list.append('mkdir -p /mnt/vol') - exec_list.append('/sbin/mke2fs %s' % self.device) - exec_list.append('mount %s /mnt/vol' % self.device) - exec_list.append('echo success') - stdin, stdout, stderr = conn.exec_command(' && '.join(exec_list)) - out = stdout.read() - conn.close() - if not out.strip().endswith('success'): - self.fail('Unable to mount: %s %s' % (out, stderr.read())) - - def test_004_can_write_to_volume(self): - ip = self.data['instance'].private_ip_address - conn = self.connect_ssh(ip, TEST_KEY) - # FIXME(devcamcar): This doesn't fail if the volume hasn't been mounted - stdin, stdout, stderr = conn.exec_command( - 'echo hello > /mnt/vol/test.txt') - err = stderr.read() - conn.close() - if len(err) > 0: - self.fail('Unable to write to mount: %s' % (err)) - - def test_005_volume_is_correct_size(self): - ip = self.data['instance'].private_ip_address - conn = self.connect_ssh(ip, TEST_KEY) - stdin, stdout, stderr = conn.exec_command( - "cat /sys/class/block/%s/size" % self.device.rpartition('/')[2]) - out = stdout.read().strip() - conn.close() - # NOTE(vish): 1G bytes / 512 bytes per block - expected_size = 1024 * 1024 * 1024 / 512 - self.assertEqual('%s' % (expected_size,), out, - 'Volume is not the right size: %s %s. Expected: %s' % - (out, stderr.read(), expected_size)) - - def test_006_me_can_umount_volume(self): - ip = self.data['instance'].private_ip_address - conn = self.connect_ssh(ip, TEST_KEY) - stdin, stdout, stderr = conn.exec_command('umount /mnt/vol') - err = stderr.read() - conn.close() - if len(err) > 0: - self.fail('Unable to unmount: %s' % (err)) - - def test_007_me_can_detach_volume(self): - result = self.conn.detach_volume(volume_id=self.data['volume'].id) - self.assertTrue(result) - volume = self.data['volume'] - for x in xrange(10): - volume.update() - if volume.status.startswith('available'): - break - time.sleep(1) - else: - self.fail('cannot detach volume. state %s' % volume.status) - - def test_008_me_can_delete_volume(self): - result = self.conn.delete_volume(self.data['volume'].id) - self.assertTrue(result) - - def test_999_tearDown(self): - self.conn.terminate_instances([self.data['instance'].id]) - self.conn.delete_key_pair(TEST_KEY)