Merge "add server reset_state tests"
diff --git a/HACKING.rst b/HACKING.rst
index 9878b67..499b436 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -2,7 +2,7 @@
====================
- Step 1: Read the OpenStack Style Commandments
- https://github.com/openstack-dev/hacking/blob/master/HACKING.rst
+ http://docs.openstack.org/developer/hacking/
- Step 2: Read on
Tempest Specific Commandments
diff --git a/run_tests.sh b/run_tests.sh
index 710fbaa..acd9497 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -58,7 +58,7 @@
-c|--nova-coverage) let nova_coverage=1;;
-C|--config) config_file=$2; shift;;
-p|--pep8) let just_pep8=1;;
- -s|--smoke) testrargs="$testrargs smoke";;
+ -s|--smoke) testrargs+="smoke"; noseargs+="--attr=type=smoke";;
-t|--serial) serial=1;;
-l|--logging) logging=1;;
-L|--logging-config) logging_config=$2; shift;;
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 40b005d..14ab236 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -97,6 +97,38 @@
self.assertEqual(aggregate['availability_zone'],
body['availability_zone'])
+ @attr(type='gate')
+ def test_aggregate_create_update_with_az(self):
+ # Update an aggregate and ensure properties are updated correctly
+ self.useFixture(fixtures.LockFixture('availability_zone'))
+ aggregate_name = rand_name(self.aggregate_name_prefix)
+ az_name = rand_name(self.az_name_prefix)
+ resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
+ self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate_name, aggregate['name'])
+ self.assertEqual(az_name, aggregate['availability_zone'])
+ self.assertIsNotNone(aggregate['id'])
+
+ aggregate_id = aggregate['id']
+ new_aggregate_name = aggregate_name + '_new'
+ new_az_name = az_name + '_new'
+
+ resp, resp_aggregate = self.client.update_aggregate(aggregate_id,
+ new_aggregate_name,
+ new_az_name)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(new_aggregate_name, resp_aggregate['name'])
+ self.assertEqual(new_az_name, resp_aggregate['availability_zone'])
+
+ resp, aggregates = self.client.list_aggregates()
+ self.assertEqual(200, resp.status)
+ self.assertIn((aggregate_id, new_aggregate_name, new_az_name),
+ map(lambda x:
+ (x['id'], x['name'], x['availability_zone']),
+ aggregates))
+
@attr(type=['negative', 'gate'])
def test_aggregate_create_as_user(self):
# Regular user is not allowed to create an aggregate.
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 2a72c95..7c72991 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -31,6 +31,7 @@
super(BaseOrchestrationTest, cls).setUpClass()
os = clients.OrchestrationManager()
cls.orchestration_cfg = os.config.orchestration
+ cls.compute_cfg = os.config.compute
if not os.config.service_available.heat:
raise cls.skipException("Heat support is required")
cls.build_timeout = cls.orchestration_cfg.build_timeout
@@ -40,10 +41,18 @@
cls.orchestration_client = os.orchestration_client
cls.servers_client = os.servers_client
cls.keypairs_client = os.keypairs_client
+ cls.network_client = os.network_client
cls.stacks = []
cls.keypairs = []
@classmethod
+ def _get_default_network(cls):
+ resp, networks = cls.network_client.list_networks()
+ for net in networks['networks']:
+ if net['name'] == cls.compute_cfg.fixed_network_name:
+ return net
+
+ @classmethod
def _get_identity_admin_client(cls):
"""
Returns an instance of the Identity Admin API client
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index defb910..0ecc5ff 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -36,6 +36,8 @@
Type: String
ImageId:
Type: String
+ Subnet:
+ Type: String
Resources:
SmokeServer:
Type: AWS::EC2::Instance
@@ -45,6 +47,7 @@
ImageId: {Ref: ImageId}
InstanceType: {Ref: InstanceType}
KeyName: {Ref: KeyName}
+ SubnetId: {Ref: Subnet}
UserData:
Fn::Base64:
Fn::Join:
@@ -78,13 +81,15 @@
cls._create_keypair()['name'])
# create the stack
+ subnet = cls._get_default_network()['subnets'][0]
cls.stack_identifier = cls.create_stack(
cls.stack_name,
cls.template,
parameters={
'KeyName': keypair_name,
'InstanceType': cls.orchestration_cfg.instance_type,
- 'ImageId': cls.orchestration_cfg.image_ref
+ 'ImageId': cls.orchestration_cfg.image_ref,
+ 'Subnet': subnet
})
cls.stack_id = cls.stack_identifier.split('/')[1]
cls.resource_name = 'SmokeServer'
diff --git a/tempest/api/orchestration/stacks/test_server_cfn_init.py b/tempest/api/orchestration/stacks/test_server_cfn_init.py
index 41849d0..d8334fa 100644
--- a/tempest/api/orchestration/stacks/test_server_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_server_cfn_init.py
@@ -43,6 +43,8 @@
Type: String
image:
Type: String
+ network:
+ Type: String
Resources:
CfnUser:
Type: AWS::IAM::User
@@ -88,6 +90,8 @@
key_name: {Ref: key_name}
security_groups:
- {Ref: SmokeSecurityGroup}
+ networks:
+ - uuid: {Ref: network}
user_data:
Fn::Base64:
Fn::Join:
@@ -142,7 +146,8 @@
parameters={
'key_name': keypair_name,
'flavor': cls.orchestration_cfg.instance_type,
- 'image': cls.orchestration_cfg.image_ref
+ 'image': cls.orchestration_cfg.image_ref,
+ 'network': cls._get_default_network()['id']
})
@attr(type='slow')
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 93dec71..8c82ec0 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -94,7 +94,9 @@
for ten in tenants:
if ten['name'] == name:
tenant = ten
- raise exceptions.NotFound('No such tenant')
+ break
+ else:
+ raise exceptions.NotFound('No such tenant')
return tenant
def _create_user(self, username, password, tenant, email):
diff --git a/tempest/config.py b/tempest/config.py
index 8421c71..eadbe9a 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -182,8 +182,8 @@
"succeed."),
cfg.IntOpt('ready_wait',
default=0,
- help="Additinal wait time for clean state, when there is"
- " no OS-EXT-STS extension availiable"),
+ help="Additional wait time for clean state, when there is "
+ "no OS-EXT-STS extension available"),
cfg.IntOpt('ssh_channel_timeout',
default=60,
help="Timeout in seconds to wait for output from ssh "
@@ -273,7 +273,7 @@
cfg.StrOpt('http_image',
default='http://download.cirros-cloud.net/0.3.1/'
'cirros-0.3.1-x86_64-uec.tar.gz',
- help='http accessable image')
+ help='http accessible image')
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index c01de83..c4b98d5 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -656,3 +656,10 @@
@classmethod
def _stack_rand_name(cls):
return rand_name(cls.__name__ + '-')
+
+ @classmethod
+ def _get_default_network(cls):
+ networks = cls.network_client.list_networks()
+ for net in networks['networks']:
+ if net['name'] == cls.config.compute.fixed_network_name:
+ return net
diff --git a/tempest/scenario/orchestration/test_autoscaling.py b/tempest/scenario/orchestration/test_autoscaling.py
index 1a4d802..658e9bb 100644
--- a/tempest/scenario/orchestration/test_autoscaling.py
+++ b/tempest/scenario/orchestration/test_autoscaling.py
@@ -37,11 +37,13 @@
self.keypair_name = self.keypair.id
def launch_stack(self):
+ net = self._get_default_network()
self.parameters = {
'KeyName': self.keypair_name,
'InstanceType': self.config.orchestration.instance_type,
'ImageId': self.config.orchestration.image_ref,
- 'StackStart': str(time.time())
+ 'StackStart': str(time.time()),
+ 'Subnet': net['subnets'][0]
}
# create the stack
diff --git a/tempest/scenario/orchestration/test_autoscaling.yaml b/tempest/scenario/orchestration/test_autoscaling.yaml
index 045b3bc..745eb05 100644
--- a/tempest/scenario/orchestration/test_autoscaling.yaml
+++ b/tempest/scenario/orchestration/test_autoscaling.yaml
@@ -8,6 +8,8 @@
Type: String
ImageId:
Type: String
+ Subnet:
+ Type: String
StackStart:
Description: Epoch seconds when the stack was launched
Type: Number
@@ -39,6 +41,7 @@
LaunchConfigurationName: {Ref: LaunchConfig}
MinSize: '1'
MaxSize: '3'
+ VPCZoneIdentifier: [{Ref: Subnet}]
SmokeServerScaleUpPolicy:
Type: AWS::AutoScaling::ScalingPolicy
Properties:
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index 7ae1eee..75ce9ff 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -52,6 +52,19 @@
body = json.loads(body)
return resp, body['aggregate']
+ def update_aggregate(self, aggregate_id, name, availability_zone=None):
+ """Update a aggregate."""
+ put_body = {
+ 'name': name,
+ 'availability_zone': availability_zone
+ }
+ put_body = json.dumps({'aggregate': put_body})
+ resp, body = self.put('os-aggregates/%s' % str(aggregate_id),
+ put_body, self.headers)
+
+ body = json.loads(body)
+ return resp, body['aggregate']
+
def delete_aggregate(self, aggregate_id):
"""Deletes the given aggregate."""
return self.delete("os-aggregates/%s" % str(aggregate_id))
diff --git a/tempest/services/compute/xml/aggregates_client.py b/tempest/services/compute/xml/aggregates_client.py
index 0ef8e22..8ef0af6 100644
--- a/tempest/services/compute/xml/aggregates_client.py
+++ b/tempest/services/compute/xml/aggregates_client.py
@@ -72,6 +72,17 @@
aggregate = self._format_aggregate(etree.fromstring(body))
return resp, aggregate
+ def update_aggregate(self, aggregate_id, name, availability_zone=None):
+ """Update a aggregate."""
+ put_body = Element("aggregate",
+ name=name,
+ availability_zone=availability_zone)
+ resp, body = self.put('os-aggregates/%s' % str(aggregate_id),
+ str(Document(put_body)),
+ self.headers)
+ aggregate = self._format_aggregate(etree.fromstring(body))
+ return resp, aggregate
+
def delete_aggregate(self, aggregate_id):
"""Deletes the given aggregate."""
return self.delete("os-aggregates/%s" % str(aggregate_id),
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index d959543..8209f17 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -35,11 +35,14 @@
username = admin_manager.config.stress.target_ssh_user
key_filename = admin_manager.config.stress.target_private_key_path
if not (username and key_filename):
+ LOG.error('username and key_filename should not be empty')
return None
ssh_client = ssh.Client(host, username, key_filename=key_filename)
try:
return ssh_client.exec_command(command)
except exceptions.SSHExecCommandFailed:
+ LOG.error('do_ssh raise exception. command:%s, host:%s.'
+ % (command, host))
return None
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 486e0a0..bce544a 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -188,13 +188,13 @@
self.assertEqual(tags[0].value, 'value1')
tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
- self.assertEqual(len(tags), 0)
+ self.assertEqual(len(tags), 0, str(tags))
for instance in reservation.instances:
instance.remove_tag('key1', value='value1')
tags = self.ec2_client.get_all_tags()
- self.assertEqual(len(tags), 0)
+ self.assertEqual(len(tags), 0, str(tags))
for instance in reservation.instances:
instance.stop()