self.volume_rpcapi = volume_rpcapi.VolumeAPI()
super(BackupManager, self).__init__(service_name='backup',
*args, **kwargs)
+ self.additional_endpoints.append(_BackupV2Proxy(self))
@property
def driver_name(self):
rpcapi = self.volume_rpcapi
rpcapi.terminate_connection(context, volume, properties, force=force)
rpcapi.remove_export(context, volume)
+
+
+# TODO(dulek): This goes away immediately in Newton and is just present in
+# Mitaka so that we can receive v1.x and v2.0 messages.
+class _BackupV2Proxy(object):
+
+ target = messaging.Target(version='2.0')
+
+ def __init__(self, manager):
+ self.manager = manager
+
+ def create_backup(self, context, backup):
+ return self.manager.create_backup(context, backup)
+
+ def restore_backup(self, context, backup, volume_id):
+ return self.manager.restore_backup(context, backup, volume_id)
+
+ def delete_backup(self, context, backup):
+ return self.manager.delete_backup(context, backup)
+
+ def export_record(self, context, backup):
+ return self.manager.export_record(context, backup)
+
+ def import_record(self, context, backup, backup_service, backup_url,
+ backup_hosts):
+ return self.manager.import_record(context, backup, backup_service,
+ backup_url, backup_hosts)
+
+ def reset_status(self, context, backup, status):
+ return self.manager.reset_status(context, backup, status)
+
+ def check_support_to_force_delete(self, context):
+ return self.manager.check_support_to_force_delete(context)
1.2 - A version that got in by mistake (without breaking anything).
1.3 - Dummy version bump to mark start of having cinder-backup service
decoupled from cinder-volume.
+
+ ... Mitaka supports messaging 1.3. Any changes to existing methods in
+ 1.x after this point should be done so that they can handle version cap
+ set to 1.3.
+
+ 2.0 - Remove 1.x compatibility
"""
RPC_API_VERSION = '1.3'
TOPIC = CONF.backup_topic
BINARY = 'cinder-backup'
+ def _compat_ver(self, current, legacy):
+ if self.client.can_send_version(current):
+ return current
+ else:
+ return legacy
+
def create_backup(self, ctxt, backup):
LOG.debug("create_backup in rpcapi backup_id %s", backup.id)
- cctxt = self.client.prepare(server=backup.host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=backup.host, version=version)
cctxt.cast(ctxt, 'create_backup', backup=backup)
def restore_backup(self, ctxt, volume_host, backup, volume_id):
LOG.debug("restore_backup in rpcapi backup_id %s", backup.id)
- cctxt = self.client.prepare(server=volume_host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=volume_host, version=version)
cctxt.cast(ctxt, 'restore_backup', backup=backup,
volume_id=volume_id)
def delete_backup(self, ctxt, backup):
LOG.debug("delete_backup rpcapi backup_id %s", backup.id)
- cctxt = self.client.prepare(server=backup.host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=backup.host, version=version)
cctxt.cast(ctxt, 'delete_backup', backup=backup)
def export_record(self, ctxt, backup):
"on host %(host)s.",
{'id': backup.id,
'host': backup.host})
- cctxt = self.client.prepare(server=backup.host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=backup.host, version=version)
return cctxt.call(ctxt, 'export_record', backup=backup)
def import_record(self,
{'id': backup.id,
'host': host,
'url': backup_url})
- cctxt = self.client.prepare(server=host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=host, version=version)
cctxt.cast(ctxt, 'import_record',
backup=backup,
backup_service=backup_service,
"on host %(host)s.",
{'id': backup.id,
'host': backup.host})
- cctxt = self.client.prepare(server=backup.host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=backup.host, version=version)
return cctxt.cast(ctxt, 'reset_status', backup=backup, status=status)
def check_support_to_force_delete(self, ctxt, host):
LOG.debug("Check if backup driver supports force delete "
"on host %(host)s.", {'host': host})
- cctxt = self.client.prepare(server=host, version='1.1')
+ version = self._compat_ver('2.0', '1.1')
+ cctxt = self.client.prepare(server=host, version=version)
return cctxt.call(ctxt, 'check_support_to_force_delete')
else:
self.assertEqual(expected_msg[kwarg], value)
- def test_create_backup(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_create_backup(self, can_send_version):
+ self._test_backup_api('create_backup',
+ rpc_method='cast',
+ server=self.fake_backup_obj.host,
+ backup=self.fake_backup_obj,
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('create_backup',
rpc_method='cast',
server=self.fake_backup_obj.host,
backup=self.fake_backup_obj,
version='1.1')
- def test_restore_backup(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_restore_backup(self, can_send_version):
+ self._test_backup_api('restore_backup',
+ rpc_method='cast',
+ server='fake_volume_host',
+ volume_host='fake_volume_host',
+ backup=self.fake_backup_obj,
+ volume_id='fake_volume_id',
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('restore_backup',
rpc_method='cast',
server='fake_volume_host',
volume_id=fake.volume_id,
version='1.1')
- def test_delete_backup(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_delete_backup(self, can_send_version):
+ self._test_backup_api('delete_backup',
+ rpc_method='cast',
+ server=self.fake_backup_obj.host,
+ backup=self.fake_backup_obj,
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('delete_backup',
rpc_method='cast',
server=self.fake_backup_obj.host,
backup=self.fake_backup_obj,
version='1.1')
- def test_export_record(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_export_record(self, can_send_version):
+ self._test_backup_api('export_record',
+ rpc_method='call',
+ server=self.fake_backup_obj.host,
+ backup=self.fake_backup_obj,
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('export_record',
rpc_method='call',
server=self.fake_backup_obj.host,
backup=self.fake_backup_obj,
version='1.1')
- def test_import_record(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_import_record(self, can_send_version):
+ self._test_backup_api('import_record',
+ rpc_method='cast',
+ server='fake_volume_host',
+ host='fake_volume_host',
+ backup=self.fake_backup_obj,
+ backup_service='fake_service',
+ backup_url='fake_url',
+ backup_hosts=['fake_host1', 'fake_host2'],
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('import_record',
rpc_method='cast',
server='fake_volume_host',
backup_hosts=['fake_host1', 'fake_host2'],
version='1.1')
- def test_reset_status(self):
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_reset_status(self, can_send_version):
+ self._test_backup_api('reset_status',
+ rpc_method='cast',
+ server=self.fake_backup_obj.host,
+ backup=self.fake_backup_obj,
+ status='error',
+ version='2.0')
+
+ can_send_version.return_value = False
self._test_backup_api('reset_status',
rpc_method='cast',
server=self.fake_backup_obj.host,
backup=self.fake_backup_obj,
status='error',
version='1.1')
+
+ @mock.patch('oslo_messaging.RPCClient.can_send_version', return_value=True)
+ def test_check_support_to_force_delete(self, can_send_version):
+ self._test_backup_api('check_support_to_force_delete',
+ rpc_method='call',
+ server='fake_volume_host',
+ host='fake_volume_host',
+ version='2.0')
+
+ can_send_version.return_value = False
+ self._test_backup_api('check_support_to_force_delete',
+ rpc_method='call',
+ server='fake_volume_host',
+ host='fake_volume_host',
+ version='1.1')