RBD: Fix containerized detection
Our detection mechanism of when we are running containerized has false positives, so we are not also checking /proc/1/mounts to see if the root directory is mounted from /var/lib/, which is the case when running containerized. Change-Id: Icad0340a9f805b59a5cddd7526a1efbb24ab652e Closes-Bug: #1885302
This commit is contained in:
		@@ -183,6 +183,23 @@ class RBDConnector(connectors.rbd.RBDConnector):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._execute('mkdir', '-p', '-m0755', path, run_as_root=True)
 | 
					            self._execute('mkdir', '-p', '-m0755', path, run_as_root=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def _in_container():
 | 
				
			||||||
 | 
					        if os.stat('/proc').st_dev <= 4:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # When running containerized / is /var/lib/docker when running in
 | 
				
			||||||
 | 
					        # Docker /var/lib/containers when running in Podman, and /var/lib/lxc
 | 
				
			||||||
 | 
					        # when in LXC
 | 
				
			||||||
 | 
					        with open('/proc/1/mounts', 'r') as f:
 | 
				
			||||||
 | 
					            for line in f.readlines():
 | 
				
			||||||
 | 
					                data = line.split(' ', 2)
 | 
				
			||||||
 | 
					                if data[1] == '/':
 | 
				
			||||||
 | 
					                    return '/var/lib/' in data[2]
 | 
				
			||||||
 | 
					        # Just in case, say we are
 | 
				
			||||||
 | 
					        LOG.warning("Couldn't detect if running on container, assuming we are")
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _setup_class(self):
 | 
					    def _setup_class(self):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self._execute('which', 'rbd')
 | 
					            self._execute('which', 'rbd')
 | 
				
			||||||
@@ -192,7 +209,7 @@ class RBDConnector(connectors.rbd.RBDConnector):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        RBDConnector.im_root = os.getuid() == 0
 | 
					        RBDConnector.im_root = os.getuid() == 0
 | 
				
			||||||
        # Check if we are running containerized
 | 
					        # Check if we are running containerized
 | 
				
			||||||
        RBDConnector.containerized = os.stat('/proc').st_dev > 4
 | 
					        RBDConnector.containerized = self._in_container()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Don't check again to speed things on following connections
 | 
					        # Don't check again to speed things on following connections
 | 
				
			||||||
        RBDConnector._setup_rbd_class = lambda *args: None
 | 
					        RBDConnector._setup_rbd_class = lambda *args: None
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,54 @@ class TestRBDConnector(base.BaseTest):
 | 
				
			|||||||
        self.connector.containerized = False
 | 
					        self.connector.containerized = False
 | 
				
			||||||
        self.connector._setup_rbd_class = lambda *args: None
 | 
					        self.connector._setup_rbd_class = lambda *args: None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch.object(nos_brick, 'open')
 | 
				
			||||||
 | 
					    @mock.patch('os.stat')
 | 
				
			||||||
 | 
					    def test__in_container_stat(self, mock_stat, mock_open):
 | 
				
			||||||
 | 
					        mock_stat.return_value.st_dev = 4
 | 
				
			||||||
 | 
					        res = self.connector._in_container()
 | 
				
			||||||
 | 
					        self.assertFalse(res)
 | 
				
			||||||
 | 
					        mock_stat.assert_called_once_with('/proc')
 | 
				
			||||||
 | 
					        mock_open.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch.object(nos_brick, 'open')
 | 
				
			||||||
 | 
					    @mock.patch('os.stat')
 | 
				
			||||||
 | 
					    def test__in_container_mounts_no_container(self, mock_stat, mock_open):
 | 
				
			||||||
 | 
					        mock_stat.return_value.st_dev = 5
 | 
				
			||||||
 | 
					        mock_read = mock_open.return_value.__enter__.return_value.readlines
 | 
				
			||||||
 | 
					        mock_read.return_value = [
 | 
				
			||||||
 | 
					            'sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0',
 | 
				
			||||||
 | 
					            'proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0',
 | 
				
			||||||
 | 
					            '/dev/mapper/fedora_think2-root / ext4 rw,seclabel,relatime 0 0',
 | 
				
			||||||
 | 
					            'selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0',
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = self.connector._in_container()
 | 
				
			||||||
 | 
					        self.assertFalse(res)
 | 
				
			||||||
 | 
					        mock_stat.assert_called_once_with('/proc')
 | 
				
			||||||
 | 
					        mock_open.assert_called_once_with('/proc/1/mounts', 'r')
 | 
				
			||||||
 | 
					        mock_read.assert_called_once_with()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @mock.patch.object(nos_brick.LOG, 'warning')
 | 
				
			||||||
 | 
					    @mock.patch.object(nos_brick, 'open')
 | 
				
			||||||
 | 
					    @mock.patch('os.stat')
 | 
				
			||||||
 | 
					    def test__in_container_mounts_in_container(self, mock_stat, mock_open,
 | 
				
			||||||
 | 
					                                               mock_warning):
 | 
				
			||||||
 | 
					        mock_stat.return_value.st_dev = 5
 | 
				
			||||||
 | 
					        mock_read = mock_open.return_value.__enter__.return_value.readlines
 | 
				
			||||||
 | 
					        mock_read.return_value = [
 | 
				
			||||||
 | 
					            'sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0',
 | 
				
			||||||
 | 
					            'proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0',
 | 
				
			||||||
 | 
					            'overlay / overlay rw,lowerdir=/var/lib/containers/...',
 | 
				
			||||||
 | 
					            'selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0',
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = self.connector._in_container()
 | 
				
			||||||
 | 
					        self.assertTrue(res)
 | 
				
			||||||
 | 
					        mock_stat.assert_called_once_with('/proc')
 | 
				
			||||||
 | 
					        mock_open.assert_called_once_with('/proc/1/mounts', 'r')
 | 
				
			||||||
 | 
					        mock_read.assert_called_once_with()
 | 
				
			||||||
 | 
					        mock_warning.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @mock.patch.object(nos_brick.RBDConnector, '_get_rbd_args')
 | 
					    @mock.patch.object(nos_brick.RBDConnector, '_get_rbd_args')
 | 
				
			||||||
    @mock.patch.object(nos_brick.RBDConnector, '_execute')
 | 
					    @mock.patch.object(nos_brick.RBDConnector, '_execute')
 | 
				
			||||||
    @mock.patch('os.path.exists', return_value=True)
 | 
					    @mock.patch('os.path.exists', return_value=True)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					fixes:
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					    Fix cases where our detection of when we are running containerized is not
 | 
				
			||||||
 | 
					    very reliable for the RBD driver.
 | 
				
			||||||
 | 
					    (Bug #1885302).
 | 
				
			||||||
		Reference in New Issue
	
	Block a user