diff --git a/nova/privsep/path.py b/nova/privsep/path.py index c35e32ce54bb..f4e8c3d579cd 100644 --- a/nova/privsep/path.py +++ b/nova/privsep/path.py @@ -34,7 +34,7 @@ def readfile(path): @nova.privsep.sys_admin_pctxt.entrypoint def writefile(path, mode, content): - if not os.path.exists(path): + if not os.path.exists(os.path.dirname(path)): raise exception.FileNotFound(file_path=path) with open(path, mode) as f: f.write(content) diff --git a/nova/tests/unit/privsep/test_path.py b/nova/tests/unit/privsep/test_path.py index cacbebd0e9f9..6cc377eb8865 100644 --- a/nova/tests/unit/privsep/test_path.py +++ b/nova/tests/unit/privsep/test_path.py @@ -1,5 +1,6 @@ # Copyright 2016 Red Hat, Inc # Copyright 2017 Rackspace Australia +# Copyright 2019 Aptira Pty Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -13,12 +14,131 @@ # License for the specific language governing permissions and limitations # under the License. +import mock import os import six import tempfile +from nova import exception import nova.privsep.path from nova import test +from nova.tests import fixtures + + +class FileTestCase(test.NoDBTestCase): + """Test file related utility methods.""" + + def setUp(self): + super(FileTestCase, self).setUp() + self.useFixture(fixtures.PrivsepFixture()) + + @mock.patch('os.path.exists', return_value=True) + def test_readfile(self, mock_exists): + mock_open = mock.mock_open(read_data='hello world') + with mock.patch.object(six.moves.builtins, 'open', + new=mock_open): + self.assertEqual('hello world', + nova.privsep.path.readfile('/fake/path')) + + @mock.patch('os.path.exists', return_value=False) + def test_readfile_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.readfile, + '/fake/path') + + @mock.patch('os.path.exists', return_value=True) + def test_write(self, mock_exists): + mock_open = mock.mock_open() + with mock.patch.object(six.moves.builtins, 'open', + new=mock_open): + nova.privsep.path.writefile('/fake/path/file', 'w', 'foo') + + handle = mock_open() + mock_exists.assert_called_with('/fake/path') + self.assertTrue(mock.call('/fake/path/file', 'w') in + mock_open.mock_calls) + handle.write.assert_called_with('foo') + + @mock.patch('os.path.exists', return_value=False) + def test_write_dir_missing(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.writefile, + '/fake/path', 'w', 'foo') + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.readlink') + def test_readlink(self, mock_readlink, mock_exists): + nova.privsep.path.readlink('/fake/path') + mock_exists.assert_called_with('/fake/path') + mock_readlink.assert_called_with('/fake/path') + + @mock.patch('os.path.exists', return_value=False) + def test_readlink_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.readlink, + '/fake/path') + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.chown') + def test_chown(self, mock_chown, mock_exists): + nova.privsep.path.chown('/fake/path', uid=42, gid=43) + mock_exists.assert_called_with('/fake/path') + mock_chown.assert_called_with('/fake/path', 42, 43) + + @mock.patch('os.path.exists', return_value=False) + def test_chown_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.chown, + '/fake/path') + + @mock.patch('oslo_utils.fileutils.ensure_tree') + def test_makedirs(self, mock_ensure_tree): + nova.privsep.path.makedirs('/fake/path') + mock_ensure_tree.assert_called_with('/fake/path') + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.chmod') + def test_chmod(self, mock_chmod, mock_exists): + nova.privsep.path.chmod('/fake/path', 0x666) + mock_exists.assert_called_with('/fake/path') + mock_chmod.assert_called_with('/fake/path', 0x666) + + @mock.patch('os.path.exists', return_value=False) + def test_chmod_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.chmod, + '/fake/path', 0x666) + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.utime') + def test_utime(self, mock_utime, mock_exists): + nova.privsep.path.utime('/fake/path') + mock_exists.assert_called_with('/fake/path') + mock_utime.assert_called_with('/fake/path', None) + + @mock.patch('os.path.exists', return_value=False) + def test_utime_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.utime, + '/fake/path') + + @mock.patch('os.path.exists', return_value=True) + @mock.patch('os.rmdir') + def test_rmdir(self, mock_rmdir, mock_exists): + nova.privsep.path.rmdir('/fake/path') + mock_exists.assert_called_with('/fake/path') + mock_rmdir.assert_called_with('/fake/path') + + @mock.patch('os.path.exists', return_value=False) + def test_rmdir_file_not_found(self, mock_exists): + self.assertRaises(exception.FileNotFound, + nova.privsep.path.rmdir, + '/fake/path') + + @mock.patch('os.path.exists', return_value=True) + def test_exists(self, mock_exists): + nova.privsep.path.path.exists('/fake/path') + mock_exists.assert_called_with('/fake/path') class LastBytesTestCase(test.NoDBTestCase):