From f776f5a56e37391386e2ce0ddc17d830aacecb3c Mon Sep 17 00:00:00 2001
From: Hamdy Khader <hamdyk@mellanox.com>
Date: Thu, 13 Sep 2018 16:18:32 +0300
Subject: [PATCH] Ignore volume disconnect if it is not connected

Starting a VM with an NVMe volume after compute node reboots fails
because nova try to disconnect the volume then connect it again.

The proposed fix is to skip volume disconnect if the device not
connected.

Change-Id: I0f5533c0f00707380aa2e8039bcb99f9fba6687a
Closes-Bug: #1792315
---
 os_brick/initiator/connectors/nvme.py            |  6 ++++++
 os_brick/tests/initiator/connectors/test_nvme.py | 12 ++++++++----
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/os_brick/initiator/connectors/nvme.py b/os_brick/initiator/connectors/nvme.py
index 2d2e4d84e..11d925ca9 100644
--- a/os_brick/initiator/connectors/nvme.py
+++ b/os_brick/initiator/connectors/nvme.py
@@ -150,6 +150,12 @@ class NVMeConnector(base.BaseLinuxConnector):
 
         conn_nqn = connection_properties['nqn']
         device_path = connection_properties['device_path']
+        current_nvme_devices = self._get_nvme_devices()
+        if device_path not in current_nvme_devices:
+            LOG.warning("Trying to disconnect device %(device_path)s that "
+                        "is not connected.", {'device_path': device_path})
+            return
+
         LOG.debug(
             "Trying to disconnect from NVMe nqn "
             "%(conn_nqn)s with device_path %(device_path)s",
diff --git a/os_brick/tests/initiator/connectors/test_nvme.py b/os_brick/tests/initiator/connectors/test_nvme.py
index a2f6fee8a..2e0093644 100644
--- a/os_brick/tests/initiator/connectors/test_nvme.py
+++ b/os_brick/tests/initiator/connectors/test_nvme.py
@@ -111,13 +111,15 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase):
                           self.connector.connect_volume,
                           connection_properties)
 
+    @mock.patch.object(nvme.NVMeConnector, '_get_nvme_devices')
     @mock.patch.object(nvme.NVMeConnector, '_execute')
-    def test_disconnect_volume(self, mock_execute):
+    def test_disconnect_volume(self, mock_devices, mock_execute):
         connection_properties = {'target_portal': 'portal',
                                  'target_port': 1,
                                  'nqn': 'nqn.volume_123',
-                                 'device_path': '',
+                                 'device_path': '/dev/nvme0n1',
                                  'transport_type': 'rdma'}
+        mock_devices.return_value = '/dev/nvme0n1'
         self.connector.disconnect_volume(connection_properties, None)
 
         mock_execute.asert_called_once_with(
@@ -126,13 +128,15 @@ class NVMeConnectorTestCase(test_connector.ConnectorTestCase):
             root_helper=None,
             run_as_root=True)
 
+    @mock.patch.object(nvme.NVMeConnector, '_get_nvme_devices')
     @mock.patch.object(nvme.NVMeConnector, '_execute')
-    def test_disconnect_volume_raise(self, mock_execute):
+    def test_disconnect_volume_raise(self, mock_devices, mock_execute):
         mock_execute.side_effect = putils.ProcessExecutionError
+        mock_devices.return_value = '/dev/nvme0n1'
         connection_properties = {'target_portal': 'portal',
                                  'target_port': 1,
                                  'nqn': 'nqn.volume_123',
-                                 'device_path': '',
+                                 'device_path': '/dev/nvme0n1',
                                  'transport_type': 'rdma'}
 
         self.assertRaises(putils.ProcessExecutionError,