Merge pull request #36 from trobert2/all_tested_with_mock
Added unit tests using mock
This commit is contained in:
commit
4dcd0f1d4a
15
cloudbaseinit/plugins/windows/userdata-plugins/__init__.py
Normal file
15
cloudbaseinit/plugins/windows/userdata-plugins/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
15
cloudbaseinit/tests/__init__.py
Normal file
15
cloudbaseinit/tests/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
15
cloudbaseinit/tests/metadata/__init__.py
Normal file
15
cloudbaseinit/tests/metadata/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
57
cloudbaseinit/tests/metadata/fake_json_response.py
Normal file
57
cloudbaseinit/tests/metadata/fake_json_response.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
def get_fake_metadata_json(version):
|
||||||
|
if version == '2013-04-04':
|
||||||
|
return {"random_seed":
|
||||||
|
"Wn51FGjZa3vlZtTxJuPr96oCf+X8jqbA9U2XR5wNdnApy1fz"
|
||||||
|
"/2NNssUwPoNzG6etw9RBn+XiZ0zKWnFzMsTopaN7WwYjWTnIsVw3cpIk"
|
||||||
|
"Td579wQgoEr1ANqhfO3qTvkOVNMhzTAw1ps+wqRmkLxH+1qYJnX06Gcd"
|
||||||
|
"KRRGkWTaOSlTkieA0LO2oTGFlbFDWcOW2vT5BvSBmqP7vNLzbLDMTc7M"
|
||||||
|
"IWRBzwmtcVPC17QL6EhZJTUcZ0mTz7l0R0DocLmFwHEXFEEr+q4WaJjt"
|
||||||
|
"1ejOOxVM3tiT7D8YpRZnnGNPfvEhq1yVMUoi8yv9pFmMmXicNBhm6zDK"
|
||||||
|
"VjcWk0gfbvaQcMnnOLrrE1VxAAzyNyPIXBI/H7AAHz2ECz7dgd2/4ocv"
|
||||||
|
"3bmTRY3hhcUKtNuat2IOvSGgMBUGdWnLorQGFz8t0/bcYhE0Dve35U6H"
|
||||||
|
"mtj78ydV/wmQWG0iq49NX6hk+VUmZtSZztlkbsaa7ajNjZ+Md9oZtlhX"
|
||||||
|
"Z5vJuhRXnHiCm7dRNO8Xo6HffEBH5A4smQ1T2Kda+1c18DZrY7+iQJRi"
|
||||||
|
"fa6witPCw0tXkQ6nlCLqL2weJD1XMiTZLSM/XsZFGGSkKCKvKLEqQrI/"
|
||||||
|
"XFUq/TA6B4aLGFlmmhOO/vMJcht06O8qVU/xtd5Mv/MRFzYaSG568Z/m"
|
||||||
|
"hk4vYLYdQYAA+pXRW9A=",
|
||||||
|
"uuid": "4b32ddf7-7941-4c36-a854-a1f5ac45b318",
|
||||||
|
"availability_zone": "nova",
|
||||||
|
"hostname": "windows.novalocal",
|
||||||
|
"launch_index": 0,
|
||||||
|
"public_keys": {"key": "ssh-rsa "
|
||||||
|
"AAAAB3NzaC1yc2EAAAADAQABAAABA"
|
||||||
|
"QDf7kQHq7zvBod3yIZs0tB/AOOZz5pab7qt/h"
|
||||||
|
"78VF7yi6qTsFdUnQxRue43R/75wa9EEyokgYR"
|
||||||
|
"LKIN+Jq2A5tXNMcK+rNOCzLJFtioAwEl+S6VL"
|
||||||
|
"G9jfkbUv++7zoSMOsanNmEDvG0B79MpyECFCl"
|
||||||
|
"th2DsdE4MQypify35U5ri5Qi7E6PEYAsU65LF"
|
||||||
|
"MG2boeCIB29BEooE6AgPr2DuJeJ+2uw+YScF9"
|
||||||
|
"FV3og4Wyz5zipPVh8YpVev6dlg0tRWUrCtZF9"
|
||||||
|
"IODpCTrT3vsPRG3xz7CppR+vGi/1gLXHtJCRj"
|
||||||
|
"frHwkY6cXyhypNmkU99K/wMqSv30vsDwdnsQ1"
|
||||||
|
"q3YhLarMHB Generated by Nova\n",
|
||||||
|
"name": "windows"},
|
||||||
|
"network_config": {"content_path": "network",
|
||||||
|
'debian_config': 'iface eth0 inet static'
|
||||||
|
'address 10.11.12.13'
|
||||||
|
'broadcast 0.0.0.0'
|
||||||
|
'netmask 255.255.255.255'
|
||||||
|
'gateway 1.2.3.4'
|
||||||
|
'dns-nameserver 8.8.8.8'}}
|
15
cloudbaseinit/tests/metadata/services/__init__.py
Normal file
15
cloudbaseinit/tests/metadata/services/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
@ -0,0 +1,84 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
_win32com_mock = mock.MagicMock()
|
||||||
|
_ctypes_mock = mock.MagicMock()
|
||||||
|
_ctypes_util_mock = mock.MagicMock()
|
||||||
|
_win32com_client_mock = mock.MagicMock()
|
||||||
|
_pywintypes_mock = mock.MagicMock()
|
||||||
|
_mock_dict = {'win32com': _win32com_mock,
|
||||||
|
'ctypes': _ctypes_mock,
|
||||||
|
'ctypes.util': _ctypes_util_mock,
|
||||||
|
'win32com.client': _win32com_client_mock,
|
||||||
|
'pywintypes': _pywintypes_mock}
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigDriveServiceTest(unittest.TestCase):
|
||||||
|
@mock.patch.dict(sys.modules, _mock_dict)
|
||||||
|
def setUp(self):
|
||||||
|
configdrive = importlib.import_module('cloudbaseinit.metadata.services'
|
||||||
|
'.configdrive.configdrive')
|
||||||
|
self._config_drive = configdrive.ConfigDriveService()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
reload(sys)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.configdrive.manager.'
|
||||||
|
'ConfigDriveManager.get_config_drive_files')
|
||||||
|
@mock.patch('tempfile.gettempdir')
|
||||||
|
@mock.patch('os.path.join')
|
||||||
|
def test_load(self, mock_join, mock_gettempdir,
|
||||||
|
mock_get_config_drive_files):
|
||||||
|
uuid.uuid4 = mock.MagicMock()
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
fake_path_found = os.path.join(fake_path, 'found')
|
||||||
|
uuid.uuid4.return_value = 'random'
|
||||||
|
mock_get_config_drive_files.return_value = fake_path_found
|
||||||
|
mock_join.return_value = fake_path
|
||||||
|
response = self._config_drive.load()
|
||||||
|
mock_join.assert_called_with(mock_gettempdir(), 'random')
|
||||||
|
mock_get_config_drive_files.assert_called_once_with(
|
||||||
|
fake_path, CONF.config_drive_raw_hhd, CONF.config_drive_cdrom)
|
||||||
|
self.assertEqual(self._config_drive._metadata_path, fake_path)
|
||||||
|
self.assertEqual(response, fake_path_found)
|
||||||
|
|
||||||
|
@mock.patch('os.path.normpath')
|
||||||
|
@mock.patch('os.path.join')
|
||||||
|
def test_get_data(self, mock_join, mock_normpath):
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
with mock.patch('__builtin__.open',
|
||||||
|
mock.mock_open(read_data='fake data'), create=True):
|
||||||
|
response = self._config_drive._get_data(fake_path)
|
||||||
|
self.assertEqual(response, 'fake data')
|
||||||
|
mock_join.assert_called_with(
|
||||||
|
self._config_drive._metadata_path, fake_path)
|
||||||
|
|
||||||
|
@mock.patch('shutil.rmtree')
|
||||||
|
def test_cleanup(self, mock_rmtree):
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
self._config_drive._metadata_path = fake_path
|
||||||
|
self._config_drive.cleanup()
|
||||||
|
self.assertEqual(self._config_drive._metadata_path, None)
|
144
cloudbaseinit/tests/metadata/services/test_ec2service.py
Normal file
144
cloudbaseinit/tests/metadata/services/test_ec2service.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.metadata.services import ec2service
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class Ec2ServiceTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._ec2service = ec2service.EC2Service()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'.get_meta_data')
|
||||||
|
def _test_load(self, mock_get_meta_data, side_effect):
|
||||||
|
mock_get_meta_data.side_effect = [side_effect]
|
||||||
|
response = self._ec2service.load()
|
||||||
|
mock_get_meta_data.assert_called_once_with('openstack')
|
||||||
|
if side_effect is Exception:
|
||||||
|
self.assertFalse(response)
|
||||||
|
else:
|
||||||
|
self.assertTrue(response)
|
||||||
|
|
||||||
|
def test_load_exception(self):
|
||||||
|
self._test_load(side_effect=Exception)
|
||||||
|
|
||||||
|
def test_load(self):
|
||||||
|
self._test_load(side_effect='fake data')
|
||||||
|
|
||||||
|
@mock.patch('posixpath.join')
|
||||||
|
@mock.patch('urllib2.Request')
|
||||||
|
@mock.patch('urllib2.urlopen')
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'._load_public_keys')
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'._check_EC2')
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'._get_EC2_value')
|
||||||
|
def _test_get_data(self, mock_get_EC2_value, mock_check_EC2,
|
||||||
|
mock_load_public_keys, mock_urlopen,
|
||||||
|
mock_Request, mock_join, check_ec2, data_type):
|
||||||
|
mock_path = mock.MagicMock()
|
||||||
|
mock_req = mock.MagicMock()
|
||||||
|
mock_response = mock.MagicMock()
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
mock_join.return_value = fake_path
|
||||||
|
mock_check_EC2.return_value = check_ec2
|
||||||
|
mock_Request.return_value = mock_req
|
||||||
|
mock_urlopen.return_value = mock_response
|
||||||
|
mock_response.read.return_value = 'fake data'
|
||||||
|
mock_path.endswith.return_value = data_type
|
||||||
|
|
||||||
|
if check_ec2 is None:
|
||||||
|
self.assertRaises(Exception, self._ec2service._get_data,
|
||||||
|
mock_path)
|
||||||
|
|
||||||
|
elif data_type is 'meta_data.json':
|
||||||
|
response = self._ec2service._get_data(mock_path)
|
||||||
|
print response
|
||||||
|
for key in ec2service.ec2nodes:
|
||||||
|
mock_get_EC2_value.assert_called_with(key)
|
||||||
|
mock_load_public_keys.assert_called_with()
|
||||||
|
|
||||||
|
elif data_type is 'user_data':
|
||||||
|
response = self._ec2service._get_data(mock_path)
|
||||||
|
mock_join.assert_called_with(CONF.ec2_metadata_base_url,
|
||||||
|
'user-data')
|
||||||
|
mock_Request.assert_called_once_with(fake_path)
|
||||||
|
mock_urlopen.assert_called_once_with(mock_req)
|
||||||
|
mock_response.read.assert_called_once_with()
|
||||||
|
self.assertEqual(response, 'fake data')
|
||||||
|
|
||||||
|
def test_get_data_metadata_json(self):
|
||||||
|
self._test_get_data(check_ec2=True, data_type='meta_data.json')
|
||||||
|
|
||||||
|
def test_get_data_user_data(self):
|
||||||
|
self._test_get_data(check_ec2=True, data_type='user_data')
|
||||||
|
|
||||||
|
def test_get_data_no_EC2(self):
|
||||||
|
self._test_get_data(check_ec2=None, data_type=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'._get_EC2_value')
|
||||||
|
def _test_check_EC2(self, mock_get_EC2_value, side_effect):
|
||||||
|
mock_get_EC2_value.side_effect = [side_effect]
|
||||||
|
response = self._ec2service._check_EC2()
|
||||||
|
if side_effect is Exception:
|
||||||
|
self.assertFalse(response)
|
||||||
|
else:
|
||||||
|
self.assertTrue(response)
|
||||||
|
|
||||||
|
def test_check_EC2_Exception(self):
|
||||||
|
self._test_check_EC2(side_effect=Exception)
|
||||||
|
|
||||||
|
def test_check_EC2(self):
|
||||||
|
self._test_check_EC2(side_effect='fake value')
|
||||||
|
|
||||||
|
@mock.patch('posixpath.join')
|
||||||
|
@mock.patch('urllib2.Request')
|
||||||
|
@mock.patch('urllib2.urlopen')
|
||||||
|
def test_get_EC2_value(self, mock_urlopen, mock_Request, mock_join):
|
||||||
|
mock_key = mock.MagicMock()
|
||||||
|
mock_response = mock.MagicMock()
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
mock_join.return_value = fake_path
|
||||||
|
mock_Request.return_value = 'fake req'
|
||||||
|
mock_urlopen.return_value = mock_response
|
||||||
|
mock_response.read.return_value = 'fake data'
|
||||||
|
response = self._ec2service._get_EC2_value(mock_key)
|
||||||
|
mock_join.assert_called_with(CONF.ec2_metadata_base_url,
|
||||||
|
'meta-data', mock_key)
|
||||||
|
mock_Request.assert_called_once_with(fake_path)
|
||||||
|
mock_urlopen.assert_called_once_with('fake req')
|
||||||
|
mock_response.read.assert_called_once_with()
|
||||||
|
self.assertEqual(response, 'fake data')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.ec2service.EC2Service'
|
||||||
|
'._get_EC2_value')
|
||||||
|
def test_load_public_keys(self, mock_get_EC2_value):
|
||||||
|
data = {}
|
||||||
|
key_list = mock.MagicMock()
|
||||||
|
mock_get_EC2_value.return_value = key_list
|
||||||
|
self._ec2service._load_public_keys(data)
|
||||||
|
mock_get_EC2_value.assert_called_with('public-keys/')
|
||||||
|
self.assertEqual(data['public_keys'], {})
|
156
cloudbaseinit/tests/metadata/services/test_httpservice.py
Normal file
156
cloudbaseinit/tests/metadata/services/test_httpservice.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import urllib2
|
||||||
|
|
||||||
|
from cloudbaseinit.metadata.services import base
|
||||||
|
from cloudbaseinit.metadata.services import httpservice
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServiceTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
CONF.set_override('retry_count_interval', 0)
|
||||||
|
self._httpservice = httpservice.HttpService()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('urlparse.urlparse')
|
||||||
|
def _test_check_metadata_ip_route(self, mock_urlparse, mock_get_os_utils,
|
||||||
|
side_effect):
|
||||||
|
mock_utils = mock.MagicMock()
|
||||||
|
mock_split = mock.MagicMock()
|
||||||
|
mock_get_os_utils.return_value = mock_utils
|
||||||
|
mock_utils.check_os_version.return_value = True
|
||||||
|
mock_urlparse().netloc.split.return_value = mock_split
|
||||||
|
mock_split[0].startswith.return_value = True
|
||||||
|
mock_utils.check_static_route_exists.return_value = False
|
||||||
|
mock_utils.get_default_gateway.return_value = (1, '0.0.0.0')
|
||||||
|
mock_utils.add_static_route.side_effect = [side_effect]
|
||||||
|
self._httpservice._check_metadata_ip_route()
|
||||||
|
mock_utils.check_os_version.assert_called_once_with(6, 0)
|
||||||
|
mock_urlparse.assert_called_with(CONF.metadata_base_url)
|
||||||
|
mock_split[0].startswith.assert_called_once_with("169.254.")
|
||||||
|
mock_utils.check_static_route_exists.assert_called_once_with(
|
||||||
|
mock_split[0])
|
||||||
|
mock_utils.get_default_gateway.assert_called_once_with()
|
||||||
|
mock_utils.add_static_route.assert_called_once_with(
|
||||||
|
mock_split[0], "255.255.255.255", '0.0.0.0', 1, 10)
|
||||||
|
|
||||||
|
def test_test_check_metadata_ip_route(self):
|
||||||
|
self._test_check_metadata_ip_route(side_effect=None)
|
||||||
|
|
||||||
|
def test_test_check_metadata_ip_route_fail(self):
|
||||||
|
self._test_check_metadata_ip_route(side_effect=Exception)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.httpservice.HttpService'
|
||||||
|
'._check_metadata_ip_route')
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.httpservice.HttpService'
|
||||||
|
'.get_meta_data')
|
||||||
|
def _test_load(self, mock_get_meta_data, mock_check_metadata_ip_route,
|
||||||
|
side_effect):
|
||||||
|
mock_get_meta_data.side_effect = [side_effect]
|
||||||
|
response = self._httpservice.load()
|
||||||
|
mock_check_metadata_ip_route.assert_called_once_with()
|
||||||
|
mock_get_meta_data.assert_called_once_with('openstack')
|
||||||
|
if side_effect:
|
||||||
|
self.assertEqual(response, False)
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, True)
|
||||||
|
|
||||||
|
def test_load(self):
|
||||||
|
self._test_load(side_effect=None)
|
||||||
|
|
||||||
|
def test_load_exception(self):
|
||||||
|
self._test_load(side_effect=Exception)
|
||||||
|
|
||||||
|
@mock.patch('urllib2.urlopen')
|
||||||
|
def _test_get_response(self, mock_urlopen, side_effect):
|
||||||
|
mock_req = mock.MagicMock
|
||||||
|
if side_effect and side_effect.code is 404:
|
||||||
|
mock_urlopen.side_effect = [side_effect]
|
||||||
|
self.assertRaises(base.NotExistingMetadataException,
|
||||||
|
self._httpservice._get_response,
|
||||||
|
mock_req)
|
||||||
|
elif side_effect and side_effect.code:
|
||||||
|
mock_urlopen.side_effect = [side_effect]
|
||||||
|
self.assertRaises(Exception, self._httpservice._get_response,
|
||||||
|
mock_req)
|
||||||
|
else:
|
||||||
|
mock_urlopen.return_value = 'fake url'
|
||||||
|
response = self._httpservice._get_response(mock_req)
|
||||||
|
self.assertEqual(response, 'fake url')
|
||||||
|
|
||||||
|
def test_get_response_fail_HTTPError(self):
|
||||||
|
error = urllib2.HTTPError("http://169.254.169.254/", 404,
|
||||||
|
'test error 404', {}, None)
|
||||||
|
self._test_get_response(side_effect=error)
|
||||||
|
|
||||||
|
def test_get_response_fail_other_exception(self):
|
||||||
|
error = urllib2.HTTPError("http://169.254.169.254/", 409,
|
||||||
|
'test error 409', {}, None)
|
||||||
|
self._test_get_response(side_effect=error)
|
||||||
|
|
||||||
|
def test_get_response(self):
|
||||||
|
self._test_get_response(side_effect=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.httpservice.HttpService'
|
||||||
|
'._get_response')
|
||||||
|
@mock.patch('posixpath.join')
|
||||||
|
@mock.patch('urllib2.Request')
|
||||||
|
def test_get_data(self, mock_Request, mock_posix_join,
|
||||||
|
mock_get_response):
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
mock_data = mock.MagicMock()
|
||||||
|
mock_norm_path = mock.MagicMock()
|
||||||
|
mock_req = mock.MagicMock()
|
||||||
|
mock_get_response.return_value = mock_data
|
||||||
|
mock_posix_join.return_value = mock_norm_path
|
||||||
|
mock_Request.return_value = mock_req
|
||||||
|
|
||||||
|
response = self._httpservice._get_data(fake_path)
|
||||||
|
|
||||||
|
mock_posix_join.assert_called_with(CONF.metadata_base_url, fake_path)
|
||||||
|
mock_Request.assert_called_once_with(mock_norm_path)
|
||||||
|
mock_get_response.assert_called_once_with(mock_req)
|
||||||
|
self.assertEqual(response, mock_data.read())
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.metadata.services.httpservice.HttpService'
|
||||||
|
'._get_response')
|
||||||
|
@mock.patch('posixpath.join')
|
||||||
|
@mock.patch('urllib2.Request')
|
||||||
|
def test_post_data(self, mock_Request, mock_posix_join,
|
||||||
|
mock_get_response):
|
||||||
|
fake_path = os.path.join('fake', 'path')
|
||||||
|
fake_data = 'fake data'
|
||||||
|
mock_data = mock.MagicMock()
|
||||||
|
mock_norm_path = mock.MagicMock()
|
||||||
|
mock_req = mock.MagicMock()
|
||||||
|
mock_get_response.return_value = mock_data
|
||||||
|
mock_posix_join.return_value = mock_norm_path
|
||||||
|
mock_Request.return_value = mock_req
|
||||||
|
|
||||||
|
response = self._httpservice._post_data(fake_path, fake_data)
|
||||||
|
|
||||||
|
mock_posix_join.assert_called_with(CONF.metadata_base_url,
|
||||||
|
fake_path)
|
||||||
|
mock_Request.assert_called_once_with(mock_norm_path, data=fake_data)
|
||||||
|
mock_get_response.assert_called_once_with(mock_req)
|
||||||
|
self.assertEqual(response, True)
|
41
cloudbaseinit/tests/metadata/test_factory.py
Normal file
41
cloudbaseinit/tests/metadata/test_factory.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.metadata import factory
|
||||||
|
|
||||||
|
|
||||||
|
class MetadataServiceFactoryTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self._factory = factory.MetadataServiceFactory()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.utils.classloader.ClassLoader.load_class')
|
||||||
|
def _test_get_metadata_service(self, mock_load_class, ret_value):
|
||||||
|
mock_load_class.side_effect = ret_value
|
||||||
|
if ret_value is Exception:
|
||||||
|
self.assertRaises(Exception, self._factory.get_metadata_service)
|
||||||
|
else:
|
||||||
|
response = self._factory.get_metadata_service()
|
||||||
|
self.assertEqual(response, mock_load_class()())
|
||||||
|
|
||||||
|
def test_get_metadata_service(self):
|
||||||
|
m = mock.MagicMock()
|
||||||
|
self._test_get_metadata_service(ret_value=m)
|
||||||
|
|
||||||
|
def test_get_metadata_service_exception(self):
|
||||||
|
self._test_get_metadata_service(ret_value=Exception)
|
15
cloudbaseinit/tests/osutils/__init__.py
Normal file
15
cloudbaseinit/tests/osutils/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
43
cloudbaseinit/tests/osutils/test_factory.py
Normal file
43
cloudbaseinit/tests/osutils/test_factory.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.osutils import factory
|
||||||
|
|
||||||
|
|
||||||
|
class OSUtilsFactory(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self._factory = factory.OSUtilsFactory()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.utils.classloader.ClassLoader.load_class')
|
||||||
|
def _test_get_os_utils(self, mock_load_class, fake_name):
|
||||||
|
os.name = fake_name
|
||||||
|
self._factory.get_os_utils()
|
||||||
|
if fake_name == 'nt':
|
||||||
|
mock_load_class.assert_called_with(
|
||||||
|
'cloudbaseinit.osutils.windows.WindowsUtils')
|
||||||
|
elif fake_name == 'posix':
|
||||||
|
mock_load_class.assert_called_with(
|
||||||
|
'cloudbaseinit.osutils.posix.PosixUtils')
|
||||||
|
|
||||||
|
def test_get_os_utils_windows(self):
|
||||||
|
self._test_get_os_utils(fake_name='nt')
|
||||||
|
|
||||||
|
def test_get_os_utils_posix(self):
|
||||||
|
self._test_get_os_utils(fake_name='posix')
|
975
cloudbaseinit/tests/osutils/test_windows.py
Normal file
975
cloudbaseinit/tests/osutils/test_windows.py
Normal file
@ -0,0 +1,975 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import mock
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import _winreg
|
||||||
|
import win32process
|
||||||
|
import win32security
|
||||||
|
import wmi
|
||||||
|
|
||||||
|
from ctypes import windll
|
||||||
|
from ctypes import wintypes
|
||||||
|
from cloudbaseinit.osutils import windows as windows_utils
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "win32", "requires Windows")
|
||||||
|
class WindowsUtilsTest(unittest.TestCase):
|
||||||
|
'''Tests for the windows utils class'''
|
||||||
|
|
||||||
|
_CONFIG_NAME = 'FakeConfig'
|
||||||
|
_DESTINATION = '192.168.192.168'
|
||||||
|
_GATEWAY = '10.7.1.1'
|
||||||
|
_NETMASK = '255.255.255.0'
|
||||||
|
_PASSWORD = 'Passw0rd'
|
||||||
|
_SECTION = 'fake_section'
|
||||||
|
_USERNAME = 'Admin'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._winutils = windows_utils.WindowsUtils()
|
||||||
|
self._conn = mock.MagicMock()
|
||||||
|
|
||||||
|
def test_enable_shutdown_privilege(self):
|
||||||
|
fake_process = mock.MagicMock()
|
||||||
|
fake_token = True
|
||||||
|
private_LUID = 'fakeid'
|
||||||
|
win32process.GetCurrentProcess = mock.MagicMock(
|
||||||
|
return_value=fake_process)
|
||||||
|
win32security.OpenProcessToken = mock.MagicMock(
|
||||||
|
return_value=fake_token)
|
||||||
|
win32security.LookupPrivilegeValue = mock.MagicMock(
|
||||||
|
return_value=private_LUID)
|
||||||
|
win32security.AdjustTokenPrivileges = mock.MagicMock()
|
||||||
|
self._winutils._enable_shutdown_privilege()
|
||||||
|
privilege = [(private_LUID, win32security.SE_PRIVILEGE_ENABLED)]
|
||||||
|
win32security.AdjustTokenPrivileges.assert_called_with(
|
||||||
|
fake_token,
|
||||||
|
False,
|
||||||
|
privilege)
|
||||||
|
|
||||||
|
win32security.OpenProcessToken.assert_called_with(
|
||||||
|
fake_process,
|
||||||
|
win32security.TOKEN_ADJUST_PRIVILEGES |
|
||||||
|
win32security.TOKEN_QUERY)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._enable_shutdown_privilege')
|
||||||
|
def _test_reboot(self, mock_enable_shutdown_privilege, ret_value):
|
||||||
|
windll.advapi32.InitiateSystemShutdownW = mock.MagicMock(
|
||||||
|
return_value=ret_value)
|
||||||
|
|
||||||
|
if not ret_value:
|
||||||
|
self.assertRaises(Exception, self._winutils.reboot)
|
||||||
|
else:
|
||||||
|
self._winutils.reboot()
|
||||||
|
|
||||||
|
windll.advapi32.InitiateSystemShutdownW.assert_called_with(
|
||||||
|
0,
|
||||||
|
"Cloudbase-Init reboot",
|
||||||
|
0, True, True)
|
||||||
|
|
||||||
|
def test_reboot(self):
|
||||||
|
self._test_reboot(ret_value=True)
|
||||||
|
|
||||||
|
def test_reboot_failed(self):
|
||||||
|
self._test_reboot(ret_value=None)
|
||||||
|
|
||||||
|
@mock.patch('wmi.WMI')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._sanitize_wmi_input')
|
||||||
|
def _test_get_user_wmi_object(self, mock_sanitize_wmi_input, mock_WMI,
|
||||||
|
returnvalue):
|
||||||
|
mock_WMI.return_value = self._conn
|
||||||
|
mock_sanitize_wmi_input.return_value = self._USERNAME
|
||||||
|
self._conn.query.return_value = returnvalue
|
||||||
|
response = self._winutils._get_user_wmi_object(self._USERNAME)
|
||||||
|
self._conn.query.assert_called_with("SELECT * FROM Win32_Account "
|
||||||
|
"where name = \'%s\'" %
|
||||||
|
self._USERNAME)
|
||||||
|
mock_sanitize_wmi_input.assert_called_with(self._USERNAME)
|
||||||
|
mock_WMI.assert_called_with(moniker='//./root/cimv2')
|
||||||
|
if returnvalue:
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
else:
|
||||||
|
self.assertTrue(response is None)
|
||||||
|
|
||||||
|
def test_get_user_wmi_object(self):
|
||||||
|
caption = 'fake'
|
||||||
|
self._test_get_user_wmi_object(returnvalue=caption)
|
||||||
|
|
||||||
|
def test_no_user_wmi_object(self):
|
||||||
|
empty_caption = ''
|
||||||
|
self._test_get_user_wmi_object(returnvalue=empty_caption)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_user_wmi_object')
|
||||||
|
def _test_user_exists(self, mock_get_user_wmi_object, returnvalue):
|
||||||
|
mock_get_user_wmi_object.return_value = returnvalue
|
||||||
|
response = self._winutils.user_exists(returnvalue)
|
||||||
|
mock_get_user_wmi_object.assert_called_with(returnvalue)
|
||||||
|
if returnvalue:
|
||||||
|
self.assertTrue(response)
|
||||||
|
else:
|
||||||
|
self.assertFalse(response)
|
||||||
|
|
||||||
|
def test_user_exists(self):
|
||||||
|
self._test_user_exists(returnvalue=self._USERNAME)
|
||||||
|
|
||||||
|
def test_username_does_not_exist(self):
|
||||||
|
self._test_user_exists(returnvalue=None)
|
||||||
|
|
||||||
|
def test_sanitize_wmi_input(self):
|
||||||
|
unsanitised = ' \' '
|
||||||
|
response = self._winutils._sanitize_wmi_input(unsanitised)
|
||||||
|
sanitised = ' \'\' '
|
||||||
|
self.assertEqual(response, sanitised)
|
||||||
|
|
||||||
|
def test_sanitize_shell_input(self):
|
||||||
|
unsanitised = ' " '
|
||||||
|
response = self._winutils.sanitize_shell_input(unsanitised)
|
||||||
|
sanitised = ' \\" '
|
||||||
|
self.assertEqual(response, sanitised)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._set_user_password_expiration')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'.execute_process')
|
||||||
|
def _test_create_or_change_user(self, mock_execute_process,
|
||||||
|
mock_set_user_password_expiration,
|
||||||
|
create, password_expires, ret_value=0):
|
||||||
|
args = ['NET', 'USER', self._USERNAME, self._PASSWORD]
|
||||||
|
if create:
|
||||||
|
args.append('/ADD')
|
||||||
|
mock_execute_process.return_value = (None, None, ret_value)
|
||||||
|
if not ret_value:
|
||||||
|
self._winutils._create_or_change_user(self._USERNAME,
|
||||||
|
self._PASSWORD, create,
|
||||||
|
password_expires)
|
||||||
|
mock_set_user_password_expiration.assert_called_with(
|
||||||
|
self._USERNAME, password_expires)
|
||||||
|
else:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils._create_or_change_user,
|
||||||
|
self._USERNAME, self._PASSWORD, create, password_expires)
|
||||||
|
mock_execute_process.assert_called_with(args)
|
||||||
|
|
||||||
|
def test_create_user_and_add_password_expire_true(self):
|
||||||
|
self._test_create_or_change_user(create=True, password_expires=True)
|
||||||
|
|
||||||
|
def test_create_user_and_add_password_expire_false(self):
|
||||||
|
self._test_create_or_change_user(create=True, password_expires=False)
|
||||||
|
|
||||||
|
def test_add_password_expire_true(self):
|
||||||
|
self._test_create_or_change_user(create=False, password_expires=True)
|
||||||
|
|
||||||
|
def test_add_password_expire_false(self):
|
||||||
|
self._test_create_or_change_user(create=False, password_expires=False)
|
||||||
|
|
||||||
|
def test_create_user_and_add_password_expire_true_with_ret_value(self):
|
||||||
|
self._test_create_or_change_user(create=True, password_expires=True,
|
||||||
|
ret_value=1)
|
||||||
|
|
||||||
|
def test_create_user_and_add_password_expire_false_with_ret_value(self):
|
||||||
|
self._test_create_or_change_user(create=True,
|
||||||
|
password_expires=False, ret_value=1)
|
||||||
|
|
||||||
|
def test_add_password_expire_true_with_ret_value(self):
|
||||||
|
self._test_create_or_change_user(create=False,
|
||||||
|
password_expires=True, ret_value=1)
|
||||||
|
|
||||||
|
def test_add_password_expire_false_with_ret_value(self):
|
||||||
|
self._test_create_or_change_user(create=False,
|
||||||
|
password_expires=False, ret_value=1)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_user_wmi_object')
|
||||||
|
def _test_set_user_password_expiration(self, mock_get_user_wmi_object,
|
||||||
|
fake_obj):
|
||||||
|
mock_get_user_wmi_object.return_value = fake_obj
|
||||||
|
response = self._winutils._set_user_password_expiration(
|
||||||
|
self._USERNAME, True)
|
||||||
|
if fake_obj:
|
||||||
|
self.assertTrue(fake_obj.PasswordExpires)
|
||||||
|
self.assertTrue(response)
|
||||||
|
else:
|
||||||
|
self.assertFalse(response)
|
||||||
|
|
||||||
|
def test_set_password_expiration(self):
|
||||||
|
fake = mock.Mock()
|
||||||
|
self._test_set_user_password_expiration(fake_obj=fake)
|
||||||
|
|
||||||
|
def test_set_password_expiration_no_object(self):
|
||||||
|
self._test_set_user_password_expiration(fake_obj=None)
|
||||||
|
|
||||||
|
def _test_get_user_sid_and_domain(self, ret_val):
|
||||||
|
cbSid = mock.Mock()
|
||||||
|
sid = mock.Mock()
|
||||||
|
size = 1024
|
||||||
|
cchReferencedDomainName = mock.Mock()
|
||||||
|
domainName = mock.Mock()
|
||||||
|
sidNameUse = mock.Mock()
|
||||||
|
|
||||||
|
ctypes.create_string_buffer = mock.MagicMock(return_value=sid)
|
||||||
|
ctypes.sizeof = mock.MagicMock(return_value=size)
|
||||||
|
wintypes.DWORD = mock.MagicMock(return_value=cchReferencedDomainName)
|
||||||
|
ctypes.create_unicode_buffer = mock.MagicMock(return_value=domainName)
|
||||||
|
|
||||||
|
ctypes.byref = mock.MagicMock()
|
||||||
|
|
||||||
|
windll.advapi32.LookupAccountNameW = mock.MagicMock(
|
||||||
|
return_value=ret_val)
|
||||||
|
if ret_val is None:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils._get_user_sid_and_domain,
|
||||||
|
self._USERNAME)
|
||||||
|
else:
|
||||||
|
response = self._winutils._get_user_sid_and_domain(self._USERNAME)
|
||||||
|
|
||||||
|
windll.advapi32.LookupAccountNameW.assert_called_with(
|
||||||
|
0, unicode(self._USERNAME), sid, ctypes.byref(cbSid),
|
||||||
|
domainName, ctypes.byref(cchReferencedDomainName),
|
||||||
|
ctypes.byref(sidNameUse))
|
||||||
|
self.assertEqual(response, (sid, domainName.value))
|
||||||
|
|
||||||
|
def test_get_user_sid_and_domain(self):
|
||||||
|
fake_obj = mock.Mock()
|
||||||
|
self._test_get_user_sid_and_domain(ret_val=fake_obj)
|
||||||
|
|
||||||
|
def test_get_user_sid_and_domain_no_return_value(self):
|
||||||
|
self._test_get_user_sid_and_domain(ret_val=None)
|
||||||
|
|
||||||
|
def _test_add_user_to_local_group(self, ret_value):
|
||||||
|
windows_utils.Win32_LOCALGROUP_MEMBERS_INFO_3 = mock.MagicMock()
|
||||||
|
lmi = windows_utils.Win32_LOCALGROUP_MEMBERS_INFO_3()
|
||||||
|
group_name = 'Admins'
|
||||||
|
|
||||||
|
windll.netapi32.NetLocalGroupAddMembers = mock.MagicMock(
|
||||||
|
return_value=ret_value)
|
||||||
|
|
||||||
|
if ret_value is not 0:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.add_user_to_local_group,
|
||||||
|
self._USERNAME, group_name)
|
||||||
|
else:
|
||||||
|
ctypes.addressof = mock.MagicMock()
|
||||||
|
self._winutils.add_user_to_local_group(self._USERNAME,
|
||||||
|
group_name)
|
||||||
|
windll.netapi32.NetLocalGroupAddMembers.assert_called_with(
|
||||||
|
0, unicode(group_name), 3, ctypes.addressof(lmi), 1)
|
||||||
|
self.assertEqual(lmi.lgrmi3_domainandname, unicode(self._USERNAME))
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_no_error(self):
|
||||||
|
self._test_add_user_to_local_group(ret_value=0)
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_not_found(self):
|
||||||
|
self._test_add_user_to_local_group(
|
||||||
|
ret_value=self._winutils.NERR_GroupNotFound)
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_access_denied(self):
|
||||||
|
self._test_add_user_to_local_group(
|
||||||
|
ret_value=self._winutils.ERROR_ACCESS_DENIED)
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_no_member(self):
|
||||||
|
self._test_add_user_to_local_group(
|
||||||
|
ret_value=self._winutils.ERROR_NO_SUCH_MEMBER)
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_member_in_alias(self):
|
||||||
|
self._test_add_user_to_local_group(
|
||||||
|
ret_value=self._winutils.ERROR_MEMBER_IN_ALIAS)
|
||||||
|
|
||||||
|
def test_add_user_to_local_group_invalid_member(self):
|
||||||
|
self._test_add_user_to_local_group(
|
||||||
|
ret_value=self._winutils.ERROR_INVALID_MEMBER)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_user_wmi_object')
|
||||||
|
def _test_get_user_sid(self, mock_get_user_wmi_object, fail):
|
||||||
|
r = mock.Mock()
|
||||||
|
if not fail:
|
||||||
|
mock_get_user_wmi_object.return_value = None
|
||||||
|
response = self._winutils.get_user_sid(self._USERNAME)
|
||||||
|
self.assertTrue(response is None)
|
||||||
|
else:
|
||||||
|
mock_get_user_wmi_object.return_value = r
|
||||||
|
response = self._winutils.get_user_sid(self._USERNAME)
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
mock_get_user_wmi_object.assert_called_with(self._USERNAME)
|
||||||
|
|
||||||
|
def test_get_user_sid(self):
|
||||||
|
self._test_get_user_sid(fail=False)
|
||||||
|
|
||||||
|
def test_get_user_sid_fail(self):
|
||||||
|
self._test_get_user_sid(fail=True)
|
||||||
|
|
||||||
|
def _test_create_user_logon_session(self, logon, loaduser,
|
||||||
|
load_profile=True):
|
||||||
|
wintypes.HANDLE = mock.MagicMock()
|
||||||
|
pi = windows_utils.Win32_PROFILEINFO()
|
||||||
|
windll.advapi32.LogonUserW = mock.MagicMock(return_value=logon)
|
||||||
|
ctypes.byref = mock.MagicMock()
|
||||||
|
|
||||||
|
if not logon:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.create_user_logon_session,
|
||||||
|
self._USERNAME, self._PASSWORD, domain='.',
|
||||||
|
load_profile=load_profile)
|
||||||
|
|
||||||
|
elif load_profile and not loaduser:
|
||||||
|
windll.userenv.LoadUserProfileW = mock.MagicMock(
|
||||||
|
return_value=None)
|
||||||
|
windll.kernel32.CloseHandle = mock.MagicMock(return_value=None)
|
||||||
|
self.assertRaises(Exception,
|
||||||
|
self._winutils.create_user_logon_session,
|
||||||
|
self._USERNAME, self._PASSWORD, domain='.',
|
||||||
|
load_profile=load_profile)
|
||||||
|
|
||||||
|
windll.userenv.LoadUserProfileW.assert_called_with(
|
||||||
|
wintypes.HANDLE(), ctypes.byref(pi))
|
||||||
|
windll.kernel32.CloseHandle.assert_called_with(wintypes.HANDLE())
|
||||||
|
|
||||||
|
elif not load_profile:
|
||||||
|
response = self._winutils.create_user_logon_session(
|
||||||
|
self._USERNAME, self._PASSWORD, domain='.',
|
||||||
|
load_profile=load_profile)
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
else:
|
||||||
|
size = 1024
|
||||||
|
windll.userenv.LoadUserProfileW = mock.MagicMock()
|
||||||
|
ctypes.sizeof = mock.MagicMock(return_value=size)
|
||||||
|
windows_utils.Win32_PROFILEINFO = mock.MagicMock(
|
||||||
|
return_value=loaduser)
|
||||||
|
|
||||||
|
response = self._winutils.create_user_logon_session(
|
||||||
|
self._USERNAME, self._PASSWORD, domain='.',
|
||||||
|
load_profile=load_profile)
|
||||||
|
|
||||||
|
windll.userenv.LoadUserProfileW.assert_called_with(
|
||||||
|
wintypes.HANDLE(), ctypes.byref(pi))
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_fail_load_false(self):
|
||||||
|
self._test_create_user_logon_session(0, 0, True)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_fail_load_true(self):
|
||||||
|
self._test_create_user_logon_session(0, 0, False)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_load_true(self):
|
||||||
|
m = mock.Mock()
|
||||||
|
n = mock.Mock()
|
||||||
|
self._test_create_user_logon_session(m, n, True)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_load_false(self):
|
||||||
|
m = mock.Mock()
|
||||||
|
n = mock.Mock()
|
||||||
|
self._test_create_user_logon_session(m, n, False)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_no_load_true(self):
|
||||||
|
m = mock.Mock()
|
||||||
|
self._test_create_user_logon_session(m, None, True)
|
||||||
|
|
||||||
|
def test_create_user_logon_session_no_load_false(self):
|
||||||
|
m = mock.Mock()
|
||||||
|
self._test_create_user_logon_session(m, None, False)
|
||||||
|
|
||||||
|
def test_close_user_logon_session(self):
|
||||||
|
token = mock.Mock()
|
||||||
|
windll.kernel32.CloseHandle = mock.MagicMock()
|
||||||
|
self._winutils.close_user_logon_session(token)
|
||||||
|
windll.kernel32.CloseHandle.assert_called_with(token)
|
||||||
|
|
||||||
|
@mock.patch('ctypes.windll.kernel32.SetComputerNameExW')
|
||||||
|
def _test_set_host_name(self, mock_SetComputerNameExW, ret_value):
|
||||||
|
wmi.WMI = mock.MagicMock(return_value=self._conn)
|
||||||
|
mock_SetComputerNameExW.return_value = ret_value
|
||||||
|
if not ret_value:
|
||||||
|
self.assertRaises(Exception, self._winutils.set_host_name,
|
||||||
|
'fake name')
|
||||||
|
else:
|
||||||
|
self._winutils.set_host_name('fake name')
|
||||||
|
mock_SetComputerNameExW.assert_called_with(
|
||||||
|
self._winutils.ComputerNamePhysicalDnsHostname,
|
||||||
|
unicode('fake name'))
|
||||||
|
|
||||||
|
def test_set_host_name(self):
|
||||||
|
self._test_set_host_name(ret_value='fake response')
|
||||||
|
|
||||||
|
def test_set_host_exception(self):
|
||||||
|
self._test_set_host_name(ret_value=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'.get_user_sid')
|
||||||
|
def _test_get_user_home(self, mock_get_user_sid, user_sid):
|
||||||
|
key = mock.MagicMock()
|
||||||
|
mock_get_user_sid.return_value = user_sid
|
||||||
|
_winreg.OpenKey = mock.MagicMock(return_value=key)
|
||||||
|
_winreg.QueryValueEx = mock.MagicMock()
|
||||||
|
response = self._winutils.get_user_home(self._USERNAME)
|
||||||
|
if user_sid:
|
||||||
|
mock_get_user_sid.assert_called_with(self._USERNAME)
|
||||||
|
_winreg.OpenKey.assert_called_with(
|
||||||
|
_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows '
|
||||||
|
'NT\\CurrentVersion\\ProfileList\\'
|
||||||
|
'%s' % mock_get_user_sid())
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
_winreg.QueryValueEx.assert_called_with(
|
||||||
|
_winreg.OpenKey().__enter__(), 'ProfileImagePath')
|
||||||
|
else:
|
||||||
|
self.assertTrue(response is None)
|
||||||
|
|
||||||
|
def test_get_user_home(self):
|
||||||
|
user = mock.MagicMock()
|
||||||
|
self._test_get_user_home(user_sid=user)
|
||||||
|
|
||||||
|
def test_get_user_home_fail(self):
|
||||||
|
self._test_get_user_home(user_sid=None)
|
||||||
|
|
||||||
|
@mock.patch('wmi.WMI')
|
||||||
|
def test_get_network_adapters(self, mock_WMI):
|
||||||
|
mock_WMI.return_value = self._conn
|
||||||
|
mock_response = mock.MagicMock()
|
||||||
|
self._conn.query.return_value = [mock_response]
|
||||||
|
response = self._winutils.get_network_adapters()
|
||||||
|
self._conn.query.assert_called_with(
|
||||||
|
'SELECT * FROM Win32_NetworkAdapter WHERE AdapterTypeId = 0 AND '
|
||||||
|
'PhysicalAdapter = True AND MACAddress IS NOT NULL')
|
||||||
|
self.assertEqual(response, [mock_response.Name])
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._sanitize_wmi_input')
|
||||||
|
def _test_set_static_network_config(self, mock_sanitize_wmi_input,
|
||||||
|
adapter, ret_val1=None,
|
||||||
|
ret_val2=None, ret_val3=None):
|
||||||
|
wmi.WMI = mock.MagicMock(return_value=self._conn)
|
||||||
|
address = '10.10.10.10'
|
||||||
|
adapter_name = 'adapter_name'
|
||||||
|
broadcast = '0.0.0.0'
|
||||||
|
dns_list = ['8.8.8.8']
|
||||||
|
|
||||||
|
if not adapter:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.set_static_network_config,
|
||||||
|
adapter_name, address, self._NETMASK,
|
||||||
|
broadcast, self._GATEWAY, dns_list)
|
||||||
|
else:
|
||||||
|
mock_sanitize_wmi_input.return_value = adapter_name
|
||||||
|
self._conn.query.return_value = adapter
|
||||||
|
adapter_config = adapter[0].associators()[0]
|
||||||
|
adapter_config.EnableStatic = mock.MagicMock(return_value=ret_val1)
|
||||||
|
adapter_config.SetGateways = mock.MagicMock(return_value=ret_val2)
|
||||||
|
adapter_config.SetDNSServerSearchOrder = mock.MagicMock(
|
||||||
|
return_value=ret_val3)
|
||||||
|
adapter.__len__ = mock.MagicMock(return_value=1)
|
||||||
|
if ret_val1[0] > 1:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.set_static_network_config,
|
||||||
|
adapter_name, address, self._NETMASK,
|
||||||
|
broadcast, self._GATEWAY, dns_list)
|
||||||
|
|
||||||
|
elif ret_val2[0] > 1:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.set_static_network_config,
|
||||||
|
adapter_name, address, self._NETMASK,
|
||||||
|
broadcast, self._GATEWAY, dns_list)
|
||||||
|
|
||||||
|
elif ret_val3[0] > 1:
|
||||||
|
self.assertRaises(
|
||||||
|
Exception, self._winutils.set_static_network_config,
|
||||||
|
adapter_name, address, self._NETMASK,
|
||||||
|
broadcast, self._GATEWAY, dns_list)
|
||||||
|
|
||||||
|
else:
|
||||||
|
response = self._winutils.set_static_network_config(
|
||||||
|
adapter_name, address, self._NETMASK,
|
||||||
|
broadcast, self._GATEWAY, dns_list)
|
||||||
|
if ret_val1[0] or ret_val2[0] or ret_val3[0] == 1:
|
||||||
|
self.assertTrue(response)
|
||||||
|
else:
|
||||||
|
self.assertFalse(response)
|
||||||
|
adapter_config.EnableStatic.assert_called_with(
|
||||||
|
[address], [self._NETMASK])
|
||||||
|
adapter_config.SetGateways.assert_called_with(
|
||||||
|
[self._GATEWAY], [1])
|
||||||
|
adapter_config.SetDNSServerSearchOrder.assert_called_with(
|
||||||
|
dns_list)
|
||||||
|
|
||||||
|
self._winutils._sanitize_wmi_input.assert_called_with(
|
||||||
|
adapter_name)
|
||||||
|
adapter[0].associators.assert_called_with(
|
||||||
|
wmi_result_class='Win32_NetworkAdapterConfiguration')
|
||||||
|
self._conn.query.assert_called_with(
|
||||||
|
'SELECT * FROM Win32_NetworkAdapter WHERE MACAddress IS '
|
||||||
|
'NOT NULL AND Name = \'%(adapter_name_san)s\'' %
|
||||||
|
{'adapter_name_san': adapter_name})
|
||||||
|
|
||||||
|
def test_set_static_network_config(self):
|
||||||
|
adapter = mock.MagicMock()
|
||||||
|
ret_val1 = (1,)
|
||||||
|
ret_val2 = (1,)
|
||||||
|
ret_val3 = (0,)
|
||||||
|
self._test_set_static_network_config(adapter=adapter,
|
||||||
|
ret_val1=ret_val1,
|
||||||
|
ret_val2=ret_val2,
|
||||||
|
ret_val3=ret_val3)
|
||||||
|
|
||||||
|
def test_set_static_network_config_query_fail(self):
|
||||||
|
self._test_set_static_network_config(adapter=None)
|
||||||
|
|
||||||
|
def test_set_static_network_config_cannot_set_ip(self):
|
||||||
|
adapter = mock.MagicMock()
|
||||||
|
ret_val1 = (2,)
|
||||||
|
self._test_set_static_network_config(adapter=adapter,
|
||||||
|
ret_val1=ret_val1)
|
||||||
|
|
||||||
|
def test_set_static_network_config_cannot_set_gateway(self):
|
||||||
|
adapter = mock.MagicMock()
|
||||||
|
ret_val1 = (1,)
|
||||||
|
ret_val2 = (2,)
|
||||||
|
self._test_set_static_network_config(adapter=adapter,
|
||||||
|
ret_val1=ret_val1,
|
||||||
|
ret_val2=ret_val2)
|
||||||
|
|
||||||
|
def test_set_static_network_config_cannot_set_DNS(self):
|
||||||
|
adapter = mock.MagicMock()
|
||||||
|
ret_val1 = (1,)
|
||||||
|
ret_val2 = (1,)
|
||||||
|
ret_val3 = (2,)
|
||||||
|
self._test_set_static_network_config(adapter=adapter,
|
||||||
|
ret_val1=ret_val1,
|
||||||
|
ret_val2=ret_val2,
|
||||||
|
ret_val3=ret_val3)
|
||||||
|
|
||||||
|
def test_set_static_network_config_no_reboot(self):
|
||||||
|
adapter = mock.MagicMock()
|
||||||
|
ret_val1 = (0,)
|
||||||
|
ret_val2 = (0,)
|
||||||
|
ret_val3 = (0,)
|
||||||
|
self._test_set_static_network_config(adapter=adapter,
|
||||||
|
ret_val1=ret_val1,
|
||||||
|
ret_val2=ret_val2,
|
||||||
|
ret_val3=ret_val3)
|
||||||
|
|
||||||
|
def _test_get_config_key_name(self, section):
|
||||||
|
response = self._winutils._get_config_key_name(section)
|
||||||
|
if section:
|
||||||
|
self.assertEqual(
|
||||||
|
response, self._winutils._config_key + section + '\\')
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, self._winutils._config_key)
|
||||||
|
|
||||||
|
def test_get_config_key_name_with_section(self):
|
||||||
|
self._test_get_config_key_name(self._SECTION)
|
||||||
|
|
||||||
|
def test_get_config_key_name_no_section(self):
|
||||||
|
self._test_get_config_key_name(None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_config_key_name')
|
||||||
|
def _test_set_config_value(self, mock_get_config_key_name, value):
|
||||||
|
key = mock.MagicMock()
|
||||||
|
key_name = self._winutils._config_key + self._SECTION + '\\' + self\
|
||||||
|
._CONFIG_NAME
|
||||||
|
mock_get_config_key_name.return_value = key_name
|
||||||
|
|
||||||
|
_winreg.CreateKey = mock.MagicMock()
|
||||||
|
_winreg.REG_DWORD = mock.Mock()
|
||||||
|
_winreg.REG_SZ = mock.Mock()
|
||||||
|
_winreg.SetValueEx = mock.MagicMock()
|
||||||
|
|
||||||
|
self._winutils.set_config_value(self._CONFIG_NAME, value,
|
||||||
|
self._SECTION)
|
||||||
|
|
||||||
|
_winreg.CreateKey.__enter__.return_value = key
|
||||||
|
with _winreg.CreateKey as m:
|
||||||
|
assert m == key
|
||||||
|
|
||||||
|
_winreg.CreateKey.__enter__.assert_called_with()
|
||||||
|
_winreg.CreateKey.__exit__.assert_called_with(None, None, None)
|
||||||
|
_winreg.CreateKey.assert_called_with(_winreg.HKEY_LOCAL_MACHINE,
|
||||||
|
key_name)
|
||||||
|
mock_get_config_key_name.assert_called_with(self._SECTION)
|
||||||
|
if type(value) == int:
|
||||||
|
_winreg.SetValueEx.assert_called_with(
|
||||||
|
_winreg.CreateKey().__enter__(), self._CONFIG_NAME, 0,
|
||||||
|
_winreg.REG_DWORD, value)
|
||||||
|
else:
|
||||||
|
_winreg.SetValueEx.assert_called_with(
|
||||||
|
_winreg.CreateKey().__enter__(), self._CONFIG_NAME, 0,
|
||||||
|
_winreg.REG_SZ, value)
|
||||||
|
|
||||||
|
def test_set_config_value_int(self):
|
||||||
|
self._test_set_config_value(value=1)
|
||||||
|
|
||||||
|
def test_set_config_value_not_int(self):
|
||||||
|
self._test_set_config_value(value='1')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_config_key_name')
|
||||||
|
def _test_get_config_value(self, mock_get_config_key_name, value):
|
||||||
|
key_name = self._winutils._config_key + self._SECTION + '\\'
|
||||||
|
key_name += self._CONFIG_NAME
|
||||||
|
_winreg.OpenKey = mock.MagicMock()
|
||||||
|
_winreg.REG_DWORD = mock.Mock()
|
||||||
|
_winreg.REG_SZ = mock.Mock()
|
||||||
|
if type(value) == int:
|
||||||
|
regtype = _winreg.REG_DWORD
|
||||||
|
else:
|
||||||
|
regtype = _winreg.REG_SZ
|
||||||
|
_winreg.QueryValueEx = mock.MagicMock(return_value=(value, regtype))
|
||||||
|
if value is None:
|
||||||
|
mock_get_config_key_name.side_effect = [WindowsError]
|
||||||
|
self.assertRaises(WindowsError, self._winutils.get_config_value,
|
||||||
|
self._CONFIG_NAME, None)
|
||||||
|
else:
|
||||||
|
mock_get_config_key_name.return_value = key_name
|
||||||
|
response = self._winutils.get_config_value(self._CONFIG_NAME,
|
||||||
|
self._SECTION)
|
||||||
|
_winreg.OpenKey.assert_called_with(_winreg.HKEY_LOCAL_MACHINE,
|
||||||
|
key_name)
|
||||||
|
mock_get_config_key_name.assert_called_with(self._SECTION)
|
||||||
|
_winreg.QueryValueEx.assert_called_with(
|
||||||
|
_winreg.OpenKey().__enter__(), self._CONFIG_NAME)
|
||||||
|
self.assertEqual(response, value)
|
||||||
|
|
||||||
|
def test_get_config_value_type_int(self):
|
||||||
|
self._test_get_config_value(value=1)
|
||||||
|
|
||||||
|
def test_get_config_value_type_str(self):
|
||||||
|
self._test_get_config_value(value='fake')
|
||||||
|
|
||||||
|
def test_get_config_value_type_error(self):
|
||||||
|
self._test_get_config_value(value=None)
|
||||||
|
|
||||||
|
def _test_wait_for_boot_completion(self, ret_val):
|
||||||
|
key = mock.MagicMock()
|
||||||
|
time.sleep = mock.MagicMock()
|
||||||
|
_winreg.OpenKey = mock.MagicMock()
|
||||||
|
_winreg.QueryValueEx = mock.MagicMock()
|
||||||
|
_winreg.QueryValueEx.side_effect = ret_val
|
||||||
|
self._winutils.wait_for_boot_completion()
|
||||||
|
_winreg.OpenKey.__enter__.return_value = key
|
||||||
|
_winreg.OpenKey.assert_called_with(
|
||||||
|
_winreg.HKEY_LOCAL_MACHINE,
|
||||||
|
"SYSTEM\\Setup\\Status\\SysprepStatus", 0, _winreg.KEY_READ)
|
||||||
|
|
||||||
|
_winreg.QueryValueEx.assert_called_with(
|
||||||
|
_winreg.OpenKey().__enter__(), "GeneralizationState")
|
||||||
|
|
||||||
|
def test_wait_for_boot_completion(self):
|
||||||
|
ret_val = [[7]]
|
||||||
|
self._test_wait_for_boot_completion(ret_val)
|
||||||
|
|
||||||
|
@mock.patch('wmi.WMI')
|
||||||
|
def test_get_service(self, mock_WMI):
|
||||||
|
mock_WMI.return_value = self._conn
|
||||||
|
self._conn.Win32_Service.return_value = ['fake name']
|
||||||
|
response = self._winutils._get_service('fake name')
|
||||||
|
mock_WMI.assert_called_with(moniker='//./root/cimv2')
|
||||||
|
self._conn.Win32_Service.assert_called_with(Name='fake name')
|
||||||
|
self.assertEqual(response, 'fake name')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def test_check_service_exists(self, mock_get_service):
|
||||||
|
mock_get_service.return_value = 'not None'
|
||||||
|
response = self._winutils.check_service_exists('fake name')
|
||||||
|
self.assertEqual(response, True)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def test_get_service_status(self, mock_get_service):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_service.return_value = mock_service
|
||||||
|
response = self._winutils.get_service_status('fake name')
|
||||||
|
self.assertEqual(response, mock_service.State)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def test_get_service_start_mode(self, mock_get_service):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_service.return_value = mock_service
|
||||||
|
response = self._winutils.get_service_start_mode('fake name')
|
||||||
|
self.assertEqual(response, mock_service.StartMode)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def _test_set_service_start_mode(self, mock_get_service, ret_val):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_service.return_value = mock_service
|
||||||
|
mock_service.ChangeStartMode.return_value = (ret_val,)
|
||||||
|
if ret_val != 0:
|
||||||
|
self.assertRaises(Exception,
|
||||||
|
self._winutils.set_service_start_mode,
|
||||||
|
'fake name', 'fake mode')
|
||||||
|
else:
|
||||||
|
self._winutils.set_service_start_mode('fake name', 'fake mode')
|
||||||
|
mock_service.ChangeStartMode.assert_called_once_with('fake mode')
|
||||||
|
|
||||||
|
def test_set_service_start_mode(self):
|
||||||
|
self._test_set_service_start_mode(ret_val=0)
|
||||||
|
|
||||||
|
def test_set_service_start_mode_exception(self):
|
||||||
|
self._test_set_service_start_mode(ret_val=1)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def _test_start_service(self, mock_get_service, ret_val):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_service.return_value = mock_service
|
||||||
|
mock_service.StartService.return_value = (ret_val,)
|
||||||
|
if ret_val != 0:
|
||||||
|
self.assertRaises(Exception,
|
||||||
|
self._winutils.start_service,
|
||||||
|
'fake name')
|
||||||
|
else:
|
||||||
|
self._winutils.start_service('fake name')
|
||||||
|
mock_service.StartService.assert_called_once_with()
|
||||||
|
|
||||||
|
def test_start_service(self):
|
||||||
|
self._test_set_service_start_mode(ret_val=0)
|
||||||
|
|
||||||
|
def test_start_service_exception(self):
|
||||||
|
self._test_set_service_start_mode(ret_val=1)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_service')
|
||||||
|
def _test_stop_service(self, mock_get_service, ret_val):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_service.return_value = mock_service
|
||||||
|
mock_service.StopService.return_value = (ret_val,)
|
||||||
|
if ret_val != 0:
|
||||||
|
self.assertRaises(Exception,
|
||||||
|
self._winutils.stop_service,
|
||||||
|
'fake name')
|
||||||
|
else:
|
||||||
|
self._winutils.stop_service('fake name')
|
||||||
|
mock_service.StopService.assert_called_once_with()
|
||||||
|
|
||||||
|
def test_stop_service(self):
|
||||||
|
self._test_stop_service(ret_val=0)
|
||||||
|
|
||||||
|
def test_stop_service_exception(self):
|
||||||
|
self._test_stop_service(ret_val=1)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'.stop_service')
|
||||||
|
def test_terminate(self, mock_stop_service):
|
||||||
|
time.sleep = mock.MagicMock()
|
||||||
|
self._winutils.terminate()
|
||||||
|
mock_stop_service.assert_called_with(self._winutils._service_name)
|
||||||
|
time.sleep.assert_called_with(3)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_ipv4_routing_table')
|
||||||
|
def _test_get_default_gateway(self, mock_get_ipv4_routing_table,
|
||||||
|
routing_table):
|
||||||
|
mock_get_ipv4_routing_table.return_value = [routing_table]
|
||||||
|
response = self._winutils.get_default_gateway()
|
||||||
|
mock_get_ipv4_routing_table.assert_called_once_with()
|
||||||
|
if routing_table[0] == '0.0.0.0':
|
||||||
|
self.assertEqual(response, (routing_table[3], routing_table[2]))
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, (None, None))
|
||||||
|
|
||||||
|
def test_get_default_gateway(self):
|
||||||
|
routing_table = ['0.0.0.0', '1.1.1.1', self._GATEWAY, '8.8.8.8']
|
||||||
|
self._test_get_default_gateway(routing_table=routing_table)
|
||||||
|
|
||||||
|
def test_get_default_gateway_error(self):
|
||||||
|
routing_table = ['1.1.1.1', '1.1.1.1', self._GATEWAY, '8.8.8.8']
|
||||||
|
self._test_get_default_gateway(routing_table=routing_table)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'._get_ipv4_routing_table')
|
||||||
|
def _test_check_static_route_exists(self, mock_get_ipv4_routing_table,
|
||||||
|
routing_table):
|
||||||
|
mock_get_ipv4_routing_table.return_value = [routing_table]
|
||||||
|
response = self._winutils.check_static_route_exists(self._DESTINATION)
|
||||||
|
mock_get_ipv4_routing_table.assert_called_once_with()
|
||||||
|
if routing_table[0] == self._DESTINATION:
|
||||||
|
self.assertTrue(response)
|
||||||
|
else:
|
||||||
|
self.assertFalse(response)
|
||||||
|
|
||||||
|
def test_check_static_route_exists_true(self):
|
||||||
|
routing_table = [self._DESTINATION, '1.1.1.1', self._GATEWAY,
|
||||||
|
'8.8.8.8']
|
||||||
|
self._test_check_static_route_exists(routing_table=routing_table)
|
||||||
|
|
||||||
|
def test_check_static_route_exists_false(self):
|
||||||
|
routing_table = ['0.0.0.0', '1.1.1.1', self._GATEWAY, '8.8.8.8']
|
||||||
|
self._test_check_static_route_exists(routing_table=routing_table)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils'
|
||||||
|
'.execute_process')
|
||||||
|
def _test_add_static_route(self, mock_execute_process, err):
|
||||||
|
next_hop = '10.10.10.10'
|
||||||
|
interface_index = 1
|
||||||
|
metric = 9
|
||||||
|
args = ['ROUTE', 'ADD', self._DESTINATION, 'MASK', self._NETMASK,
|
||||||
|
next_hop]
|
||||||
|
mock_execute_process.return_value = (None, err, None)
|
||||||
|
if err:
|
||||||
|
self.assertRaises(Exception, self._winutils.add_static_route,
|
||||||
|
self._DESTINATION, self._NETMASK, next_hop,
|
||||||
|
interface_index, metric)
|
||||||
|
else:
|
||||||
|
self._winutils.add_static_route(self._DESTINATION, self._NETMASK,
|
||||||
|
next_hop, interface_index, metric)
|
||||||
|
mock_execute_process.assert_called_with(args)
|
||||||
|
|
||||||
|
def test_add_static_route(self):
|
||||||
|
self._test_add_static_route(err=404)
|
||||||
|
|
||||||
|
def test_add_static_route_fail(self):
|
||||||
|
self._test_add_static_route(err=None)
|
||||||
|
|
||||||
|
@mock.patch('ctypes.sizeof')
|
||||||
|
@mock.patch('ctypes.byref')
|
||||||
|
@mock.patch('ctypes.windll.kernel32.VerSetConditionMask')
|
||||||
|
@mock.patch('ctypes.windll.kernel32.VerifyVersionInfoW')
|
||||||
|
@mock.patch('ctypes.windll.kernel32.GetLastError')
|
||||||
|
def _test_check_os_version(self, mock_GetLastError,
|
||||||
|
mock_VerifyVersionInfoW,
|
||||||
|
mock_VerSetConditionMask, mock_byref,
|
||||||
|
mock_sizeof, ret_value, error_value=None):
|
||||||
|
mock_VerSetConditionMask.return_value = 2
|
||||||
|
mock_VerifyVersionInfoW.return_value = ret_value
|
||||||
|
mock_GetLastError.return_value = error_value
|
||||||
|
old_version = self._winutils.ERROR_OLD_WIN_VERSION
|
||||||
|
if error_value and error_value is not old_version:
|
||||||
|
self.assertRaises(Exception, self._winutils.check_os_version, 3,
|
||||||
|
1, 2)
|
||||||
|
mock_GetLastError.assert_called_once_with()
|
||||||
|
else:
|
||||||
|
response = self._winutils.check_os_version(3, 1, 2)
|
||||||
|
mock_sizeof.assert_called_once_with(
|
||||||
|
windows_utils.Win32_OSVERSIONINFOEX_W)
|
||||||
|
self.assertEqual(mock_VerSetConditionMask.call_count, 3)
|
||||||
|
mock_VerifyVersionInfoW.assert_called_with(mock_byref(),
|
||||||
|
1 | 2 | 3 | 7,
|
||||||
|
2)
|
||||||
|
if error_value is old_version:
|
||||||
|
mock_GetLastError.assert_called_with()
|
||||||
|
self.assertEqual(response, False)
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, True)
|
||||||
|
|
||||||
|
def test_check_os_version(self):
|
||||||
|
m = mock.MagicMock()
|
||||||
|
self._test_check_os_version(ret_value=m)
|
||||||
|
|
||||||
|
def test_check_os_version_expect_False(self):
|
||||||
|
self._test_check_os_version(
|
||||||
|
ret_value=None, error_value=self._winutils.ERROR_OLD_WIN_VERSION)
|
||||||
|
|
||||||
|
def test_check_os_version_exception(self):
|
||||||
|
self._test_check_os_version(ret_value=None, error_value=9999)
|
||||||
|
|
||||||
|
def _test_get_volume_label(self, ret_val):
|
||||||
|
label = mock.MagicMock()
|
||||||
|
max_label_size = 261
|
||||||
|
drive = 'Fake_drive'
|
||||||
|
ctypes.create_unicode_buffer = mock.MagicMock(return_value=label)
|
||||||
|
ctypes.windll.kernel32.GetVolumeInformationW = mock.MagicMock(
|
||||||
|
return_value=ret_val)
|
||||||
|
response = self._winutils.get_volume_label(drive)
|
||||||
|
if ret_val:
|
||||||
|
self.assertTrue(response is not None)
|
||||||
|
else:
|
||||||
|
self.assertTrue(response is None)
|
||||||
|
|
||||||
|
ctypes.create_unicode_buffer.assert_called_with(max_label_size)
|
||||||
|
ctypes.windll.kernel32.GetVolumeInformationW.assert_called_with(
|
||||||
|
drive, label, max_label_size, 0, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
def test_get_volume_label(self):
|
||||||
|
self._test_get_volume_label('ret')
|
||||||
|
|
||||||
|
def test_get_volume_label_no_return_value(self):
|
||||||
|
self._test_get_volume_label(None)
|
||||||
|
|
||||||
|
@mock.patch('re.search')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.base.BaseOSUtils.'
|
||||||
|
'generate_random_password')
|
||||||
|
def test_generate_random_password(self, mock_generate_random_password,
|
||||||
|
mock_search):
|
||||||
|
length = 14
|
||||||
|
mock_search.return_value = True
|
||||||
|
mock_generate_random_password.return_value = 'Passw0rd'
|
||||||
|
response = self._winutils.generate_random_password(length)
|
||||||
|
mock_generate_random_password.assert_called_once_with(length)
|
||||||
|
self.assertEqual(response, 'Passw0rd')
|
||||||
|
|
||||||
|
@mock.patch('ctypes.create_unicode_buffer')
|
||||||
|
@mock.patch('ctypes.windll.kernel32.GetLogicalDriveStringsW')
|
||||||
|
def _test_get_logical_drives(self, mock_GetLogicalDriveStringsW,
|
||||||
|
mock_create_unicode_buffer, buf_length):
|
||||||
|
mock_buf = mock.MagicMock()
|
||||||
|
mock_buf.__getitem__.side_effect = ['1', '\x00']
|
||||||
|
mock_create_unicode_buffer.return_value = mock_buf
|
||||||
|
mock_GetLogicalDriveStringsW.return_value = buf_length
|
||||||
|
if buf_length is None:
|
||||||
|
self.assertRaises(Exception, self._winutils._get_logical_drives)
|
||||||
|
else:
|
||||||
|
response = self._winutils._get_logical_drives()
|
||||||
|
print mock_buf.mock_calls
|
||||||
|
mock_create_unicode_buffer.assert_called_with(261)
|
||||||
|
mock_GetLogicalDriveStringsW.assert_called_with(260, mock_buf)
|
||||||
|
self.assertEqual(response, ['1'])
|
||||||
|
|
||||||
|
def test_get_logical_drives_exception(self):
|
||||||
|
self._test_get_logical_drives(buf_length=None)
|
||||||
|
|
||||||
|
def test_get_logical_drives(self):
|
||||||
|
self._test_get_logical_drives(buf_length=2)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils.'
|
||||||
|
'_get_logical_drives')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.kernel32')
|
||||||
|
def test_get_cdrom_drives(self, mock_kernel32, mock_get_logical_drives):
|
||||||
|
mock_get_logical_drives.return_value = ['drive']
|
||||||
|
mock_kernel32.GetDriveTypeW.return_value = self._winutils.DRIVE_CDROM
|
||||||
|
response = self._winutils.get_cdrom_drives()
|
||||||
|
mock_get_logical_drives.assert_called_with()
|
||||||
|
self.assertEqual(response, ['drive'])
|
||||||
|
|
||||||
|
@mock.patch('win32com.client.Dispatch')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils._get_fw_protocol')
|
||||||
|
def _test_firewall_create_rule(self, mock_get_fw_protocol, mock_Dispatch):
|
||||||
|
self._winutils.firewall_create_rule(
|
||||||
|
name='fake name', port=9999, protocol=self._winutils.PROTOCOL_TCP)
|
||||||
|
expected = [mock.call("HNetCfg.FWOpenPort"),
|
||||||
|
mock.call("HNetCfg.FwMgr")]
|
||||||
|
self.assertEqual(mock_Dispatch.call_args_list, expected)
|
||||||
|
mock_get_fw_protocol.assert_called_once_with(
|
||||||
|
self._winutils.PROTOCOL_TCP)
|
||||||
|
|
||||||
|
@mock.patch('win32com.client.Dispatch')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.windows.WindowsUtils._get_fw_protocol')
|
||||||
|
def test_firewall_remove_rule(self, mock_get_fw_protocol, mock_Dispatch):
|
||||||
|
self._winutils.firewall_remove_rule(
|
||||||
|
name='fake name', port=9999, protocol=self._winutils.PROTOCOL_TCP)
|
||||||
|
mock_Dispatch.assert_called_once_with("HNetCfg.FwMgr")
|
||||||
|
mock_get_fw_protocol.assert_called_once_with(
|
||||||
|
self._winutils.PROTOCOL_TCP)
|
15
cloudbaseinit/tests/plugins/__init__.py
Normal file
15
cloudbaseinit/tests/plugins/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
37
cloudbaseinit/tests/plugins/test_factory.py
Normal file
37
cloudbaseinit/tests/plugins/test_factory.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.plugins import factory
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class PluginFactoryTests(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self._factory = factory.PluginFactory()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.utils.classloader.ClassLoader.load_class')
|
||||||
|
def test_load_plugins(self, mock_load_class):
|
||||||
|
expected = []
|
||||||
|
for path in CONF.plugins:
|
||||||
|
expected.append(mock.call(path))
|
||||||
|
response = self._factory.load_plugins()
|
||||||
|
self.assertEqual(mock_load_class.call_args_list, expected)
|
||||||
|
self.assertTrue(response is not None)
|
15
cloudbaseinit/tests/plugins/windows/__init__.py
Normal file
15
cloudbaseinit/tests/plugins/windows/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
77
cloudbaseinit/tests/plugins/windows/test_createuser.py
Normal file
77
cloudbaseinit/tests/plugins/windows/test_createuser.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins import base
|
||||||
|
from cloudbaseinit.plugins.windows import createuser
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class CreateUserPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._create_user = createuser.CreateUserPlugin()
|
||||||
|
|
||||||
|
def test_get_password(self):
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_osutils.generate_random_password.return_value = 'fake password'
|
||||||
|
response = self._create_user._get_password(mock_osutils)
|
||||||
|
mock_osutils.generate_random_password.assert_called_once_with(14)
|
||||||
|
self.assertEqual(response, 'fake password')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.createuser.CreateUserPlugin'
|
||||||
|
'._get_password')
|
||||||
|
def _test_execute(self, mock_get_password, mock_get_os_utils,
|
||||||
|
user_exists=True):
|
||||||
|
CONF.set_override('groups', ['Admins'])
|
||||||
|
shared_data = {}
|
||||||
|
mock_token = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_password.return_value = 'password'
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_osutils.user_exists.return_value = user_exists
|
||||||
|
mock_osutils.create_user_logon_session.return_value = mock_token
|
||||||
|
|
||||||
|
response = self._create_user.execute(mock_service, shared_data)
|
||||||
|
|
||||||
|
mock_get_os_utils.assert_called_once_with()
|
||||||
|
mock_get_password.assert_called_once_with(mock_osutils)
|
||||||
|
mock_osutils.user_exists.assert_called_once_with(CONF.username)
|
||||||
|
if user_exists:
|
||||||
|
mock_osutils.set_user_password.assert_called_once_with(
|
||||||
|
CONF.username, 'password')
|
||||||
|
else:
|
||||||
|
mock_osutils.create_user.assert_called_once_with(CONF.username,
|
||||||
|
'password')
|
||||||
|
mock_osutils.create_user_logon_session.assert_called_once_with(
|
||||||
|
CONF.username, 'password', True)
|
||||||
|
mock_osutils.close_user_logon_session.assert_called_once_with(
|
||||||
|
mock_token)
|
||||||
|
mock_osutils.add_user_to_local_group.assert_called_once_with(
|
||||||
|
CONF.username, CONF.groups[0])
|
||||||
|
self.assertEqual(response, (base.PLUGIN_EXECUTION_DONE, False))
|
||||||
|
|
||||||
|
def test_execute_user_exists(self):
|
||||||
|
self._test_execute(user_exists=True)
|
||||||
|
|
||||||
|
def test_execute_no_user(self):
|
||||||
|
self._test_execute(user_exists=False)
|
210
cloudbaseinit/tests/plugins/windows/test_extendvolumes.py
Normal file
210
cloudbaseinit/tests/plugins/windows/test_extendvolumes.py
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright (c) 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
_ctypes_mock = mock.MagicMock()
|
||||||
|
_comtypes_mock = mock.MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendVolumesPluginTests(unittest.TestCase):
|
||||||
|
@mock.patch.dict(sys.modules, {'comtypes': _comtypes_mock,
|
||||||
|
'ctypes': _ctypes_mock})
|
||||||
|
def setUp(self):
|
||||||
|
extendvolumes = importlib.import_module('cloudbaseinit.plugins.'
|
||||||
|
'windows.extendvolumes')
|
||||||
|
self._extend_volumes = extendvolumes.ExtendVolumesPlugin()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
reload(sys)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes'
|
||||||
|
'.ExtendVolumesPlugin._get_volume_index')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes'
|
||||||
|
'.ExtendVolumesPlugin._extend_volume')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.IVdsVolume')
|
||||||
|
def test_extend_volumes(self, _vds_mock, mock_extend_volume,
|
||||||
|
mock_get_volume_index):
|
||||||
|
mock_pack = mock.MagicMock()
|
||||||
|
mock_volume_idxs = mock.MagicMock()
|
||||||
|
mock_enum = mock.MagicMock()
|
||||||
|
mock_unk = mock.MagicMock()
|
||||||
|
mock_c = mock.MagicMock()
|
||||||
|
mock_volume = mock.MagicMock()
|
||||||
|
mock_properties = mock.MagicMock()
|
||||||
|
mock_pack.QueryVolumes.return_value = mock_enum
|
||||||
|
mock_enum.Next.side_effect = [(mock_unk, mock_c), (None, None)]
|
||||||
|
mock_unk.QueryInterface.return_value = mock_volume
|
||||||
|
mock_volume.GetProperties.return_value = mock_properties
|
||||||
|
_ctypes_mock.wstring_at.return_value = 'fake name'
|
||||||
|
mock_get_volume_index.return_value = mock_volume_idxs
|
||||||
|
self._extend_volumes._extend_volumes(mock_pack, [mock_volume_idxs])
|
||||||
|
mock_pack.QueryVolumes.assert_called_once_with()
|
||||||
|
mock_enum.Next.assert_called_with(1)
|
||||||
|
mock_unk.QueryInterface.assert_called_once_with(_vds_mock)
|
||||||
|
mock_volume.GetProperties.assert_called_once_with()
|
||||||
|
_ctypes_mock.wstring_at.assert_called_with(mock_properties.pwszName)
|
||||||
|
mock_get_volume_index.assert_called_once_with('fake name')
|
||||||
|
mock_extend_volume.assert_called_once_with(mock_pack, mock_volume,
|
||||||
|
mock_properties)
|
||||||
|
_ctypes_mock.windll.ole32.CoTaskMemFree.assert_called_once_with(
|
||||||
|
mock_properties.pwszName)
|
||||||
|
|
||||||
|
def test_get_volume_index(self):
|
||||||
|
mock_value = mock.MagicMock()
|
||||||
|
re.match = mock.MagicMock(return_value=mock_value)
|
||||||
|
mock_value.group.return_value = '9999'
|
||||||
|
response = self._extend_volumes._get_volume_index('$2')
|
||||||
|
mock_value.group.assert_called_once_with(1)
|
||||||
|
self.assertTrue(response == 9999)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes'
|
||||||
|
'.ExtendVolumesPlugin._get_volume_extents_to_resize')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.VDS_INPUT_DISK')
|
||||||
|
def test_extend_volume(self, mock_VDS_INPUT_DISK,
|
||||||
|
mock_get_volume_extents_to_resize):
|
||||||
|
mock_disk = mock.MagicMock()
|
||||||
|
mock_pack = mock.MagicMock()
|
||||||
|
mock_volume = mock.MagicMock()
|
||||||
|
mock_properties = mock.MagicMock()
|
||||||
|
mock_volume_extent = mock.MagicMock()
|
||||||
|
mock_async = mock.MagicMock()
|
||||||
|
mock_get_volume_extents_to_resize.return_value = [(mock_volume_extent,
|
||||||
|
9999)]
|
||||||
|
mock_VDS_INPUT_DISK.return_value = mock_disk
|
||||||
|
mock_volume.Extend.return_value = mock_async
|
||||||
|
|
||||||
|
self._extend_volumes._extend_volume(mock_pack, mock_volume,
|
||||||
|
mock_properties)
|
||||||
|
|
||||||
|
mock_get_volume_extents_to_resize.assert_called_once_with(
|
||||||
|
mock_pack, mock_properties.id)
|
||||||
|
_ctypes_mock.wstring_at.assert_called_with(mock_properties.pwszName)
|
||||||
|
mock_volume.Extend.assert_called_once_with(
|
||||||
|
mock_VDS_INPUT_DISK.__mul__()(), 1)
|
||||||
|
mock_async.Wait.assert_called_once_with()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.IVdsDisk')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.VDS_DISK_EXTENT')
|
||||||
|
def test_get_volume_extents_to_resize(self, mock_VDS_DISK_EXTENT,
|
||||||
|
mock_IVdsDisk):
|
||||||
|
mock_pack = mock.MagicMock()
|
||||||
|
mock_extents_p = mock.MagicMock()
|
||||||
|
mock_unk = mock.MagicMock()
|
||||||
|
mock_c = mock.MagicMock()
|
||||||
|
mock_disk = mock.MagicMock()
|
||||||
|
mock_enum = mock.MagicMock()
|
||||||
|
fake_volume_id = '$1'
|
||||||
|
mock_array = mock.MagicMock()
|
||||||
|
mock_array.volumeId = fake_volume_id
|
||||||
|
mock_pack.QueryDisks.return_value = mock_enum
|
||||||
|
mock_enum.Next.side_effect = [(mock_unk, mock_c), (None, None)]
|
||||||
|
mock_unk.QueryInterface.return_value = mock_disk
|
||||||
|
mock_disk.QueryExtents.return_value = (mock_extents_p,
|
||||||
|
1)
|
||||||
|
mock_VDS_DISK_EXTENT.__mul__().from_address.return_value = [mock_array]
|
||||||
|
|
||||||
|
response = self._extend_volumes._get_volume_extents_to_resize(
|
||||||
|
mock_pack, fake_volume_id)
|
||||||
|
|
||||||
|
mock_pack.QueryDisks.assert_called_once_with()
|
||||||
|
mock_enum.Next.assert_called_with(1)
|
||||||
|
mock_unk.QueryInterface.assert_called_once_with(mock_IVdsDisk)
|
||||||
|
_ctypes_mock.addressof.assert_called_with(mock_extents_p.contents)
|
||||||
|
mock_VDS_DISK_EXTENT.__mul__().from_address.assert_called_with(
|
||||||
|
_ctypes_mock.addressof(mock_extents_p.contents))
|
||||||
|
|
||||||
|
_ctypes_mock.pointer.assert_called_once_with(
|
||||||
|
mock_VDS_DISK_EXTENT())
|
||||||
|
self.assertEqual(response, [])
|
||||||
|
|
||||||
|
_ctypes_mock.windll.ole32.CoTaskMemFree.assert_called_with(
|
||||||
|
mock_extents_p)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.'
|
||||||
|
'VDS_QUERY_SOFTWARE_PROVIDERS')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.IVdsSwProvider')
|
||||||
|
def test_query_providers(self, mock_IVdsSwProvider,
|
||||||
|
mock_VDS_QUERY_SOFTWARE_PROVIDERS):
|
||||||
|
mock_svc = mock.MagicMock()
|
||||||
|
mock_enum = mock.MagicMock()
|
||||||
|
mock_unk = mock.MagicMock()
|
||||||
|
mock_c = mock.MagicMock()
|
||||||
|
mock_svc.QueryProviders.return_value = mock_enum
|
||||||
|
mock_enum.Next.side_effect = [(mock_unk, mock_c), (None, None)]
|
||||||
|
mock_unk.QueryInterface.return_value = 'fake providers'
|
||||||
|
|
||||||
|
response = self._extend_volumes._query_providers(mock_svc)
|
||||||
|
mock_svc.QueryProviders.assert_called_once_with(
|
||||||
|
mock_VDS_QUERY_SOFTWARE_PROVIDERS)
|
||||||
|
mock_enum.Next.assert_called_with(1)
|
||||||
|
mock_unk.QueryInterface.assert_called_once_with(mock_IVdsSwProvider)
|
||||||
|
self.assertEqual(response, ['fake providers'])
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.IVdsPack')
|
||||||
|
def test_query_packs(self, mock_IVdsPack):
|
||||||
|
mock_provider = mock.MagicMock()
|
||||||
|
mock_enum = mock.MagicMock()
|
||||||
|
mock_unk = mock.MagicMock()
|
||||||
|
mock_c = mock.MagicMock()
|
||||||
|
mock_provider.QueryPacks.return_value = mock_enum
|
||||||
|
mock_enum.Next.side_effect = [(mock_unk, mock_c), (None, None)]
|
||||||
|
mock_unk.QueryInterface.return_value = 'fake packs'
|
||||||
|
|
||||||
|
response = self._extend_volumes._query_packs(mock_provider)
|
||||||
|
|
||||||
|
mock_provider.QueryPacks.assert_called_once_with()
|
||||||
|
mock_enum.Next.assert_called_with(1)
|
||||||
|
mock_unk.QueryInterface.assert_called_once_with(mock_IVdsPack)
|
||||||
|
self.assertEqual(response, ['fake packs'])
|
||||||
|
|
||||||
|
def test_get_volumes_to_extend(self):
|
||||||
|
CONF.set_override('volumes_to_extend', '1')
|
||||||
|
response = self._extend_volumes._get_volumes_to_extend()
|
||||||
|
self.assertEqual(response, [1])
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.vds.load_vds_service')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes.'
|
||||||
|
'ExtendVolumesPlugin._query_providers')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes.'
|
||||||
|
'ExtendVolumesPlugin._query_packs')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.extendvolumes.'
|
||||||
|
'ExtendVolumesPlugin._extend_volumes')
|
||||||
|
def test_execute(self, mock_extend_volumes, mock_query_packs,
|
||||||
|
mock_query_providers, mock_load_vds_service):
|
||||||
|
CONF.set_override('volumes_to_extend', '1')
|
||||||
|
mock_svc = mock.MagicMock()
|
||||||
|
fake_providers = ['fake providers']
|
||||||
|
fake_packs = ['fake packs']
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
fake_data = 'fake data'
|
||||||
|
mock_load_vds_service.return_value = mock_svc
|
||||||
|
mock_query_providers.return_value = fake_providers
|
||||||
|
mock_query_packs.return_value = fake_packs
|
||||||
|
|
||||||
|
self._extend_volumes.execute(mock_service, fake_data)
|
||||||
|
|
||||||
|
mock_query_providers.assert_called_once_with(mock_svc)
|
||||||
|
mock_query_packs.assert_called_once_with('fake providers')
|
||||||
|
mock_extend_volumes.assert_called_with('fake packs', [1])
|
79
cloudbaseinit/tests/plugins/windows/test_networkconfig.py
Normal file
79
cloudbaseinit/tests/plugins/windows/test_networkconfig.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import networkconfig
|
||||||
|
from cloudbaseinit.tests.metadata import fake_json_response
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkConfigPluginPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._network_plugin = networkconfig.NetworkConfigPlugin()
|
||||||
|
self.fake_data = fake_json_response.get_fake_metadata_json(
|
||||||
|
'2013-04-04')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
def _test_execute(self, mock_get_os_utils, search_result, no_adapters):
|
||||||
|
CONF.set_override('network_adapter', 'fake adapter')
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
re.search = mock.MagicMock(return_value=search_result)
|
||||||
|
fake_shared_data = 'fake shared data'
|
||||||
|
mock_service.get_meta_data.return_value = self.fake_data
|
||||||
|
mock_service.get_content.return_value = search_result
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_osutils.set_static_network_config.return_value = False
|
||||||
|
if search_result is None:
|
||||||
|
self.assertRaises(Exception, self._network_plugin.execute,
|
||||||
|
mock_service, fake_shared_data)
|
||||||
|
elif no_adapters:
|
||||||
|
CONF.set_override('network_adapter', None)
|
||||||
|
mock_osutils.get_network_adapters.return_value = None
|
||||||
|
self.assertRaises(Exception, self._network_plugin.execute,
|
||||||
|
mock_service, fake_shared_data)
|
||||||
|
|
||||||
|
else:
|
||||||
|
response = self._network_plugin.execute(mock_service,
|
||||||
|
fake_shared_data)
|
||||||
|
|
||||||
|
mock_service.get_meta_data.assert_called_once_with('openstack')
|
||||||
|
mock_service.get_content.assert_called_once_with(
|
||||||
|
'openstack', self.fake_data['network_config']['content_path'])
|
||||||
|
mock_osutils.set_static_network_config.assert_called_once_with(
|
||||||
|
'fake adapter', search_result.group('address'),
|
||||||
|
search_result.group('netmask'),
|
||||||
|
search_result.group('broadcast'),
|
||||||
|
search_result.group('gateway'),
|
||||||
|
search_result.group('dnsnameservers').strip().split(' '))
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
m = mock.MagicMock()
|
||||||
|
self._test_execute(search_result=m, no_adapters=False)
|
||||||
|
|
||||||
|
def test_execute_no_debian(self):
|
||||||
|
self._test_execute(search_result=None, no_adapters=False)
|
||||||
|
|
||||||
|
def test_execute_no_adapters(self):
|
||||||
|
m = mock.MagicMock()
|
||||||
|
self._test_execute(search_result=m, no_adapters=True)
|
57
cloudbaseinit/tests/plugins/windows/test_sethostname.py
Normal file
57
cloudbaseinit/tests/plugins/windows/test_sethostname.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import sethostname
|
||||||
|
from cloudbaseinit.tests.metadata import fake_json_response
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class SetHostNamePluginPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._sethostname_plugin = sethostname.SetHostNamePlugin()
|
||||||
|
self.fake_data = fake_json_response.get_fake_metadata_json(
|
||||||
|
'2013-04-04')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
def _test_execute(self, mock_get_os_utils, hostname_exists):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
fake_shared_data = 'fake data'
|
||||||
|
mock_service.get_meta_data.return_value = self.fake_data
|
||||||
|
if hostname_exists is False:
|
||||||
|
del self.fake_data['hostname']
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_osutils.set_host_name.return_value = False
|
||||||
|
response = self._sethostname_plugin.execute(mock_service,
|
||||||
|
fake_shared_data)
|
||||||
|
mock_service.get_meta_data.assert_called_once_with('openstack')
|
||||||
|
if hostname_exists is True:
|
||||||
|
mock_get_os_utils.assert_called_once_with()
|
||||||
|
mock_osutils.set_host_name.assert_called_once_with(
|
||||||
|
self.fake_data['hostname'].split('.', 1)[0])
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
self._test_execute(hostname_exists=True)
|
||||||
|
|
||||||
|
def test_execute_no_hostname(self):
|
||||||
|
self._test_execute(hostname_exists=False)
|
166
cloudbaseinit/tests/plugins/windows/test_setuserpassword.py
Normal file
166
cloudbaseinit/tests/plugins/windows/test_setuserpassword.py
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins import constants
|
||||||
|
from cloudbaseinit.plugins.windows import setuserpassword
|
||||||
|
from cloudbaseinit.tests.metadata import fake_json_response
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class SetUserPasswordPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._setpassword_plugin = setuserpassword.SetUserPasswordPlugin()
|
||||||
|
self.fake_data = fake_json_response.get_fake_metadata_json(
|
||||||
|
'2013-04-04')
|
||||||
|
|
||||||
|
@mock.patch('base64.b64encode')
|
||||||
|
@mock.patch('cloudbaseinit.utils.crypt.CryptManager'
|
||||||
|
'.load_ssh_rsa_public_key')
|
||||||
|
def test_encrypt_password(self, mock_load_ssh_key, mock_b64encode):
|
||||||
|
mock_rsa = mock.MagicMock()
|
||||||
|
fake_ssh_pub_key = 'fake key'
|
||||||
|
fake_password = 'fake password'
|
||||||
|
mock_load_ssh_key.return_value = mock_rsa
|
||||||
|
mock_rsa.__enter__().public_encrypt.return_value = 'public encrypted'
|
||||||
|
mock_b64encode.return_value = 'encrypted password'
|
||||||
|
|
||||||
|
response = self._setpassword_plugin._encrypt_password(
|
||||||
|
fake_ssh_pub_key, fake_password)
|
||||||
|
print mock_rsa.mock_calls
|
||||||
|
|
||||||
|
mock_load_ssh_key.assert_called_with(fake_ssh_pub_key)
|
||||||
|
mock_rsa.__enter__().public_encrypt.assert_called_with('fake password')
|
||||||
|
mock_b64encode.assert_called_with('public encrypted')
|
||||||
|
self.assertEqual(response, 'encrypted password')
|
||||||
|
|
||||||
|
def _test_get_ssh_public_key(self, data_exists):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_service.get_meta_data.return_value = self.fake_data
|
||||||
|
if data_exists is False:
|
||||||
|
del self.fake_data['public_keys']
|
||||||
|
response = self._setpassword_plugin._get_ssh_public_key(
|
||||||
|
mock_service)
|
||||||
|
self.assertEqual(response, False)
|
||||||
|
else:
|
||||||
|
response = self._setpassword_plugin._get_ssh_public_key(
|
||||||
|
mock_service)
|
||||||
|
mock_service.get_meta_data.assert_called_with(
|
||||||
|
'openstack', self._setpassword_plugin._post_password_md_ver)
|
||||||
|
self.assertEqual(response, self.fake_data['public_keys']['name'])
|
||||||
|
|
||||||
|
def test_get_ssh_plublic_key(self):
|
||||||
|
self._test_get_ssh_public_key(data_exists=True)
|
||||||
|
|
||||||
|
def test_get_ssh_plublic_key_no_pub_keys(self):
|
||||||
|
self._test_get_ssh_public_key(data_exists=False)
|
||||||
|
|
||||||
|
def test_get_password(self):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_service.get_meta_data.return_value = self.fake_data
|
||||||
|
CONF.set_override('inject_user_password', False)
|
||||||
|
mock_osutils.generate_random_password.return_value = 'Passw0rd'
|
||||||
|
response = self._setpassword_plugin._get_password(mock_service,
|
||||||
|
mock_osutils)
|
||||||
|
mock_service.get_meta_data.assert_called_with('openstack')
|
||||||
|
mock_osutils.generate_random_password.assert_called_once_with(14)
|
||||||
|
self.assertEqual(response, 'Passw0rd')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.setuserpassword.'
|
||||||
|
'SetUserPasswordPlugin._get_ssh_public_key')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.setuserpassword.'
|
||||||
|
'SetUserPasswordPlugin._encrypt_password')
|
||||||
|
def _test_set_metadata_password(self, mock_encrypt_password,
|
||||||
|
mock_get_key, ssh_pub_key):
|
||||||
|
fake_passw0rd = 'fake Passw0rd'
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_get_key.return_value = ssh_pub_key
|
||||||
|
mock_encrypt_password.return_value = 'encrypted password'
|
||||||
|
mock_service.post_password.return_value = 'value'
|
||||||
|
|
||||||
|
response = self._setpassword_plugin._set_metadata_password(
|
||||||
|
fake_passw0rd, mock_service)
|
||||||
|
|
||||||
|
if ssh_pub_key is None:
|
||||||
|
self.assertEqual(response, True)
|
||||||
|
else:
|
||||||
|
mock_get_key.assert_called_once_with(mock_service)
|
||||||
|
mock_encrypt_password.assert_called_once_with(ssh_pub_key,
|
||||||
|
fake_passw0rd)
|
||||||
|
mock_service.post_password.assert_called_with(
|
||||||
|
'encrypted password',
|
||||||
|
self._setpassword_plugin._post_password_md_ver)
|
||||||
|
self.assertEqual(response, 'value')
|
||||||
|
|
||||||
|
def test_set_metadata_password_with_ssh_key(self):
|
||||||
|
fake_key = 'fake key'
|
||||||
|
self._test_set_metadata_password(ssh_pub_key=fake_key)
|
||||||
|
|
||||||
|
def test_set_metadata_password_no_ssh_key(self):
|
||||||
|
self._test_set_metadata_password(ssh_pub_key=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.setuserpassword.'
|
||||||
|
'SetUserPasswordPlugin._get_password')
|
||||||
|
def test_set_password(self, mock_get_password):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_get_password.return_value = 'fake password'
|
||||||
|
|
||||||
|
response = self._setpassword_plugin._set_password(mock_service,
|
||||||
|
mock_osutils,
|
||||||
|
'fake user')
|
||||||
|
|
||||||
|
mock_get_password.assert_called_once_with(mock_service, mock_osutils)
|
||||||
|
mock_osutils.set_user_password.assert_called_once_with('fake user',
|
||||||
|
'fake password')
|
||||||
|
self.assertEqual(response, 'fake password')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.setuserpassword.'
|
||||||
|
'SetUserPasswordPlugin._set_password')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.setuserpassword.'
|
||||||
|
'SetUserPasswordPlugin._set_metadata_password')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
def test_execute(self, mock_get_os_utils, mock_set_metadata_password,
|
||||||
|
mock_set_password):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
fake_shared_data = mock.MagicMock()
|
||||||
|
fake_shared_data.get.return_value = 'fake username'
|
||||||
|
mock_service.is_password_set.return_value = False
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_osutils.user_exists.return_value = True
|
||||||
|
mock_set_password.return_value = 'fake password'
|
||||||
|
|
||||||
|
response = self._setpassword_plugin.execute(mock_service,
|
||||||
|
fake_shared_data)
|
||||||
|
|
||||||
|
fake_shared_data.get.assert_called_with(
|
||||||
|
constants.SHARED_DATA_USERNAME, CONF.username)
|
||||||
|
mock_service.is_password_set.assert_called_once_with(
|
||||||
|
self._setpassword_plugin._post_password_md_ver)
|
||||||
|
mock_get_os_utils.assert_called_once_with()
|
||||||
|
mock_osutils.user_exists.assert_called_once_with('fake username')
|
||||||
|
mock_set_password.assert_called_once_with(mock_service, mock_osutils,
|
||||||
|
'fake username')
|
||||||
|
mock_set_metadata_password.assert_called_once_with('fake password',
|
||||||
|
mock_service)
|
||||||
|
self.assertEqual(response, (2, False))
|
70
cloudbaseinit/tests/plugins/windows/test_sshpublickeys.py
Normal file
70
cloudbaseinit/tests/plugins/windows/test_sshpublickeys.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.plugins.windows import sshpublickeys
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.tests.metadata import fake_json_response
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class SetUserSSHPublicKeysPluginTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._set_ssh_keys_plugin = sshpublickeys.SetUserSSHPublicKeysPlugin()
|
||||||
|
self.fake_data = fake_json_response.get_fake_metadata_json(
|
||||||
|
'2013-04-04')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('os.path')
|
||||||
|
@mock.patch('os.makedirs')
|
||||||
|
def _test_execute(self, mock_os_makedirs, mock_os_path,
|
||||||
|
mock_get_os_utils, user_home):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
fake_shared_data = 'fake data'
|
||||||
|
mock_service.get_meta_data.return_value = self.fake_data
|
||||||
|
CONF.set_override('username', 'fake user')
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_osutils.get_user_home.return_value = user_home
|
||||||
|
mock_os_path.exists.return_value = False
|
||||||
|
|
||||||
|
if user_home is None:
|
||||||
|
self.assertRaises(Exception, self._set_ssh_keys_plugin,
|
||||||
|
mock_service, fake_shared_data)
|
||||||
|
else:
|
||||||
|
with mock.patch('cloudbaseinit.plugins.windows.sshpublickeys'
|
||||||
|
'.open',
|
||||||
|
mock.mock_open(), create=True):
|
||||||
|
response = self._set_ssh_keys_plugin.execute(mock_service,
|
||||||
|
fake_shared_data)
|
||||||
|
mock_service.get_meta_data.assert_called_with('openstack')
|
||||||
|
mock_osutils.get_user_home.assert_called_with('fake user')
|
||||||
|
self.assertEqual(mock_os_path.join.call_count, 2)
|
||||||
|
mock_os_makedirs.assert_called_once_with(mock_os_path.join())
|
||||||
|
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute_with_user_home(self):
|
||||||
|
fake_user_home = os.path.join('fake', 'home')
|
||||||
|
self._test_execute(user_home=fake_user_home)
|
||||||
|
|
||||||
|
def test_execute_with_no_user_home(self):
|
||||||
|
self._test_execute(user_home=None)
|
263
cloudbaseinit/tests/plugins/windows/test_userdata.py
Normal file
263
cloudbaseinit/tests/plugins/windows/test_userdata.py
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import tempfile
|
||||||
|
import uuid
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.metadata.services import base as base_metadata
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import userdata
|
||||||
|
from cloudbaseinit.tests.metadata import fake_json_response
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class UserDataPluginTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._userdata = userdata.UserDataPlugin()
|
||||||
|
self.fake_data = fake_json_response.get_fake_metadata_json(
|
||||||
|
'2013-04-04')
|
||||||
|
|
||||||
|
@mock.patch('os.path')
|
||||||
|
def test_get_plugin_path(self, mock_ospath):
|
||||||
|
mock_ospath.join.return_value = 'fake path'
|
||||||
|
response = self._userdata._get_plugin_path()
|
||||||
|
mock_ospath.join.assert_called_with(
|
||||||
|
mock_ospath.dirname(mock_ospath.dirname(mock_ospath.realpath())),
|
||||||
|
"windows/userdata-plugins")
|
||||||
|
self.assertEqual(response, 'fake path')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._process_userdata')
|
||||||
|
def _test_execute(self, mock_process_userdata, user_data, exception):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
fake_shared_data = 'fake data'
|
||||||
|
if exception:
|
||||||
|
e = base_metadata.NotExistingMetadataException()
|
||||||
|
mock_service.side_effect = e
|
||||||
|
else:
|
||||||
|
mock_service.get_user_data.return_value = user_data
|
||||||
|
response = self._userdata.execute(mock_service, fake_shared_data)
|
||||||
|
mock_service.get_user_data.assert_called_with('openstack')
|
||||||
|
if user_data:
|
||||||
|
mock_process_userdata.assert_called_with(user_data)
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
self._test_execute(user_data=self.fake_data, exception=False)
|
||||||
|
|
||||||
|
def test_execute_no_data(self):
|
||||||
|
self._test_execute(user_data=None, exception=False)
|
||||||
|
|
||||||
|
def test_execute_exception(self):
|
||||||
|
self._test_execute(user_data=None, exception=True)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.handle')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._parse_mime')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._process_part')
|
||||||
|
def _test_process_userdata(self, mock_process_part, mock_parse_mime,
|
||||||
|
mock_handle, user_data):
|
||||||
|
mock_process_part().__iter__.side_effect = ['fake']
|
||||||
|
self._userdata._process_userdata(user_data)
|
||||||
|
print mock_parse_mime.mock_calls
|
||||||
|
print mock_process_part.mock_calls
|
||||||
|
if user_data.startswith('Content-Type: multipart'):
|
||||||
|
mock_parse_mime.assert_called_once_with(user_data)
|
||||||
|
self.assertEqual(mock_process_part.call_count, 1)
|
||||||
|
else:
|
||||||
|
mock_handle.assert_called_once_with(user_data)
|
||||||
|
|
||||||
|
def test_process_userdata_multipart(self):
|
||||||
|
user_data = 'Content-Type: multipart fake data'
|
||||||
|
self._test_process_userdata(user_data=user_data)
|
||||||
|
|
||||||
|
def test_process_userdata(self):
|
||||||
|
user_data = 'fake data'
|
||||||
|
self._test_process_userdata(user_data=user_data)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._get_part_handler')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._begin_part_process_event')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._end_part_process_event')
|
||||||
|
def test_process_part(self, mock_end_part_process_event,
|
||||||
|
mock_begin_part_process_event,
|
||||||
|
mock_get_part_handler):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part_handler = mock.MagicMock()
|
||||||
|
mock_get_part_handler.return_value = mock_part_handler
|
||||||
|
|
||||||
|
self._userdata._process_part(mock_part)
|
||||||
|
|
||||||
|
mock_get_part_handler.assert_called_once_with(mock_part)
|
||||||
|
mock_begin_part_process_event.assert_called_once_with(mock_part)
|
||||||
|
mock_part.get_content_type.assert_called_once_with()
|
||||||
|
mock_part.get_filename.assert_called_once_with()
|
||||||
|
mock_part_handler.process.assert_called_with(mock_part)
|
||||||
|
mock_end_part_process_event.assert_called_with(mock_part)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._get_custom_handler')
|
||||||
|
def test_begin_part_process_event(self, mock_get_custom_handler):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_handler = mock.MagicMock()
|
||||||
|
mock_get_custom_handler.return_value = mock_handler
|
||||||
|
self._userdata._begin_part_process_event(mock_part)
|
||||||
|
mock_part.get_filename.assert_called_with()
|
||||||
|
mock_part.get_payload.assert_called_with()
|
||||||
|
mock_handler.assert_called_with("", "__begin__",
|
||||||
|
mock_part.get_filename(),
|
||||||
|
mock_part.get_payload())
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.UserDataPlugin'
|
||||||
|
'._get_custom_handler')
|
||||||
|
def test_end_part_process_event(self, mock_get_custom_handler):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_handler = mock.MagicMock()
|
||||||
|
mock_get_custom_handler.return_value = mock_handler
|
||||||
|
self._userdata._end_part_process_event(mock_part)
|
||||||
|
mock_part.get_payload.assert_called_with()
|
||||||
|
mock_handler.assert_called_with("", "__end__",
|
||||||
|
mock_part.get_filename(),
|
||||||
|
mock_part.get_payload())
|
||||||
|
|
||||||
|
def test_get_custom_handler(self):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part.get_content_type.return_value = 0
|
||||||
|
self._userdata.plugin_set.has_custom_handlers = True
|
||||||
|
self._userdata.plugin_set.custom_handlers = [0]
|
||||||
|
response = self._userdata._get_custom_handler(mock_part)
|
||||||
|
mock_part.get_content_type.assert_called_with()
|
||||||
|
self.assertEqual(response, 0)
|
||||||
|
|
||||||
|
def test_get_part_handler(self):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part.get_content_type.return_value = 0
|
||||||
|
self._userdata.plugin_set.set = {0: 'fake value'}
|
||||||
|
response = self._userdata._get_part_handler(mock_part)
|
||||||
|
mock_part.get_content_type.assert_called_with()
|
||||||
|
self.assertEqual(response, 'fake value')
|
||||||
|
|
||||||
|
@mock.patch('email.message_from_string')
|
||||||
|
def test_parse_mime(self, mock_message_from_string):
|
||||||
|
mock_msg = mock.MagicMock()
|
||||||
|
mock_message_from_string.return_value = mock_msg
|
||||||
|
response = self._userdata._parse_mime(self.fake_data)
|
||||||
|
mock_message_from_string.assert_called_once_with(self.fake_data)
|
||||||
|
mock_msg.walk.assert_called_once_with()
|
||||||
|
self.assertEqual(response, mock_msg.walk())
|
||||||
|
|
||||||
|
@mock.patch('re.search')
|
||||||
|
@mock.patch('tempfile.gettempdir')
|
||||||
|
@mock.patch('os.remove')
|
||||||
|
@mock.patch('os.path.isdir')
|
||||||
|
@mock.patch('os.path.join')
|
||||||
|
@mock.patch('os.path.exists')
|
||||||
|
@mock.patch('os.path.expandvars')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
def _test_handle(self, mock_get_os_utils, mock_path_expandvars,
|
||||||
|
mock_path_exists, mock_path_join, mock_path_isdir,
|
||||||
|
mock_os_remove, mock_gettempdir, mock_re_search,
|
||||||
|
fake_user_data, directory_exists):
|
||||||
|
#TODO: recheck, these are old!
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
uuid.uuid4 = mock.MagicMock(return_value='randomID')
|
||||||
|
mock_path_join.return_value = 'fake_temp\\randomID'
|
||||||
|
match_instance = mock.MagicMock()
|
||||||
|
path = 'fake_temp\\randomID'
|
||||||
|
args = None
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
|
||||||
|
if fake_user_data == '^rem cmd\s':
|
||||||
|
side_effect = [match_instance]
|
||||||
|
number_of_calls = 1
|
||||||
|
extension = '.cmd'
|
||||||
|
args = [path+extension]
|
||||||
|
shell = True
|
||||||
|
elif fake_user_data == '#!':
|
||||||
|
side_effect = [None, match_instance]
|
||||||
|
number_of_calls = 2
|
||||||
|
extension = '.sh'
|
||||||
|
args = ['bash.exe', path+extension]
|
||||||
|
shell = False
|
||||||
|
elif fake_user_data == '#ps1\s':
|
||||||
|
side_effect = [None, None, match_instance]
|
||||||
|
number_of_calls = 3
|
||||||
|
extension = '.ps1'
|
||||||
|
args = ['powershell.exe', '-ExecutionPolicy', 'RemoteSigned',
|
||||||
|
'-NonInteractive', path+extension]
|
||||||
|
shell = False
|
||||||
|
else:
|
||||||
|
side_effect = [None, None, None, match_instance]
|
||||||
|
number_of_calls = 4
|
||||||
|
extension = '.ps1'
|
||||||
|
shell = False
|
||||||
|
if directory_exists:
|
||||||
|
args = [mock_path_expandvars('%windir%\\sysnative\\'
|
||||||
|
'WindowsPowerShell\\v1.0\\'
|
||||||
|
'powershell.exe'),
|
||||||
|
'-ExecutionPolicy',
|
||||||
|
'RemoteSigned', '-NonInteractive', path+extension]
|
||||||
|
mock_path_isdir.return_value = True
|
||||||
|
else:
|
||||||
|
mock_path_isdir.return_value = False
|
||||||
|
|
||||||
|
mock_re_search.side_effect = side_effect
|
||||||
|
|
||||||
|
with mock.patch('cloudbaseinit.plugins.windows.userdata.open',
|
||||||
|
mock.mock_open(), create=True):
|
||||||
|
response = userdata.handle(fake_user_data)
|
||||||
|
|
||||||
|
tempfile.gettempdir.assert_called_once_with()
|
||||||
|
|
||||||
|
mock_path_join.assert_called_once_with(mock_gettempdir(),
|
||||||
|
str(uuid.uuid4()))
|
||||||
|
assert mock_re_search.call_count == number_of_calls
|
||||||
|
if args:
|
||||||
|
mock_osutils.execute_process.assert_called_with(args, shell)
|
||||||
|
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_handle_batch(self):
|
||||||
|
fake_user_data = '^rem cmd\s'
|
||||||
|
self._test_handle(fake_user_data=fake_user_data,
|
||||||
|
directory_exists=True)
|
||||||
|
|
||||||
|
def test_handle_shell(self):
|
||||||
|
fake_user_data = '^#!'
|
||||||
|
self._test_handle(fake_user_data=fake_user_data,
|
||||||
|
directory_exists=True)
|
||||||
|
|
||||||
|
def test_handle_powershell(self):
|
||||||
|
fake_user_data = '^#ps1\s'
|
||||||
|
self._test_handle(fake_user_data=fake_user_data,
|
||||||
|
directory_exists=True)
|
||||||
|
|
||||||
|
def test_handle_powershell_sysnative(self):
|
||||||
|
fake_user_data = '#ps1_sysnative\s'
|
||||||
|
self._test_handle(fake_user_data=fake_user_data,
|
||||||
|
directory_exists=True)
|
||||||
|
|
||||||
|
def test_handle_powershell_sysnative_no_sysnative(self):
|
||||||
|
fake_user_data = '#ps1_sysnative\s'
|
||||||
|
self._test_handle(fake_user_data=fake_user_data,
|
||||||
|
directory_exists=False)
|
43
cloudbaseinit/tests/plugins/windows/test_userdata_plugins.py
Normal file
43
cloudbaseinit/tests/plugins/windows/test_userdata_plugins.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.plugins.windows import userdata_plugins
|
||||||
|
|
||||||
|
|
||||||
|
class MultipartUserDataPluginTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
fake_path = 'fake path'
|
||||||
|
self._userdata = userdata_plugins.PluginSet(fake_path)
|
||||||
|
|
||||||
|
@mock.patch('glob.glob')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata_plugins.'
|
||||||
|
'load_from_file')
|
||||||
|
def test_load(self, mock_load_from_file, mock_glob):
|
||||||
|
fake_files = ['fake_file.py']
|
||||||
|
mock_plugin = mock.MagicMock()
|
||||||
|
mock_glob.return_value = fake_files
|
||||||
|
mock_load_from_file.return_value = mock_plugin
|
||||||
|
|
||||||
|
self._userdata.load()
|
||||||
|
mock_glob.assert_called_once_with(self._userdata.path + '/*.py')
|
||||||
|
mock_load_from_file.assert_called_once_with('fake_file.py',
|
||||||
|
self._userdata)
|
||||||
|
self.assertEqual(self._userdata.set[mock_plugin.type], mock_plugin)
|
156
cloudbaseinit/tests/plugins/windows/test_winrmcertificateauth.py
Normal file
156
cloudbaseinit/tests/plugins/windows/test_winrmcertificateauth.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
_ctypes_mock = mock.MagicMock()
|
||||||
|
_win32com_mock = mock.MagicMock()
|
||||||
|
_pywintypes_mock = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_dict = {'ctypes': _ctypes_mock,
|
||||||
|
'win32com': _win32com_mock,
|
||||||
|
'pywintypes': _pywintypes_mock}
|
||||||
|
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins import constants
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigWinRMCertificateAuthPluginTests(unittest.TestCase):
|
||||||
|
@mock.patch.dict(sys.modules, mock_dict)
|
||||||
|
def setUp(self):
|
||||||
|
winrmcert = importlib.import_module('cloudbaseinit.plugins.windows.'
|
||||||
|
'winrmcertificateauth')
|
||||||
|
self.x509 = importlib.import_module('cloudbaseinit.plugins.windows'
|
||||||
|
'.x509')
|
||||||
|
self._certif_auth = winrmcert.ConfigWinRMCertificateAuthPlugin()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
reload(sys)
|
||||||
|
|
||||||
|
def _test_get_client_auth_cert(self, chunk):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_meta_data = mock.MagicMock()
|
||||||
|
mock_meta = mock.MagicMock()
|
||||||
|
mock_service.get_meta_data.return_value = mock_meta_data
|
||||||
|
mock_meta_data.get.return_value = mock_meta
|
||||||
|
mock_meta.get.side_effect = chunk
|
||||||
|
mock_service.get_user_data.return_value = self.x509.PEM_HEADER
|
||||||
|
|
||||||
|
response = self._certif_auth._get_client_auth_cert(mock_service)
|
||||||
|
mock_service.get_meta_data.assert_called_once_with('openstack')
|
||||||
|
mock_meta_data.get.assert_called_once_with('meta')
|
||||||
|
if chunk == [None]:
|
||||||
|
mock_service.get_user_data.assert_called_once_with('openstack')
|
||||||
|
mock_meta.get.assert_called_once_with('admin_cert0')
|
||||||
|
self.assertEqual(response, self.x509.PEM_HEADER)
|
||||||
|
else:
|
||||||
|
expected = [mock.call('admin_cert0'), mock.call('admin_cert1')]
|
||||||
|
self.assertEqual(mock_meta.get.call_args_list, expected)
|
||||||
|
self.assertEqual(response, 'fake data')
|
||||||
|
|
||||||
|
def test_get_client_auth_cert(self):
|
||||||
|
chunk = ['fake data', None]
|
||||||
|
self._test_get_client_auth_cert(chunk=chunk)
|
||||||
|
|
||||||
|
def test_get_client_auth_cert_no_cert_data(self):
|
||||||
|
self._test_get_client_auth_cert(chunk=[None])
|
||||||
|
|
||||||
|
def _test_get_credentials(self, fake_user, fake_password):
|
||||||
|
mock_shared_data = mock.MagicMock()
|
||||||
|
mock_shared_data.get.side_effect = [fake_user, fake_password]
|
||||||
|
if fake_user is None or fake_password is None:
|
||||||
|
self.assertRaises(Exception,
|
||||||
|
self._certif_auth._get_credentials,
|
||||||
|
mock_shared_data)
|
||||||
|
else:
|
||||||
|
response = self._certif_auth._get_credentials(mock_shared_data)
|
||||||
|
expected = [mock.call(constants.SHARED_DATA_USERNAME),
|
||||||
|
mock.call(constants.SHARED_DATA_PASSWORD)]
|
||||||
|
self.assertEqual(mock_shared_data.get.call_args_list, expected)
|
||||||
|
mock_shared_data.__setitem__.assert_called_once_with(
|
||||||
|
'admin_password', None)
|
||||||
|
self.assertEqual(response, (fake_user, fake_password))
|
||||||
|
|
||||||
|
def test_test_get_credentials(self):
|
||||||
|
self._test_get_credentials(fake_user='fake user',
|
||||||
|
fake_password='fake password')
|
||||||
|
|
||||||
|
def test_test_get_credentials_no_user(self):
|
||||||
|
self._test_get_credentials(fake_user=None,
|
||||||
|
fake_password='fake password')
|
||||||
|
|
||||||
|
def test_test_get_credentials_no_password(self):
|
||||||
|
self._test_get_credentials(fake_user='fake user',
|
||||||
|
fake_password=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmcertificateauth'
|
||||||
|
'.ConfigWinRMCertificateAuthPlugin._get_credentials')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmcertificateauth'
|
||||||
|
'.ConfigWinRMCertificateAuthPlugin._get_client_auth_cert')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'.import_cert')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig')
|
||||||
|
def _test_execute(self, mock_WinRMConfig, mock_import_cert,
|
||||||
|
mock_get_client_auth_cert, mock_get_credentials,
|
||||||
|
cert_data, cert_upn):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_cert_thumprint = mock.MagicMock()
|
||||||
|
fake_credentials = ('fake user', 'fake password')
|
||||||
|
mock_shared_data = mock.MagicMock()
|
||||||
|
mock_get_client_auth_cert.return_value = cert_data
|
||||||
|
mock_get_credentials.return_value = fake_credentials
|
||||||
|
mock_import_cert.return_value = (mock_cert_thumprint, cert_upn)
|
||||||
|
mock_WinRMConfig.get_cert_mapping.return_value = True
|
||||||
|
|
||||||
|
response = self._certif_auth.execute(mock_service,
|
||||||
|
mock_shared_data)
|
||||||
|
if not cert_data or not cert_upn:
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
else:
|
||||||
|
mock_get_client_auth_cert.assert_called_once_with(mock_service)
|
||||||
|
mock_get_credentials.assert_called_once_with(mock_shared_data)
|
||||||
|
mock_import_cert.assert_called_once_with(
|
||||||
|
cert_data, store_name=self.x509.STORE_NAME_ROOT)
|
||||||
|
|
||||||
|
mock_WinRMConfig().set_auth_config.assert_called_once_with(
|
||||||
|
certificate=True)
|
||||||
|
mock_WinRMConfig().get_cert_mapping.assert_called_once_with(
|
||||||
|
mock_cert_thumprint, cert_upn)
|
||||||
|
mock_WinRMConfig().delete_cert_mapping.assert_called_once_with(
|
||||||
|
mock_cert_thumprint, cert_upn)
|
||||||
|
mock_WinRMConfig().create_cert_mapping.assert_called_once_with(
|
||||||
|
mock_cert_thumprint, cert_upn, 'fake user',
|
||||||
|
'fake password')
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
cert_data = 'fake cert data'
|
||||||
|
cert_upn = mock.MagicMock()
|
||||||
|
self._test_execute(cert_data=cert_data, cert_upn=cert_upn)
|
||||||
|
|
||||||
|
def test_execute_no_cert_data(self):
|
||||||
|
cert_upn = mock.MagicMock()
|
||||||
|
self._test_execute(cert_data=None, cert_upn=cert_upn)
|
||||||
|
|
||||||
|
def test_execute_no_cert_upn(self):
|
||||||
|
cert_data = 'fake cert data'
|
||||||
|
self._test_execute(cert_data=cert_data, cert_upn=None)
|
378
cloudbaseinit/tests/plugins/windows/test_winrmconfig.py
Normal file
378
cloudbaseinit/tests/plugins/windows/test_winrmconfig.py
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
from cloudbaseinit.plugins.windows import winrmconfig
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "win32", "requires Windows")
|
||||||
|
class WinRMConfigTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._winrmconfig = winrmconfig.WinRMConfig()
|
||||||
|
|
||||||
|
@mock.patch('win32com.client.Dispatch')
|
||||||
|
def test_get_wsman_session(self, mock_Dispatch):
|
||||||
|
mock_wsman = mock.MagicMock()
|
||||||
|
mock_Dispatch.return_value = mock_wsman
|
||||||
|
response = self._winrmconfig._get_wsman_session()
|
||||||
|
mock_Dispatch.assert_called_once_with('WSMan.Automation')
|
||||||
|
mock_wsman.CreateSession.assert_called_once_with()
|
||||||
|
self.assertEqual(response, mock_wsman.CreateSession())
|
||||||
|
|
||||||
|
@mock.patch('re.match')
|
||||||
|
def test_get_node_tag(self, mock_match):
|
||||||
|
mock_tag = mock.MagicMock()
|
||||||
|
response = self._winrmconfig._get_node_tag(mock_tag)
|
||||||
|
mock_match.assert_called_once_with("^{.*}(.*)$", mock_tag)
|
||||||
|
self.assertEqual(response, mock_match().groups().__getitem__())
|
||||||
|
|
||||||
|
@mock.patch('xml.etree.ElementTree.fromstring')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_node_tag')
|
||||||
|
def _test_parse_listener_xml(self, mock_get_node_tag, mock_fromstring,
|
||||||
|
data_xml, tag=None, text='Fake'):
|
||||||
|
mock_node = mock.MagicMock()
|
||||||
|
mock_node.tag = tag
|
||||||
|
mock_node.text = text
|
||||||
|
fake_tree = [mock_node]
|
||||||
|
mock_get_node_tag.return_value = tag
|
||||||
|
mock_fromstring.return_value = fake_tree
|
||||||
|
response = self._winrmconfig._parse_listener_xml(data_xml=data_xml)
|
||||||
|
if data_xml is None:
|
||||||
|
self.assertEqual(response, None)
|
||||||
|
else:
|
||||||
|
mock_fromstring.assert_called_once_with(data_xml)
|
||||||
|
mock_get_node_tag.assert_called_once_with(tag)
|
||||||
|
if tag is "ListeningOn":
|
||||||
|
self.assertEqual(response, {'ListeningOn': ['Fake']})
|
||||||
|
elif tag is "Enabled":
|
||||||
|
if text is 'true':
|
||||||
|
self.assertEqual(response, {'ListeningOn': [],
|
||||||
|
'Enabled': True})
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, {'ListeningOn': [],
|
||||||
|
'Enabled': False})
|
||||||
|
elif tag is 'Port':
|
||||||
|
self.assertEqual(response, {'ListeningOn': [],
|
||||||
|
'Port': int(text)})
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, {'ListeningOn': [],
|
||||||
|
tag: text})
|
||||||
|
|
||||||
|
def test_parse_listener_xml_no_data(self):
|
||||||
|
self._test_parse_listener_xml(data_xml=None)
|
||||||
|
|
||||||
|
def test_parse_listener_xml_listening_on(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag="ListeningOn")
|
||||||
|
|
||||||
|
def test_parse_listener_xml_enabled_true(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data',
|
||||||
|
tag="Enabled", text='true')
|
||||||
|
|
||||||
|
def test_parse_listener_xml_enabled_false(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag='Enabled',
|
||||||
|
text='false')
|
||||||
|
|
||||||
|
def test_parse_listener_xml_port(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag='Port',
|
||||||
|
text='9999')
|
||||||
|
|
||||||
|
def test_parse_listener_xml_other_tag(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag='fake tag',
|
||||||
|
text='fake text')
|
||||||
|
|
||||||
|
@mock.patch('xml.etree.ElementTree.fromstring')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_node_tag')
|
||||||
|
def _test_parse_cert_mapping_xml(self, mock_get_node_tag,
|
||||||
|
mock_fromstring, data_xml, tag=None,
|
||||||
|
text='Fake'):
|
||||||
|
mock_node = mock.MagicMock()
|
||||||
|
mock_node.tag = tag
|
||||||
|
mock_node.text = text
|
||||||
|
fake_tree = [mock_node]
|
||||||
|
mock_get_node_tag.return_value = tag
|
||||||
|
mock_fromstring.return_value = fake_tree
|
||||||
|
response = self._winrmconfig._parse_cert_mapping_xml(data_xml=data_xml)
|
||||||
|
if data_xml is None:
|
||||||
|
self.assertEqual(response, None)
|
||||||
|
else:
|
||||||
|
mock_fromstring.assert_called_once_with(data_xml)
|
||||||
|
mock_get_node_tag.assert_called_once_with(tag)
|
||||||
|
if tag is "Enabled":
|
||||||
|
if text is 'true':
|
||||||
|
self.assertEqual(response, {'Enabled': True})
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, {'Enabled': False})
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, {tag: text})
|
||||||
|
|
||||||
|
def test_parse_cert_mapping_xml_no_data(self):
|
||||||
|
self._test_parse_cert_mapping_xml(data_xml=None)
|
||||||
|
|
||||||
|
def test_parse_cert_mapping_xml_enabled_true(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data',
|
||||||
|
tag="Enabled", text='true')
|
||||||
|
|
||||||
|
def test_parse_cert_mapping_xml_enabled_false(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag='Enabled',
|
||||||
|
text='false')
|
||||||
|
|
||||||
|
def test_parse_cert_mapping_xml_other_tag(self):
|
||||||
|
self._test_parse_listener_xml(data_xml='fake data', tag='fake tag',
|
||||||
|
text='fake text')
|
||||||
|
|
||||||
|
def _test_get_xml_bool(self, value):
|
||||||
|
response = self._winrmconfig._get_xml_bool(value)
|
||||||
|
if value:
|
||||||
|
self.assertEqual(response, 'true')
|
||||||
|
else:
|
||||||
|
self.assertEqual(response, 'false')
|
||||||
|
|
||||||
|
def test_get_xml_bool_true(self):
|
||||||
|
self._test_get_xml_bool(value='fake value')
|
||||||
|
|
||||||
|
def test_get_xml_bool_false(self):
|
||||||
|
self._test_get_xml_bool(value=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_wsman_session')
|
||||||
|
def _test_get_resource(self, mock_get_wsman_session, resource):
|
||||||
|
fake_session = mock.MagicMock()
|
||||||
|
fake_uri = 'fake:\\uri'
|
||||||
|
fake_session.Get.side_effect = [resource]
|
||||||
|
mock_get_wsman_session.return_value = fake_session
|
||||||
|
if resource is Exception:
|
||||||
|
self.assertRaises(Exception, self._winrmconfig._get_resource,
|
||||||
|
fake_uri)
|
||||||
|
else:
|
||||||
|
response = self._winrmconfig._get_resource(fake_uri)
|
||||||
|
mock_get_wsman_session.assert_called_once_with()
|
||||||
|
fake_session.Get.assert_called_once_with(fake_uri)
|
||||||
|
self.assertEqual(response, resource)
|
||||||
|
|
||||||
|
def test_get_resource(self):
|
||||||
|
self._test_get_resource(resource='fake resource')
|
||||||
|
|
||||||
|
def test_get_resource_exception(self):
|
||||||
|
self._test_get_resource(resource=Exception)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_wsman_session')
|
||||||
|
def test_delete_resource(self, mock_get_wsman_session):
|
||||||
|
fake_session = mock.MagicMock()
|
||||||
|
fake_uri = 'fake:\\uri'
|
||||||
|
mock_get_wsman_session.return_value = fake_session
|
||||||
|
self._winrmconfig._delete_resource(fake_uri)
|
||||||
|
fake_session.Delete.assert_called_once_with(fake_uri)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_wsman_session')
|
||||||
|
def test_create_resource(self, mock_get_wsman_session):
|
||||||
|
fake_session = mock.MagicMock()
|
||||||
|
fake_uri = 'fake:\\uri'
|
||||||
|
mock_get_wsman_session.return_value = fake_session
|
||||||
|
self._winrmconfig._create_resource(fake_uri, 'fake data')
|
||||||
|
fake_session.Create.assert_called_once_with(fake_uri, 'fake data')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_parse_cert_mapping_xml')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_resource')
|
||||||
|
def test_get_cert_mapping(self, mock_get_resource,
|
||||||
|
mock_parse_cert_mapping_xml):
|
||||||
|
fake_dict = {'issuer': 'issuer',
|
||||||
|
'subject': 'subject',
|
||||||
|
'uri': 'fake:\\uri'}
|
||||||
|
mock_parse_cert_mapping_xml.return_value = 'fake response'
|
||||||
|
mock_get_resource.return_value = 'fake resource'
|
||||||
|
response = self._winrmconfig.get_cert_mapping('issuer', 'subject',
|
||||||
|
uri='fake:\\uri')
|
||||||
|
mock_parse_cert_mapping_xml.assert_called_with('fake resource')
|
||||||
|
mock_get_resource.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_CERTMAPPING_URI % fake_dict)
|
||||||
|
self.assertEqual(response, 'fake response')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_delete_resource')
|
||||||
|
def test_delete_cert_mapping(self, mock_delete_resource):
|
||||||
|
fake_dict = {'issuer': 'issuer',
|
||||||
|
'subject': 'subject',
|
||||||
|
'uri': 'fake:\\uri'}
|
||||||
|
self._winrmconfig.delete_cert_mapping('issuer', 'subject',
|
||||||
|
uri='fake:\\uri')
|
||||||
|
mock_delete_resource.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_CERTMAPPING_URI % fake_dict)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_xml_bool')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_create_resource')
|
||||||
|
def test_create_cert_mapping(self, mock_create_resource,
|
||||||
|
mock_get_xml_bool):
|
||||||
|
fake_dict = {'issuer': 'issuer',
|
||||||
|
'subject': 'subject',
|
||||||
|
'uri': 'fake:\\uri'}
|
||||||
|
mock_get_xml_bool.return_value = True
|
||||||
|
self._winrmconfig.create_cert_mapping(
|
||||||
|
issuer='issuer', subject='subject', username='fake user',
|
||||||
|
password='fake password', uri='fake:\\uri', enabled=True)
|
||||||
|
mock_get_xml_bool.assert_called_once_with(True)
|
||||||
|
mock_create_resource.assert_called_once_with(
|
||||||
|
self._winrmconfig._SERVICE_CERTMAPPING_URI % fake_dict,
|
||||||
|
'<p:certmapping xmlns:p="http://schemas.microsoft.com/wbem/wsman/'
|
||||||
|
'1/config/service/certmapping.xsd">'
|
||||||
|
'<p:Enabled>%(enabled)s</p:Enabled>'
|
||||||
|
'<p:Password>%(password)s</p:Password>'
|
||||||
|
'<p:UserName>%(username)s</p:UserName>'
|
||||||
|
'</p:certmapping>' % {'enabled': True,
|
||||||
|
'username': 'fake user',
|
||||||
|
'password': 'fake password'})
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_resource')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_parse_listener_xml')
|
||||||
|
def test_get_listener(self, mock_parse_listener_xml, mock_get_resource):
|
||||||
|
dict = {'protocol': 'HTTPS',
|
||||||
|
'address': 'fake:\\address'}
|
||||||
|
mock_get_resource.return_value = 'fake resource'
|
||||||
|
mock_parse_listener_xml.return_value = 'fake response'
|
||||||
|
response = self._winrmconfig.get_listener(protocol='HTTPS',
|
||||||
|
address="fake:\\address")
|
||||||
|
mock_get_resource.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_LISTENER_URI % dict)
|
||||||
|
mock_parse_listener_xml.assert_called_once_with('fake resource')
|
||||||
|
self.assertEqual(response, 'fake response')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_delete_resource')
|
||||||
|
def test_delete_listener(self, mock_delete_resource):
|
||||||
|
dict = {'protocol': 'HTTPS',
|
||||||
|
'address': 'fake:\\address'}
|
||||||
|
self._winrmconfig.delete_listener(protocol='HTTPS',
|
||||||
|
address="fake:\\address")
|
||||||
|
mock_delete_resource.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_LISTENER_URI % dict)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_create_resource')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_xml_bool')
|
||||||
|
def test_create_listener(self, mock_get_xml_bool, mock_create_resource):
|
||||||
|
dict = {'protocol': 'HTTPS',
|
||||||
|
'address': 'fake:\\address'}
|
||||||
|
mock_get_xml_bool.return_value = True
|
||||||
|
self._winrmconfig.create_listener(protocol='HTTPS',
|
||||||
|
cert_thumbprint=None,
|
||||||
|
address="fake:\\address",
|
||||||
|
enabled=True)
|
||||||
|
mock_create_resource.assert_called_once_with(
|
||||||
|
self._winrmconfig._SERVICE_LISTENER_URI % dict,
|
||||||
|
'<p:Listener xmlns:p="http://schemas.microsoft.com/'
|
||||||
|
'wbem/wsman/1/config/listener.xsd">'
|
||||||
|
'<p:Enabled>%(enabled)s</p:Enabled>'
|
||||||
|
'<p:CertificateThumbPrint>%(cert_thumbprint)s'
|
||||||
|
'</p:CertificateThumbPrint>'
|
||||||
|
'<p:URLPrefix>wsman</p:URLPrefix>'
|
||||||
|
'</p:Listener>' % {"enabled": True,
|
||||||
|
"cert_thumbprint": None})
|
||||||
|
|
||||||
|
@mock.patch('xml.etree.ElementTree.fromstring')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_node_tag')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_resource')
|
||||||
|
def test_get_auth_config(self, mock_get_resource, mock_get_node_tag,
|
||||||
|
mock_fromstring):
|
||||||
|
mock_node = mock.MagicMock()
|
||||||
|
mock_node.tag = 'tag'
|
||||||
|
mock_node.text = 'value'
|
||||||
|
fake_tree = [mock_node]
|
||||||
|
mock_get_resource.return_value = 'fake data xml'
|
||||||
|
mock_fromstring.return_value = fake_tree
|
||||||
|
mock_get_node_tag.return_value = 'tag'
|
||||||
|
|
||||||
|
response = self._winrmconfig.get_auth_config()
|
||||||
|
|
||||||
|
mock_get_resource.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_AUTH_URI)
|
||||||
|
mock_fromstring.assert_called_once_with('fake data xml')
|
||||||
|
mock_get_node_tag.assert_called_once_with(mock_node.tag)
|
||||||
|
self.assertEqual(response, {'tag': 'value'})
|
||||||
|
|
||||||
|
@mock.patch('xml.etree.ElementTree.fromstring')
|
||||||
|
@mock.patch('xml.etree.ElementTree.tostring')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_wsman_session')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig.'
|
||||||
|
'_get_xml_bool')
|
||||||
|
def test_set_auth_config(self, mock_get_xml_bool, mock_get_wsman_session,
|
||||||
|
mock_tostring, mock_fromstring):
|
||||||
|
mock_session = mock.MagicMock()
|
||||||
|
mock_tree = mock.MagicMock()
|
||||||
|
mock_node = mock.MagicMock()
|
||||||
|
base_url = 'http://schemas.microsoft.com/wbem/wsman/1/config/service/'
|
||||||
|
expected_find = [
|
||||||
|
mock.call('.//cfg:Certificate', namespaces={
|
||||||
|
'cfg': base_url + 'auth'}),
|
||||||
|
mock.call('.//cfg:Kerberos',
|
||||||
|
namespaces={'cfg': base_url + 'auth'}),
|
||||||
|
mock.call('.//cfg:CbtHardeningLevel',
|
||||||
|
namespaces={'cfg': base_url + 'auth'}),
|
||||||
|
mock.call('.//cfg:Negotiate',
|
||||||
|
namespaces={'cfg': base_url + 'auth'}),
|
||||||
|
mock.call('.//cfg:CredSSP',
|
||||||
|
namespaces={'cfg': base_url + 'auth'}),
|
||||||
|
mock.call('.//cfg:Basic',
|
||||||
|
namespaces={'cfg': base_url + 'auth'})]
|
||||||
|
expected_get_xml_bool = [mock.call('certificate'),
|
||||||
|
mock.call('kerberos'),
|
||||||
|
mock.call('cbt_hardening_level'),
|
||||||
|
mock.call('negotiate'),
|
||||||
|
mock.call('credSSP'),
|
||||||
|
mock.call('basic')]
|
||||||
|
|
||||||
|
mock_get_wsman_session.return_value = mock_session
|
||||||
|
mock_session.Get.return_value = 'fake xml'
|
||||||
|
mock_fromstring.return_value = mock_tree
|
||||||
|
mock_get_xml_bool.return_value = 'true'
|
||||||
|
mock_tostring.return_value = 'fake xml'
|
||||||
|
mock_tree.find.return_value = mock_node
|
||||||
|
mock_node.text.lower.return_value = 'old value'
|
||||||
|
|
||||||
|
self._winrmconfig.set_auth_config(
|
||||||
|
basic='basic', kerberos='kerberos', negotiate='negotiate',
|
||||||
|
certificate='certificate', credSSP='credSSP',
|
||||||
|
cbt_hardening_level='cbt_hardening_level')
|
||||||
|
self.assertEqual(mock_tree.find.call_args_list, expected_find)
|
||||||
|
self.assertEqual(mock_get_xml_bool.call_args_list,
|
||||||
|
expected_get_xml_bool)
|
||||||
|
|
||||||
|
mock_get_wsman_session.assert_called_once_with()
|
||||||
|
mock_session.Get.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_AUTH_URI)
|
||||||
|
mock_fromstring.assert_called_once_with('fake xml')
|
||||||
|
mock_session.Put.assert_called_with(
|
||||||
|
self._winrmconfig._SERVICE_AUTH_URI, 'fake xml')
|
117
cloudbaseinit/tests/plugins/windows/test_winrmlistener.py
Normal file
117
cloudbaseinit/tests/plugins/windows/test_winrmlistener.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
_mock_wintypes = mock.MagicMock()
|
||||||
|
mock_dict = {'ctypes.wintypes': _mock_wintypes}
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigWinRMListenerPluginTests(unittest.TestCase):
|
||||||
|
@mock.patch.dict(sys.modules, mock_dict)
|
||||||
|
def setUp(self):
|
||||||
|
winrmlistener = importlib.import_module('cloudbaseinit.plugins.'
|
||||||
|
'windows.winrmlistener')
|
||||||
|
self._winrmlistener = winrmlistener.ConfigWinRMListenerPlugin()
|
||||||
|
|
||||||
|
def _test_check_winrm_service(self, service_exists):
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_osutils.check_service_exists.return_value = service_exists
|
||||||
|
mock_osutils.SERVICE_START_MODE_MANUAL = 'fake start'
|
||||||
|
mock_osutils.SERVICE_START_MODE_DISABLED = 'fake start'
|
||||||
|
mock_osutils.SERVICE_STATUS_STOPPED = 'fake status'
|
||||||
|
mock_osutils.get_service_start_mode.return_value = 'fake start'
|
||||||
|
mock_osutils.get_service_status.return_value = 'fake status'
|
||||||
|
|
||||||
|
response = self._winrmlistener._check_winrm_service(mock_osutils)
|
||||||
|
if not service_exists:
|
||||||
|
self.assertEqual(response, False)
|
||||||
|
else:
|
||||||
|
|
||||||
|
mock_osutils.get_service_start_mode.assert_called_once_with(
|
||||||
|
self._winrmlistener._winrm_service_name)
|
||||||
|
mock_osutils.get_service_start_mode.assert_called_once_with(
|
||||||
|
self._winrmlistener._winrm_service_name)
|
||||||
|
mock_osutils.set_service_start_mode.assert_called_once_with(
|
||||||
|
self._winrmlistener._winrm_service_name,
|
||||||
|
mock_osutils .SERVICE_START_MODE_AUTOMATIC)
|
||||||
|
mock_osutils.get_service_status.assert_called_once_with(
|
||||||
|
self._winrmlistener._winrm_service_name)
|
||||||
|
mock_osutils.start_service.assert_called_once_with(
|
||||||
|
self._winrmlistener._winrm_service_name)
|
||||||
|
self.assertEqual(response, True)
|
||||||
|
|
||||||
|
def test_check_winrm_service(self):
|
||||||
|
self._test_check_winrm_service(service_exists=True)
|
||||||
|
|
||||||
|
def test_check_winrm_service_no_service(self):
|
||||||
|
self._test_check_winrm_service(service_exists=False)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmlistener.'
|
||||||
|
'ConfigWinRMListenerPlugin._check_winrm_service')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.winrmconfig.WinRMConfig')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'.create_self_signed_cert')
|
||||||
|
def _test_execute(self, mock_create_cert, mock_WinRMConfig,
|
||||||
|
mock_check_winrm_service, mock_get_os_utils,
|
||||||
|
service_status):
|
||||||
|
mock_service = mock.MagicMock()
|
||||||
|
mock_listener_config = mock.MagicMock()
|
||||||
|
mock_cert_thumbprint = mock.MagicMock()
|
||||||
|
shared_data = 'fake data'
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
mock_check_winrm_service.return_value = service_status
|
||||||
|
mock_create_cert.return_value = mock_cert_thumbprint
|
||||||
|
mock_WinRMConfig().get_listener.return_value = mock_listener_config
|
||||||
|
mock_listener_config.get.return_value = 9999
|
||||||
|
|
||||||
|
response = self._winrmlistener.execute(mock_service, shared_data)
|
||||||
|
|
||||||
|
mock_get_os_utils.assert_called_once_with()
|
||||||
|
mock_check_winrm_service.assert_called_once_with(mock_osutils)
|
||||||
|
|
||||||
|
if not service_status:
|
||||||
|
self.assertEqual(response, (2, False))
|
||||||
|
else:
|
||||||
|
mock_WinRMConfig().set_auth_config.assert_called_once_with(
|
||||||
|
basic=CONF.winrm_enable_basic_auth)
|
||||||
|
mock_create_cert.assert_called_once_with(
|
||||||
|
self._winrmlistener._cert_subject)
|
||||||
|
|
||||||
|
mock_WinRMConfig().get_listener.assert_called_with(
|
||||||
|
protocol="HTTPS")
|
||||||
|
mock_WinRMConfig().delete_listener.assert_called_once_with(
|
||||||
|
protocol="HTTPS")
|
||||||
|
mock_WinRMConfig().create_listener.assert_called_once_with(
|
||||||
|
protocol="HTTPS", cert_thumbprint=mock_cert_thumbprint)
|
||||||
|
mock_listener_config.get.assert_called_once_with("Port")
|
||||||
|
mock_osutils.firewall_create_rule.assert_called_once_with(
|
||||||
|
"WinRM HTTPS", 9999, mock_osutils.PROTOCOL_TCP)
|
||||||
|
self.assertEqual(response, (1, False))
|
||||||
|
|
||||||
|
def test_execute(self):
|
||||||
|
self._test_execute(service_status=True)
|
||||||
|
|
||||||
|
def test_execute_service_status_is_false(self):
|
||||||
|
self._test_execute(service_status=False)
|
383
cloudbaseinit/tests/plugins/windows/test_x509.py
Normal file
383
cloudbaseinit/tests/plugins/windows/test_x509.py
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
from cloudbaseinit.plugins.windows import cryptoapi
|
||||||
|
from cloudbaseinit.plugins.windows import x509
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform == "win32", "requires Windows")
|
||||||
|
class CryptoAPICertManagerTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self._x509 = x509.CryptoAPICertManager()
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.free')
|
||||||
|
@mock.patch('ctypes.c_ubyte')
|
||||||
|
@mock.patch('ctypes.POINTER')
|
||||||
|
@mock.patch('ctypes.cast')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.malloc')
|
||||||
|
@mock.patch('ctypes.byref')
|
||||||
|
@mock.patch('ctypes.wintypes.DWORD')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertGetCertificateContextProperty')
|
||||||
|
def _test_get_cert_thumprint(self,
|
||||||
|
mock_CertGetCertificateContextProperty,
|
||||||
|
mock_DWORD, mock_byref, mock_malloc,
|
||||||
|
mock_cast, mock_POINTER, mock_c_ubyte,
|
||||||
|
mock_free, ret_val):
|
||||||
|
|
||||||
|
mock_pointer = mock.MagicMock()
|
||||||
|
fake_cert_context_p = 'fake context'
|
||||||
|
mock_DWORD().value = 10
|
||||||
|
mock_CertGetCertificateContextProperty.return_value = ret_val
|
||||||
|
mock_POINTER.return_value = mock_pointer
|
||||||
|
mock_cast().contents = [16]
|
||||||
|
if not ret_val:
|
||||||
|
self.assertRaises(cryptoapi.CryptoAPIException,
|
||||||
|
self._x509._get_cert_thumprint,
|
||||||
|
fake_cert_context_p)
|
||||||
|
else:
|
||||||
|
expected = [mock.call(fake_cert_context_p,
|
||||||
|
cryptoapi.CERT_SHA1_HASH_PROP_ID,
|
||||||
|
None, mock_byref()),
|
||||||
|
mock.call(fake_cert_context_p,
|
||||||
|
cryptoapi.CERT_SHA1_HASH_PROP_ID,
|
||||||
|
mock_malloc(), mock_byref())]
|
||||||
|
response = self._x509._get_cert_thumprint(fake_cert_context_p)
|
||||||
|
self.assertEqual(
|
||||||
|
mock_CertGetCertificateContextProperty.call_args_list,
|
||||||
|
expected)
|
||||||
|
mock_malloc.assert_called_with(mock_DWORD())
|
||||||
|
mock_cast.assert_called_with(mock_malloc(), mock_pointer)
|
||||||
|
mock_free.assert_called_with(mock_malloc())
|
||||||
|
self.assertEqual(response, '10')
|
||||||
|
|
||||||
|
def test_get_cert_thumprint(self):
|
||||||
|
self._test_get_cert_thumprint(ret_val=True)
|
||||||
|
|
||||||
|
def test_get_cert_thumprint_GetCertificateContextProperty_exception(self):
|
||||||
|
self._test_get_cert_thumprint(ret_val=False)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CryptDestroyKey')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CryptReleaseContext')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CryptGenKey')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CryptAcquireContext')
|
||||||
|
@mock.patch('ctypes.byref')
|
||||||
|
@mock.patch('ctypes.wintypes.HANDLE')
|
||||||
|
def _test_generate_key(self, mock_HANDLE, mock_byref,
|
||||||
|
mock_CryptAcquireContext, mock_CryptGenKey,
|
||||||
|
mock_CryptReleaseContext, mock_CryptDestroyKey,
|
||||||
|
acquired_context, generate_key_ret_val):
|
||||||
|
mock_CryptAcquireContext.return_value = acquired_context
|
||||||
|
mock_CryptGenKey.return_value = generate_key_ret_val
|
||||||
|
if not acquired_context:
|
||||||
|
self.assertRaises(cryptoapi.CryptoAPIException,
|
||||||
|
self._x509._generate_key,
|
||||||
|
'fake container', True)
|
||||||
|
else:
|
||||||
|
if generate_key_ret_val is None:
|
||||||
|
self.assertRaises(cryptoapi.CryptoAPIException,
|
||||||
|
self._x509._generate_key, 'fake container',
|
||||||
|
True)
|
||||||
|
mock_byref.assert_called_with(mock_HANDLE())
|
||||||
|
else:
|
||||||
|
self._x509._generate_key('fake container', True)
|
||||||
|
mock_CryptAcquireContext.assert_called_with(
|
||||||
|
mock_byref(), 'fake container', None,
|
||||||
|
cryptoapi.PROV_RSA_FULL, cryptoapi.CRYPT_MACHINE_KEYSET)
|
||||||
|
mock_CryptGenKey.assert_called_with(mock_HANDLE(),
|
||||||
|
cryptoapi.AT_SIGNATURE,
|
||||||
|
0x08000000, mock_HANDLE())
|
||||||
|
mock_CryptDestroyKey.assert_called_once_with(
|
||||||
|
mock_HANDLE())
|
||||||
|
mock_CryptReleaseContext.assert_called_once_with(
|
||||||
|
mock_HANDLE(), 0)
|
||||||
|
|
||||||
|
def test_generate_key(self):
|
||||||
|
self._test_generate_key(acquired_context=True,
|
||||||
|
generate_key_ret_val='fake key')
|
||||||
|
|
||||||
|
def test_generate_key_GetCertificateContextProperty_exception(self):
|
||||||
|
self._test_generate_key(acquired_context=False,
|
||||||
|
generate_key_ret_val='fake key')
|
||||||
|
|
||||||
|
def test_generate_key_CryptGenKey_exception(self):
|
||||||
|
self._test_generate_key(acquired_context=True,
|
||||||
|
generate_key_ret_val=None)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.free')
|
||||||
|
@mock.patch('copy.copy')
|
||||||
|
@mock.patch('ctypes.byref')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.malloc')
|
||||||
|
@mock.patch('ctypes.POINTER')
|
||||||
|
@mock.patch('ctypes.cast')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'._generate_key')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'._get_cert_thumprint')
|
||||||
|
@mock.patch('uuid.uuid4')
|
||||||
|
@mock.patch('ctypes.wintypes.DWORD')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertStrToName')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CRYPTOAPI_BLOB')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CRYPT_KEY_PROV_INFO')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CRYPT_ALGORITHM_IDENTIFIER')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'SYSTEMTIME')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'GetSystemTime')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertCreateSelfSignCertificate')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertAddEnhancedKeyUsageIdentifier')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertOpenStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertAddCertificateContextToStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertCloseStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertFreeCertificateContext')
|
||||||
|
def _test_create_self_signed_cert(self, mock_CertFreeCertificateContext,
|
||||||
|
mock_CertCloseStore,
|
||||||
|
mock_CertAddCertificateContextToStore,
|
||||||
|
mock_CertOpenStore,
|
||||||
|
mock_CertAddEnhancedKeyUsageIdentifier,
|
||||||
|
mock_CertCreateSelfSignCertificate,
|
||||||
|
mock_GetSystemTime, mock_SYSTEMTIME,
|
||||||
|
mock_CRYPT_ALGORITHM_IDENTIFIER,
|
||||||
|
mock_CRYPT_KEY_PROV_INFO,
|
||||||
|
mock_CRYPTOAPI_BLOB,
|
||||||
|
mock_CertStrToName, mock_DWORD,
|
||||||
|
mock_uuid4, mock_get_cert_thumprint,
|
||||||
|
mock_generate_key, mock_cast,
|
||||||
|
mock_POINTER, mock_malloc, mock_byref,
|
||||||
|
mock_copy, mock_free, certstr,
|
||||||
|
certificate, enhanced_key,
|
||||||
|
store_handle, context_to_store):
|
||||||
|
|
||||||
|
mock_uuid4.return_value = 'fake_name'
|
||||||
|
mock_CertCreateSelfSignCertificate.return_value = certificate
|
||||||
|
mock_CertAddEnhancedKeyUsageIdentifier.return_value = enhanced_key
|
||||||
|
mock_CertStrToName.return_value = certstr
|
||||||
|
mock_CertOpenStore.return_value = store_handle
|
||||||
|
mock_CertAddCertificateContextToStore.return_value = context_to_store
|
||||||
|
if (certstr is None or certificate is None or enhanced_key is None
|
||||||
|
or store_handle is None or context_to_store is None):
|
||||||
|
self.assertRaises(cryptoapi.CryptoAPIException,
|
||||||
|
self._x509.create_self_signed_cert,
|
||||||
|
'fake subject', 10, True, x509.STORE_NAME_MY)
|
||||||
|
else:
|
||||||
|
response = self._x509.create_self_signed_cert(
|
||||||
|
subject='fake subject')
|
||||||
|
mock_cast.assert_called_with(mock_malloc(), mock_POINTER())
|
||||||
|
mock_CRYPTOAPI_BLOB.assert_called_once_with()
|
||||||
|
mock_CRYPT_KEY_PROV_INFO.assert_called_once_with()
|
||||||
|
mock_CRYPT_ALGORITHM_IDENTIFIER.assert_called_once_with()
|
||||||
|
mock_SYSTEMTIME.assert_called_once_with()
|
||||||
|
mock_GetSystemTime.assert_called_once_with(mock_byref())
|
||||||
|
mock_copy.assert_called_once_with(mock_SYSTEMTIME())
|
||||||
|
mock_CertCreateSelfSignCertificate.assert_called_once_with(
|
||||||
|
None, mock_byref(), 0, mock_byref(),
|
||||||
|
mock_byref(), mock_byref(), mock_byref(), None)
|
||||||
|
mock_CertAddEnhancedKeyUsageIdentifier.assert_called_with(
|
||||||
|
mock_CertCreateSelfSignCertificate(),
|
||||||
|
cryptoapi.szOID_PKIX_KP_SERVER_AUTH)
|
||||||
|
mock_CertOpenStore.assert_called_with(
|
||||||
|
cryptoapi.CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||||
|
cryptoapi.CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
||||||
|
unicode(x509.STORE_NAME_MY))
|
||||||
|
mock_get_cert_thumprint.assert_called_once_with(
|
||||||
|
mock_CertCreateSelfSignCertificate())
|
||||||
|
|
||||||
|
mock_CertCloseStore.assert_called_once_with(store_handle, 0)
|
||||||
|
mock_CertFreeCertificateContext.assert_called_once_with(
|
||||||
|
mock_CertCreateSelfSignCertificate())
|
||||||
|
mock_free.assert_called_once_with(mock_cast())
|
||||||
|
|
||||||
|
self.assertEqual(response, mock_get_cert_thumprint())
|
||||||
|
|
||||||
|
mock_generate_key.assert_called_once_with('fake_name', True)
|
||||||
|
|
||||||
|
def test_create_self_signed_cert(self):
|
||||||
|
self._test_create_self_signed_cert(certstr='fake cert name',
|
||||||
|
certificate='fake certificate',
|
||||||
|
enhanced_key='fake key',
|
||||||
|
store_handle='fake handle',
|
||||||
|
context_to_store='fake context')
|
||||||
|
|
||||||
|
def test_create_self_signed_cert_CertStrToName_fail(self):
|
||||||
|
self._test_create_self_signed_cert(certstr=None,
|
||||||
|
certificate='fake certificate',
|
||||||
|
enhanced_key='fake key',
|
||||||
|
store_handle='fake handle',
|
||||||
|
context_to_store='fake context')
|
||||||
|
|
||||||
|
def test_create_self_signed_cert_CertCreateSelfSignCertificate_fail(self):
|
||||||
|
self._test_create_self_signed_cert(certstr='fake cert name',
|
||||||
|
certificate=None,
|
||||||
|
enhanced_key='fake key',
|
||||||
|
store_handle='fake handle',
|
||||||
|
context_to_store='fake context')
|
||||||
|
|
||||||
|
def test_create_self_signed_cert_AddEnhancedKeyUsageIdentifier_fail(self):
|
||||||
|
self._test_create_self_signed_cert(certstr='fake cert name',
|
||||||
|
certificate='fake certificate',
|
||||||
|
enhanced_key=None,
|
||||||
|
store_handle='fake handle',
|
||||||
|
context_to_store='fake context')
|
||||||
|
|
||||||
|
def test_create_self_signed_cert_CertOpenStore_fail(self):
|
||||||
|
self._test_create_self_signed_cert(certstr='fake cert name',
|
||||||
|
certificate='fake certificate',
|
||||||
|
enhanced_key='fake key',
|
||||||
|
store_handle=None,
|
||||||
|
context_to_store='fake context')
|
||||||
|
|
||||||
|
def test_create_self_signed_cert_AddCertificateContextToStore_fail(self):
|
||||||
|
self._test_create_self_signed_cert(certstr='fake cert name',
|
||||||
|
certificate='fake certificate',
|
||||||
|
enhanced_key='fake key',
|
||||||
|
store_handle='fake handle',
|
||||||
|
context_to_store=None)
|
||||||
|
|
||||||
|
def test_get_cert_base64(self):
|
||||||
|
fake_cert_data = ''
|
||||||
|
fake_cert_data += x509.PEM_HEADER + '\n'
|
||||||
|
fake_cert_data += 'fake cert' + '\n'
|
||||||
|
fake_cert_data += x509.PEM_FOOTER
|
||||||
|
response = self._x509._get_cert_base64(fake_cert_data)
|
||||||
|
self.assertEqual(response, 'fake cert')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.free')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'._get_cert_thumprint')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertCloseStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertFreeCertificateContext')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertGetNameString')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertAddEncodedCertificateToStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CertOpenStore')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.cryptoapi.'
|
||||||
|
'CryptStringToBinaryA')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.CryptoAPICertManager'
|
||||||
|
'._get_cert_base64')
|
||||||
|
@mock.patch('ctypes.POINTER')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.x509.malloc')
|
||||||
|
@mock.patch('ctypes.cast')
|
||||||
|
@mock.patch('ctypes.byref')
|
||||||
|
@mock.patch('ctypes.wintypes.DWORD')
|
||||||
|
@mock.patch('ctypes.create_unicode_buffer')
|
||||||
|
def _test_import_cert(self, mock_create_unicode_buffer, mock_DWORD,
|
||||||
|
mock_byref, mock_cast,
|
||||||
|
mock_malloc, mock_POINTER, mock_get_cert_base64,
|
||||||
|
mock_CryptStringToBinaryA, mock_CertOpenStore,
|
||||||
|
mock_CertAddEncodedCertificateToStore,
|
||||||
|
mock_CertGetNameString,
|
||||||
|
mock_CertFreeCertificateContext,
|
||||||
|
mock_CertCloseStore, mock_get_cert_thumprint,
|
||||||
|
mock_free, crypttstr, store_handle, add_enc_cert,
|
||||||
|
upn_len):
|
||||||
|
fake_cert_data = ''
|
||||||
|
fake_cert_data += x509.PEM_HEADER + '\n'
|
||||||
|
fake_cert_data += 'fake cert' + '\n'
|
||||||
|
fake_cert_data += x509.PEM_FOOTER
|
||||||
|
mock_get_cert_base64.return_value = 'fake cert'
|
||||||
|
mock_CryptStringToBinaryA.return_value = crypttstr
|
||||||
|
mock_CertOpenStore.return_value = store_handle
|
||||||
|
mock_CertAddEncodedCertificateToStore.return_value = add_enc_cert
|
||||||
|
mock_CertGetNameString.side_effect = [2, upn_len]
|
||||||
|
|
||||||
|
expected = [mock.call('fake cert', len('fake cert'),
|
||||||
|
cryptoapi.CRYPT_STRING_BASE64, None,
|
||||||
|
mock_byref(), None, None),
|
||||||
|
mock.call('fake cert', len('fake cert'),
|
||||||
|
cryptoapi.CRYPT_STRING_BASE64, mock_cast(),
|
||||||
|
mock_byref(), None, None)]
|
||||||
|
expected2 = [mock.call(mock_POINTER()(), cryptoapi.CERT_NAME_UPN_TYPE,
|
||||||
|
0, None, None, 0),
|
||||||
|
mock.call(mock_POINTER()(), cryptoapi.CERT_NAME_UPN_TYPE,
|
||||||
|
0, None, mock_create_unicode_buffer(), 2)]
|
||||||
|
|
||||||
|
if (not crypttstr or store_handle is None or add_enc_cert is None or
|
||||||
|
upn_len != 2):
|
||||||
|
self.assertRaises(cryptoapi.CryptoAPIException,
|
||||||
|
self._x509.import_cert, fake_cert_data, True,
|
||||||
|
x509.STORE_NAME_MY)
|
||||||
|
else:
|
||||||
|
response = self._x509.import_cert(fake_cert_data)
|
||||||
|
mock_cast.assert_called_with(mock_malloc(), mock_POINTER())
|
||||||
|
self.assertEqual(mock_CryptStringToBinaryA.call_args_list,
|
||||||
|
expected)
|
||||||
|
mock_CertOpenStore.assert_called_with(
|
||||||
|
cryptoapi.CERT_STORE_PROV_SYSTEM, 0, 0,
|
||||||
|
cryptoapi.CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
||||||
|
unicode(x509.STORE_NAME_MY))
|
||||||
|
mock_CertAddEncodedCertificateToStore.assert_called_with(
|
||||||
|
mock_CertOpenStore(),
|
||||||
|
cryptoapi.X509_ASN_ENCODING | cryptoapi.PKCS_7_ASN_ENCODING,
|
||||||
|
mock_cast(), mock_DWORD(),
|
||||||
|
cryptoapi.CERT_STORE_ADD_REPLACE_EXISTING, mock_byref())
|
||||||
|
mock_create_unicode_buffer.assert_called_with(2)
|
||||||
|
self.assertEqual(mock_CertGetNameString.call_args_list, expected2)
|
||||||
|
mock_get_cert_thumprint.assert_called_once_with(mock_POINTER()())
|
||||||
|
mock_CertFreeCertificateContext.assert_called_once_with(
|
||||||
|
mock_POINTER()())
|
||||||
|
mock_CertCloseStore.assert_called_once_with(
|
||||||
|
mock_CertOpenStore(), 0)
|
||||||
|
mock_free.assert_called_once_with(mock_cast())
|
||||||
|
self.assertEqual(response, (mock_get_cert_thumprint(),
|
||||||
|
mock_create_unicode_buffer().value))
|
||||||
|
mock_get_cert_base64.assert_called_with(fake_cert_data)
|
||||||
|
|
||||||
|
def test_import_cert(self):
|
||||||
|
self._test_import_cert(crypttstr=True, store_handle='fake handle',
|
||||||
|
add_enc_cert='fake encoded cert', upn_len=2)
|
||||||
|
|
||||||
|
def test_import_cert_CryptStringToBinaryA_fail(self):
|
||||||
|
self._test_import_cert(crypttstr=False, store_handle='fake handle',
|
||||||
|
add_enc_cert='fake encoded cert', upn_len=2)
|
||||||
|
|
||||||
|
def test_import_cert_CertOpenStore_fail(self):
|
||||||
|
self._test_import_cert(crypttstr=False, store_handle=None,
|
||||||
|
add_enc_cert='fake encoded cert', upn_len=2)
|
||||||
|
|
||||||
|
def test_import_cert_CertAddEncodedCertificateToStore_fail(self):
|
||||||
|
self._test_import_cert(crypttstr=True, store_handle='fake handle',
|
||||||
|
add_enc_cert=None, upn_len=2)
|
||||||
|
|
||||||
|
def test_import_cert_CertGetNameString_fail(self):
|
||||||
|
self._test_import_cert(crypttstr=True, store_handle='fake handle',
|
||||||
|
add_enc_cert='fake encoded cert', upn_len=3)
|
@ -0,0 +1,15 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
@ -0,0 +1,42 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import userdata_plugins
|
||||||
|
#the name of the module includes "-", importlib.import_module is needed:
|
||||||
|
heathandler = importlib.import_module("cloudbaseinit.plugins.windows"
|
||||||
|
".userdata-plugins.heathandler")
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class HeatUserDataHandlerTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
parent_set = userdata_plugins.PluginSet
|
||||||
|
self._heathandler = heathandler.HeatUserDataHandler(parent_set)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata.handle')
|
||||||
|
def test_process(self, mock_handle):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part.get_filename.return_value = "cfn-userdata"
|
||||||
|
self._heathandler.process(mock_part)
|
||||||
|
mock_part.get_filename.assert_called_once_with()
|
||||||
|
mock_handle.assert_called_once_with(mock_part.get_payload())
|
@ -0,0 +1,87 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import userdata_plugins
|
||||||
|
#the name of the module includes "-", importlib.import_module is needed:
|
||||||
|
parthandler = importlib.import_module("cloudbaseinit.plugins.windows"
|
||||||
|
".userdata-plugins.parthandler")
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class PartHandlerScriptHandlerTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
parent_set = userdata_plugins.PluginSet('fake_path')
|
||||||
|
self._parthandler = parthandler.PartHandlerScriptHandler(parent_set)
|
||||||
|
|
||||||
|
@mock.patch('imp.load_source')
|
||||||
|
@mock.patch('imp.load_compiled')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata-plugins.parthandler'
|
||||||
|
'.__import__', create=True)
|
||||||
|
def _test_load_from_file(self, mock__import__, mock_load_compiled,
|
||||||
|
mock_load_source, filepath):
|
||||||
|
mock_module = mock.MagicMock()
|
||||||
|
mock__import__.return_value = mock_module
|
||||||
|
mod_name, file_ext = os.path.splitext(os.path.split(filepath)[-1])
|
||||||
|
response = parthandler.load_from_file(filepath, 'fake_function')
|
||||||
|
print response
|
||||||
|
if file_ext.lower() == '.py':
|
||||||
|
mock_load_source.assert_called_with('path', filepath)
|
||||||
|
elif file_ext.lower() == '.pyc':
|
||||||
|
mock_load_compiled.assert_called_with('path', filepath)
|
||||||
|
mock__import__.assert_called_once_with('path')
|
||||||
|
self.assertEqual(response, mock_module.fake_function)
|
||||||
|
|
||||||
|
def test_load_from_file_py(self):
|
||||||
|
fake_file_path = os.path.join(os.path.join('fake', 'file'), 'path')
|
||||||
|
self._test_load_from_file(filepath=fake_file_path + '.py')
|
||||||
|
|
||||||
|
def test_load_from_file_pyc(self):
|
||||||
|
fake_file_path = os.path.join(os.path.join('fake', 'file'), 'path')
|
||||||
|
self._test_load_from_file(filepath=fake_file_path + '.pyc')
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.plugins.windows.userdata-plugins.parthandler.'
|
||||||
|
'load_from_file')
|
||||||
|
def test_process(self, mock_load_from_file):
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part.get_filename.return_value = 'fake_name'
|
||||||
|
handler_path = self._parthandler.parent_set.path + "/part-handler/"
|
||||||
|
handler_path += 'fake_name'
|
||||||
|
expected = [mock.call(),
|
||||||
|
mock.call(handler_path, "list_types"),
|
||||||
|
mock.call(handler_path, "handle_part")]
|
||||||
|
mock_load_from_file().return_value = ['fake part']
|
||||||
|
with mock.patch("cloudbaseinit.plugins.windows.userdata-plugins."
|
||||||
|
"parthandler.open", mock.mock_open(), create=True):
|
||||||
|
self._parthandler.process(mock_part)
|
||||||
|
|
||||||
|
print mock_load_from_file.mock_calls
|
||||||
|
print self._parthandler.parent_set.custom_handlers
|
||||||
|
|
||||||
|
mock_part.get_filename.assert_called_once_with()
|
||||||
|
mock_part.get_payload.assert_called_once_with()
|
||||||
|
self.assertEqual(mock_load_from_file.call_args_list, expected)
|
||||||
|
self.assertEqual(self._parthandler.parent_set.has_custom_handlers,
|
||||||
|
True)
|
||||||
|
self.assertEqual(self._parthandler.parent_set.custom_handlers,
|
||||||
|
{'fake part': mock_load_from_file()})
|
@ -0,0 +1,84 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import importlib
|
||||||
|
import mock
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
from cloudbaseinit.plugins.windows import userdata_plugins
|
||||||
|
#the name of the module includes "-", importlib.import_module is needed:
|
||||||
|
shellscript = importlib.import_module("cloudbaseinit.plugins.windows"
|
||||||
|
".userdata-plugins.shellscript")
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class ShellScriptHandlerTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
parent_set = userdata_plugins.PluginSet('fake_path')
|
||||||
|
self._shellscript = shellscript.ShellScriptHandler(parent_set)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('tempfile.gettempdir')
|
||||||
|
def _test_process(self, mock_gettempdir, mock_get_os_utils, filename,
|
||||||
|
exception=False):
|
||||||
|
fake_dir_path = os.path.join("fake", "dir")
|
||||||
|
mock_osutils = mock.MagicMock()
|
||||||
|
mock_part = mock.MagicMock()
|
||||||
|
mock_part.get_filename.return_value = filename
|
||||||
|
mock_gettempdir.return_value = fake_dir_path
|
||||||
|
|
||||||
|
mock_get_os_utils.return_value = mock_osutils
|
||||||
|
|
||||||
|
if exception:
|
||||||
|
mock_osutils.execute_process.side_effect = [Exception]
|
||||||
|
|
||||||
|
with mock.patch("cloudbaseinit.plugins.windows.userdata-plugins."
|
||||||
|
"shellscript.open", mock.mock_open(), create=True):
|
||||||
|
response = self._shellscript.process(mock_part)
|
||||||
|
|
||||||
|
mock_part.get_filename.assert_called_once_with()
|
||||||
|
mock_gettempdir.assert_called_once_with()
|
||||||
|
if filename.endswith(".cmd"):
|
||||||
|
mock_osutils.execute_process.assert_called_with(
|
||||||
|
[os.path.join(fake_dir_path, filename)], True)
|
||||||
|
elif filename.endswith(".sh"):
|
||||||
|
mock_osutils.execute_process.assert_called_with(
|
||||||
|
['bash.exe', os.path.join(fake_dir_path, filename)], False)
|
||||||
|
elif filename.endswith(".ps1"):
|
||||||
|
mock_osutils.execute_process.assert_called_with(
|
||||||
|
['powershell.exe', '-ExecutionPolicy', 'RemoteSigned',
|
||||||
|
'-NonInteractive', os.path.join(fake_dir_path, filename)],
|
||||||
|
False)
|
||||||
|
self.assertFalse(response)
|
||||||
|
|
||||||
|
def test_process_cmd(self):
|
||||||
|
self._test_process(filename='fake.cmd')
|
||||||
|
|
||||||
|
def test_process_sh(self):
|
||||||
|
self._test_process(filename='fake.cmd')
|
||||||
|
|
||||||
|
def test_process_ps1(self):
|
||||||
|
self._test_process(filename='fake.cmd')
|
||||||
|
|
||||||
|
def test_process_other(self):
|
||||||
|
self._test_process(filename='fake.other')
|
||||||
|
|
||||||
|
def test_process_exception(self):
|
||||||
|
self._test_process(filename='fake.cmd', exception=True)
|
141
cloudbaseinit/tests/test_init.py
Normal file
141
cloudbaseinit/tests/test_init.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
|
# Copyright 2013 Cloudbase Solutions Srl
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from cloudbaseinit import init
|
||||||
|
from cloudbaseinit.plugins import base
|
||||||
|
from cloudbaseinit.openstack.common import cfg
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
_win32com_mock = mock.MagicMock()
|
||||||
|
_comtypes_mock = mock.MagicMock()
|
||||||
|
_pywintypes_mock = mock.MagicMock()
|
||||||
|
_ctypes_mock = mock.MagicMock()
|
||||||
|
_ctypes_util_mock = mock.MagicMock()
|
||||||
|
mock_dict = {'ctypes.util': _ctypes_util_mock,
|
||||||
|
'win32com': _win32com_mock,
|
||||||
|
'comtypes': _comtypes_mock,
|
||||||
|
'pywintypes': _pywintypes_mock,
|
||||||
|
'ctypes': _ctypes_mock}
|
||||||
|
|
||||||
|
|
||||||
|
class InitManagerTest(unittest.TestCase):
|
||||||
|
@mock.patch.dict(sys.modules, mock_dict)
|
||||||
|
def setUp(self):
|
||||||
|
self.osutils = mock.MagicMock()
|
||||||
|
self.plugin = mock.MagicMock()
|
||||||
|
self._init = init.InitManager()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
reload(sys)
|
||||||
|
reload(init)
|
||||||
|
|
||||||
|
def test_get_plugin_status(self):
|
||||||
|
self.osutils.get_config_value.return_value = 1
|
||||||
|
response = self._init._get_plugin_status(self.osutils, 'fake plugin')
|
||||||
|
self.osutils.get_config_value.assert_called_once_with(
|
||||||
|
'fake plugin', self._init._PLUGINS_CONFIG_SECTION)
|
||||||
|
self.assertTrue(response == 1)
|
||||||
|
|
||||||
|
def test_set_plugin_status(self):
|
||||||
|
|
||||||
|
self._init._set_plugin_status(self.osutils, 'fake plugin', 'status')
|
||||||
|
self.osutils.set_config_value.assert_called_once_with(
|
||||||
|
'fake plugin', 'status', self._init._PLUGINS_CONFIG_SECTION)
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.init.InitManager._get_plugin_status')
|
||||||
|
@mock.patch('cloudbaseinit.init.InitManager._set_plugin_status')
|
||||||
|
def _test_exec_plugin(self, status, mock_set_plugin_status,
|
||||||
|
mock_get_plugin_status):
|
||||||
|
fake_name = 'fake name'
|
||||||
|
self.plugin.get_name.return_value = fake_name
|
||||||
|
self.plugin.execute.return_value = (status, True)
|
||||||
|
mock_get_plugin_status.return_value = status
|
||||||
|
|
||||||
|
response = self._init._exec_plugin(osutils=self.osutils,
|
||||||
|
service='fake service',
|
||||||
|
plugin=self.plugin,
|
||||||
|
shared_data='shared data')
|
||||||
|
|
||||||
|
mock_get_plugin_status.assert_called_once_with(self.osutils,
|
||||||
|
fake_name)
|
||||||
|
if status is base.PLUGIN_EXECUTE_ON_NEXT_BOOT:
|
||||||
|
self.plugin.execute.assert_called_once_with('fake service',
|
||||||
|
'shared data')
|
||||||
|
mock_set_plugin_status.assert_called_once_with(self.osutils,
|
||||||
|
fake_name, status)
|
||||||
|
self.assertTrue(response)
|
||||||
|
|
||||||
|
def test_test_exec_plugin_execution_done(self):
|
||||||
|
self._test_exec_plugin(base.PLUGIN_EXECUTION_DONE)
|
||||||
|
|
||||||
|
def test_test_exec_plugin(self):
|
||||||
|
self._test_exec_plugin(base.PLUGIN_EXECUTE_ON_NEXT_BOOT)
|
||||||
|
|
||||||
|
def _test_check_plugin_os_requirements(self, requirements):
|
||||||
|
sys.platform = 'win32'
|
||||||
|
fake_name = 'fake name'
|
||||||
|
self.plugin.get_name.return_value = fake_name
|
||||||
|
self.plugin.get_os_requirements.return_value = requirements
|
||||||
|
|
||||||
|
response = self._init._check_plugin_os_requirements(self.osutils,
|
||||||
|
self.plugin)
|
||||||
|
|
||||||
|
self.plugin.get_name.assert_called_once_with()
|
||||||
|
self.plugin.get_os_requirements.assert_called_once_with()
|
||||||
|
if requirements[0] == 'win32':
|
||||||
|
self.assertTrue(response)
|
||||||
|
else:
|
||||||
|
self.assertFalse(response)
|
||||||
|
|
||||||
|
def test_check_plugin_os_requirements(self):
|
||||||
|
self._test_check_plugin_os_requirements(('win32', (5, 2)))
|
||||||
|
|
||||||
|
def test_check_plugin_os_requirements_other_requirenments(self):
|
||||||
|
self._test_check_plugin_os_requirements(('linux', (5, 2)))
|
||||||
|
|
||||||
|
@mock.patch('cloudbaseinit.init.InitManager'
|
||||||
|
'._check_plugin_os_requirements')
|
||||||
|
@mock.patch('cloudbaseinit.init.InitManager._exec_plugin')
|
||||||
|
@mock.patch('cloudbaseinit.plugins.factory.PluginFactory.load_plugins')
|
||||||
|
@mock.patch('cloudbaseinit.osutils.factory.OSUtilsFactory.get_os_utils')
|
||||||
|
@mock.patch('cloudbaseinit.metadata.factory.MetadataServiceFactory.'
|
||||||
|
'get_metadata_service')
|
||||||
|
def test_configure_host(self, mock_get_metadata_service,
|
||||||
|
mock_get_os_utils, mock_load_plugins,
|
||||||
|
mock_exec_plugin,
|
||||||
|
mock_check_os_requirements):
|
||||||
|
fake_service = mock.MagicMock()
|
||||||
|
fake_plugin = mock.MagicMock()
|
||||||
|
mock_load_plugins.return_value = [fake_plugin]
|
||||||
|
mock_get_os_utils.return_value = self.osutils
|
||||||
|
mock_get_metadata_service.return_value = fake_service
|
||||||
|
fake_service.get_name.return_value = 'fake name'
|
||||||
|
|
||||||
|
self._init.configure_host()
|
||||||
|
|
||||||
|
self.osutils.wait_for_boot_completion.assert_called_once()
|
||||||
|
mock_get_metadata_service.assert_called_once_with()
|
||||||
|
fake_service.get_name.assert_called_once_with()
|
||||||
|
mock_check_os_requirements.assert_called_once_with(self.osutils,
|
||||||
|
fake_plugin)
|
||||||
|
mock_exec_plugin.assert_called_once_with(self.osutils, fake_service,
|
||||||
|
fake_plugin, {})
|
||||||
|
fake_service.cleanup.assert_called_once_with()
|
||||||
|
self.osutils.reboot.assert_called_once_with()
|
Loading…
Reference in New Issue
Block a user