327 lines
15 KiB
Python
327 lines
15 KiB
Python
# Copyright 2014 OpenStack Foundation
|
|
# 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.
|
|
|
|
from oslo_log import log
|
|
from tempest_lib.common.utils import data_utils
|
|
import testtools
|
|
|
|
from ec2api.tests.functional import base
|
|
from ec2api.tests.functional import config
|
|
|
|
CONF = config.CONF
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
class InstanceTest(base.EC2TestCase):
|
|
|
|
@classmethod
|
|
@base.safe_setup
|
|
def setUpClass(cls):
|
|
super(InstanceTest, cls).setUpClass()
|
|
if not CONF.aws.image_id:
|
|
raise cls.skipException('aws image_id does not provided')
|
|
cls.zone = CONF.aws.aws_zone
|
|
|
|
def test_create_delete_instance(self):
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.assertEqual(1, len(data['Instances']))
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
data = self.client.describe_instances(InstanceIds=[instance_id])
|
|
reservations = data.get('Reservations', [])
|
|
self.assertNotEmpty(reservations)
|
|
instances = reservations[0].get('Instances', [])
|
|
self.assertEqual(1, len(instances))
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
# NOTE(andrey-mp): There is difference between Openstack and Amazon.
|
|
# Amazon returns instance in 'terminated' state some time after
|
|
# instance deletion. But Openstack doesn't return such instance.
|
|
|
|
def test_create_idempotent_instance(self):
|
|
client_token = data_utils.rand_name('t')
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
|
ClientToken=client_token)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.assertEqual(1, len(data['Instances']))
|
|
reservation_id = data['ReservationId']
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
|
ClientToken=client_token)
|
|
|
|
# NOTE(andrey-mp): if idempotent run will fail this will terminate
|
|
# second instance
|
|
self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[data['Instances'][0]['InstanceId']])
|
|
|
|
self.assertEqual(1, len(data['Instances']))
|
|
self.assertEqual(reservation_id, data['ReservationId'])
|
|
self.assertEqual(instance_id, data['Instances'][0]['InstanceId'])
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
def test_describe_instances_filter(self):
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
# NOTE(andrey-mp): by real id
|
|
data = self.client.describe_instances(InstanceIds=[instance_id])
|
|
self._assert_instance(data, instance_id)
|
|
instances = data['Reservations'][0]['Instances']
|
|
private_dns = instances[0]['PrivateDnsName']
|
|
private_ip = instances[0]['PrivateIpAddress']
|
|
|
|
# NOTE(andrey-mp): by fake id
|
|
self.assertRaises('InvalidInstanceID.NotFound',
|
|
self.client.describe_instances,
|
|
InstanceIds=['i-0'])
|
|
|
|
# NOTE(andrey-mp): by private ip
|
|
data = self.client.describe_instances(
|
|
Filters=[{'Name': 'private-ip-address', 'Values': ['1.2.3.4']}])
|
|
self.assertEqual(0, len(data['Reservations']))
|
|
|
|
data = self.client.describe_instances(
|
|
Filters=[{'Name': 'private-ip-address', 'Values': [private_ip]}])
|
|
self._assert_instance(data, instance_id)
|
|
|
|
# NOTE(andrey-mp): by private dns
|
|
data = self.client.describe_instances(
|
|
Filters=[{'Name': 'private-dns-name', 'Values': ['fake.com']}])
|
|
self.assertEqual(0, len(data['Reservations']))
|
|
|
|
data = self.client.describe_instances(
|
|
Filters=[{'Name': 'private-dns-name', 'Values': [private_dns]}])
|
|
self._assert_instance(data, instance_id)
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
def _assert_instance(self, data, instance_id):
|
|
reservations = data.get('Reservations', [])
|
|
self.assertNotEmpty(reservations)
|
|
instances = reservations[0].get('Instances', [])
|
|
self.assertNotEmpty(instances)
|
|
self.assertEqual(instance_id, instances[0]['InstanceId'])
|
|
|
|
def test_get_password_data_and_console_output(self):
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
data = self.client.get_password_data(InstanceId=instance_id)
|
|
self.assertEqual(instance_id, data['InstanceId'])
|
|
self.assertIsNotNone(data['Timestamp'])
|
|
self.assertIn('PasswordData', data)
|
|
|
|
waiter = base.EC2Waiter(self.client.get_console_output)
|
|
waiter.wait_no_exception(InstanceId=instance_id)
|
|
|
|
data = self.client.get_console_output(InstanceId=instance_id)
|
|
self.assertEqual(instance_id, data['InstanceId'])
|
|
self.assertIsNotNone(data['Timestamp'])
|
|
self.assertIn('Output', data)
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
def test_stop_instance(self):
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
data = self.client.stop_instances(InstanceIds=[instance_id])
|
|
if CONF.aws.run_incompatible_tests:
|
|
instances = data['StoppingInstances']
|
|
self.assertEqual(1, len(instances))
|
|
instance = instances[0]
|
|
self.assertEqual(instance_id, instance['InstanceId'])
|
|
self.assertEqual('running', instance['PreviousState']['Name'])
|
|
self.assertEqual('stopping', instance['CurrentState']['Name'])
|
|
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('stopped'))
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
|
"Openstack doesn't assign public ip automatically for new instance")
|
|
def test_public_ip_is_assigned(self):
|
|
"""Is public IP assigned to launched instnace?"""
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
self.assertEqual(1, len(data['Instances']))
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
instance = self.get_instance(instance_id)
|
|
self.assertIsNotNone(instance.get('PublicIpAddress'))
|
|
self.assertIsNotNone(instance.get('PrivateIpAddress'))
|
|
self.assertNotEqual(instance.get('PublicIpAddress'),
|
|
instance.get('PrivateIpAddress'))
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
def test_describe_instance_attributes(self):
|
|
instance_type = CONF.aws.instance_type
|
|
image_id = CONF.aws.image_id
|
|
data = self.client.run_instances(
|
|
ImageId=image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.assertEqual(1, len(data['Instances']))
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
if CONF.aws.run_incompatible_tests:
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='blockDeviceMapping')
|
|
bdms = data.get('BlockDeviceMappings', [])
|
|
self.assertNotEmpty(bdms)
|
|
self.assertEqual(1, len(bdms))
|
|
self.assertIn('DeviceName', bdms[0])
|
|
self.assertIn('Ebs', bdms[0])
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='disableApiTermination')
|
|
self.assertIn('DisableApiTermination', data)
|
|
self.assertIn('Value', data['DisableApiTermination'])
|
|
self.assertFalse(data['DisableApiTermination']['Value'])
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='groupSet')
|
|
self.assertIn('Groups', data)
|
|
self.assertNotEmpty(data['Groups'], data)
|
|
self.assertTrue('GroupId' in data['Groups'][0]
|
|
or 'GroupName' in data['Groups'][0])
|
|
self.assertTrue(data['Groups'][0].get('GroupId')
|
|
or data['Groups'][0].get('GroupName'))
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='instanceType')
|
|
self.assertIn('InstanceType', data)
|
|
self.assertIn('Value', data['InstanceType'])
|
|
self.assertEqual(instance_type, data['InstanceType']['Value'])
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='kernel')
|
|
self.assertIn('KernelId', data)
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='ramdisk')
|
|
self.assertIn('RamdiskId', data)
|
|
|
|
data = self.client.describe_instance_attribute(
|
|
InstanceId=instance_id, Attribute='rootDeviceName')
|
|
self.assertIn('RootDeviceName', data)
|
|
self.assertIn('Value', data['RootDeviceName'])
|
|
self.assertTrue(data['RootDeviceName']['Value'])
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|
|
|
|
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
|
"Error from nova: "
|
|
"Invalid input for field/attribute 0. ...")
|
|
def test_launch_instance_with_creating_blank_volume(self):
|
|
"""Launch instance with creating blank volume."""
|
|
device_name = '/dev/xvdh'
|
|
instance_type = CONF.aws.instance_type
|
|
data = self.client.run_instances(
|
|
ImageId=CONF.aws.image_id, InstanceType=instance_type,
|
|
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
|
BlockDeviceMappings=[{'DeviceName': device_name,
|
|
'Ebs': {'VolumeSize': 1}}])
|
|
instance_id = data['Instances'][0]['InstanceId']
|
|
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
|
InstanceIds=[instance_id])
|
|
self.get_instance_waiter().wait_available(instance_id,
|
|
final_set=('running'))
|
|
|
|
bdt = self.get_instance_bdm(instance_id, device_name)
|
|
self.assertIsNotNone(bdt)
|
|
volume_id = bdt['Ebs'].get('VolumeId')
|
|
self.assertIsNotNone(volume_id)
|
|
self.assertTrue(bdt['Ebs']['DeleteOnTermination'])
|
|
|
|
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
|
self.assertEqual(1, len(data['Volumes']))
|
|
volume = data['Volumes'][0]
|
|
self.assertEqual(1, volume['Size'])
|
|
|
|
self.client.terminate_instances(InstanceIds=[instance_id])
|
|
self.cancelResourceCleanUp(res_clean)
|
|
self.get_instance_waiter().wait_delete(instance_id)
|