فهرست منبع

Move backup writer initialization to Coriolis core

The Coriolis providers currently duplicate the code that initializes
the backup writers and returns the backup writer connection info.

We'll move that along with the corresponding constants to Coriolis
core.

Coriolis providers are free to define custom backup providers if
necessary.
Lucian Petrut 2 هفته پیش
والد
کامیت
0ecdb8acd4
2فایلهای تغییر یافته به همراه104 افزوده شده و 0 حذف شده
  1. 61 0
      coriolis/providers/backup_writers.py
  2. 43 0
      coriolis/tests/providers/test_backup_writers.py

+ 61 - 0
coriolis/providers/backup_writers.py

@@ -22,6 +22,7 @@ from six import with_metaclass
 
 from coriolis import constants
 from coriolis import data_transfer
+from coriolis import events
 from coriolis import exception
 from coriolis.providers import provider_utils
 from coriolis import utils
@@ -51,6 +52,18 @@ BACKUP_WRITERS = [
     BACKUP_WRITER_FILE
 ]
 
+# Common data transfer mechanisms exposed to Coriolis users.
+DATA_TRANSFER_MECHANISM_SSH = "SSH"
+DATA_TRANSFER_MECHANISM_HTTPS = "HTTPS"
+# Can't be the same as replicator port.
+DATA_TRANSFER_MECHANISM_HTTPS_PORT = 5566
+
+# The file writer is meant for testing purposes and will not be exposed here.
+DATA_TRANSFER_MECHANISM_MAP = {
+    DATA_TRANSFER_MECHANISM_SSH: BACKUP_WRITER_SSH,
+    DATA_TRANSFER_MECHANISM_HTTPS: BACKUP_WRITER_HTTP,
+}
+
 _WRITER_ERR_MAP = {
     -1: "ERR_MORE_MSG",
     0: "ERR_DONE",
@@ -176,6 +189,54 @@ class BackupWritersFactory(object):
             raise exception.CoriolisException(
                 "Missing credentials in connection info")
 
+    @classmethod
+    def get_backup_writer_connection_info(
+        cls,
+        event_manager: events.EventManager,
+        ssh_connection_info: dict,
+        data_transfer_mechanism: str,
+    ) -> dict:
+        """Initialize the backup writer and obtain connection info.
+
+        :param ssh_connection_info: a dict containing the following keys:
+            * ip
+            * port - usually SSH port (22)
+            * username
+            * password
+            * pkey - Paramiko keypair
+        :param data_transfer_mechanism: SSH or HTTPS
+        :returns: a dict describing the backend type and backup writer
+                  connection details, used to subsequently retrieve the
+                  backup writer.
+        """
+        if data_transfer_mechanism == DATA_TRANSFER_MECHANISM_HTTPS:
+            event_manager.progress_update(
+                "Setting up HTTPS backup writer service on disk copy worker VM"
+            )
+            writer_bootstrapper = HTTPBackupWriterBootstrapper(
+                ssh_connection_info,
+                DATA_TRANSFER_MECHANISM_HTTPS_PORT,
+            )
+            https_conn_info = writer_bootstrapper.setup_writer()
+            writer_conn_info = {
+                "backend": DATA_TRANSFER_MECHANISM_MAP[
+                    DATA_TRANSFER_MECHANISM_HTTPS],
+                "connection_details": https_conn_info,
+            }
+        elif data_transfer_mechanism == DATA_TRANSFER_MECHANISM_SSH:
+            writer_conn_info = {
+                "backend": DATA_TRANSFER_MECHANISM_MAP[
+                    DATA_TRANSFER_MECHANISM_SSH],
+                "connection_details": ssh_connection_info,
+            }
+        else:
+            raise ValueError(
+                "Unhandleable data transfer mechanism '%s'" % (
+                    data_transfer_mechanism)
+            )
+
+        return writer_conn_info
+
 
 class BaseBackupWriterImpl(with_metaclass(abc.ABCMeta)):
     def __init__(self, path, disk_id):

+ 43 - 0
coriolis/tests/providers/test_backup_writers.py

@@ -164,6 +164,49 @@ class BackupWritersFactoryTestCase(test_base.CoriolisBaseTestCase):
         self.assertRaises(exception.CoriolisException,
                           self._get_factory, {"backend": "ssh"})
 
+    @mock.patch.object(backup_writers, "HTTPBackupWriterBootstrapper")
+    def test_get_conn_info_https(self, mock_https_bootstrapper):
+        mechanism = backup_writers.DATA_TRANSFER_MECHANISM_HTTPS
+        factory = backup_writers.BackupWritersFactory
+        writer_conn_info = factory.get_backup_writer_connection_info(
+            event_manager=mock.Mock(),
+            ssh_connection_info=mock.sentinel.instance_conn_info,
+            data_transfer_mechanism=mechanism,
+        )
+        self.assertEqual(
+            writer_conn_info["backend"], backup_writers.BACKUP_WRITER_HTTP)
+        self.assertEqual(
+            writer_conn_info["connection_details"],
+            mock_https_bootstrapper.return_value.setup_writer.return_value)
+        mock_https_bootstrapper.assert_called_once_with(
+            mock.sentinel.instance_conn_info,
+            backup_writers.DATA_TRANSFER_MECHANISM_HTTPS_PORT,
+        )
+
+    def test_get_conn_info_ssh(self):
+        mechanism = backup_writers.DATA_TRANSFER_MECHANISM_SSH
+        factory = backup_writers.BackupWritersFactory
+        writer_conn_info = factory.get_backup_writer_connection_info(
+            event_manager=mock.Mock(),
+            ssh_connection_info=mock.sentinel.instance_conn_info,
+            data_transfer_mechanism=mechanism,
+        )
+        self.assertEqual(
+            writer_conn_info["backend"], backup_writers.BACKUP_WRITER_SSH)
+        self.assertEqual(
+            writer_conn_info["connection_details"],
+            mock.sentinel.instance_conn_info)
+
+    def test_get_conn_info_unsupported(self):
+        factory = backup_writers.BackupWritersFactory
+        self.assertRaises(
+            ValueError,
+            factory.get_backup_writer_connection_info,
+            event_manager=mock.Mock(),
+            ssh_connection_info=mock.sentinel.instance_conn_info,
+            data_transfer_mechanism="fake-mechanism",
+        )
+
 
 class BaseBackupWriterTestCase(test_base.CoriolisBaseTestCase):
     """Test suite for the Coriolis BaseBackupWriter class."""