Migrate server snapshot tests to requests_mock

Change-Id: Ic6a489ac25688b7666a6a130f7daf43841909f30
This commit is contained in:
Monty Taylor 2017-04-02 09:11:02 -05:00
parent cf54ef6b92
commit 413965c331
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
5 changed files with 127 additions and 70 deletions

View File

@ -3314,7 +3314,7 @@ class OpenStackCloud(_normalize.Normalizer):
" could not be snapshotted.".format(server=server))
server = server_obj
image_id = str(self.manager.submit_task(_tasks.ImageSnapshotCreate(
image_name=name, server=server, metadata=metadata)))
image_name=name, server=server['id'], metadata=metadata)))
self.list_images.invalidate(self)
image = self.get_image(image_id)

View File

@ -28,6 +28,8 @@ STRAWBERRY_FLAVOR_ID = u'0c1d9008-f546-4608-9e8f-f8bdaec8dddf'
COMPUTE_ENDPOINT = 'https://compute.example.com/v2.1'
ORCHESTRATION_ENDPOINT = 'https://orchestration.example.com/v1/{p}'.format(
p=PROJECT_ID)
NO_MD5 = '93b885adfe0da089cdf634904fd59f71'
NO_SHA256 = '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d'
def make_fake_flavor(flavor_id, name, ram=100, disk=1600, vcpus=24):
@ -177,6 +179,37 @@ def make_fake_stack_event(
}
def make_fake_image(
image_id=None, md5=NO_MD5, sha256=NO_SHA256, status='active'):
return {
u'image_state': u'available',
u'container_format': u'bare',
u'min_ram': 0,
u'ramdisk_id': None,
u'updated_at': u'2016-02-10T05:05:02Z',
u'file': '/v2/images/' + image_id + '/file',
u'size': 3402170368,
u'image_type': u'snapshot',
u'disk_format': u'qcow2',
u'id': image_id,
u'schema': u'/v2/schemas/image',
u'status': status,
u'tags': [],
u'visibility': u'private',
u'locations': [{
u'url': u'http://127.0.0.1/images/' + image_id,
u'metadata': {}}],
u'min_disk': 40,
u'virtual_size': None,
u'name': u'fake_image',
u'checksum': u'ee36e35a297980dee1b514de9803ec6d',
u'created_at': u'2016-02-10T05:03:11Z',
u'owner_specified.shade.md5': NO_MD5,
u'owner_specified.shade.sha256': NO_SHA256,
u'owner_specified.shade.object': 'images/fake_image',
u'protected': False}
class FakeEndpoint(object):
def __init__(self, id, service_id, region, publicurl, internalurl=None,
adminurl=None):

View File

@ -550,7 +550,7 @@ class RequestsMockTestCase(BaseTestCase):
mock_method, mock_uri, params['response_list'],
**params['kw_params'])
def assert_calls(self, stop_after=None):
def assert_calls(self, stop_after=None, do_count=True):
for (x, (call, history)) in enumerate(
zip(self.calls, self.adapter.request_history)):
if stop_after and x > stop_after:
@ -571,4 +571,6 @@ class RequestsMockTestCase(BaseTestCase):
self.assertEqual(
value, history.headers[key],
'header mismatch in call {index}'.format(index=x))
self.assertEqual(len(self.calls), len(self.adapter.request_history))
if do_count:
self.assertEqual(
len(self.calls), len(self.adapter.request_history))

View File

@ -24,11 +24,10 @@ import six
import shade
from shade import exc
from shade import meta
from shade.tests import fakes
from shade.tests.unit import base
NO_MD5 = '93b885adfe0da089cdf634904fd59f71'
NO_SHA256 = '6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d'
CINDER_URL = 'https://volume.example.com/v2/1c36b64c840a42cd9e9b931a369337f0'
@ -40,33 +39,7 @@ class BaseTestImage(base.RequestsMockTestCase):
self.imagefile = tempfile.NamedTemporaryFile(delete=False)
self.imagefile.write(b'\0')
self.imagefile.close()
self.fake_image_dict = {
u'image_state': u'available',
u'container_format': u'bare',
u'min_ram': 0,
u'ramdisk_id': None,
u'updated_at': u'2016-02-10T05:05:02Z',
u'file': '/v2/images/' + self.image_id + '/file',
u'size': 3402170368,
u'image_type': u'snapshot',
u'disk_format': u'qcow2',
u'id': self.image_id,
u'schema': u'/v2/schemas/image',
u'status': u'active',
u'tags': [],
u'visibility': u'private',
u'locations': [{
u'url': u'http://127.0.0.1/images/' + self.image_id,
u'metadata': {}}],
u'min_disk': 40,
u'virtual_size': None,
u'name': u'fake_image',
u'checksum': u'ee36e35a297980dee1b514de9803ec6d',
u'created_at': u'2016-02-10T05:03:11Z',
u'owner_specified.shade.md5': NO_MD5,
u'owner_specified.shade.sha256': NO_SHA256,
u'owner_specified.shade.object': 'images/fake_image',
u'protected': False}
self.fake_image_dict = fakes.make_fake_image(image_id=self.image_id)
self.fake_search_return = {'images': [self.fake_image_dict]}
self.output = uuid.uuid4().bytes
@ -193,9 +166,9 @@ class TestImage(BaseTestImage):
json={u'container_format': u'bare',
u'disk_format': u'qcow2',
u'name': u'fake_image',
u'owner_specified.shade.md5': NO_MD5,
u'owner_specified.shade.md5': fakes.NO_MD5,
u'owner_specified.shade.object': u'images/fake_image', # noqa
u'owner_specified.shade.sha256': NO_SHA256,
u'owner_specified.shade.sha256': fakes.NO_SHA256,
u'visibility': u'private'})
),
dict(method='PUT',
@ -275,8 +248,8 @@ class TestImage(BaseTestImage):
object=image_name),
status_code=201,
validate=dict(
headers={'x-object-meta-x-shade-md5': NO_MD5,
'x-object-meta-x-shade-sha256': NO_SHA256})
headers={'x-object-meta-x-shade-md5': fakes.NO_MD5,
'x-object-meta-x-shade-sha256': fakes.NO_SHA256})
),
dict(method='GET', uri='https://image.example.com/v2/images',
json={'images': []}),
@ -308,9 +281,9 @@ class TestImage(BaseTestImage):
container=container_name,
object=image_name),
u'path': u'/owner_specified.shade.object'},
{u'op': u'add', u'value': NO_MD5,
{u'op': u'add', u'value': fakes.NO_MD5,
u'path': u'/owner_specified.shade.md5'},
{u'op': u'add', u'value': NO_SHA256,
{u'op': u'add', u'value': fakes.NO_SHA256,
u'path': u'/owner_specified.shade.sha256'}],
key=operator.itemgetter('value')),
headers={

View File

@ -14,51 +14,100 @@
import uuid
import mock
import shade
from shade import exc
from shade.tests import fakes
from shade.tests.unit import base
class TestImageSnapshot(base.TestCase):
class TestImageSnapshot(base.RequestsMockTestCase):
def setUp(self):
super(TestImageSnapshot, self).setUp()
self.server_id = str(uuid.uuid4())
self.image_id = str(uuid.uuid4())
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
@mock.patch.object(shade.OpenStackCloud, 'get_image')
def test_create_image_snapshot_wait_until_active_never_active(self,
mock_get,
mock_nova):
mock_nova.servers.create_image.return_value = {
'status': 'queued',
'id': self.image_id,
}
mock_get.return_value = {'status': 'saving', 'id': self.image_id}
self.assertRaises(exc.OpenStackCloudTimeout,
self.cloud.create_image_snapshot,
'test-snapshot', dict(id='fake-server'),
wait=True, timeout=0.01)
def test_create_image_snapshot_wait_until_active_never_active(self):
snapshot_name = 'test-snapshot'
fake_image = fakes.make_fake_image(self.image_id, status='pending')
self.register_uris([
dict(
method='POST',
uri='{endpoint}/servers/{server_id}/action'.format(
endpoint=fakes.COMPUTE_ENDPOINT,
server_id=self.server_id),
headers=dict(
Location='{endpoint}/images/{image_id}'.format(
endpoint='https://images.example.com',
image_id=self.image_id)),
validate=dict(
json={
"createImage": {
"name": snapshot_name,
"metadata": {},
}})),
self.get_glance_discovery_mock_dict(),
dict(
method='GET',
uri='https://image.example.com/v2/images',
json=dict(images=[fake_image])),
])
@mock.patch.object(shade.OpenStackCloud, 'nova_client')
@mock.patch.object(shade.OpenStackCloud, 'get_image')
def test_create_image_snapshot_wait_active(self, mock_get, mock_nova):
mock_nova.servers.create_image.return_value = {
'status': 'queued',
'id': self.image_id,
}
mock_get.return_value = {'status': 'active', 'id': self.image_id}
self.assertRaises(
exc.OpenStackCloudTimeout,
self.cloud.create_image_snapshot,
snapshot_name, dict(id=self.server_id),
wait=True, timeout=0.01)
# After the fifth call, we just keep polling get images for status.
# Due to mocking sleep, we have no clue how many times we'll call it.
self.assert_calls(stop_after=5, do_count=False)
def test_create_image_snapshot_wait_active(self):
snapshot_name = 'test-snapshot'
pending_image = fakes.make_fake_image(self.image_id, status='pending')
fake_image = fakes.make_fake_image(self.image_id)
self.register_uris([
dict(
method='POST',
uri='{endpoint}/servers/{server_id}/action'.format(
endpoint=fakes.COMPUTE_ENDPOINT,
server_id=self.server_id),
headers=dict(
Location='{endpoint}/images/{image_id}'.format(
endpoint='https://images.example.com',
image_id=self.image_id)),
validate=dict(
json={
"createImage": {
"name": snapshot_name,
"metadata": {},
}})),
self.get_glance_discovery_mock_dict(),
dict(
method='GET',
uri='https://image.example.com/v2/images',
json=dict(images=[pending_image])),
dict(
method='GET',
uri='https://image.example.com/v2/images',
json=dict(images=[fake_image])),
])
image = self.cloud.create_image_snapshot(
'test-snapshot', dict(id='fake-server'), wait=True, timeout=2)
'test-snapshot', dict(id=self.server_id), wait=True, timeout=2)
self.assertEqual(image['id'], self.image_id)
@mock.patch.object(shade.OpenStackCloud, 'get_server')
def test_create_image_snapshot_bad_name_exception(
self, mock_get_server):
mock_get_server.return_value = None
self.assert_calls()
def test_create_image_snapshot_bad_name_exception(self):
self.register_uris([
dict(
method='POST',
uri='{endpoint}/servers/{server_id}/action'.format(
endpoint=fakes.COMPUTE_ENDPOINT,
server_id=self.server_id),
json=dict(servers=[])),
])
self.assertRaises(
exc.OpenStackCloudException,
self.cloud.create_image_snapshot,
'test-snapshot', 'missing-server')
'test-snapshot', self.server_id)