summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-01-20 10:06:14 +0000
committerGerrit Code Review <review@openstack.org>2016-01-20 10:06:14 +0000
commita9f2bd1af0e7452e425ef314a95d8d647f5a05e6 (patch)
treed3c5611f260444d9b1c765440f395eade16884b2
parente983e894d4fb6d03e1d54529da532db436c012a1 (diff)
parenta4ec8a272921fe55879ad0dc1b2cb850f1ea993f (diff)
downloadglance_store-a9f2bd1af0e7452e425ef314a95d8d647f5a05e6.tar.gz
Merge "Sheepdog: Change storelocation format"
-rw-r--r--glance_store/_drivers/sheepdog.py36
-rw-r--r--glance_store/tests/unit/test_sheepdog_store.py79
2 files changed, 102 insertions, 13 deletions
diff --git a/glance_store/_drivers/sheepdog.py b/glance_store/_drivers/sheepdog.py
index 18a5b29..f5031ad 100644
--- a/glance_store/_drivers/sheepdog.py
+++ b/glance_store/_drivers/sheepdog.py
@@ -81,7 +81,7 @@ class SheepdogImage(object):
Sheepdog Usage: collie vdi list -r -a address -p port image
"""
out = self._run_command("list -r", None)
- return long(out.split(' ')[3])
+ return int(out.split(' ')[3])
def read(self, offset, count):
"""
@@ -134,22 +134,34 @@ class StoreLocation(glance_store.location.StoreLocation):
"""
Class describing a Sheepdog URI. This is of the form:
- sheepdog://image
+ sheepdog://addr:port:image
"""
def process_specs(self):
self.image = self.specs.get('image')
+ self.addr = self.specs.get('addr')
+ self.port = self.specs.get('port')
def get_uri(self):
- return "sheepdog://%s" % self.image
+ return "sheepdog://%(addr)s:%(port)s:%(image)s" % {
+ 'addr': self.addr,
+ 'port': self.port,
+ 'image': self.image}
def parse_uri(self, uri):
valid_schema = 'sheepdog://'
if not uri.startswith(valid_schema):
- reason = _("URI must start with '%s://'") % valid_schema
+ reason = _("URI must start with '%s'") % valid_schema
raise exceptions.BadStoreUri(message=reason)
- self.image = uri[11:]
+ pieces = uri[len(valid_schema):].split(':')
+ if len(pieces) == 3:
+ self.addr, self.port, self.image = pieces
+ # This is used for backwards compatibility.
+ else:
+ self.image = pieces[0]
+ self.port = self.conf.glance_store.sheepdog_store_port
+ self.addr = self.conf.glance_store.sheepdog_store_address
class ImageIterator(object):
@@ -177,7 +189,7 @@ class Store(glance_store.driver.Store):
_CAPABILITIES = (capabilities.BitMasks.RW_ACCESS |
capabilities.BitMasks.DRIVER_REUSABLE)
OPTIONS = _SHEEPDOG_OPTS
- EXAMPLE_URL = "sheepdog://image"
+ EXAMPLE_URL = "sheepdog://addr:port:image"
def get_schemes(self):
return ('sheepdog',)
@@ -225,7 +237,7 @@ class Store(glance_store.driver.Store):
"""
loc = location.store_location
- image = SheepdogImage(self.addr, self.port, loc.image,
+ image = SheepdogImage(loc.addr, loc.port, loc.image,
self.READ_CHUNKSIZE)
if not image.exist():
raise exceptions.NotFound(_("Sheepdog image %s does not exist")
@@ -244,7 +256,7 @@ class Store(glance_store.driver.Store):
"""
loc = location.store_location
- image = SheepdogImage(self.addr, self.port, loc.image,
+ image = SheepdogImage(loc.addr, loc.port, loc.image,
self.READ_CHUNKSIZE)
if not image.exist():
raise exceptions.NotFound(_("Sheepdog image %s does not exist")
@@ -273,7 +285,11 @@ class Store(glance_store.driver.Store):
raise exceptions.Duplicate(_("Sheepdog image %s already exists")
% image_id)
- location = StoreLocation({'image': image_id}, self.conf)
+ location = StoreLocation({
+ 'image': image_id,
+ 'addr': self.addr,
+ 'port': self.port
+ }, self.conf)
checksum = hashlib.md5()
image.create(image_size)
@@ -307,7 +323,7 @@ class Store(glance_store.driver.Store):
"""
loc = location.store_location
- image = SheepdogImage(self.addr, self.port, loc.image,
+ image = SheepdogImage(loc.addr, loc.port, loc.image,
self.WRITE_CHUNKSIZE)
if not image.exist():
raise exceptions.NotFound(_("Sheepdog image %s does not exist") %
diff --git a/glance_store/tests/unit/test_sheepdog_store.py b/glance_store/tests/unit/test_sheepdog_store.py
index 39f8e05..213b090 100644
--- a/glance_store/tests/unit/test_sheepdog_store.py
+++ b/glance_store/tests/unit/test_sheepdog_store.py
@@ -42,8 +42,11 @@ class TestSheepdogStore(base.StoreBaseTest,
self.addCleanup(execute.stop)
self.store = sheepdog.Store(self.conf)
self.store.configure()
+ self.store_specs = {'image': 'fake_image',
+ 'addr': 'fake_addr',
+ 'port': 'fake_port'}
- def test_cleanup_when_add_image_exception(self):
+ def test_add_image(self):
called_commands = []
def _fake_run_command(command, data, *params):
@@ -52,11 +55,81 @@ class TestSheepdogStore(base.StoreBaseTest,
with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
cmd.side_effect = _fake_run_command
data = six.BytesIO(b'xx')
- self.store.add('fake_image_id', data, 2)
+ ret = self.store.add('fake_image_id', data, 2)
self.assertEqual(called_commands, ['list -r', 'create', 'write'])
+ self.assertEqual(ret[1], 2)
+
+ def test_cleanup_when_add_image_exception(self):
+ called_commands = []
+
+ def _fake_run_command(command, data, *params):
+ if command == 'write':
+ raise exceptions.BackendException
+ else:
+ called_commands.append(command)
+
+ with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
+ cmd.side_effect = _fake_run_command
+ data = six.BytesIO(b'xx')
+ self.assertRaises(exceptions.BackendException, self.store.add,
+ 'fake_image_id', data, 2)
+ self.assertTrue('delete' in called_commands)
+
+ def test_add_duplicate_image(self):
+ def _fake_run_command(command, data, *params):
+ if command == "list -r":
+ return "= fake_volume 0 1000"
+
+ with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
+ cmd.side_effect = _fake_run_command
+ data = six.BytesIO(b'xx')
+ self.assertRaises(exceptions.Duplicate, self.store.add,
+ 'fake_image_id', data, 2)
+
+ def test_get(self):
+ def _fake_run_command(command, data, *params):
+ if command == "list -r":
+ return "= fake_volume 0 1000"
+
+ with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
+ cmd.side_effect = _fake_run_command
+ loc = location.Location('test_sheepdog_store',
+ sheepdog.StoreLocation,
+ self.conf, store_specs=self.store_specs)
+ ret = self.store.get(loc)
+ self.assertEqual(ret[1], 1000)
def test_partial_get(self):
loc = location.Location('test_sheepdog_store', sheepdog.StoreLocation,
- self.conf, store_specs={'image': 'fake_image'})
+ self.conf, store_specs=self.store_specs)
self.assertRaises(exceptions.StoreRandomGetNotSupported,
self.store.get, loc, chunk_size=1)
+
+ def test_get_size(self):
+ def _fake_run_command(command, data, *params):
+ if command == "list -r":
+ return "= fake_volume 0 1000"
+
+ with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
+ cmd.side_effect = _fake_run_command
+ loc = location.Location('test_sheepdog_store',
+ sheepdog.StoreLocation,
+ self.conf, store_specs=self.store_specs)
+ ret = self.store.get_size(loc)
+ self.assertEqual(ret, 1000)
+
+ def test_delete(self):
+ called_commands = []
+
+ def _fake_run_command(command, data, *params):
+ called_commands.append(command)
+ if command == "list -r":
+ return "= fake_volume 0 1000"
+
+ with mock.patch.object(sheepdog.SheepdogImage, '_run_command') as cmd:
+ cmd.side_effect = _fake_run_command
+ loc = location.Location('test_sheepdog_store',
+ sheepdog.StoreLocation,
+ self.conf, store_specs=self.store_specs)
+ self.store.delete(loc)
+ self.assertEqual(called_commands, ['list -r', 'delete'])