os-xenapi: fix CI to fit the change that glance-api use uwsgi

Need change xenapi code to fit the change that glance-api switched
to uwsgi and add back the glance relative tests. Use urlparser to
get the suffix of the endepoint to build the http url. Using it in
glance service request in order to specify glance service

Change-Id: I5abdba24dc77c165100ba7d20cc731ce6076a4c7
This commit is contained in:
naichuans
2017-07-11 05:50:34 +00:00
parent b338f128dd
commit cc580828e7
2 changed files with 171 additions and 20 deletions

View File

@@ -297,7 +297,7 @@ def _upload_tarball_by_url_v1(staging_path, image_id, glance_endpoint,
conn.close()
def _update_image_meta_v2(conn, image_id, extra_headers, properties):
def _update_image_meta_v2(conn, extra_headers, properties, patch_path):
# NOTE(sirp): There is some confusion around OVF. Here's a summary
# of where we currently stand:
# 1. OVF as a container format is misnamed. We really should be
@@ -321,8 +321,8 @@ def _update_image_meta_v2(conn, image_id, extra_headers, properties):
"op": "add"}
body.append(prop)
body = json.dumps(body)
conn.request('PATCH', '/v2/images/%s' % image_id,
body=body, headers=headers)
conn.request('PATCH', patch_path, body=body, headers=headers)
resp = conn.getresponse()
resp.read()
@@ -364,9 +364,17 @@ def _upload_tarball_by_url_v2(staging_path, image_id, glance_endpoint,
raise RetryableError(error)
try:
_update_image_meta_v2(conn, image_id, extra_headers, properties)
mgt_url = "%(glance_endpoint)s/v2/images/%(image_id)s" % {
'glance_endpoint': glance_endpoint,
'image_id': image_id}
mgt_parts = urlparse(mgt_url)
mgt_path = mgt_parts[2]
validate_image_status_before_upload_v2(conn, url, extra_headers)
_update_image_meta_v2(conn, image_id, extra_headers, properties,
mgt_path)
validate_image_status_before_upload_v2(conn, url, extra_headers,
mgt_path)
try:
conn.connect()
@@ -537,7 +545,8 @@ def validate_image_status_before_upload_v1(conn, url, extra_headers):
'image_status': image_status})
def validate_image_status_before_upload_v2(conn, url, extra_headers):
def validate_image_status_before_upload_v2(conn, url, extra_headers,
get_path):
try:
parts = urlparse(url)
path = parts[2]
@@ -548,8 +557,7 @@ def validate_image_status_before_upload_v2(conn, url, extra_headers):
# it is not 'active' and send back a 409. Hence, the data will be
# unnecessarily buffered by Glance. This wastes time and bandwidth.
# LP bug #1202785
conn.request('GET', '/v2/images/%s' % image_id, headers=extra_headers)
conn.request('GET', get_path, headers=extra_headers)
get_resp = conn.getresponse()
except Exception, error: # noqa
logging.exception('Failed to GET the image %(image_id)s while '

View File

@@ -333,6 +333,7 @@ class GlanceTestCase(plugin_test.PluginTestBase):
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', 'fake_image_id', fake_endpoint,
@@ -341,7 +342,8 @@ class GlanceTestCase(plugin_test.PluginTestBase):
self.assertTrue(mock_HTTPConn.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers)
fake_extra_headers,
expected_wsgi_path)
self.assertTrue(mock_update_image_meta.called)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
@@ -369,6 +371,7 @@ class GlanceTestCase(plugin_test.PluginTestBase):
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', 'fake_image_id', fake_endpoint,
@@ -378,12 +381,89 @@ class GlanceTestCase(plugin_test.PluginTestBase):
self.assertTrue(mock_update_image_meta.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers)
fake_extra_headers,
expected_wsgi_path)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_HTTPSConn.return_value.getresponse.called)
self.assertFalse(mock_check_resp_status.called)
def test_upload_tarball_by_url_v2_with_api_endpoint(self):
fake_conn = mock.Mock()
mock_Conn = self.mock_patch_object(
self.glance, '_create_connection', fake_conn)
mock_validate_image = self.mock_patch_object(
self.glance, 'validate_image_status_before_upload_v2')
mock_create_tarball = self.mock_patch_object(
self.glance.utils, 'create_tarball')
mock_check_resp_status = self.mock_patch_object(
self.glance, 'check_resp_status_and_retry')
mock_update_image_meta = self.mock_patch_object(
self.glance, '_update_image_meta_v2')
self.glance._create_connection().getresponse = mock.Mock()
self.glance._create_connection().getresponse().status = \
httplib.NO_CONTENT
fake_extra_headers = {}
fake_properties = {}
fake_endpoint = 'https://fake_netloc:fake_port'
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
expected_api_path = '/v2/images/%s' % 'fake_image_id'
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', 'fake_image_id', fake_endpoint,
fake_extra_headers, fake_properties)
self.assertTrue(mock_Conn.called)
self.assertTrue(mock_update_image_meta.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers,
expected_api_path)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_Conn.return_value.getresponse.called)
self.assertFalse(mock_check_resp_status.called)
def test_upload_tarball_by_url_v2_with_wsgi_endpoint(self):
fake_conn = mock.Mock()
mock_Conn = self.mock_patch_object(
self.glance, '_create_connection', fake_conn)
mock_validate_image = self.mock_patch_object(
self.glance, 'validate_image_status_before_upload_v2')
mock_create_tarball = self.mock_patch_object(
self.glance.utils, 'create_tarball')
mock_check_resp_status = self.mock_patch_object(
self.glance, 'check_resp_status_and_retry')
mock_update_image_meta = self.mock_patch_object(
self.glance, '_update_image_meta_v2')
self.glance._create_connection().getresponse = mock.Mock()
self.glance._create_connection().getresponse().status = \
httplib.NO_CONTENT
fake_extra_headers = {}
fake_properties = {}
fake_endpoint = 'https://fake_netloc/fake_path'
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', 'fake_image_id', fake_endpoint,
fake_extra_headers, fake_properties)
self.assertTrue(mock_Conn.called)
self.assertTrue(mock_update_image_meta.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers,
expected_wsgi_path)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_Conn.return_value.getresponse.called)
self.assertFalse(mock_check_resp_status.called)
def test_upload_tarball_by_url_https_failed_retry_v2(self):
fake_conn = mock.Mock()
mock_HTTPSConn = self.mock_patch_object(
@@ -405,6 +485,7 @@ class GlanceTestCase(plugin_test.PluginTestBase):
expected_url = "%(glance_endpoint)s/v2/images/%(image_id)s/file" % {
'glance_endpoint': fake_endpoint,
'image_id': 'fake_image_id'}
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance._upload_tarball_by_url_v2(
'fake_staging_path', 'fake_image_id', fake_endpoint,
@@ -414,13 +495,14 @@ class GlanceTestCase(plugin_test.PluginTestBase):
self.assertTrue(mock_update_image_meta.called)
mock_validate_image.assert_called_with(fake_conn,
expected_url,
fake_extra_headers)
fake_extra_headers,
expected_wsgi_path)
self.assertTrue(mock_create_tarball.called)
self.assertTrue(
mock_HTTPSConn.return_value.getresponse.called)
self.assertTrue(mock_check_resp_status.called)
def test_update_image_meta_ok_v2(self):
def test_update_image_meta_ok_v2_using_api_service(self):
fake_conn = mock.Mock()
fake_extra_headers = {'fake_type': 'fake_content'}
fake_properties = {'fake_path': True}
@@ -438,15 +520,45 @@ class GlanceTestCase(plugin_test.PluginTestBase):
fake_headers.update(**fake_extra_headers)
fake_conn.getresponse.return_value = mock.Mock()
fake_conn.getresponse().status = httplib.OK
expected_api_path = '/v2/images/%s' % 'fake_image_id'
self.glance._update_image_meta_v2(fake_conn, 'fake_image_id',
fake_extra_headers, fake_properties)
self.glance._update_image_meta_v2(fake_conn, fake_extra_headers,
fake_properties, expected_api_path)
fake_conn.request.assert_called_with('PATCH',
'/v2/images/%s' % 'fake_image_id',
body=fake_body_json,
headers=fake_headers)
fake_conn.getresponse.assert_called()
def test_update_image_meta_ok_v2_using_uwsgi_service(self):
fake_conn = mock.Mock()
fake_extra_headers = {'fake_type': 'fake_content'}
fake_properties = {'fake_path': True}
new_fake_properties = {'path': '/fake-path',
'value': "True",
'op': 'add'}
fake_body = [
{"path": "/container_format", "value": "ovf", "op": "add"},
{"path": "/disk_format", "value": "vhd", "op": "add"},
{"path": "/visibility", "value": "private", "op": "add"}]
fake_body.append(new_fake_properties)
fake_body_json = json.dumps(fake_body)
fake_headers = {
'Content-Type': 'application/openstack-images-v2.1-json-patch'}
fake_headers.update(**fake_extra_headers)
fake_conn.getresponse.return_value = mock.Mock()
fake_conn.getresponse().status = httplib.OK
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance._update_image_meta_v2(fake_conn, fake_extra_headers,
fake_properties, expected_wsgi_path)
fake_conn.request.assert_called_with('PATCH',
'/fake_path/v2/images/%s' %
'fake_image_id',
body=fake_body_json,
headers=fake_headers)
fake_conn.getresponse.assert_called()
def test_check_resp_status_and_retry_plugin_error(self):
mock_resp_badrequest = mock.Mock()
mock_resp_badrequest.status = httplib.BAD_REQUEST
@@ -579,7 +691,30 @@ class GlanceTestCase(plugin_test.PluginTestBase):
mock_head_resp, fake_image_id, fake_url)
mock_conn.request.assert_called_once()
def test_validate_image_status_before_upload_ok_v2(self):
def test_validate_image_status_before_upload_ok_v2_using_api_service(self):
mock_conn = mock.Mock()
fake_url = 'http://fake_host:fake_port/fake_path/fake_image_id'
mock_check_resp_status_and_retry = self.mock_patch_object(
self.glance, 'check_resp_status_and_retry')
mock_head_resp = mock.Mock()
mock_head_resp.status = httplib.OK
mock_head_resp.read.return_value = '{"status": "queued"}'
mock_conn.getresponse.return_value = mock_head_resp
fake_extra_headers = mock.Mock()
expected_api_path = '/v2/images/%s' % 'fake_image_id'
self.glance.validate_image_status_before_upload_v2(
mock_conn, fake_url, fake_extra_headers, expected_api_path)
self.assertTrue(mock_conn.getresponse.called)
self.assertEqual(
mock_head_resp.read.call_count, 2)
self.assertFalse(mock_check_resp_status_and_retry.called)
mock_conn.request.assert_called_with('GET',
'/v2/images/fake_image_id',
headers=fake_extra_headers)
def test_validate_image_status_before_upload_ok_v2_using_uwsgi(self):
mock_conn = mock.Mock()
fake_url = 'http://fake_host/fake_path/fake_image_id'
mock_check_resp_status_and_retry = self.mock_patch_object(
@@ -589,14 +724,19 @@ class GlanceTestCase(plugin_test.PluginTestBase):
mock_head_resp.read.return_value = '{"status": "queued"}'
mock_conn.getresponse.return_value = mock_head_resp
fake_extra_headers = mock.Mock()
fake_patch_path = 'fake_patch_path'
self.glance.validate_image_status_before_upload_v2(
mock_conn, fake_url, extra_headers=mock.Mock())
mock_conn, fake_url, fake_extra_headers, fake_patch_path)
self.assertTrue(mock_conn.getresponse.called)
self.assertEqual(
mock_head_resp.read.call_count, 2)
self.assertFalse(mock_check_resp_status_and_retry.called)
mock_conn.request.assert_called_once()
mock_conn.request.assert_called_with('GET',
'fake_patch_path',
headers=fake_extra_headers)
def test_validate_image_status_before_upload_get_image_failed_v2(self):
mock_conn = mock.Mock()
@@ -605,10 +745,11 @@ class GlanceTestCase(plugin_test.PluginTestBase):
mock_head_resp = mock.Mock()
mock_head_resp.status = httplib.OK
mock_conn.getresponse.return_value = mock_head_resp
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.assertRaises(self.glance.RetryableError,
self.glance.validate_image_status_before_upload_v2,
mock_conn, fake_url, extra_headers=mock.Mock())
mock_conn, fake_url, mock.Mock(), expected_wsgi_path)
mock_conn.request.assert_called_once()
mock_head_resp.read.assert_not_called()
mock_conn.getresponse.assert_not_called()
@@ -620,9 +761,10 @@ class GlanceTestCase(plugin_test.PluginTestBase):
mock_head_resp = mock.Mock()
mock_head_resp.status = httplib.BAD_REQUEST
mock_conn.getresponse.return_value = mock_head_resp
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.glance.validate_image_status_before_upload_v2(
mock_conn, fake_url, extra_headers=mock.Mock())
mock_conn, fake_url, mock.Mock(), expected_wsgi_path)
mock_conn.request.assert_called_once()
mock_conn.getresponse.assert_called_once()
mock_head_resp.read.assert_called_once()
@@ -635,10 +777,11 @@ class GlanceTestCase(plugin_test.PluginTestBase):
mock_head_resp.status = httplib.OK
mock_head_resp.read.return_value = '{"status": "not-queued"}'
mock_conn.getresponse.return_value = mock_head_resp
expected_wsgi_path = '/fake_path/v2/images/%s' % 'fake_image_id'
self.assertRaises(self.glance.PluginError,
self.glance.validate_image_status_before_upload_v2,
mock_conn, fake_url, extra_headers=mock.Mock())
mock_conn, fake_url, mock.Mock(), expected_wsgi_path)
mock_conn.request.assert_called_once()
mock_head_resp.read.assert_called_once()