Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sheepdog: Implement abstract methods of manage volume with resizing VDI #78

Open
wants to merge 5 commits into
base: manage_volume
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 289 additions & 0 deletions cinder/tests/unit/test_sheepdog.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from cinder import utils
from cinder.volume import configuration as conf
from cinder.volume.drivers import sheepdog
from cinder.volume import utils as volutils

SHEEP_ADDR = '127.0.0.1'
SHEEP_PORT = 7000
Expand Down Expand Up @@ -105,6 +106,10 @@ def cmd_dog_vdi_resize(self, name, size):
return ('env', 'LC_ALL=C', 'LANG=C', 'dog', 'vdi', 'resize', name,
size, '-a', SHEEP_ADDR, '-p', SHEEP_PORT)

def cmd_dog_vdi_list(self, vdiname):
return ('env', 'LC_ALL=C', 'LANG=C', 'dog', 'vdi', 'list', vdiname,
'-a', SHEEP_ADDR, '-p', SHEEP_PORT)

CMD_DOG_CLUSTER_INFO = ('env', 'LC_ALL=C', 'LANG=C', 'dog', 'cluster',
'info', '-a', SHEEP_ADDR, '-p', SHEEP_PORT)

Expand Down Expand Up @@ -173,6 +178,11 @@ def cmd_dog_vdi_resize(self, name, size):
'QoS_support': False,
}

TEST_EXISTING_REF = {
'source-name': 'test-vdi',
'source-id': '',
}

COLLIE_CLUSTER_INFO_0_5 = """\
Cluster status: running

Expand Down Expand Up @@ -260,6 +270,27 @@ def cmd_dog_vdi_resize(self, name, size):

DOG_NODE_INFO_ERROR_GET_NO_NODE_INFO = """\
Cannot get information from any nodes
"""

DOG_VDI_LIST = """\
= test-vdi 0 10737418240 0 0 1442379755 7be7f9 3
"""

DOG_VDI_LIST_WITH_SNAPSHOT = """\
s test-vdi 1 10737418240 0 0 1442379755 7be7f9 3
= test-vdi 0 16106127360 0 0 1442381817 7be7fb 3
"""

DOG_VDI_LIST_CLONE = """\
c test-clone 0 10737418240 0 0 1442381753 ce8575 3
"""

DOG_VDI_LIST_SIZE_10G_MORE_1 = """\
= test-vdi 0 10737418241 0 0 1442379755 7be7f9 3
"""

DOG_VDI_LIST_SIZE_11G_LESS_1 = """\
= test-vdi 0 11811160063 0 0 1442379755 7be7f9 3
"""

DOG_COMMAND_ERROR_VDI_NOT_EXISTS = """\
Expand Down Expand Up @@ -1603,6 +1634,113 @@ def test_get_disk_capacity_parse_stdout_error(self, fake_logger,
self.assertRaises(AttributeError, self.client.get_disk_capacity)
self.assertTrue(fake_logger.exception.called)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_success(self, fake_execute):
expected_cmd = ('vdi', 'list', '-r', self._vdiname)
fake_execute.return_value = (self.test_data.DOG_VDI_LIST, '')

actual = self.client.get_vdi_size(self._vdiname)
fake_execute.assert_called_once_with(*expected_cmd)
self.assertEqual(10, actual)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_with_snapshot_success(self, fake_execute):
expected_cmd = ('vdi', 'list', '-r', self._vdiname)
fake_execute.return_value = (self.test_data.DOG_VDI_LIST_WITH_SNAPSHOT,
'')
actual = self.client.get_vdi_size(self._vdiname)
fake_execute.assert_called_once_with(*expected_cmd)
self.assertEqual(15, actual)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_clone_success(self, fake_execute):
expected_cmd = ('vdi', 'list', '-r', self._vdiname)
fake_execute.return_value = (self.test_data.DOG_VDI_LIST_CLONE, '')

actual = self.client.get_vdi_size(self._vdiname)
fake_execute.assert_called_once_with(*expected_cmd)
self.assertEqual(10, actual)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_round_up_1_success(self, fake_execute):
expected_cmd = ('vdi', 'list', '-r', self._vdiname)
fake_execute.return_value = (
self.test_data.DOG_VDI_LIST_SIZE_10G_MORE_1, '')

actual = self.client.get_vdi_size(self._vdiname)
fake_execute.assert_called_once_with(*expected_cmd)
self.assertEqual(11, actual)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_round_up_2_success(self, fake_execute):
expected_cmd = ('vdi', 'list', '-r', self._vdiname)
fake_execute.return_value = (
self.test_data.DOG_VDI_LIST_SIZE_11G_LESS_1, '')

actual = self.client.get_vdi_size(self._vdiname)
fake_execute.assert_called_once_with(*expected_cmd)
self.assertEqual(11, actual)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
def test_get_vdi_size_not_found_error(self, fake_execute):
stdout = ''
stderr = ''
fake_execute.return_value = (stdout, stderr)

self.assertRaises(exception.NotFound, self.client.get_vdi_size,
self._vdiname)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
@mock.patch.object(sheepdog, 'LOG')
def test_get_vdi_size_stdout_parse_error(self, fake_logger, fake_execute):
stdout = 'dummy'
stderr = ''
fake_execute.return_value = (stdout, stderr)

self.assertRaises(IndexError, self.client.get_vdi_size, self._vdiname)
self.assertTrue(fake_logger.exception.called)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
@mock.patch.object(sheepdog, 'LOG')
def test_get_vdi_size_failed_to_connect(self, fake_logger, fake_execute):
cmd = self.test_data.cmd_dog_vdi_list(self._vdiname)
exit_code = 2
stdout = 'stdout_dummy'
stderr = self.test_data.DOG_COMMAND_ERROR_FAIL_TO_CONNECT
expected_msg = self.test_data.sheepdog_cmd_error(cmd=cmd,
exit_code=exit_code,
stdout=stdout,
stderr=stderr)
fake_execute.side_effect = exception.SheepdogCmdError(
cmd=cmd, exit_code=exit_code, stdout=stdout.replace('\n', '\\n'),
stderr=stderr.replace('\n', '\\n'))

ex = self.assertRaises(exception.SheepdogCmdError,
self.client.get_vdi_size, self._vdiname)
self.assertTrue(fake_logger.exception.called)
self.assertEqual(expected_msg, ex.msg)

@mock.patch.object(sheepdog.SheepdogClient, '_run_dog')
@mock.patch.object(sheepdog, 'LOG')
def test_get_vdi_size_unknown_error(self, fake_logger, fake_execute):
cmd = self.test_data.cmd_dog_vdi_list(self._vdiname)
exit_code = 2
stdout = 'stdout_dummy'
stderr = 'unknown'
expected_msg = self.test_data.sheepdog_cmd_error(cmd=cmd,
exit_code=exit_code,
stdout=stdout,
stderr=stderr)
fake_execute.side_effect = exception.SheepdogCmdError(
cmd=cmd, exit_code=exit_code,
stdout=stdout.replace('\n', '\\n'),
stderr=stderr.replace('\n', '\\n'))

ex = self.assertRaises(exception.SheepdogCmdError,
self.client.get_vdi_size, self._vdiname)
self.assertTrue(fake_logger.exception.called)
self.assertEqual(expected_msg, ex.msg)


class SheepdogDriverTestCase(test.TestCase):
def setUp(self):
Expand Down Expand Up @@ -2014,3 +2152,154 @@ def test_restore_backup(self, fake_backup_service):
self.assertEqual(fake_backup, call_backup)
self.assertEqual(fake_volume.id, call_volume_id)
self.assertIsInstance(call_sheepdog_fd, sheepdog.SheepdogIOWrapper)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(volutils, 'check_already_managed_volume')
def test_manage_existing_success(self, fake_check_already_managed_volume,
fake_create_cloned_volume, fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_existing_ref = self.test_data.TEST_EXISTING_REF
source_name = fake_existing_ref['source-name']
fake_vref = {'name': source_name, 'size': fake_volume.size}
fake_check_already_managed_volume.return_value = False

self.driver.manage_existing(fake_volume, fake_existing_ref)
fake_check_already_managed_volume.assert_called_once_with(self.db,
source_name)
fake_create_cloned_volume.assert_called_once_with(fake_volume,
fake_vref)
fake_delete.assert_called_once_with(source_name)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(volutils, 'check_already_managed_volume')
def test_manage_existing_fail_already_managed_volume(
self, fake_check_already_managed_volume, fake_create_cloned_volume,
fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_existing_ref = self.test_data.TEST_EXISTING_REF
fake_check_already_managed_volume.return_value = True

self.assertRaises(exception.ManageExistingAlreadyManaged,
self.driver.manage_existing,
fake_volume, fake_existing_ref)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(volutils, 'check_already_managed_volume')
@mock.patch.object(sheepdog, 'LOG')
def test_manage_existing_fail_create_cloned_volume(
self, fake_logger, fake_check_already_managed_volume,
fake_create_cloned_volume, fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_existing_ref = self.test_data.TEST_EXISTING_REF
fake_check_already_managed_volume.return_value = False
fake_create_cloned_volume.side_effect = exception.SheepdogCmdError(
cmd='dummy', exit_code=1, stdout='dummy', stderr='dummy')

self.assertRaises(exception.SheepdogCmdError,
self.driver.manage_existing, fake_volume,
fake_existing_ref)
self.assertTrue(fake_logger.error.called)
self.assertTrue(fake_check_already_managed_volume.called)
self.assertTrue(fake_create_cloned_volume.called)
self.assertFalse(fake_delete.called)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(volutils, 'check_already_managed_volume')
@mock.patch.object(sheepdog, 'LOG')
def test_manage_existing_fail_delete(
self, fake_logger, fake_check_already_managed_volume,
fake_create_cloned_volume, fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_existing_ref = self.test_data.TEST_EXISTING_REF
fake_check_already_managed_volume.return_value = False
fake_delete.side_effect = exception.SheepdogCmdError(
cmd='dummy', exit_code=1, stdout='dummy', stderr='dummy')

self.driver.manage_existing(fake_volume, fake_existing_ref)
self.assertTrue(fake_logger.warning.called)
self.assertTrue(fake_check_already_managed_volume.called)
self.assertTrue(fake_create_cloned_volume.called)
self.assertTrue(fake_delete.called)

@mock.patch.object(sheepdog.SheepdogClient, 'get_vdi_size')
def test_manage_existing_get_size_success(self, fake_get_vdi_size):
fake_get_vdi_size.return_value = 10
fake_existing_ref = self.test_data.TEST_EXISTING_REF

size = self.driver.manage_existing_get_size(self.test_data.TEST_VOLUME,
fake_existing_ref)
fake_get_vdi_size.assert_called_once_with(
fake_existing_ref['source-name'])
self.assertEqual(10, size)

@mock.patch.object(sheepdog.SheepdogClient, 'get_vdi_size')
def test_manage_existing_get_size_sourcename_key_empty(
self, fake_get_vdi_size):
fake_existing_ref = {'source-id': ''}

self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
self.test_data.TEST_VOLUME, fake_existing_ref)

@mock.patch.object(sheepdog.SheepdogClient, 'get_vdi_size')
def test_manage_existing_get_size_sourcename_value_empty(
self, fake_get_vdi_size):
fake_existing_ref = {'source-name': '', 'source-id': ''}

self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
self.test_data.TEST_VOLUME, fake_existing_ref)

@mock.patch.object(sheepdog.SheepdogClient, 'get_vdi_size')
def test_manage_existing_get_size_vdi_not_found(
self, fake_get_vdi_size):
fake_get_vdi_size.side_effect = exception.NotFound()

self.assertRaises(exception.ManageExistingInvalidReference,
self.driver.manage_existing_get_size,
self.test_data.TEST_VOLUME,
self.test_data.TEST_EXISTING_REF)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
def test_unmanage_success(self, fake_create_cloned_volume, fake_delete):
fake_volume = self.test_data.TEST_VOLUME
vref = {'name': fake_volume.name, 'size': fake_volume.size}
self.driver.unmanage(fake_volume)
fake_create_cloned_volume.assert_called_once_with(fake_volume,
vref)
fake_delete.assert_called_once_with(vref['name'])

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(sheepdog, 'LOG')
def test_unmanage_fail_create_cloned_volume(self, fake_logger,
fake_create_cloned_volume,
fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_create_cloned_volume.side_effect = exception.SheepdogCmdError(
cmd='dummy', exit_code=1, stdout='dummy', stderr='dummy')

self.assertRaises(exception.SheepdogCmdError,
self.driver.unmanage, fake_volume)
self.assertTrue(fake_logger.error.called)
self.assertTrue(fake_create_cloned_volume.called)
self.assertFalse(fake_delete.called)

@mock.patch.object(sheepdog.SheepdogClient, 'delete')
@mock.patch.object(sheepdog.SheepdogDriver, 'create_cloned_volume')
@mock.patch.object(sheepdog, 'LOG')
def test_unmanage_fail_delete(self, fake_logger, fake_create_cloned_volume,
fake_delete):
fake_volume = self.test_data.TEST_VOLUME
fake_delete.side_effect = exception.SheepdogCmdError(
cmd='dummy', exit_code=1, stdout='dummy', stderr='dummy')

self.driver.unmanage(fake_volume)
self.assertTrue(fake_logger.warning.called)
self.assertTrue(fake_create_cloned_volume.called)
self.assertTrue(fake_delete.called)
Loading