Skip to content

Commit

Permalink
Better coverage for storage links.
Browse files Browse the repository at this point in the history
  • Loading branch information
enolfc committed Apr 17, 2015
1 parent 8c25302 commit 088ce08
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 12 deletions.
5 changes: 4 additions & 1 deletion ooi/api/storage_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ def index(self, req):

def _get_attachment_from_id(self, req, id):
tenant_id = req.environ["keystone.token_auth"].user.project_id
server_id, vol_id = id.split('_', 1)
try:
server_id, vol_id = id.split('_', 1)
except ValueError:
raise webob.exc.HTTPNotFound()

req_path = "/%s/servers/%s/os-volume_attachments" % (tenant_id,
server_id)
Expand Down
38 changes: 27 additions & 11 deletions ooi/tests/fakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,22 @@
"id": uuid.uuid4().hex,
"displayName": "foo",
"size": 2,
"status": "in-use",
"status": "available",
"attachments": [],
},
{
"id": uuid.uuid4().hex,
"displayName": "bar",
"size": 3,
"status": "in-use",
"status": "available",
"attachments": [],
},
{
"id": uuid.uuid4().hex,
"displayName": "baz",
"size": 5,
"status": "in-use",
"status": "available",
"attachments": [],
},
],
tenants["bar"]["id"]: [],
Expand Down Expand Up @@ -134,6 +137,20 @@
],
}

# avoid circular definition of attachments
volumes[tenants["baz"]["id"]][0]["attachments"] = [{
# how consistent can OpenStack be!
# depending on using /servers/os-volume_attachments
# or /os-volumes it will return different field names
"server_id": servers[tenants["baz"]["id"]][0]["id"],
"serverId": servers[tenants["baz"]["id"]][0]["id"],
"attachment_id": uuid.uuid4().hex,
"volumeId": volumes[tenants["baz"]["id"]][0]["id"],
"volume_id": volumes[tenants["baz"]["id"]][0]["id"],
"device": "/dev/vdb",
"id": volumes[tenants["baz"]["id"]][0]["id"],
}]


def fake_query_results():
cats = []
Expand Down Expand Up @@ -279,7 +296,8 @@ def __init__(self):
# NOTE(aloga): dict_values un Py3 is not serializable in JSON
self._populate(path, "image", list(images.values()))
self._populate(path, "flavor", list(flavors.values()))
self._populate_attached_volumes(path, servers[tenant["id"]])
self._populate_attached_volumes(path, servers[tenant["id"]],
volumes[tenant["id"]])

def _populate(self, path_base, obj_name, obj_list, objs_path=None):
objs_name = "%ss" % obj_name
Expand All @@ -296,16 +314,14 @@ def _populate(self, path_base, obj_name, obj_list, objs_path=None):
obj_path = "%s/%s" % (path, o["id"])
self.routes[obj_path] = create_fake_json_resp({obj_name: o})

def _populate_attached_volumes(self, path, server_list):
def _populate_attached_volumes(self, path, server_list, vol_list):
for s in server_list:
attachments = []
if "os-extended-volumes:volumes_attached" in s:
for vol in s["os-extended-volumes:volumes_attached"]:
attachments.append({
"volumeId": vol["id"],
"device": "/dev/foo",
"id": uuid.uuid4().hex
})
for attach in s["os-extended-volumes:volumes_attached"]:
for v in vol_list:
if attach["id"] == v["id"]:
attachments.append(v["attachments"][0])
path_base = "%s/servers/%s/os-volume_attachments" % (path, s["id"])
self.routes[path_base] = create_fake_json_resp(
{"volumeAttachments": attachments}
Expand Down
141 changes: 141 additions & 0 deletions ooi/tests/middleware/test_storagelink_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-

# Copyright 2015 Spanish National Research Council
#
# 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 uuid

import mock

from ooi.tests import fakes
from ooi.tests.middleware import test_middleware
from ooi import utils


class TestStorageLinkController(test_middleware.TestMiddleware):
"""Test OCCI storage link controller."""
def test_list_vols_empty(self):
tenant = fakes.tenants["bar"]
app = self.get_app()

for url in ("/storagelink/", "/storagelink"):
req = self._build_req(url, tenant["id"], method="GET")

m = mock.MagicMock()
m.user.project_id = tenant["id"]
req.environ["keystone.token_auth"] = m

resp = req.get_response(app)

expected_result = ""
self.assertContentType(resp)
self.assertExpectedResult(expected_result, resp)
self.assertEqual(204, resp.status_code)

def test_list_attachments_empty(self):
tenant = fakes.tenants["foo"]
app = self.get_app()

for url in ("/storagelink/", "/storagelink"):
req = self._build_req(url, tenant["id"], method="GET")

m = mock.MagicMock()
m.user.project_id = tenant["id"]
req.environ["keystone.token_auth"] = m

resp = req.get_response(app)

expected_result = ""
self.assertContentType(resp)
self.assertExpectedResult(expected_result, resp)
self.assertEqual(204, resp.status_code)

def test_list_attachments(self):
tenant = fakes.tenants["baz"]
app = self.get_app()

for url in ("/storagelink/", "/storagelink"):
req = self._build_req(url, tenant["id"], method="GET")

resp = req.get_response(app)

self.assertEqual(200, resp.status_code)
expected = []
for v in fakes.volumes[tenant["id"]]:
for a in v["attachments"]:
link_id = '_'.join([a["serverId"], v["id"]])
expected.append(
("X-OCCI-Location",
utils.join_url(self.application_url + "/",
"storagelink/%s" % link_id))
)
self.assertExpectedResult(expected, resp)

def test_show_link(self):
tenant = fakes.tenants["baz"]
app = self.get_app()

for volume in fakes.volumes[tenant["id"]]:
for a in volume["attachments"]:
link_id = '_'.join([a["serverId"], volume["id"]])
req = self._build_req("/storagelink/%s" % link_id,
tenant["id"], method="GET")

resp = req.get_response(app)
self.assertContentType(resp)
link_id = '_'.join([a["serverId"], a["volumeId"]])
source = utils.join_url(self.application_url + "/",
"compute/%s" % a["serverId"])
target = utils.join_url(self.application_url + "/",
"storage/%s" % a["volumeId"])
self.assertResultIncludesLink(link_id, source, target, resp)
self.assertEqual(200, resp.status_code)

def test_show_invalid_id(self):
tenant = fakes.tenants["foo"]

app = self.get_app()
req = self._build_req("/storagelink/%s" % uuid.uuid4().hex,
tenant["id"], method="GET")
resp = req.get_response(app)
self.assertEqual(404, resp.status_code)

def test_show_non_existant_compute(self):
tenant = fakes.tenants["foo"]

app = self.get_app()
req = self._build_req("/storagelink/%s_foo" % uuid.uuid4().hex,
tenant["id"], method="GET")
resp = req.get_response(app)
self.assertEqual(404, resp.status_code)

def test_show_non_existant_volume(self):
tenant = fakes.tenants["foo"]
server_id = fakes.servers[tenant["id"]][0]["id"]

app = self.get_app()
req = self._build_req("/storagelink/%s_foo" % server_id,
tenant["id"], method="GET")
resp = req.get_response(app)
self.assertEqual(404, resp.status_code)


class StorageLinkControllerTextPlain(test_middleware.TestMiddlewareTextPlain,
TestStorageLinkController):
"""Test OCCI storage link controller with Accept: text/plain."""


class StorageLinkControllerTextOcci(test_middleware.TestMiddlewareTextOcci,
TestStorageLinkController):
"""Test OCCI storage link controller with Accept: text/occi."""

0 comments on commit 088ce08

Please sign in to comment.