diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-01-20 10:06:14 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-01-20 10:06:14 +0000 |
commit | a9f2bd1af0e7452e425ef314a95d8d647f5a05e6 (patch) | |
tree | d3c5611f260444d9b1c765440f395eade16884b2 | |
parent | e983e894d4fb6d03e1d54529da532db436c012a1 (diff) | |
parent | a4ec8a272921fe55879ad0dc1b2cb850f1ea993f (diff) | |
download | glance_store-a9f2bd1af0e7452e425ef314a95d8d647f5a05e6.tar.gz |
Merge "Sheepdog: Change storelocation format"
-rw-r--r-- | glance_store/_drivers/sheepdog.py | 36 | ||||
-rw-r--r-- | glance_store/tests/unit/test_sheepdog_store.py | 79 |
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']) |