Merge "Refactor Windows API usage"
This commit is contained in:
commit
ff86810181
@ -19,6 +19,8 @@ import sys
|
||||
from eventlet import patcher
|
||||
import pbr.version
|
||||
|
||||
from os_win.utils.winapi import libs as w_libs
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo(
|
||||
'os_win').version_string()
|
||||
@ -27,3 +29,7 @@ if sys.platform == 'win32':
|
||||
import wmi
|
||||
# We need to make sure that WMI uses the unpatched threading module.
|
||||
wmi.threading = patcher.original('threading')
|
||||
|
||||
# The following will set the argument and return value types for the
|
||||
# foreign functions used throughout os_win using ctypes.
|
||||
w_libs.register()
|
||||
|
@ -22,6 +22,9 @@ from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils.compute import _clusapi_utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.libs import clusapi as clusapi_def
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -83,8 +86,8 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
clusprop_val_struct = self._clusapi_utils._get_clusprop_value_struct(
|
||||
val_type)
|
||||
|
||||
expected_fields = [('syntax', _clusapi_utils.DWORD),
|
||||
('length', _clusapi_utils.DWORD),
|
||||
expected_fields = [('syntax', wintypes.DWORD),
|
||||
('length', wintypes.DWORD),
|
||||
('value', val_type),
|
||||
('_padding', ctypes.c_ubyte * expected_padding_sz)]
|
||||
self.assertEqual(expected_fields, clusprop_val_struct._fields_)
|
||||
@ -100,7 +103,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
syntax=fake_prop_syntax,
|
||||
value=fake_prop_val)
|
||||
|
||||
self.assertEqual(_clusapi_utils.CLUSPROP_SYNTAX_NAME,
|
||||
self.assertEqual(w_const.CLUSPROP_SYNTAX_NAME,
|
||||
entry.name.syntax)
|
||||
self.assertEqual(fake_prop_name,
|
||||
entry.name.value)
|
||||
@ -116,7 +119,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
ctypes.sizeof(fake_prop_val),
|
||||
entry.value.length)
|
||||
|
||||
self.assertEqual(_clusapi_utils.CLUSPROP_SYNTAX_ENDMARK,
|
||||
self.assertEqual(w_const.CLUSPROP_SYNTAX_ENDMARK,
|
||||
entry._endmark)
|
||||
|
||||
def test_get_property_list(self):
|
||||
@ -197,11 +200,11 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._clusapi.CloseClusterNode.assert_called_once_with(
|
||||
mock.sentinel.handle)
|
||||
|
||||
@ddt.data(0, _clusapi_utils.ERROR_IO_PENDING)
|
||||
@ddt.data(0, w_const.ERROR_IO_PENDING)
|
||||
def test_cancel_cluster_group_operation(self, cancel_ret_val):
|
||||
self._mock_run.return_value = cancel_ret_val
|
||||
|
||||
expected_ret_val = cancel_ret_val != _clusapi_utils.ERROR_IO_PENDING
|
||||
expected_ret_val = cancel_ret_val != w_const.ERROR_IO_PENDING
|
||||
ret_val = self._clusapi_utils.cancel_cluster_group_operation(
|
||||
mock.sentinel.group_handle)
|
||||
|
||||
@ -211,7 +214,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._clusapi.CancelClusterGroupOperation,
|
||||
mock.sentinel.group_handle,
|
||||
0,
|
||||
ignored_error_codes=[_clusapi_utils.ERROR_IO_PENDING])
|
||||
ignored_error_codes=[w_const.ERROR_IO_PENDING])
|
||||
|
||||
@ddt.data(mock.sentinel.prop_list, None)
|
||||
def test_move_cluster_group(self, prop_list):
|
||||
@ -235,7 +238,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
mock.sentinel.move_flags,
|
||||
expected_prop_list_arg,
|
||||
expected_prop_list_sz,
|
||||
ignored_error_codes=[_clusapi_utils.ERROR_IO_PENDING])
|
||||
ignored_error_codes=[w_const.ERROR_IO_PENDING])
|
||||
|
||||
def test_get_cluster_group_state(self):
|
||||
owner_node = 'fake owner node'
|
||||
@ -257,15 +260,15 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
node_name_len_arg = ctypes.cast(
|
||||
node_name_len,
|
||||
ctypes.POINTER(_clusapi_utils.DWORD)).contents
|
||||
self.assertEqual(self._clusapi_utils._MAX_NODE_NAME,
|
||||
wintypes.PDWORD).contents
|
||||
self.assertEqual(w_const.MAX_PATH,
|
||||
node_name_len_arg.value)
|
||||
|
||||
node_name_arg = ctypes.cast(
|
||||
node_name_buff,
|
||||
ctypes.POINTER(
|
||||
ctypes.c_wchar *
|
||||
self._clusapi_utils._MAX_NODE_NAME)).contents
|
||||
w_const.MAX_PATH)).contents
|
||||
node_name_arg.value = owner_node
|
||||
return mock.sentinel.group_state
|
||||
|
||||
@ -277,9 +280,9 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
owner_node=owner_node)
|
||||
self.assertEqual(expected_state_info, state_info)
|
||||
|
||||
@ddt.data({'notif_filters': (_clusapi_utils.NOTIFY_FILTER_AND_TYPE * 2)(),
|
||||
@ddt.data({'notif_filters': (clusapi_def.NOTIFY_FILTER_AND_TYPE * 2)(),
|
||||
'exp_notif_filters_len': 2},
|
||||
{'notif_filters': _clusapi_utils.NOTIFY_FILTER_AND_TYPE(),
|
||||
{'notif_filters': clusapi_def.NOTIFY_FILTER_AND_TYPE(),
|
||||
'notif_port_h': mock.sentinel.notif_port_h,
|
||||
'notif_key': mock.sentinel.notif_key})
|
||||
@ddt.unpack
|
||||
@ -297,7 +300,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
notif_key)
|
||||
|
||||
exp_notif_key_p = self._ctypes.byref(notif_key) if notif_key else None
|
||||
exp_notif_port_h = notif_port_h or _clusapi_utils.INVALID_HANDLE_VALUE
|
||||
exp_notif_port_h = notif_port_h or w_const.INVALID_HANDLE_VALUE
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
self._clusapi.CreateClusterNotifyPortV2,
|
||||
@ -337,10 +340,10 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
obj_name_buff_sz = ctypes.cast(
|
||||
p_obj_name_buff_sz,
|
||||
ctypes.POINTER(_clusapi_utils.DWORD)).contents
|
||||
wintypes.PDWORD).contents
|
||||
buff_sz = ctypes.cast(
|
||||
p_buff_sz,
|
||||
ctypes.POINTER(_clusapi_utils.DWORD)).contents
|
||||
wintypes.PDWORD).contents
|
||||
|
||||
# We'll just request the tested method to pass us
|
||||
# a buffer this large.
|
||||
@ -349,7 +352,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
buff_sz.value = requested_buff_sz
|
||||
obj_name_buff_sz.value = requested_buff_sz
|
||||
raise exceptions.ClusterWin32Exception(
|
||||
error_code=_clusapi_utils.ERROR_MORE_DATA,
|
||||
error_code=w_const.ERROR_MORE_DATA,
|
||||
func_name='GetClusterNotify',
|
||||
error_message='error more data')
|
||||
|
||||
@ -359,7 +362,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
filter_and_type = ctypes.cast(
|
||||
p_filter_and_type,
|
||||
ctypes.POINTER(_clusapi_utils.NOTIFY_FILTER_AND_TYPE)).contents
|
||||
ctypes.POINTER(clusapi_def.NOTIFY_FILTER_AND_TYPE)).contents
|
||||
filter_and_type.dwObjectType = fake_notif_type
|
||||
filter_and_type.FilterFlags = fake_filter_flags
|
||||
|
||||
@ -404,18 +407,18 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self.assertEqual(expected_event, event)
|
||||
|
||||
def _get_fake_prop_list(self):
|
||||
syntax = _clusapi_utils.CLUSPROP_SYNTAX_LIST_VALUE_DWORD
|
||||
migr_type = _clusapi_utils.DWORD(self._LIVE_MIGRATION_TYPE)
|
||||
syntax = w_const.CLUSPROP_SYNTAX_LIST_VALUE_DWORD
|
||||
migr_type = wintypes.DWORD(self._LIVE_MIGRATION_TYPE)
|
||||
|
||||
prop_entries = [
|
||||
self._clusapi_utils.get_property_list_entry(
|
||||
_clusapi_utils.CLUSPROP_NAME_VM, syntax, migr_type),
|
||||
w_const.CLUS_RESTYPE_NAME_VM, syntax, migr_type),
|
||||
self._clusapi_utils.get_property_list_entry(
|
||||
_clusapi_utils.CLUSPROP_NAME_VM_CONFIG, syntax, migr_type),
|
||||
w_const.CLUS_RESTYPE_NAME_VM_CONFIG, syntax, migr_type),
|
||||
self._clusapi_utils.get_property_list_entry(
|
||||
_clusapi_utils.CLUSPROP_GROUP_STATUS_INFO,
|
||||
_clusapi_utils.CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER,
|
||||
ctypes.c_ulonglong(_clusapi_utils.
|
||||
w_const.CLUSREG_NAME_GRP_STATUS_INFORMATION,
|
||||
w_const.CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER,
|
||||
ctypes.c_ulonglong(w_const.
|
||||
CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE)) # noqa
|
||||
]
|
||||
|
||||
@ -444,7 +447,7 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._clusapi_utils.get_prop_list_entry_p,
|
||||
ctypes.byref(prop_list),
|
||||
ctypes.sizeof(prop_list),
|
||||
_clusapi_utils.CLUSPROP_NAME_VM)
|
||||
w_const.CLUS_RESTYPE_NAME_VM)
|
||||
|
||||
def test_get_prop_list_entry_p(self):
|
||||
prop_list = self._get_fake_prop_list()
|
||||
@ -452,10 +455,10 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
prop_entry = self._clusapi_utils.get_prop_list_entry_p(
|
||||
ctypes.byref(prop_list),
|
||||
ctypes.sizeof(prop_list),
|
||||
_clusapi_utils.CLUSPROP_NAME_VM_CONFIG)
|
||||
w_const.CLUS_RESTYPE_NAME_VM_CONFIG)
|
||||
|
||||
self.assertEqual(
|
||||
_clusapi_utils.CLUSPROP_SYNTAX_LIST_VALUE_DWORD,
|
||||
w_const.CLUSPROP_SYNTAX_LIST_VALUE_DWORD,
|
||||
prop_entry['syntax'])
|
||||
self.assertEqual(
|
||||
ctypes.sizeof(ctypes.c_ulong),
|
||||
@ -483,14 +486,14 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
req_buff_sz = ctypes.cast(
|
||||
requested_buff_sz_p,
|
||||
ctypes.POINTER(_clusapi_utils.DWORD)).contents
|
||||
wintypes.PDWORD).contents
|
||||
req_buff_sz.value = requested_buff_sz
|
||||
|
||||
# We'll just request the tested method to pass us
|
||||
# a buffer this large.
|
||||
if (out_buff_sz.value < requested_buff_sz):
|
||||
raise exceptions.ClusterWin32Exception(
|
||||
error_code=_clusapi_utils.ERROR_MORE_DATA,
|
||||
error_code=w_const.ERROR_MORE_DATA,
|
||||
func_name='ClusterGroupControl',
|
||||
error_message='error more data')
|
||||
|
||||
@ -522,5 +525,5 @@ class ClusApiUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
status_info = self._clusapi_utils.get_cluster_group_status_info(
|
||||
ctypes.byref(prop_list), ctypes.sizeof(prop_list))
|
||||
self.assertEqual(
|
||||
_clusapi_utils.CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE,
|
||||
w_const.CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE,
|
||||
status_info)
|
||||
|
@ -22,8 +22,10 @@ from six.moves import queue
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils.compute import _clusapi_utils
|
||||
from os_win.utils.compute import clusterutils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.libs import clusapi as clusapi_def
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -295,7 +297,7 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
constants.CLUSTER_GROUP_ONLINE,
|
||||
mock.sentinel.timeout)
|
||||
|
||||
@mock.patch.object(_clusapi_utils, 'DWORD')
|
||||
@mock.patch.object(wintypes, 'DWORD')
|
||||
@mock.patch.object(clusterutils.ClusterUtils,
|
||||
'_wait_for_cluster_group_migration')
|
||||
@mock.patch.object(clusterutils.ClusterUtils,
|
||||
@ -327,10 +329,10 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self._clusapi.get_property_list_entry.assert_has_calls(
|
||||
[mock.call(prop_name,
|
||||
_clusapi_utils.CLUSPROP_SYNTAX_LIST_VALUE_DWORD,
|
||||
w_const.CLUSPROP_SYNTAX_LIST_VALUE_DWORD,
|
||||
mock_dword.return_value)
|
||||
for prop_name in (_clusapi_utils.CLUSPROP_NAME_VM,
|
||||
_clusapi_utils.CLUSPROP_NAME_VM_CONFIG)])
|
||||
for prop_name in (w_const.CLUS_RESTYPE_NAME_VM,
|
||||
w_const.CLUS_RESTYPE_NAME_VM_CONFIG)])
|
||||
|
||||
expected_prop_entries = [
|
||||
self._clusapi.get_property_list_entry.return_value] * 2
|
||||
@ -338,9 +340,9 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
expected_prop_entries)
|
||||
|
||||
expected_migrate_flags = (
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR |
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_QUEUE_ENABLED |
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START)
|
||||
w_const.CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR |
|
||||
w_const.CLUSAPI_GROUP_MOVE_QUEUE_ENABLED |
|
||||
w_const.CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START)
|
||||
|
||||
exp_clus_h = self._clusapi.open_cluster.return_value
|
||||
exp_clus_node_h = self._clusapi.open_cluster_node.return_value
|
||||
@ -505,18 +507,18 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
{'cancel_exception': test_base.TestingException()},
|
||||
{'cancel_exception':
|
||||
exceptions.Win32Exception(
|
||||
error_code=_clusapi_utils.INVALID_HANDLE_VALUE,
|
||||
error_code=w_const.INVALID_HANDLE_VALUE,
|
||||
func_name=mock.sentinel.func_name,
|
||||
error_message=mock.sentinel.error_message)},
|
||||
{'cancel_exception':
|
||||
exceptions.Win32Exception(
|
||||
error_code=_clusapi_utils.ERROR_INVALID_STATE,
|
||||
error_code=w_const.ERROR_INVALID_STATE,
|
||||
func_name=mock.sentinel.func_name,
|
||||
error_message=mock.sentinel.error_message),
|
||||
'invalid_state_for_cancel': True},
|
||||
{'cancel_exception':
|
||||
exceptions.Win32Exception(
|
||||
error_code=_clusapi_utils.ERROR_INVALID_STATE,
|
||||
error_code=w_const.ERROR_INVALID_STATE,
|
||||
func_name=mock.sentinel.func_name,
|
||||
error_message=mock.sentinel.error_message),
|
||||
'invalid_state_for_cancel': True,
|
||||
@ -589,7 +591,7 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self.assertTrue(
|
||||
self._clusterutils._is_migration_pending(
|
||||
group_state=constants.CLUSTER_GROUP_ONLINE,
|
||||
group_status_info=_clusapi_utils.
|
||||
group_status_info=w_const.
|
||||
CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE | 1, # noqa
|
||||
expected_state=constants.CLUSTER_GROUP_ONLINE))
|
||||
self.assertFalse(
|
||||
@ -726,7 +728,7 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
mock.sentinel.group_handle)
|
||||
self._clusapi.cluster_group_control.assert_called_once_with(
|
||||
mock.sentinel.group_handle,
|
||||
_clusapi_utils.CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES)
|
||||
w_const.CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES)
|
||||
self._clusapi.get_cluster_group_status_info.assert_called_once_with(
|
||||
mock_byref(mock.sentinel.buff), mock.sentinel.buff_sz)
|
||||
|
||||
@ -838,7 +840,7 @@ class ClusterEventListenerTestCase(test_base.OsWinBaseTestCase):
|
||||
mock.sentinel.notif_key_dw_2)])
|
||||
|
||||
@mock.patch.object(clusterutils._ClusterEventListener, '_add_filter')
|
||||
@mock.patch.object(_clusapi_utils, 'NOTIFY_FILTER_AND_TYPE')
|
||||
@mock.patch.object(clusapi_def, 'NOTIFY_FILTER_AND_TYPE')
|
||||
def test_setup_notif_port(self, mock_filter_struct_cls, mock_add_filter):
|
||||
notif_filter = dict(object_type=mock.sentinel.object_type,
|
||||
filter_flags=mock.sentinel.filter_flags,
|
||||
|
@ -20,6 +20,8 @@ import six
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.io import ioutils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
|
||||
class IOUtilsTestCase(base.BaseTestCase):
|
||||
@ -84,7 +86,7 @@ class IOUtilsTestCase(base.BaseTestCase):
|
||||
mock.sentinel.create_disposition,
|
||||
mock.sentinel.flags,
|
||||
None,
|
||||
error_ret_vals=[ioutils.INVALID_HANDLE_VALUE],
|
||||
error_ret_vals=[w_const.INVALID_HANDLE_VALUE],
|
||||
**self._run_args)
|
||||
self.assertEqual(self._mock_run.return_value, handle)
|
||||
|
||||
@ -93,8 +95,8 @@ class IOUtilsTestCase(base.BaseTestCase):
|
||||
mock.sentinel.overlapped_struct,
|
||||
ignore_invalid_handle=True)
|
||||
|
||||
expected_ignored_err_codes = [ioutils.ERROR_NOT_FOUND,
|
||||
ioutils.ERROR_INVALID_HANDLE]
|
||||
expected_ignored_err_codes = [w_const.ERROR_NOT_FOUND,
|
||||
w_const.ERROR_INVALID_HANDLE]
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
ioutils.kernel32.CancelIoEx,
|
||||
@ -118,7 +120,7 @@ class IOUtilsTestCase(base.BaseTestCase):
|
||||
mock.sentinel.event,
|
||||
ioutils.WAIT_INFINITE_TIMEOUT,
|
||||
True,
|
||||
error_ret_vals=[ioutils.WAIT_FAILED],
|
||||
error_ret_vals=[w_const.WAIT_FAILED],
|
||||
**self._run_args)
|
||||
|
||||
def test_set_event(self):
|
||||
@ -150,8 +152,8 @@ class IOUtilsTestCase(base.BaseTestCase):
|
||||
**self._run_args)
|
||||
self.assertEqual(self._mock_run.return_value, event)
|
||||
|
||||
@mock.patch.object(ioutils, 'LPOVERLAPPED', create=True)
|
||||
@mock.patch.object(ioutils, 'LPOVERLAPPED_COMPLETION_ROUTINE',
|
||||
@mock.patch.object(wintypes, 'LPOVERLAPPED', create=True)
|
||||
@mock.patch.object(wintypes, 'LPOVERLAPPED_COMPLETION_ROUTINE',
|
||||
lambda x: x, create=True)
|
||||
@mock.patch.object(ioutils.IOUtils, 'set_event')
|
||||
def test_get_completion_routine(self, mock_set_event,
|
||||
@ -164,12 +166,12 @@ class IOUtilsTestCase(base.BaseTestCase):
|
||||
mock.sentinel.lpOverLapped)
|
||||
|
||||
self._ctypes.cast.assert_called_once_with(mock.sentinel.lpOverLapped,
|
||||
ioutils.LPOVERLAPPED)
|
||||
wintypes.LPOVERLAPPED)
|
||||
mock_overlapped_struct = self._ctypes.cast.return_value.contents
|
||||
mock_set_event.assert_called_once_with(mock_overlapped_struct.hEvent)
|
||||
mock_callback.assert_called_once_with(mock.sentinel.num_bytes)
|
||||
|
||||
@mock.patch.object(ioutils, 'OVERLAPPED', create=True)
|
||||
@mock.patch.object(wintypes, 'OVERLAPPED', create=True)
|
||||
@mock.patch.object(ioutils.IOUtils, '_create_event')
|
||||
def test_get_new_overlapped_structure(self, mock_create_event,
|
||||
mock_OVERLAPPED):
|
||||
|
@ -21,8 +21,8 @@ from six.moves import builtins
|
||||
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.io import ioutils
|
||||
from os_win.utils.io import namedpipe
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
|
||||
class NamedPipeTestCase(base.BaseTestCase):
|
||||
@ -180,10 +180,10 @@ class NamedPipeTestCase(base.BaseTestCase):
|
||||
mock.sentinel.pipe_name)
|
||||
self._ioutils.open.assert_called_once_with(
|
||||
mock.sentinel.pipe_name,
|
||||
desired_access=(ioutils.GENERIC_READ | ioutils.GENERIC_WRITE),
|
||||
share_mode=(ioutils.FILE_SHARE_READ | ioutils.FILE_SHARE_WRITE),
|
||||
creation_disposition=ioutils.OPEN_EXISTING,
|
||||
flags_and_attributes=ioutils.FILE_FLAG_OVERLAPPED)
|
||||
desired_access=(w_const.GENERIC_READ | w_const.GENERIC_WRITE),
|
||||
share_mode=(w_const.FILE_SHARE_READ | w_const.FILE_SHARE_WRITE),
|
||||
creation_disposition=w_const.OPEN_EXISTING,
|
||||
flags_and_attributes=w_const.FILE_FLAG_OVERLAPPED)
|
||||
|
||||
self.assertEqual(self._ioutils.open.return_value,
|
||||
self._handler._pipe_handle)
|
||||
|
@ -20,8 +20,8 @@ from oslotest import base
|
||||
import six
|
||||
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage.initiator import fc_structures as fc_struct
|
||||
from os_win.utils.storage.initiator import fc_utils
|
||||
from os_win.utils.winapi.libs import hbaapi as fc_struct
|
||||
|
||||
|
||||
class FCUtilsTestCase(base.BaseTestCase):
|
||||
@ -72,62 +72,76 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(fc_utils.hbaapi.HBA_GetNumberOfAdapters.return_value,
|
||||
hba_count)
|
||||
|
||||
def _test_open_adapter(self, adapter_name=None, adapter_wwn=None):
|
||||
def test_open_adapter_by_name(self):
|
||||
self._ctypes_mocker.stop()
|
||||
|
||||
self._mock_run.return_value = mock.sentinel.handle
|
||||
|
||||
if adapter_name:
|
||||
expected_func = fc_utils.hbaapi.HBA_OpenAdapter
|
||||
elif adapter_wwn:
|
||||
expected_func = fc_utils.hbaapi.HBA_OpenAdapterByWWN
|
||||
|
||||
resulted_handle = self._fc_utils._open_adapter(
|
||||
adapter_name=adapter_name, adapter_wwn=adapter_wwn)
|
||||
resulted_handle = self._fc_utils._open_adapter_by_name(
|
||||
self._FAKE_ADAPTER_NAME)
|
||||
|
||||
args_list = self._mock_run.call_args_list[0][0]
|
||||
self.assertEqual(expected_func, args_list[0])
|
||||
if adapter_name:
|
||||
self.assertEqual(six.b(adapter_name),
|
||||
args_list[1].value)
|
||||
else:
|
||||
self.assertEqual(adapter_wwn, list(args_list[1]))
|
||||
self.assertEqual(fc_utils.hbaapi.HBA_OpenAdapter, args_list[0])
|
||||
self.assertEqual(six.b(self._FAKE_ADAPTER_NAME), args_list[1].value)
|
||||
|
||||
self.assertEqual(mock.sentinel.handle, resulted_handle)
|
||||
|
||||
def test_open_adapter_by_name(self):
|
||||
self._test_open_adapter(adapter_name=self._FAKE_ADAPTER_NAME)
|
||||
@mock.patch.object(fc_utils.fc_struct, 'HBA_HANDLE')
|
||||
def test_open_adapter_by_wwn(self, mock_hba_handle_struct):
|
||||
exp_handle = mock_hba_handle_struct.return_value
|
||||
resulted_handle = self._fc_utils._open_adapter_by_wwn(
|
||||
self._FAKE_ADAPTER_WWN)
|
||||
|
||||
def test_open_adapter_by_wwn(self):
|
||||
self._test_open_adapter(adapter_wwn=self._FAKE_ADAPTER_WWN)
|
||||
self.assertEqual(exp_handle, resulted_handle)
|
||||
|
||||
def test_open_adapter_not_specified(self):
|
||||
self.assertRaises(exceptions.FCException,
|
||||
self._fc_utils._open_adapter)
|
||||
args_list = self._mock_run.call_args_list[0][0]
|
||||
self.assertEqual(fc_utils.hbaapi.HBA_OpenAdapterByWWN,
|
||||
args_list[0])
|
||||
self.assertEqual(self._FAKE_ADAPTER_WWN, list(args_list[2].wwn))
|
||||
|
||||
self.assertEqual(self._ctypes.byref(exp_handle), args_list[1])
|
||||
|
||||
def test_close_adapter(self):
|
||||
self._fc_utils._close_adapter(mock.sentinel.hba_handle)
|
||||
fc_utils.hbaapi.HBA_CloseAdapter.assert_called_once_with(
|
||||
mock.sentinel.hba_handle)
|
||||
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter_by_name')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
def test_get_hba_handle(self, mock_close_adapter, mock_open_adapter):
|
||||
def test_get_hba_handle_by_name(self, mock_close_adapter,
|
||||
mock_open_adapter):
|
||||
with self._fc_utils._get_hba_handle(
|
||||
adapter_name=self._FAKE_ADAPTER_NAME):
|
||||
adapter_name=self._FAKE_ADAPTER_NAME) as handle:
|
||||
self.assertEqual(mock_open_adapter.return_value, handle)
|
||||
mock_open_adapter.assert_called_once_with(
|
||||
adapter_name=self._FAKE_ADAPTER_NAME)
|
||||
self._FAKE_ADAPTER_NAME)
|
||||
mock_close_adapter.assert_called_once_with(
|
||||
mock_open_adapter.return_value)
|
||||
|
||||
@mock.patch.object(ctypes, 'byref')
|
||||
def test_get_adapter_name(self, mock_byref):
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter_by_wwn')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
def test_get_hba_handle_by_wwn(self, mock_close_adapter,
|
||||
mock_open_adapter):
|
||||
with self._fc_utils._get_hba_handle(
|
||||
adapter_wwn=self._FAKE_ADAPTER_WWN) as handle:
|
||||
self.assertEqual(mock_open_adapter.return_value, handle)
|
||||
mock_open_adapter.assert_called_once_with(
|
||||
self._FAKE_ADAPTER_WWN)
|
||||
mock_close_adapter.assert_called_once_with(
|
||||
mock_open_adapter.return_value)
|
||||
|
||||
def test_get_hba_handle_missing_params(self):
|
||||
self.assertRaises(exceptions.FCException,
|
||||
self._fc_utils._get_hba_handle().__enter__)
|
||||
|
||||
def test_get_adapter_name(self):
|
||||
self._ctypes_mocker.stop()
|
||||
fake_adapter_index = 1
|
||||
|
||||
def update_buff(buff):
|
||||
def update_buff(func, adapter_index, buff):
|
||||
buff.value = six.b(self._FAKE_ADAPTER_NAME)
|
||||
|
||||
mock_byref.side_effect = update_buff
|
||||
self._mock_run.side_effect = update_buff
|
||||
|
||||
resulted_adapter_name = self._fc_utils._get_adapter_name(
|
||||
fake_adapter_index)
|
||||
@ -139,8 +153,7 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
self.assertIsInstance(args_list[1], ctypes.c_uint32)
|
||||
self.assertEqual(fake_adapter_index, args_list[1].value)
|
||||
|
||||
arg_byref = mock_byref.call_args_list[0][0][0]
|
||||
buff = ctypes.cast(arg_byref, ctypes.POINTER(
|
||||
buff = ctypes.cast(args_list[2], ctypes.POINTER(
|
||||
ctypes.c_char * 256)).contents
|
||||
self.assertIsInstance(buff, ctypes.c_char * 256)
|
||||
self.assertEqual(self._FAKE_ADAPTER_NAME, resulted_adapter_name)
|
||||
@ -228,7 +241,7 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
mock_get_adapter_ports.assert_has_calls(
|
||||
[mock.call(mock.sentinel.adapter_name)] * 2)
|
||||
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter_by_name')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_port_attributes')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_adapter_attributes')
|
||||
@ -245,8 +258,8 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
mock_adapter_attributes = mock.MagicMock()
|
||||
mock_adapter_attributes.NumberOfPorts = fake_port_count
|
||||
mock_port_attributes = mock.MagicMock()
|
||||
mock_port_attributes.NodeWWN = fake_node_wwn
|
||||
mock_port_attributes.PortWWN = fake_port_wwn
|
||||
mock_port_attributes.NodeWWN.wwn = fake_node_wwn
|
||||
mock_port_attributes.PortWWN.wwn = fake_port_wwn
|
||||
|
||||
mock_get_adapter_attributes.return_value = mock_adapter_attributes
|
||||
mock_get_adapter_port_attributes.return_value = mock_port_attributes
|
||||
@ -260,8 +273,7 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
}]
|
||||
self.assertEqual(expected_hba_ports, resulted_hba_ports)
|
||||
|
||||
mock_open_adapter.assert_called_once_with(
|
||||
adapter_name=mock.sentinel.adapter_name)
|
||||
mock_open_adapter.assert_called_once_with(mock.sentinel.adapter_name)
|
||||
mock_close_adapter.assert_called_once_with(
|
||||
mock_open_adapter(mock.sentinel.adapter_nam))
|
||||
mock_get_adapter_attributes.assert_called_once_with(
|
||||
@ -286,7 +298,7 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
expected_string = '000102'
|
||||
self.assertEqual(expected_string, resulted_string)
|
||||
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_open_adapter_by_wwn')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_close_adapter')
|
||||
@mock.patch.object(fc_utils.FCUtils, '_get_target_mapping')
|
||||
def test_get_fc_target_mapping(self, mock_get_target_mapping,
|
||||
@ -299,8 +311,8 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
mock_fcp_mappings = mock.MagicMock()
|
||||
mock_entry = mock.MagicMock()
|
||||
mock_entry.FcpId.NodeWWN = fake_node_wwn
|
||||
mock_entry.FcpId.PortWWN = fake_port_wwn
|
||||
mock_entry.FcpId.NodeWWN.wwn = fake_node_wwn
|
||||
mock_entry.FcpId.PortWWN.wwn = fake_port_wwn
|
||||
mock_entry.ScsiId.OSDeviceName = mock.sentinel.OSDeviceName
|
||||
mock_entry.ScsiId.ScsiOSLun = mock.sentinel.ScsiOSLun
|
||||
mock_fcp_mappings.Entries = [mock_entry]
|
||||
@ -318,7 +330,7 @@ class FCUtilsTestCase(base.BaseTestCase):
|
||||
'lun': mock.sentinel.ScsiOSLun
|
||||
}]
|
||||
self.assertEqual(expected_mappings, resulted_mappings)
|
||||
mock_open_adapter.assert_called_once_with(adapter_wwn=mock_node_wwn)
|
||||
mock_open_adapter.assert_called_once_with(mock_node_wwn)
|
||||
mock_close_adapter.assert_called_once_with(
|
||||
mock_open_adapter.return_value)
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
#
|
||||
# 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 ctypes
|
||||
|
||||
import six
|
||||
|
||||
from os_win import constants
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils.storage.initiator import iscsidsc_structures as iscsi_struct
|
||||
|
||||
|
||||
class ISCSIStructTestCase(test_base.OsWinBaseTestCase):
|
||||
def test_iscsi_login_opts_setup(self):
|
||||
fake_username = 'fake_chap_username'
|
||||
fake_password = 'fake_chap_secret'
|
||||
auth_type = constants.ISCSI_CHAP_AUTH_TYPE
|
||||
|
||||
login_opts = iscsi_struct.ISCSI_LOGIN_OPTIONS(Username=fake_username,
|
||||
Password=fake_password,
|
||||
AuthType=auth_type)
|
||||
|
||||
self.assertIsInstance(login_opts.Username, iscsi_struct.PUCHAR)
|
||||
self.assertIsInstance(login_opts.Password, iscsi_struct.PUCHAR)
|
||||
|
||||
self.assertEqual(len(fake_username), login_opts.UsernameLength)
|
||||
self.assertEqual(len(fake_password), login_opts.PasswordLength)
|
||||
|
||||
username_struct_contents = ctypes.cast(
|
||||
login_opts.Username,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_username))).contents.value
|
||||
pwd_struct_contents = ctypes.cast(
|
||||
login_opts.Password,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_password))).contents.value
|
||||
|
||||
self.assertEqual(six.b(fake_username), username_struct_contents)
|
||||
self.assertEqual(six.b(fake_password), pwd_struct_contents)
|
||||
|
||||
expected_info_bitmap = (iscsi_struct.ISCSI_LOGIN_OPTIONS_USERNAME |
|
||||
iscsi_struct.ISCSI_LOGIN_OPTIONS_PASSWORD |
|
||||
iscsi_struct.ISCSI_LOGIN_OPTIONS_AUTH_TYPE)
|
||||
self.assertEqual(expected_info_bitmap,
|
||||
login_opts.InformationSpecified)
|
@ -19,14 +19,16 @@ import ctypes
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
import six
|
||||
|
||||
from os_win import _utils
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils.storage.initiator import iscsi_utils
|
||||
from os_win.utils.storage.initiator import iscsidsc_structures as iscsi_struct
|
||||
from os_win.utils.storage.initiator import iscsierr
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.errmsg import iscsierr
|
||||
from os_win.utils.winapi.libs import iscsidsc as iscsi_struct
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -95,7 +97,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
parse_output=False):
|
||||
insufficient_buff_exc = exceptions.Win32Exception(
|
||||
message='fake_err_msg',
|
||||
error_code=iscsi_utils.ERROR_INSUFFICIENT_BUFFER)
|
||||
error_code=w_const.ERROR_INSUFFICIENT_BUFFER)
|
||||
func_requests_buff_sz = required_buff_sz is not None
|
||||
struct_type = ctypes.c_uint
|
||||
|
||||
@ -119,19 +121,13 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
# We expect our decorated method to be called exactly two times.
|
||||
first_call_args_dict = func_side_effect.call_args_list[0][1]
|
||||
self.assertIsInstance(first_call_args_dict['buff'],
|
||||
ctypes.c_ubyte * 0)
|
||||
ctypes.POINTER(struct_type))
|
||||
self.assertEqual(first_call_args_dict['buff_size_val'], 0)
|
||||
self.assertEqual(first_call_args_dict['element_count_val'], 0)
|
||||
|
||||
if required_buff_sz:
|
||||
expected_buff_sz = required_buff_sz
|
||||
else:
|
||||
expected_buff_sz = ctypes.sizeof(
|
||||
struct_type) * returned_element_count
|
||||
|
||||
second_call_args_dict = func_side_effect.call_args_list[1][1]
|
||||
self.assertIsInstance(second_call_args_dict['buff'],
|
||||
ctypes.c_ubyte * expected_buff_sz)
|
||||
ctypes.POINTER(struct_type))
|
||||
self.assertEqual(second_call_args_dict['buff_size_val'],
|
||||
required_buff_sz or 0)
|
||||
self.assertEqual(second_call_args_dict['element_count_val'],
|
||||
@ -151,7 +147,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
func_side_effect = mock.Mock(side_effect=fake_exc)
|
||||
fake_func = self._get_fake_iscsi_utils_getter_func(
|
||||
func_side_effect=func_side_effect,
|
||||
decorator_args={})
|
||||
decorator_args={'struct_type': ctypes.c_ubyte})
|
||||
|
||||
self.assertRaises(exceptions.Win32Exception, fake_func,
|
||||
self._initiator)
|
||||
@ -199,7 +195,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._mock_run.assert_called_once_with(
|
||||
self._iscsidsc.ReportIScsiPersistentLoginsW,
|
||||
self._ctypes.byref(mock.sentinel.element_count),
|
||||
self._ctypes.byref(mock.sentinel.buff),
|
||||
mock.sentinel.buff,
|
||||
self._ctypes.byref(mock.sentinel.buff_size))
|
||||
|
||||
@mock.patch.object(iscsi_utils.ISCSIInitiatorUtils,
|
||||
@ -223,7 +219,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._iscsidsc.ReportIScsiTargetsW,
|
||||
mock.sentinel.forced_update,
|
||||
self._ctypes.byref(mock_el_count),
|
||||
self._ctypes.byref(mock.sentinel.buff))
|
||||
mock.sentinel.buff)
|
||||
mock_parse_string_list.assert_called_once_with(
|
||||
mock.sentinel.buff, mock.sentinel.element_count)
|
||||
|
||||
@ -246,7 +242,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._mock_run.assert_called_once_with(
|
||||
self._iscsidsc.ReportIScsiInitiatorListW,
|
||||
self._ctypes.byref(mock_el_count),
|
||||
self._ctypes.byref(mock.sentinel.buff))
|
||||
mock.sentinel.buff)
|
||||
mock_parse_string_list.assert_called_once_with(
|
||||
mock.sentinel.buff, mock.sentinel.element_count)
|
||||
|
||||
@ -270,14 +266,14 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self._ctypes.c_wchar = mock.MagicMock()
|
||||
fake_buff = (self._ctypes.c_wchar * (
|
||||
iscsi_struct.MAX_ISCSI_NAME_LEN + 1))()
|
||||
w_const.MAX_ISCSI_NAME_LEN + 1))()
|
||||
fake_buff.value = mock.sentinel.buff_value
|
||||
|
||||
resulted_iscsi_initiator = self._initiator.get_iscsi_initiator()
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
self._iscsidsc.GetIScsiInitiatorNodeNameW,
|
||||
self._ctypes.byref(fake_buff))
|
||||
fake_buff)
|
||||
self.assertEqual(mock.sentinel.buff_value,
|
||||
resulted_iscsi_initiator)
|
||||
|
||||
@ -315,11 +311,10 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self.assertEqual(fake_target_name, args_list[1].value)
|
||||
self.assertIsInstance(args_list[4], ctypes.c_ulong)
|
||||
self.assertEqual(
|
||||
ctypes.c_ulong(iscsi_struct.ISCSI_ANY_INITIATOR_PORT).value,
|
||||
ctypes.c_ulong(w_const.ISCSI_ANY_INITIATOR_PORT).value,
|
||||
args_list[4].value)
|
||||
self.assertIsInstance(args_list[6], ctypes.c_ulonglong)
|
||||
self.assertEqual(iscsi_struct.ISCSI_DEFAULT_SECURITY_FLAGS,
|
||||
args_list[6].value)
|
||||
self.assertEqual(0, args_list[6].value)
|
||||
self.assertIsInstance(args_list[9], ctypes.c_ulong)
|
||||
self.assertEqual(0, args_list[9].value)
|
||||
|
||||
@ -348,7 +343,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._iscsidsc.GetIScsiSessionListW,
|
||||
self._ctypes.byref(mock.sentinel.buff_size),
|
||||
self._ctypes.byref(mock.sentinel.element_count),
|
||||
self._ctypes.byref(mock.sentinel.buff))
|
||||
mock.sentinel.buff)
|
||||
|
||||
@mock.patch.object(iscsi_utils.ISCSIInitiatorUtils,
|
||||
'_get_iscsi_sessions')
|
||||
@ -385,14 +380,13 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._iscsidsc.GetDevicesForIScsiSessionW,
|
||||
self._ctypes.byref(mock.sentinel.session_id),
|
||||
self._ctypes.byref(mock.sentinel.element_count),
|
||||
self._ctypes.byref(mock.sentinel.buff))
|
||||
mock.sentinel.buff)
|
||||
|
||||
@mock.patch.object(iscsi_utils.ISCSIInitiatorUtils,
|
||||
'_get_iscsi_session_devices')
|
||||
def test_get_iscsi_session_luns(self, mock_get_iscsi_session_devices):
|
||||
fake_device = mock.Mock()
|
||||
fake_device.StorageDeviceNumber.DeviceType = (
|
||||
iscsi_struct.FILE_DEVICE_DISK)
|
||||
fake_device.StorageDeviceNumber.DeviceType = w_const.FILE_DEVICE_DISK
|
||||
mock_get_iscsi_session_devices.return_value = [fake_device,
|
||||
mock.Mock()]
|
||||
|
||||
@ -533,45 +527,44 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self._initiator._remove_static_target(mock.sentinel.target_name)
|
||||
|
||||
expected_ignored_err_codes = [iscsierr.ISDSC_TARGET_NOT_FOUND]
|
||||
expected_ignored_err_codes = [w_const.ISDSC_TARGET_NOT_FOUND]
|
||||
self._mock_run.assert_called_once_with(
|
||||
self._iscsidsc.RemoveIScsiStaticTargetW,
|
||||
self._ctypes.c_wchar_p(mock.sentinel.target_name),
|
||||
ignored_error_codes=expected_ignored_err_codes)
|
||||
|
||||
@mock.patch.object(iscsi_struct, 'ISCSI_LOGIN_OPTIONS')
|
||||
def _test_get_login_opts(self, mock_cls_ISCSI_LOGIN_OPTIONS,
|
||||
auth_type=None, creds_specified=False):
|
||||
auth_user = mock.sentinel.auth_user if creds_specified else None
|
||||
auth_pwd = mock.sentinel.auth_pwd if creds_specified else None
|
||||
def test_get_login_opts(self):
|
||||
fake_username = 'fake_chap_username'
|
||||
fake_password = 'fake_chap_secret'
|
||||
auth_type = constants.ISCSI_CHAP_AUTH_TYPE
|
||||
login_flags = w_const.ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED
|
||||
|
||||
if not auth_type:
|
||||
expected_auth_type = (constants.ISCSI_CHAP_AUTH_TYPE
|
||||
if creds_specified
|
||||
else constants.ISCSI_NO_AUTH_TYPE)
|
||||
else:
|
||||
expected_auth_type = auth_type
|
||||
login_opts = self._initiator._get_login_opts(
|
||||
auth_username=fake_username,
|
||||
auth_password=fake_password,
|
||||
auth_type=auth_type,
|
||||
login_flags=login_flags)
|
||||
|
||||
resulted_login_opts = self._initiator._get_login_opts(
|
||||
auth_user, auth_pwd, auth_type,
|
||||
mock.sentinel.login_flags)
|
||||
self.assertEqual(len(fake_username), login_opts.UsernameLength)
|
||||
self.assertEqual(len(fake_password), login_opts.PasswordLength)
|
||||
|
||||
expected_login_opts = mock_cls_ISCSI_LOGIN_OPTIONS.return_value
|
||||
mock_cls_ISCSI_LOGIN_OPTIONS.assert_called_once_with(
|
||||
Username=auth_user,
|
||||
Password=auth_pwd,
|
||||
AuthType=expected_auth_type,
|
||||
LoginFlags=mock.sentinel.login_flags)
|
||||
self.assertEqual(expected_login_opts, resulted_login_opts)
|
||||
username_struct_contents = ctypes.cast(
|
||||
login_opts.Username,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_username))).contents.value
|
||||
pwd_struct_contents = ctypes.cast(
|
||||
login_opts.Password,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_password))).contents.value
|
||||
|
||||
def test_get_login_opts_without_creds_and_explicit_auth_type(self):
|
||||
self._test_get_login_opts()
|
||||
self.assertEqual(six.b(fake_username), username_struct_contents)
|
||||
self.assertEqual(six.b(fake_password), pwd_struct_contents)
|
||||
|
||||
def test_get_login_opts_with_creds_and_without_explicit_auth_type(self):
|
||||
self._test_get_login_opts(creds_specified=True)
|
||||
|
||||
def test_get_login_opts_with_explicit_auth_type(self):
|
||||
self._test_get_login_opts(auth_type=mock.sentinel.auth_type)
|
||||
expected_info_bitmap = (w_const.ISCSI_LOGIN_OPTIONS_USERNAME |
|
||||
w_const.ISCSI_LOGIN_OPTIONS_PASSWORD |
|
||||
w_const.ISCSI_LOGIN_OPTIONS_AUTH_TYPE)
|
||||
self.assertEqual(expected_info_bitmap,
|
||||
login_opts.InformationSpecified)
|
||||
self.assertEqual(login_flags,
|
||||
login_opts.LoginFlags)
|
||||
|
||||
@mock.patch.object(iscsi_utils.ISCSIInitiatorUtils,
|
||||
'_get_iscsi_session_devices')
|
||||
@ -687,7 +680,7 @@ class ISCSIInitiatorUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
if login_required:
|
||||
expected_login_flags = (
|
||||
iscsi_struct.ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED
|
||||
w_const.ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED
|
||||
if mpio_enabled else 0)
|
||||
mock_get_login_opts.assert_called_once_with(
|
||||
mock.sentinel.auth_username,
|
||||
|
@ -1,56 +0,0 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
#
|
||||
# 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 ctypes
|
||||
|
||||
import six
|
||||
|
||||
from os_win import constants
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils.storage.initiator import iscsidsc_structures as iscsi_struct
|
||||
|
||||
|
||||
class ISCSIStructTestCase(test_base.OsWinBaseTestCase):
|
||||
def test_iscsi_login_opts_setup(self):
|
||||
fake_username = 'fake_chap_username'
|
||||
fake_password = 'fake_chap_secret'
|
||||
auth_type = constants.ISCSI_CHAP_AUTH_TYPE
|
||||
|
||||
login_opts = iscsi_struct.ISCSI_LOGIN_OPTIONS(Username=fake_username,
|
||||
Password=fake_password,
|
||||
AuthType=auth_type)
|
||||
|
||||
self.assertIsInstance(login_opts.Username, iscsi_struct.PUCHAR)
|
||||
self.assertIsInstance(login_opts.Password, iscsi_struct.PUCHAR)
|
||||
|
||||
self.assertEqual(len(fake_username), login_opts.UsernameLength)
|
||||
self.assertEqual(len(fake_password), login_opts.PasswordLength)
|
||||
|
||||
username_struct_contents = ctypes.cast(
|
||||
login_opts.Username,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_username))).contents.value
|
||||
pwd_struct_contents = ctypes.cast(
|
||||
login_opts.Password,
|
||||
ctypes.POINTER(ctypes.c_char * len(fake_password))).contents.value
|
||||
|
||||
self.assertEqual(six.b(fake_username), username_struct_contents)
|
||||
self.assertEqual(six.b(fake_password), pwd_struct_contents)
|
||||
|
||||
expected_info_bitmap = (iscsi_struct.ISCSI_LOGIN_OPTIONS_USERNAME |
|
||||
iscsi_struct.ISCSI_LOGIN_OPTIONS_PASSWORD |
|
||||
iscsi_struct.ISCSI_LOGIN_OPTIONS_AUTH_TYPE)
|
||||
self.assertEqual(expected_info_bitmap,
|
||||
login_opts.InformationSpecified)
|
@ -20,9 +20,8 @@ import six
|
||||
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage.virtdisk import (
|
||||
virtdisk_constants as vdisk_const)
|
||||
from os_win.utils.storage.virtdisk import vhdutils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
|
||||
class VHDUtilsTestCase(base.BaseTestCase):
|
||||
@ -32,11 +31,12 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
super(VHDUtilsTestCase, self).setUp()
|
||||
self._setup_lib_mocks()
|
||||
|
||||
self._fake_vst_struct = self._vdisk_struct.Win32_VIRTUAL_STORAGE_TYPE
|
||||
self._fake_vst_struct = self._vdisk_struct.VIRTUAL_STORAGE_TYPE
|
||||
|
||||
self._vhdutils = vhdutils.VHDUtils()
|
||||
self._vhdutils._win32_utils = mock.Mock()
|
||||
|
||||
self._mock_close = self._vhdutils._win32_utils.close_handle
|
||||
self._mock_run = self._vhdutils._win32_utils.run_and_check_output
|
||||
self._run_args = self._vhdutils._virtdisk_run_args
|
||||
|
||||
@ -57,8 +57,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
vdisk_struct=self._vdisk_struct,
|
||||
create=True).start()
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
def _test_run_and_check_output(self, mock_close, raised_exc=None):
|
||||
def _test_run_and_check_output(self, raised_exc=None):
|
||||
self._mock_run.side_effect = raised_exc(
|
||||
func_name='fake_func_name',
|
||||
error_code='fake_error_code',
|
||||
@ -80,7 +79,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
mock.sentinel.func, mock.sentinel.arg, **self._run_args)
|
||||
mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
self._mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
|
||||
def test_run_and_check_output(self):
|
||||
self._test_run_and_check_output()
|
||||
@ -103,7 +102,8 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
self.assertEqual(vhdutils.wintypes.HANDLE.return_value, handle)
|
||||
self._fake_vst_struct.assert_called_once_with(
|
||||
DeviceId=mock.sentinel.device_id)
|
||||
DeviceId=mock.sentinel.device_id,
|
||||
VendorId=w_const.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
vhdutils.virtdisk.OpenVirtualDisk,
|
||||
@ -121,14 +121,16 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
mock.sentinel.handle)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_get_vhd_device_id')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
def _test_create_vhd(self, mock_close, mock_get_dev_id, new_vhd_type):
|
||||
def _test_create_vhd(self, mock_get_dev_id, new_vhd_type):
|
||||
create_params_struct = (
|
||||
self._vdisk_struct.Win32_CREATE_VIRTUAL_DISK_PARAMETERS)
|
||||
self._vdisk_struct.CREATE_VIRTUAL_DISK_PARAMETERS)
|
||||
mock_handle = vhdutils.wintypes.HANDLE.return_value
|
||||
|
||||
fake_vst = self._fake_vst_struct.return_value
|
||||
fake_create_params = create_params_struct.return_value
|
||||
|
||||
expected_create_vhd_flag = (
|
||||
vdisk_const.CREATE_VIRTUAL_DISK_FLAGS.get(new_vhd_type))
|
||||
vhdutils.CREATE_VIRTUAL_DISK_FLAGS.get(new_vhd_type, 0))
|
||||
|
||||
self._vhdutils.create_vhd(
|
||||
new_vhd_path=mock.sentinel.new_vhd_path,
|
||||
@ -138,22 +140,41 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
parent_path=mock.sentinel.parent_path)
|
||||
|
||||
self._fake_vst_struct.assert_called_once_with(
|
||||
DeviceId=mock_get_dev_id.return_value)
|
||||
create_params_struct.assert_called_once_with(
|
||||
MaximumSize=mock.sentinel.max_internal_size,
|
||||
ParentPath=mock.sentinel.parent_path,
|
||||
SourcePath=mock.sentinel.src_path)
|
||||
DeviceId=mock_get_dev_id.return_value,
|
||||
VendorId=w_const.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT)
|
||||
|
||||
self.assertEqual(w_const.CREATE_VIRTUAL_DISK_VERSION_2,
|
||||
fake_create_params.Version)
|
||||
self.assertEqual(mock.sentinel.max_internal_size,
|
||||
fake_create_params.Version2.MaximumSize)
|
||||
self.assertEqual(mock.sentinel.parent_path,
|
||||
fake_create_params.Version2.ParentPath)
|
||||
self.assertEqual(mock.sentinel.src_path,
|
||||
fake_create_params.Version2.SourcePath)
|
||||
self.assertEqual(
|
||||
vhdutils.VIRTUAL_DISK_DEFAULT_PHYS_SECTOR_SIZE,
|
||||
fake_create_params.Version2.PhysicalSectorSizeInBytes)
|
||||
self.assertEqual(
|
||||
w_const.CREATE_VHD_PARAMS_DEFAULT_BLOCK_SIZE,
|
||||
fake_create_params.Version2.BlockSizeInBytes)
|
||||
self.assertEqual(
|
||||
vhdutils.VIRTUAL_DISK_DEFAULT_SECTOR_SIZE,
|
||||
fake_create_params.Version2.SectorSizeInBytes)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
vhdutils.virtdisk.CreateVirtualDisk,
|
||||
self._ctypes.byref(self._fake_vst_struct.return_value),
|
||||
self._ctypes.c_wchar_p(mock.sentinel.new_vhd_path), None,
|
||||
None, expected_create_vhd_flag, None,
|
||||
self._ctypes.byref(create_params_struct.return_value), None,
|
||||
self._ctypes.byref(fake_vst),
|
||||
self._ctypes.c_wchar_p(mock.sentinel.new_vhd_path),
|
||||
0,
|
||||
None,
|
||||
expected_create_vhd_flag,
|
||||
0,
|
||||
self._ctypes.byref(fake_create_params),
|
||||
None,
|
||||
self._ctypes.byref(mock_handle),
|
||||
**self._run_args)
|
||||
|
||||
mock_close.assert_called_once_with(mock_handle)
|
||||
self._mock_close.assert_called_once_with(mock_handle)
|
||||
|
||||
def test_create_dynamic_vhd(self):
|
||||
self._test_create_vhd(new_vhd_type=constants.VHD_TYPE_DYNAMIC)
|
||||
@ -230,7 +251,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
dev_id = self._vhdutils._get_vhd_device_id(mock.sentinel.vhd_path)
|
||||
|
||||
mock_get_vhd_fmt.assert_called_once_with(mock.sentinel.vhd_path)
|
||||
self.assertEqual(vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
self.assertEqual(w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
dev_id)
|
||||
|
||||
def _mock_open(self, read_data=None, curr_f_pos=0):
|
||||
@ -245,7 +266,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
return mock_open
|
||||
|
||||
def test_get_vhd_format_by_sig_vhdx(self):
|
||||
read_data = (vdisk_const.VHDX_SIGNATURE, )
|
||||
read_data = (vhdutils.VHDX_SIGNATURE, )
|
||||
self._mock_open(read_data=read_data)
|
||||
|
||||
fmt = self._vhdutils._get_vhd_format_by_signature(
|
||||
@ -254,7 +275,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(constants.DISK_FORMAT_VHDX, fmt)
|
||||
|
||||
def test_get_vhd_format_by_sig_vhd(self):
|
||||
read_data = ('notthesig', vdisk_const.VHD_SIGNATURE)
|
||||
read_data = ('notthesig', vhdutils.VHD_SIGNATURE)
|
||||
mock_open = self._mock_open(read_data=read_data, curr_f_pos=1024)
|
||||
|
||||
fmt = self._vhdutils._get_vhd_format_by_signature(
|
||||
@ -282,19 +303,18 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
mock_open.return_value.seek.assert_called_once_with(0, 2)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_open')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_get_vhd_info_member')
|
||||
def test_get_vhd_info(self, mock_get_vhd_info_member,
|
||||
mock_close, mock_open):
|
||||
fake_info_member = vdisk_const.GET_VIRTUAL_DISK_INFO_SIZE
|
||||
mock_open):
|
||||
fake_info_member = w_const.GET_VIRTUAL_DISK_INFO_SIZE
|
||||
fake_vhd_info = {'VirtualSize': mock.sentinel.virtual_size}
|
||||
|
||||
mock_open.return_value = mock.sentinel.handle
|
||||
mock_get_vhd_info_member.return_value = fake_vhd_info
|
||||
|
||||
expected_open_flag = vdisk_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS
|
||||
expected_access_mask = (vdisk_const.VIRTUAL_DISK_ACCESS_GET_INFO |
|
||||
vdisk_const.VIRTUAL_DISK_ACCESS_DETACH)
|
||||
expected_open_flag = w_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS
|
||||
expected_access_mask = (w_const.VIRTUAL_DISK_ACCESS_GET_INFO |
|
||||
w_const.VIRTUAL_DISK_ACCESS_DETACH)
|
||||
|
||||
ret_val = self._vhdutils.get_vhd_info(mock.sentinel.vhd_path,
|
||||
[fake_info_member])
|
||||
@ -307,16 +327,16 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self._vhdutils._get_vhd_info_member.assert_called_once_with(
|
||||
mock.sentinel.handle,
|
||||
fake_info_member)
|
||||
mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
self._mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_parse_vhd_info')
|
||||
def test_get_vhd_info_member(self, mock_parse_vhd_info):
|
||||
get_vd_info_struct = (
|
||||
self._vdisk_struct.Win32_GET_VIRTUAL_DISK_INFO_PARAMETERS)
|
||||
self._vdisk_struct.GET_VIRTUAL_DISK_INFO)
|
||||
fake_params = get_vd_info_struct.return_value
|
||||
fake_info_size = self._ctypes.sizeof.return_value
|
||||
|
||||
info_member = vdisk_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION
|
||||
info_member = w_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION
|
||||
|
||||
vhd_info = self._vhdutils._get_vhd_info_member(
|
||||
mock.sentinel.vhd_path,
|
||||
@ -328,7 +348,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self._ctypes.byref(
|
||||
self._ctypes.c_ulong(fake_info_size)),
|
||||
self._ctypes.byref(fake_params), None,
|
||||
ignored_error_codes=[vdisk_const.ERROR_VHD_INVALID_TYPE],
|
||||
ignored_error_codes=[w_const.ERROR_VHD_INVALID_TYPE],
|
||||
**self._run_args)
|
||||
|
||||
self.assertEqual(mock_parse_vhd_info.return_value, vhd_info)
|
||||
@ -336,13 +356,13 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
info_member)
|
||||
|
||||
def test_parse_vhd_info(self):
|
||||
fake_info_member = vdisk_const.GET_VIRTUAL_DISK_INFO_SIZE
|
||||
fake_info_member = w_const.GET_VIRTUAL_DISK_INFO_SIZE
|
||||
fake_info = mock.Mock()
|
||||
fake_info.VhdInfo.Size._fields_ = [
|
||||
fake_info.Size._fields_ = [
|
||||
("VirtualSize", vhdutils.wintypes.ULARGE_INTEGER),
|
||||
("PhysicalSize", vhdutils.wintypes.ULARGE_INTEGER)]
|
||||
fake_info.VhdInfo.Size.VirtualSize = mock.sentinel.virt_size
|
||||
fake_info.VhdInfo.Size.PhysicalSize = mock.sentinel.phys_size
|
||||
fake_info.Size.VirtualSize = mock.sentinel.virt_size
|
||||
fake_info.Size.PhysicalSize = mock.sentinel.phys_size
|
||||
|
||||
ret_val = self._vhdutils._parse_vhd_info(fake_info,
|
||||
fake_info_member)
|
||||
@ -352,10 +372,9 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(expected, ret_val)
|
||||
|
||||
def test_parse_vhd_provider_subtype_member(self):
|
||||
fake_info_member = (
|
||||
vdisk_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE)
|
||||
fake_info_member = w_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE
|
||||
fake_info = mock.Mock()
|
||||
fake_info.VhdInfo.ProviderSubtype = mock.sentinel.provider_subtype
|
||||
fake_info.ProviderSubtype = mock.sentinel.provider_subtype
|
||||
|
||||
ret_val = self._vhdutils._parse_vhd_info(fake_info, fake_info_member)
|
||||
expected = {'ProviderSubtype': mock.sentinel.provider_subtype}
|
||||
@ -369,7 +388,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(mock_get_vhd_info.return_value, ret_val)
|
||||
mock_get_vhd_info.assert_called_once_with(
|
||||
mock.sentinel.vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_SIZE])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_SIZE])
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, 'get_vhd_info')
|
||||
def test_get_vhd_parent_path(self, mock_get_vhd_info):
|
||||
@ -381,7 +400,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(mock.sentinel.parent_path, ret_val)
|
||||
mock_get_vhd_info.assert_called_once_with(
|
||||
mock.sentinel.vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION])
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, 'get_vhd_info')
|
||||
def test_get_vhd_type(self, mock_get_vhd_info):
|
||||
@ -393,16 +412,15 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self.assertEqual(mock.sentinel.provider_subtype, ret_val)
|
||||
mock_get_vhd_info.assert_called_once_with(
|
||||
mock.sentinel.vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE])
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_open')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
@mock.patch('os.remove')
|
||||
def test_merge_vhd(self, mock_remove, mock_close, mock_open):
|
||||
def test_merge_vhd(self, mock_remove, mock_open):
|
||||
open_params_struct = (
|
||||
self._vdisk_struct.Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V1)
|
||||
self._vdisk_struct.OPEN_VIRTUAL_DISK_PARAMETERS)
|
||||
merge_params_struct = (
|
||||
self._vdisk_struct.Win32_MERGE_VIRTUAL_DISK_PARAMETERS)
|
||||
self._vdisk_struct.MERGE_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
fake_open_params = open_params_struct.return_value
|
||||
fake_merge_params = merge_params_struct.return_value
|
||||
@ -410,30 +428,37 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
self._vhdutils.merge_vhd(mock.sentinel.vhd_path)
|
||||
|
||||
open_params_struct.assert_called_once_with(RWDepth=2)
|
||||
self.assertEqual(w_const.OPEN_VIRTUAL_DISK_VERSION_1,
|
||||
fake_open_params.Version)
|
||||
self.assertEqual(2,
|
||||
fake_open_params.Version1.RWDepth)
|
||||
|
||||
mock_open.assert_called_once_with(
|
||||
mock.sentinel.vhd_path,
|
||||
open_params=self._ctypes.byref(fake_open_params))
|
||||
merge_params_struct.assert_called_once_with(MergeDepth=1)
|
||||
|
||||
self.assertEqual(w_const.MERGE_VIRTUAL_DISK_VERSION_1,
|
||||
fake_merge_params.Version)
|
||||
self.assertEqual(1,
|
||||
fake_merge_params.Version1.MergeDepth)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
vhdutils.virtdisk.MergeVirtualDisk,
|
||||
mock.sentinel.handle,
|
||||
None,
|
||||
0,
|
||||
self._ctypes.byref(fake_merge_params),
|
||||
None,
|
||||
**self._run_args)
|
||||
mock_remove.assert_called_once_with(
|
||||
mock.sentinel.vhd_path)
|
||||
mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
self._mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_open')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
def test_reconnect_parent_vhd(self, mock_close, mock_open):
|
||||
def test_reconnect_parent_vhd(self, mock_open):
|
||||
set_vdisk_info_struct = (
|
||||
self._vdisk_struct.Win32_SET_VIRTUAL_DISK_INFO_PARAMETERS)
|
||||
self._vdisk_struct.SET_VIRTUAL_DISK_INFO)
|
||||
open_params_struct = (
|
||||
self._vdisk_struct.Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V2)
|
||||
self._vdisk_struct.OPEN_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
fake_set_params = set_vdisk_info_struct.return_value
|
||||
fake_open_params = open_params_struct.return_value
|
||||
@ -442,21 +467,27 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self._vhdutils.reconnect_parent_vhd(mock.sentinel.vhd_path,
|
||||
mock.sentinel.parent_path)
|
||||
|
||||
open_params_struct.assert_called_once_with(GetInfoOnly=False)
|
||||
self.assertEqual(w_const.OPEN_VIRTUAL_DISK_VERSION_2,
|
||||
fake_open_params.Version)
|
||||
self.assertFalse(fake_open_params.Version2.GetInfoOnly)
|
||||
|
||||
self._vhdutils._open.assert_called_once_with(
|
||||
mock.sentinel.vhd_path,
|
||||
open_flag=vdisk_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
|
||||
open_access_mask=None,
|
||||
open_flag=w_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
|
||||
open_access_mask=0,
|
||||
open_params=vhdutils.ctypes.byref(fake_open_params))
|
||||
set_vdisk_info_struct.assert_called_once_with(
|
||||
ParentFilePath=mock.sentinel.parent_path)
|
||||
|
||||
self.assertEqual(w_const.SET_VIRTUAL_DISK_INFO_PARENT_PATH,
|
||||
fake_set_params.Version)
|
||||
self.assertEqual(mock.sentinel.parent_path,
|
||||
fake_set_params.ParentFilePath)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
vhdutils.virtdisk.SetVirtualDiskInformation,
|
||||
mock.sentinel.handle,
|
||||
vhdutils.ctypes.byref(fake_set_params),
|
||||
**self._run_args)
|
||||
mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
self._mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, 'get_internal_vhd_size_by_file_size')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_resize_vhd')
|
||||
@ -520,10 +551,9 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self._test_check_resize_needed(current_size=1, new_size=1)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_open')
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_close')
|
||||
def test_resize_vhd_helper(self, mock_close, mock_open):
|
||||
def test_resize_vhd_helper(self, mock_open):
|
||||
resize_vdisk_struct = (
|
||||
self._vdisk_struct.Win32_RESIZE_VIRTUAL_DISK_PARAMETERS)
|
||||
self._vdisk_struct.RESIZE_VIRTUAL_DISK_PARAMETERS)
|
||||
fake_params = resize_vdisk_struct.return_value
|
||||
|
||||
mock_open.return_value = mock.sentinel.handle
|
||||
@ -531,16 +561,19 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
self._vhdutils._resize_vhd(mock.sentinel.vhd_path,
|
||||
mock.sentinel.new_size)
|
||||
|
||||
resize_vdisk_struct.assert_called_once_with(
|
||||
NewSize=mock.sentinel.new_size)
|
||||
self.assertEqual(w_const.RESIZE_VIRTUAL_DISK_VERSION_1,
|
||||
fake_params.Version)
|
||||
self.assertEqual(mock.sentinel.new_size,
|
||||
fake_params.Version1.NewSize)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
vhdutils.virtdisk.ResizeVirtualDisk,
|
||||
mock.sentinel.handle,
|
||||
None,
|
||||
0,
|
||||
vhdutils.ctypes.byref(fake_params),
|
||||
None,
|
||||
**self._run_args)
|
||||
mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
self._mock_close.assert_called_once_with(mock.sentinel.handle)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, 'get_vhd_info')
|
||||
@mock.patch.object(vhdutils.VHDUtils,
|
||||
@ -550,7 +583,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
def _test_get_int_sz_by_file_size(
|
||||
self, mock_get_vhdx_int_size,
|
||||
mock_get_vhd_int_size, mock_get_vhd_info,
|
||||
vhd_dev_id=vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
vhd_dev_id=w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
vhd_type=constants.VHD_TYPE_DYNAMIC):
|
||||
fake_vhd_info = dict(ProviderSubtype=vhd_type,
|
||||
ParentPath=mock.sentinel.parent_path,
|
||||
@ -569,7 +602,7 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
mock.call(mock.sentinel.parent_path))
|
||||
expected_vhd_checked = mock.sentinel.parent_path
|
||||
|
||||
is_vhd = vhd_dev_id == vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD
|
||||
is_vhd = vhd_dev_id == w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD
|
||||
expected_helper = (mock_get_vhd_int_size
|
||||
if is_vhd
|
||||
else mock_get_vhdx_int_size)
|
||||
@ -588,11 +621,11 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
def test_get_int_sz_by_file_size_vhdx(self):
|
||||
self._test_get_int_sz_by_file_size(
|
||||
vhd_dev_id=vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX)
|
||||
vhd_dev_id=w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX)
|
||||
|
||||
def test_get_int_sz_by_file_size_differencing(self):
|
||||
self._test_get_int_sz_by_file_size(
|
||||
vhd_dev_id=vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX)
|
||||
vhd_dev_id=w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX)
|
||||
|
||||
def _mocked_get_internal_vhd_size(self, root_vhd_size, vhd_type):
|
||||
fake_vhd_info = dict(ProviderSubtype=vhd_type,
|
||||
@ -672,11 +705,11 @@ class VHDUtilsTestCase(base.BaseTestCase):
|
||||
|
||||
offset = self._vhdutils._get_vhdx_current_header_offset(mock_handle)
|
||||
|
||||
self.assertEqual(vdisk_const.VHDX_HEADER_OFFSETS[1], offset)
|
||||
self.assertEqual(vhdutils.VHDX_HEADER_OFFSETS[1], offset)
|
||||
|
||||
@mock.patch.object(vhdutils.VHDUtils, '_get_vhdx_current_header_offset')
|
||||
def test_get_log_size(self, mock_get_vhdx_curr_hd_offset):
|
||||
fake_curr_header_offset = vdisk_const.VHDX_HEADER_OFFSETS[0]
|
||||
fake_curr_header_offset = vhdutils.VHDX_HEADER_OFFSETS[0]
|
||||
fake_log_sz = bytearray(b'\x01\x00\x00\x00')
|
||||
|
||||
mock_get_vhdx_curr_hd_offset.return_value = fake_curr_header_offset
|
||||
|
@ -18,6 +18,7 @@ import mock
|
||||
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils import _acl_utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -38,7 +39,7 @@ class ACLUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
mock.patch.multiple(_acl_utils,
|
||||
ctypes=self._ctypes,
|
||||
advapi=mock.DEFAULT,
|
||||
advapi32=mock.DEFAULT,
|
||||
kernel32=mock.DEFAULT,
|
||||
create=True).start()
|
||||
|
||||
@ -52,12 +53,12 @@ class ACLUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
@ddt.data(
|
||||
{'security_info_flags':
|
||||
(_acl_utils.OWNER_SECURITY_INFORMATION |
|
||||
_acl_utils.GROUP_SECURITY_INFORMATION |
|
||||
_acl_utils.DACL_SECURITY_INFORMATION),
|
||||
(w_const.OWNER_SECURITY_INFORMATION |
|
||||
w_const.GROUP_SECURITY_INFORMATION |
|
||||
w_const.DACL_SECURITY_INFORMATION),
|
||||
'expected_info': ['pp_sid_owner', 'pp_sid_group',
|
||||
'pp_dacl', 'pp_sec_desc']},
|
||||
{'security_info_flags': _acl_utils.SACL_SECURITY_INFORMATION,
|
||||
{'security_info_flags': w_const.SACL_SECURITY_INFORMATION,
|
||||
'expected_info': ['pp_sacl', 'pp_sec_desc']})
|
||||
@ddt.unpack
|
||||
@mock.patch.object(_acl_utils.ACLUtils, '_get_void_pp')
|
||||
@ -75,10 +76,10 @@ class ACLUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
mock_get_void_pp.return_value)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
_acl_utils.advapi.GetNamedSecurityInfoW,
|
||||
_acl_utils.advapi32.GetNamedSecurityInfoW,
|
||||
self._ctypes.c_wchar_p(mock.sentinel.obj_name),
|
||||
self._ctypes.c_uint(mock.sentinel.obj_type),
|
||||
self._ctypes.c_uint(security_info_flags),
|
||||
mock.sentinel.obj_type,
|
||||
security_info_flags,
|
||||
sec_info.get('pp_sid_owner'),
|
||||
sec_info.get('pp_sid_group'),
|
||||
sec_info.get('pp_dacl'),
|
||||
@ -96,8 +97,8 @@ class ACLUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self.assertEqual(new_acl, returned_acl)
|
||||
self._mock_run.assert_called_once_with(
|
||||
_acl_utils.advapi.SetEntriesInAclW,
|
||||
self._ctypes.c_ulong(mock.sentinel.entry_count),
|
||||
_acl_utils.advapi32.SetEntriesInAclW,
|
||||
mock.sentinel.entry_count,
|
||||
mock.sentinel.entry_list,
|
||||
mock.sentinel.old_acl,
|
||||
new_acl)
|
||||
@ -114,10 +115,10 @@ class ACLUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
mock.sentinel.p_sacl)
|
||||
|
||||
self._mock_run.assert_called_once_with(
|
||||
_acl_utils.advapi.SetNamedSecurityInfoW,
|
||||
_acl_utils.advapi32.SetNamedSecurityInfoW,
|
||||
self._ctypes.c_wchar_p(mock.sentinel.obj_name),
|
||||
self._ctypes.c_uint(mock.sentinel.obj_type),
|
||||
self._ctypes.c_uint(mock.sentinel.security_info_flags),
|
||||
mock.sentinel.obj_type,
|
||||
mock.sentinel.security_info_flags,
|
||||
mock.sentinel.p_sid_owner,
|
||||
mock.sentinel.p_sid_group,
|
||||
mock.sentinel.p_dacl,
|
||||
|
@ -51,10 +51,10 @@ class HostUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
super(HostUtilsTestCase, self).setUp()
|
||||
|
||||
@mock.patch('os_win.utils.hostutils.ctypes')
|
||||
def test_get_host_tick_count64(self, mock_ctypes):
|
||||
@mock.patch('os_win.utils.hostutils.kernel32')
|
||||
def test_get_host_tick_count64(self, mock_kernel32):
|
||||
tick_count64 = "100"
|
||||
mock_ctypes.windll.kernel32.GetTickCount64.return_value = tick_count64
|
||||
mock_kernel32.GetTickCount64.return_value = tick_count64
|
||||
response = self._hostutils.get_host_tick_count64()
|
||||
self.assertEqual(tick_count64, response)
|
||||
|
||||
|
@ -21,8 +21,9 @@ import mock
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.tests.unit import test_base
|
||||
from os_win.utils import _acl_utils
|
||||
from os_win.utils import pathutils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.libs import advapi32 as advapi32_def
|
||||
|
||||
|
||||
class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
@ -99,7 +100,7 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
@mock.patch.object(pathutils.shutil, 'rmtree')
|
||||
def test_rmtree(self, mock_rmtree, mock_sleep):
|
||||
exc = exceptions.WindowsError()
|
||||
exc.winerror = pathutils.ERROR_DIR_IS_NOT_EMPTY
|
||||
exc.winerror = w_const.ERROR_DIR_IS_NOT_EMPTY
|
||||
mock_rmtree.side_effect = [exc] * 5 + [None]
|
||||
|
||||
self._pathutils.rmtree(mock.sentinel.FAKE_PATH)
|
||||
@ -118,7 +119,7 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
def test_rmtree_exceeded(self):
|
||||
exc = exceptions.WindowsError()
|
||||
exc.winerror = pathutils.ERROR_DIR_IS_NOT_EMPTY
|
||||
exc.winerror = w_const.ERROR_DIR_IS_NOT_EMPTY
|
||||
self._check_rmtree(side_effect=[exc] * 6)
|
||||
|
||||
@mock.patch.object(pathutils.PathUtils, 'makedirs')
|
||||
@ -164,6 +165,7 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
self._mock_run.assert_called_once_with(
|
||||
pathutils.kernel32.GetFileAttributesW,
|
||||
fake_path,
|
||||
error_ret_vals=[w_const.INVALID_FILE_ATTRIBUTES],
|
||||
kernel32_lib_func=True)
|
||||
|
||||
self.assertEqual(is_symlink, ret_value)
|
||||
@ -287,23 +289,23 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self._acl_utils.get_named_security_info.assert_called_once_with(
|
||||
obj_name=mock.sentinel.path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION)
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION)
|
||||
self._acl_utils.set_entries_in_acl.assert_called_once_with(
|
||||
entry_count=1,
|
||||
p_explicit_entry_list=mock.ANY,
|
||||
p_old_acl=mock_sec_info['pp_dacl'].contents)
|
||||
self._acl_utils.set_named_security_info.assert_called_once_with(
|
||||
obj_name=mock.sentinel.path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION,
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION,
|
||||
p_dacl=pp_new_dacl.contents)
|
||||
|
||||
p_access = self._acl_utils.set_entries_in_acl.call_args_list[0][1][
|
||||
'p_explicit_entry_list']
|
||||
access = ctypes.cast(
|
||||
p_access,
|
||||
ctypes.POINTER(_acl_utils.EXPLICIT_ACCESS)).contents
|
||||
ctypes.POINTER(advapi32_def.EXPLICIT_ACCESS)).contents
|
||||
|
||||
self.assertEqual(constants.ACE_GENERIC_READ,
|
||||
access.grfAccessPermissions)
|
||||
@ -311,7 +313,7 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
access.grfAccessMode)
|
||||
self.assertEqual(constants.ACE_OBJECT_INHERIT,
|
||||
access.grfInheritance)
|
||||
self.assertEqual(_acl_utils.TRUSTEE_IS_NAME,
|
||||
self.assertEqual(w_const.TRUSTEE_IS_NAME,
|
||||
access.Trustee.TrusteeForm)
|
||||
self.assertEqual(fake_trustee,
|
||||
access.Trustee.pstrName)
|
||||
@ -336,12 +338,12 @@ class PathUtilsTestCase(test_base.OsWinBaseTestCase):
|
||||
|
||||
self._acl_utils.get_named_security_info.assert_called_once_with(
|
||||
obj_name=mock.sentinel.src,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION)
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION)
|
||||
self._acl_utils.set_named_security_info.assert_called_once_with(
|
||||
obj_name=mock.sentinel.dest,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION,
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION,
|
||||
p_dacl=mock_sec_info['pp_dacl'].contents)
|
||||
|
||||
self._pathutils._win32_utils.local_free.assert_called_once_with(
|
||||
|
@ -21,6 +21,7 @@ from oslotest import base
|
||||
from os_win import _utils
|
||||
from os_win import exceptions
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -162,9 +163,9 @@ class Win32UtilsTestCase(base.BaseTestCase):
|
||||
|
||||
fake_msg_buff = win32utils.ctypes.c_char_p.return_value
|
||||
|
||||
expected_flags = (win32utils.FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
win32utils.FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
win32utils.FORMAT_MESSAGE_IGNORE_INSERTS)
|
||||
expected_flags = (w_const.FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
w_const.FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
w_const.FORMAT_MESSAGE_IGNORE_INSERTS)
|
||||
|
||||
win32utils.kernel32.FormatMessageA.assert_called_once_with(
|
||||
expected_flags, None, mock.sentinel.err_code, 0,
|
||||
|
@ -14,39 +14,12 @@
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
|
||||
if sys.platform == 'win32':
|
||||
advapi = ctypes.windll.AdvApi32
|
||||
|
||||
|
||||
OWNER_SECURITY_INFORMATION = 0x00000001
|
||||
GROUP_SECURITY_INFORMATION = 0x00000002
|
||||
DACL_SECURITY_INFORMATION = 0x00000004
|
||||
SACL_SECURITY_INFORMATION = 0x00000008
|
||||
|
||||
# Trustee form constants
|
||||
TRUSTEE_IS_NAME = 1
|
||||
|
||||
# Indicates a file or directory object.
|
||||
SE_FILE_OBJECT = 1
|
||||
|
||||
|
||||
class TRUSTEE(ctypes.Structure):
|
||||
_fields_ = [('pMultipleTrustee', ctypes.c_void_p),
|
||||
('MultipleTrusteeOperation', ctypes.c_uint),
|
||||
('TrusteeForm', ctypes.c_uint),
|
||||
('TrusteeType', ctypes.c_uint),
|
||||
('pstrName', ctypes.c_wchar_p)]
|
||||
|
||||
|
||||
class EXPLICIT_ACCESS(ctypes.Structure):
|
||||
_fields_ = [('grfAccessPermissions', ctypes.c_ulong),
|
||||
('grfAccessMode', ctypes.c_uint),
|
||||
('grfInheritance', ctypes.c_ulong),
|
||||
('Trustee', TRUSTEE)]
|
||||
advapi32 = w_lib.get_shared_lib_handle(w_lib.ADVAPI32)
|
||||
|
||||
|
||||
class ACLUtils(object):
|
||||
@ -70,21 +43,21 @@ class ACLUtils(object):
|
||||
"""
|
||||
sec_info = {}
|
||||
|
||||
if security_info_flags & OWNER_SECURITY_INFORMATION:
|
||||
if security_info_flags & w_const.OWNER_SECURITY_INFORMATION:
|
||||
sec_info['pp_sid_owner'] = self._get_void_pp()
|
||||
if security_info_flags & GROUP_SECURITY_INFORMATION:
|
||||
if security_info_flags & w_const.GROUP_SECURITY_INFORMATION:
|
||||
sec_info['pp_sid_group'] = self._get_void_pp()
|
||||
if security_info_flags & DACL_SECURITY_INFORMATION:
|
||||
if security_info_flags & w_const.DACL_SECURITY_INFORMATION:
|
||||
sec_info['pp_dacl'] = self._get_void_pp()
|
||||
if security_info_flags & SACL_SECURITY_INFORMATION:
|
||||
if security_info_flags & w_const.SACL_SECURITY_INFORMATION:
|
||||
sec_info['pp_sacl'] = self._get_void_pp()
|
||||
sec_info['pp_sec_desc'] = self._get_void_pp()
|
||||
|
||||
self._win32_utils.run_and_check_output(
|
||||
advapi.GetNamedSecurityInfoW,
|
||||
advapi32.GetNamedSecurityInfoW,
|
||||
ctypes.c_wchar_p(obj_name),
|
||||
ctypes.c_uint(obj_type),
|
||||
ctypes.c_uint(security_info_flags),
|
||||
obj_type,
|
||||
security_info_flags,
|
||||
sec_info.get('pp_sid_owner'),
|
||||
sec_info.get('pp_sid_group'),
|
||||
sec_info.get('pp_dacl'),
|
||||
@ -99,8 +72,8 @@ class ACLUtils(object):
|
||||
pp_new_acl = self._get_void_pp()
|
||||
|
||||
self._win32_utils.run_and_check_output(
|
||||
advapi.SetEntriesInAclW,
|
||||
ctypes.c_ulong(entry_count),
|
||||
advapi32.SetEntriesInAclW,
|
||||
entry_count,
|
||||
p_explicit_entry_list,
|
||||
p_old_acl,
|
||||
pp_new_acl)
|
||||
@ -111,10 +84,10 @@ class ACLUtils(object):
|
||||
p_sid_owner=None, p_sid_group=None,
|
||||
p_dacl=None, p_sacl=None):
|
||||
self._win32_utils.run_and_check_output(
|
||||
advapi.SetNamedSecurityInfoW,
|
||||
advapi32.SetNamedSecurityInfoW,
|
||||
ctypes.c_wchar_p(obj_name),
|
||||
ctypes.c_uint(obj_type),
|
||||
ctypes.c_uint(security_info_flags),
|
||||
obj_type,
|
||||
security_info_flags,
|
||||
p_sid_owner,
|
||||
p_sid_group,
|
||||
p_dacl,
|
||||
|
@ -14,58 +14,19 @@
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi.libs import clusapi as clusapi_def
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
if sys.platform == 'win32':
|
||||
clusapi = ctypes.windll.clusapi
|
||||
resutils = ctypes.windll.resutils
|
||||
|
||||
|
||||
DWORD = ctypes.c_ulong
|
||||
|
||||
# TODO(lpetrut): aggregate windows specific constants
|
||||
INVALID_HANDLE_VALUE = -1
|
||||
|
||||
CLUSPROP_SYNTAX_NAME = 262147
|
||||
CLUSPROP_SYNTAX_ENDMARK = 0
|
||||
CLUSPROP_SYNTAX_LIST_VALUE_DWORD = 65538
|
||||
CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER = 65542
|
||||
|
||||
CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR = 2
|
||||
CLUSAPI_GROUP_MOVE_QUEUE_ENABLED = 4
|
||||
CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START = 8
|
||||
|
||||
CLUSTER_OBJECT_TYPE_GROUP = 2
|
||||
|
||||
CLUSTER_CHANGE_GROUP_COMMON_PROPERTY_V2 = 2
|
||||
CLUSTER_CHANGE_GROUP_STATE_V2 = 8
|
||||
|
||||
CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE = 4
|
||||
|
||||
ERROR_MORE_DATA = 234
|
||||
ERROR_INVALID_STATE = 5023
|
||||
ERROR_WAIT_TIMEOUT = 258
|
||||
ERROR_IO_PENDING = 997
|
||||
|
||||
CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES = 0x3000055
|
||||
|
||||
CLUSPROP_GROUP_STATUS_INFO = 'StatusInformation'
|
||||
CLUSPROP_NAME_VM = 'Virtual Machine'
|
||||
CLUSPROP_NAME_VM_CONFIG = 'Virtual Machine Configuration'
|
||||
|
||||
|
||||
class NOTIFY_FILTER_AND_TYPE(ctypes.Structure):
|
||||
_fields_ = [('dwObjectType', DWORD),
|
||||
('FilterFlags', ctypes.c_longlong)]
|
||||
clusapi = w_lib.get_shared_lib_handle(w_lib.CLUSAPI)
|
||||
|
||||
|
||||
class ClusApiUtils(object):
|
||||
_MAX_NODE_NAME = 255
|
||||
|
||||
_open_handle_check_flags = dict(ret_val_is_err_code=False,
|
||||
error_on_nonzero_ret_val=False,
|
||||
error_ret_vals=[0, None])
|
||||
@ -89,8 +50,8 @@ class ClusApiUtils(object):
|
||||
# For convenience, as opposed to the homonymous ClusAPI
|
||||
# structure, we add the actual value as well.
|
||||
class CLUSPROP_VALUE(ctypes.Structure):
|
||||
_fields_ = [('syntax', DWORD),
|
||||
('length', DWORD),
|
||||
_fields_ = [('syntax', wintypes.DWORD),
|
||||
('length', wintypes.DWORD),
|
||||
('value', val_type),
|
||||
('_padding', ctypes.c_ubyte * _get_padding())]
|
||||
return CLUSPROP_VALUE
|
||||
@ -106,11 +67,11 @@ class ClusApiUtils(object):
|
||||
val_type=ctypes.c_wchar * name_len)),
|
||||
('value', self._get_clusprop_value_struct(
|
||||
val_type=ctypes.c_ubyte * val_sz)),
|
||||
('_endmark', DWORD)
|
||||
('_endmark', wintypes.DWORD)
|
||||
]
|
||||
|
||||
entry = CLUSPROP_LIST_ENTRY()
|
||||
entry.name.syntax = CLUSPROP_SYNTAX_NAME
|
||||
entry.name.syntax = w_const.CLUSPROP_SYNTAX_NAME
|
||||
entry.name.length = name_len * ctypes.sizeof(ctypes.c_wchar)
|
||||
entry.name.value = name
|
||||
|
||||
@ -118,7 +79,7 @@ class ClusApiUtils(object):
|
||||
entry.value.length = val_sz
|
||||
entry.value.value[0:val_sz] = bytearray(value)
|
||||
|
||||
entry._endmark = CLUSPROP_SYNTAX_ENDMARK
|
||||
entry._endmark = w_const.CLUSPROP_SYNTAX_ENDMARK
|
||||
|
||||
return entry
|
||||
|
||||
@ -127,7 +88,7 @@ class ClusApiUtils(object):
|
||||
for entry in property_entries])
|
||||
|
||||
class CLUSPROP_LIST(ctypes.Structure):
|
||||
_fields_ = [('count', DWORD),
|
||||
_fields_ = [('count', wintypes.DWORD),
|
||||
('entries_buff', ctypes.c_ubyte * prop_entries_sz)]
|
||||
|
||||
prop_list = CLUSPROP_LIST(count=len(property_entries))
|
||||
@ -194,9 +155,9 @@ class ClusApiUtils(object):
|
||||
clusapi.CancelClusterGroupOperation,
|
||||
group_handle,
|
||||
0, # cancel flags (reserved for future use by MS)
|
||||
ignored_error_codes=[ERROR_IO_PENDING])
|
||||
ignored_error_codes=[w_const.ERROR_IO_PENDING])
|
||||
|
||||
cancel_completed = ret_val != ERROR_IO_PENDING
|
||||
cancel_completed = ret_val != w_const.ERROR_IO_PENDING
|
||||
return cancel_completed
|
||||
|
||||
def move_cluster_group(self, group_handle, destination_node_handle,
|
||||
@ -210,16 +171,17 @@ class ClusApiUtils(object):
|
||||
move_flags,
|
||||
prop_list_p,
|
||||
prop_list_sz,
|
||||
ignored_error_codes=[ERROR_IO_PENDING])
|
||||
ignored_error_codes=[
|
||||
w_const.ERROR_IO_PENDING])
|
||||
|
||||
def get_cluster_group_state(self, group_handle):
|
||||
node_name_len = DWORD(self._MAX_NODE_NAME)
|
||||
node_name_len = wintypes.DWORD(w_const.MAX_PATH)
|
||||
node_name_buff = (ctypes.c_wchar * node_name_len.value)()
|
||||
|
||||
group_state = self._run_and_check_output(
|
||||
clusapi.GetClusterGroupState,
|
||||
group_handle,
|
||||
ctypes.byref(node_name_buff),
|
||||
node_name_buff,
|
||||
ctypes.byref(node_name_len),
|
||||
error_ret_vals=[constants.CLUSTER_GROUP_STATE_UNKNOWN],
|
||||
error_on_nonzero_ret_val=False,
|
||||
@ -251,7 +213,7 @@ class ClusApiUtils(object):
|
||||
while waiting for events.
|
||||
:return: the requested notify port handle,
|
||||
"""
|
||||
notif_port_h = notif_port_h or INVALID_HANDLE_VALUE
|
||||
notif_port_h = notif_port_h or w_const.INVALID_HANDLE_VALUE
|
||||
notif_filters_len = (len(notif_filters)
|
||||
if isinstance(notif_filters, ctypes.Array)
|
||||
else 1)
|
||||
@ -275,14 +237,14 @@ class ClusApiUtils(object):
|
||||
clusapi.CloseClusterNotifyPort(notif_port_h)
|
||||
|
||||
def get_cluster_notify_v2(self, notif_port_h, timeout_ms):
|
||||
filter_and_type = NOTIFY_FILTER_AND_TYPE()
|
||||
obj_name_buff_sz = ctypes.c_ulong(self._MAX_NODE_NAME)
|
||||
notif_key_p = ctypes.c_void_p()
|
||||
buff_sz = ctypes.c_ulong(self._MAX_NODE_NAME)
|
||||
filter_and_type = clusapi_def.NOTIFY_FILTER_AND_TYPE()
|
||||
obj_name_buff_sz = ctypes.c_ulong(w_const.MAX_PATH)
|
||||
notif_key_p = wintypes.PDWORD()
|
||||
buff_sz = ctypes.c_ulong(w_const.MAX_PATH)
|
||||
|
||||
# Event notification buffer. The notification format depends
|
||||
# on the event type and filter flags.
|
||||
buff = (ctypes.c_ubyte * buff_sz.value)()
|
||||
buff = (wintypes.BYTE * buff_sz.value)()
|
||||
obj_name_buff = (ctypes.c_wchar * obj_name_buff_sz.value)()
|
||||
|
||||
def get_args(buff, obj_name_buff):
|
||||
@ -290,13 +252,13 @@ class ClusApiUtils(object):
|
||||
notif_port_h,
|
||||
ctypes.byref(notif_key_p),
|
||||
ctypes.byref(filter_and_type),
|
||||
ctypes.byref(buff),
|
||||
buff,
|
||||
ctypes.byref(buff_sz),
|
||||
None, # object id
|
||||
None, # object id sz
|
||||
None, # parent id
|
||||
None, # parent id sz
|
||||
ctypes.byref(obj_name_buff),
|
||||
obj_name_buff,
|
||||
ctypes.byref(obj_name_buff_sz),
|
||||
None, # object type
|
||||
None, # object type sz
|
||||
@ -304,10 +266,10 @@ class ClusApiUtils(object):
|
||||
try:
|
||||
self._run_and_check_output(*get_args(buff, obj_name_buff))
|
||||
except exceptions.ClusterWin32Exception as ex:
|
||||
if ex.error_code == ERROR_MORE_DATA:
|
||||
if ex.error_code == w_const.ERROR_MORE_DATA:
|
||||
# This function will specify the buffer sizes it needs using
|
||||
# the references we pass.
|
||||
buff = (ctypes.c_ubyte * buff_sz.value)()
|
||||
buff = (wintypes.BYTE * buff_sz.value)()
|
||||
obj_name_buff = (ctypes.c_wchar * obj_name_buff_sz.value)()
|
||||
|
||||
self._run_and_check_output(*get_args(buff, obj_name_buff))
|
||||
@ -317,7 +279,7 @@ class ClusApiUtils(object):
|
||||
# We'll leverage notification key values instead of their addresses,
|
||||
# although this returns us the address we passed in when setting up
|
||||
# the notification port.
|
||||
notif_key = DWORD.from_address(notif_key_p.value).value
|
||||
notif_key = notif_key_p.contents.value
|
||||
event = {'cluster_object_name': obj_name_buff.value,
|
||||
'object_type': filter_and_type.dwObjectType,
|
||||
'filter_flags': filter_and_type.FilterFlags,
|
||||
@ -344,20 +306,22 @@ class ClusApiUtils(object):
|
||||
raise exceptions.ClusterPropertyListEntryNotFound(
|
||||
property_name=property_name)
|
||||
|
||||
prop_name_len_pos = prop_name_pos - ctypes.sizeof(DWORD)
|
||||
prop_name_len_pos = prop_name_pos - ctypes.sizeof(wintypes.DWORD)
|
||||
prop_name_len_addr = prop_list_addr + prop_name_len_pos
|
||||
prop_name_len = self._dword_align(
|
||||
DWORD.from_address(prop_name_len_addr).value)
|
||||
prop_addr = prop_name_len_addr + prop_name_len + ctypes.sizeof(DWORD)
|
||||
if (prop_addr + ctypes.sizeof(DWORD * 3) >
|
||||
wintypes.DWORD.from_address(prop_name_len_addr).value)
|
||||
prop_addr = prop_name_len_addr + prop_name_len + ctypes.sizeof(
|
||||
wintypes.DWORD)
|
||||
if (prop_addr + ctypes.sizeof(wintypes.DWORD * 3) >
|
||||
prop_list_addr + prop_list_sz):
|
||||
raise exceptions.ClusterPropertyListParsingError()
|
||||
|
||||
prop_entry = {
|
||||
'syntax': DWORD.from_address(prop_addr).value,
|
||||
'length': DWORD.from_address(
|
||||
prop_addr + ctypes.sizeof(DWORD)).value,
|
||||
'val_p': ctypes.c_void_p(prop_addr + 2 * ctypes.sizeof(DWORD))
|
||||
'syntax': wintypes.DWORD.from_address(prop_addr).value,
|
||||
'length': wintypes.DWORD.from_address(
|
||||
prop_addr + ctypes.sizeof(wintypes.DWORD)).value,
|
||||
'val_p': ctypes.c_void_p(prop_addr + 2 * ctypes.sizeof(
|
||||
wintypes.DWORD))
|
||||
}
|
||||
|
||||
return prop_entry
|
||||
@ -365,7 +329,7 @@ class ClusApiUtils(object):
|
||||
def cluster_group_control(self, group_handle, control_code,
|
||||
node_handle=None,
|
||||
in_buff_p=None, in_buff_sz=0):
|
||||
out_buff_sz = ctypes.c_ulong(self._MAX_NODE_NAME)
|
||||
out_buff_sz = ctypes.c_ulong(w_const.MAX_PATH)
|
||||
out_buff = (ctypes.c_ubyte * out_buff_sz.value)()
|
||||
|
||||
def get_args(out_buff):
|
||||
@ -375,14 +339,14 @@ class ClusApiUtils(object):
|
||||
control_code,
|
||||
in_buff_p,
|
||||
in_buff_sz,
|
||||
ctypes.byref(out_buff),
|
||||
out_buff,
|
||||
out_buff_sz,
|
||||
ctypes.byref(out_buff_sz))
|
||||
|
||||
try:
|
||||
self._run_and_check_output(*get_args(out_buff))
|
||||
except exceptions.ClusterWin32Exception as ex:
|
||||
if ex.error_code == ERROR_MORE_DATA:
|
||||
if ex.error_code == w_const.ERROR_MORE_DATA:
|
||||
out_buff = (ctypes.c_ubyte * out_buff_sz.value)()
|
||||
self._run_and_check_output(*get_args(out_buff))
|
||||
else:
|
||||
@ -393,11 +357,11 @@ class ClusApiUtils(object):
|
||||
def get_cluster_group_status_info(self, prop_list_p, prop_list_sz):
|
||||
prop_entry = self.get_prop_list_entry_p(
|
||||
prop_list_p, prop_list_sz,
|
||||
CLUSPROP_GROUP_STATUS_INFO)
|
||||
w_const.CLUSREG_NAME_GRP_STATUS_INFORMATION)
|
||||
|
||||
if (prop_entry['length'] != ctypes.sizeof(ctypes.c_ulonglong) or
|
||||
prop_entry['syntax'] !=
|
||||
CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER):
|
||||
w_const.CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER):
|
||||
raise exceptions.ClusterPropertyListParsingError()
|
||||
|
||||
status_info_p = prop_entry['val_p']
|
||||
|
@ -35,6 +35,9 @@ from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils import baseutils
|
||||
from os_win.utils.compute import _clusapi_utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.libs import clusapi as clusapi_def
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -194,21 +197,21 @@ class ClusterUtils(baseutils.BaseUtils):
|
||||
|
||||
def _migrate_vm(self, vm_name, new_host, migration_type,
|
||||
exp_state_after_migr, timeout):
|
||||
syntax = _clusapi_utils.CLUSPROP_SYNTAX_LIST_VALUE_DWORD
|
||||
migr_type = _clusapi_utils.DWORD(migration_type)
|
||||
syntax = w_const.CLUSPROP_SYNTAX_LIST_VALUE_DWORD
|
||||
migr_type = wintypes.DWORD(migration_type)
|
||||
|
||||
prop_entries = [
|
||||
self._clusapi_utils.get_property_list_entry(
|
||||
_clusapi_utils.CLUSPROP_NAME_VM, syntax, migr_type),
|
||||
w_const.CLUS_RESTYPE_NAME_VM, syntax, migr_type),
|
||||
self._clusapi_utils.get_property_list_entry(
|
||||
_clusapi_utils.CLUSPROP_NAME_VM_CONFIG, syntax, migr_type)
|
||||
w_const.CLUS_RESTYPE_NAME_VM_CONFIG, syntax, migr_type)
|
||||
]
|
||||
prop_list = self._clusapi_utils.get_property_list(prop_entries)
|
||||
|
||||
flags = (
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR |
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_QUEUE_ENABLED |
|
||||
_clusapi_utils.CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START)
|
||||
w_const.CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR |
|
||||
w_const.CLUSAPI_GROUP_MOVE_QUEUE_ENABLED |
|
||||
w_const.CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START)
|
||||
|
||||
cluster_handle = None
|
||||
group_handle = None
|
||||
@ -319,7 +322,7 @@ class ClusterUtils(baseutils.BaseUtils):
|
||||
group_state_info['status_info'],
|
||||
expected_state)
|
||||
|
||||
if (ex.error_code == _clusapi_utils.ERROR_INVALID_STATE and
|
||||
if (ex.error_code == w_const.ERROR_INVALID_STATE and
|
||||
not migration_pending):
|
||||
LOG.debug('Ignoring group migration cancel error. '
|
||||
'No migration is pending.')
|
||||
@ -343,7 +346,7 @@ class ClusterUtils(baseutils.BaseUtils):
|
||||
def _is_migration_queued(self, group_status_info):
|
||||
return bool(
|
||||
group_status_info &
|
||||
_clusapi_utils.CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE)
|
||||
w_const.CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE)
|
||||
|
||||
def _is_migration_pending(self, group_state, group_status_info,
|
||||
expected_state):
|
||||
@ -431,7 +434,7 @@ class ClusterUtils(baseutils.BaseUtils):
|
||||
|
||||
buff, buff_sz = self._clusapi_utils.cluster_group_control(
|
||||
group_handle,
|
||||
_clusapi_utils.CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES)
|
||||
w_const.CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES)
|
||||
status_info = self._clusapi_utils.get_cluster_group_status_info(
|
||||
ctypes.byref(buff), buff_sz)
|
||||
|
||||
@ -528,7 +531,7 @@ class _ClusterEventListener(object):
|
||||
def _get_notif_key_dw(self, notif_key):
|
||||
notif_key_dw = self._notif_keys.get(notif_key)
|
||||
if notif_key_dw is None:
|
||||
notif_key_dw = _clusapi_utils.DWORD(notif_key)
|
||||
notif_key_dw = wintypes.DWORD(notif_key)
|
||||
# We have to make sure those addresses are preserved.
|
||||
self._notif_keys[notif_key] = notif_key_dw
|
||||
return notif_key_dw
|
||||
@ -543,7 +546,7 @@ class _ClusterEventListener(object):
|
||||
|
||||
def _setup_notif_port(self):
|
||||
for notif_filter in self._notif_filters_list:
|
||||
filter_struct = _clusapi_utils.NOTIFY_FILTER_AND_TYPE(
|
||||
filter_struct = clusapi_def.NOTIFY_FILTER_AND_TYPE(
|
||||
dwObjectType=notif_filter['object_type'],
|
||||
FilterFlags=notif_filter['filter_flags'])
|
||||
notif_key = notif_filter.get('notif_key', 0)
|
||||
@ -617,12 +620,11 @@ class _ClusterGroupStateChangeListener(_ClusterEventListener):
|
||||
_NOTIF_KEY_GROUP_COMMON_PROP = 1
|
||||
|
||||
_notif_filters_list = [
|
||||
dict(object_type=_clusapi_utils.CLUSTER_OBJECT_TYPE_GROUP,
|
||||
filter_flags=_clusapi_utils.CLUSTER_CHANGE_GROUP_STATE_V2,
|
||||
dict(object_type=w_const.CLUSTER_OBJECT_TYPE_GROUP,
|
||||
filter_flags=w_const.CLUSTER_CHANGE_GROUP_STATE_V2,
|
||||
notif_key=_NOTIF_KEY_GROUP_STATE),
|
||||
dict(object_type=_clusapi_utils.CLUSTER_OBJECT_TYPE_GROUP,
|
||||
filter_flags=_clusapi_utils.
|
||||
CLUSTER_CHANGE_GROUP_COMMON_PROPERTY_V2, # noqa
|
||||
dict(object_type=w_const.CLUSTER_OBJECT_TYPE_GROUP,
|
||||
filter_flags=w_const.CLUSTER_CHANGE_GROUP_COMMON_PROPERTY_V2,
|
||||
notif_key=_NOTIF_KEY_GROUP_COMMON_PROP)]
|
||||
|
||||
def __init__(self, cluster_handle, group_name=None):
|
||||
@ -642,10 +644,9 @@ class _ClusterGroupStateChangeListener(_ClusterEventListener):
|
||||
|
||||
notif_key = event['notif_key']
|
||||
if notif_key == self._NOTIF_KEY_GROUP_STATE:
|
||||
if event['buff_sz'] != ctypes.sizeof(_clusapi_utils.DWORD):
|
||||
if event['buff_sz'] != ctypes.sizeof(wintypes.DWORD):
|
||||
raise exceptions.ClusterPropertyRetrieveFailed()
|
||||
state_p = ctypes.cast(event['buff'],
|
||||
ctypes.POINTER(_clusapi_utils.DWORD))
|
||||
state_p = ctypes.cast(event['buff'], wintypes.PDWORD)
|
||||
state = state_p.contents.value
|
||||
processed_event['state'] = state
|
||||
return processed_event
|
||||
|
@ -13,7 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
import socket
|
||||
|
||||
from oslo_log import log as logging
|
||||
@ -23,6 +22,9 @@ from os_win import _utils
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils import baseutils
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -75,7 +77,7 @@ class HostUtils(baseutils.BaseUtilsVirt):
|
||||
|
||||
def is_cpu_feature_present(self, feature_key):
|
||||
"""Checks if the host's CPUs have the given feature."""
|
||||
return ctypes.windll.kernel32.IsProcessorFeaturePresent(feature_key)
|
||||
return kernel32.IsProcessorFeaturePresent(feature_key)
|
||||
|
||||
def get_memory_info(self):
|
||||
"""Returns a tuple with total visible memory and free physical memory.
|
||||
@ -129,7 +131,7 @@ class HostUtils(baseutils.BaseUtilsVirt):
|
||||
|
||||
def get_host_tick_count64(self):
|
||||
"""Returns host uptime in miliseconds."""
|
||||
return ctypes.windll.kernel32.GetTickCount64()
|
||||
return kernel32.GetTickCount64()
|
||||
|
||||
def host_power_action(self, action):
|
||||
win32_os = self._conn_cimv2.Win32_OperatingSystem()[0]
|
||||
|
@ -26,6 +26,11 @@ from os_win import _utils
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -35,55 +40,6 @@ if sys.version_info > (3, 0):
|
||||
else:
|
||||
Queue = patcher.original('Queue')
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from ctypes import wintypes
|
||||
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
|
||||
class OVERLAPPED(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Internal', wintypes.ULONG),
|
||||
('InternalHigh', wintypes.ULONG),
|
||||
('Offset', wintypes.DWORD),
|
||||
('OffsetHigh', wintypes.DWORD),
|
||||
('hEvent', wintypes.HANDLE)
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self.Offset = 0
|
||||
self.OffsetHigh = 0
|
||||
|
||||
LPOVERLAPPED = ctypes.POINTER(OVERLAPPED)
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE = ctypes.WINFUNCTYPE(
|
||||
None, wintypes.DWORD, wintypes.DWORD, LPOVERLAPPED)
|
||||
|
||||
kernel32.ReadFileEx.argtypes = [
|
||||
wintypes.HANDLE, wintypes.LPVOID, wintypes.DWORD,
|
||||
LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE]
|
||||
kernel32.WriteFileEx.argtypes = [
|
||||
wintypes.HANDLE, wintypes.LPCVOID, wintypes.DWORD,
|
||||
LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE]
|
||||
|
||||
|
||||
FILE_FLAG_OVERLAPPED = 0x40000000
|
||||
FILE_SHARE_READ = 1
|
||||
FILE_SHARE_WRITE = 2
|
||||
GENERIC_READ = 0x80000000
|
||||
GENERIC_WRITE = 0x40000000
|
||||
OPEN_EXISTING = 3
|
||||
|
||||
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
|
||||
|
||||
INVALID_HANDLE_VALUE = -1
|
||||
WAIT_FAILED = 0xFFFFFFFF
|
||||
WAIT_FINISHED = 0
|
||||
ERROR_INVALID_HANDLE = 6
|
||||
ERROR_PIPE_BUSY = 231
|
||||
ERROR_PIPE_NOT_CONNECTED = 233
|
||||
ERROR_NOT_FOUND = 1168
|
||||
|
||||
WAIT_PIPE_DEFAULT_TIMEOUT = 5 # seconds
|
||||
WAIT_IO_COMPLETION_TIMEOUT = 2 * units.k
|
||||
WAIT_INFINITE_TIMEOUT = 0xFFFFFFFF
|
||||
@ -115,7 +71,7 @@ class IOUtils(object):
|
||||
|
||||
def open(self, path, desired_access=None, share_mode=None,
|
||||
creation_disposition=None, flags_and_attributes=None):
|
||||
error_ret_vals = [INVALID_HANDLE_VALUE]
|
||||
error_ret_vals = [w_const.INVALID_HANDLE_VALUE]
|
||||
handle = self._run_and_check_output(kernel32.CreateFileW,
|
||||
ctypes.c_wchar_p(path),
|
||||
desired_access,
|
||||
@ -139,9 +95,9 @@ class IOUtils(object):
|
||||
"""
|
||||
# Ignore errors thrown when there are no requests
|
||||
# to be canceled.
|
||||
ignored_error_codes = [ERROR_NOT_FOUND]
|
||||
ignored_error_codes = [w_const.ERROR_NOT_FOUND]
|
||||
if ignore_invalid_handle:
|
||||
ignored_error_codes.append(ERROR_INVALID_HANDLE)
|
||||
ignored_error_codes.append(w_const.ERROR_INVALID_HANDLE)
|
||||
lp_overlapped = (ctypes.byref(overlapped_structure)
|
||||
if overlapped_structure else None)
|
||||
|
||||
@ -154,7 +110,7 @@ class IOUtils(object):
|
||||
# In order to cancel this, we simply set the event.
|
||||
self._run_and_check_output(kernel32.WaitForSingleObjectEx,
|
||||
event, WAIT_INFINITE_TIMEOUT,
|
||||
True, error_ret_vals=[WAIT_FAILED])
|
||||
True, error_ret_vals=[w_const.WAIT_FAILED])
|
||||
|
||||
def set_event(self, event):
|
||||
self._run_and_check_output(kernel32.SetEvent, event)
|
||||
@ -172,20 +128,21 @@ class IOUtils(object):
|
||||
def get_completion_routine(self, callback=None):
|
||||
def _completion_routine(error_code, num_bytes, lpOverLapped):
|
||||
"""Sets the completion event and executes callback, if passed."""
|
||||
overlapped = ctypes.cast(lpOverLapped, LPOVERLAPPED).contents
|
||||
overlapped = ctypes.cast(lpOverLapped,
|
||||
wintypes.LPOVERLAPPED).contents
|
||||
self.set_event(overlapped.hEvent)
|
||||
|
||||
if callback:
|
||||
callback(num_bytes)
|
||||
|
||||
return LPOVERLAPPED_COMPLETION_ROUTINE(_completion_routine)
|
||||
return wintypes.LPOVERLAPPED_COMPLETION_ROUTINE(_completion_routine)
|
||||
|
||||
def get_new_overlapped_structure(self):
|
||||
"""Structure used for asyncronous IO operations."""
|
||||
# Event used for signaling IO completion
|
||||
hEvent = self._create_event()
|
||||
|
||||
overlapped_structure = OVERLAPPED()
|
||||
overlapped_structure = wintypes.OVERLAPPED()
|
||||
overlapped_structure.hEvent = hEvent
|
||||
return overlapped_structure
|
||||
|
||||
|
@ -23,6 +23,7 @@ from os_win._i18n import _
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.io import ioutils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
threading = patcher.original('threading')
|
||||
time = patcher.original('time')
|
||||
@ -136,10 +137,10 @@ class NamedPipeHandler(object):
|
||||
|
||||
self._pipe_handle = self._ioutils.open(
|
||||
self._pipe_name,
|
||||
desired_access=(ioutils.GENERIC_READ | ioutils.GENERIC_WRITE),
|
||||
share_mode=(ioutils.FILE_SHARE_READ | ioutils.FILE_SHARE_WRITE),
|
||||
creation_disposition=ioutils.OPEN_EXISTING,
|
||||
flags_and_attributes=ioutils.FILE_FLAG_OVERLAPPED)
|
||||
desired_access=(w_const.GENERIC_READ | w_const.GENERIC_WRITE),
|
||||
share_mode=(w_const.FILE_SHARE_READ | w_const.FILE_SHARE_WRITE),
|
||||
creation_disposition=w_const.OPEN_EXISTING,
|
||||
flags_and_attributes=w_const.FILE_FLAG_OVERLAPPED)
|
||||
|
||||
def _close_pipe(self):
|
||||
if self._pipe_handle:
|
||||
|
@ -29,18 +29,17 @@ from os_win import _utils
|
||||
from os_win import exceptions
|
||||
from os_win.utils import _acl_utils
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi.libs import advapi32 as advapi32_def
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from ctypes import wintypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
ERROR_DIR_IS_NOT_EMPTY = 145
|
||||
|
||||
|
||||
class PathUtils(object):
|
||||
_FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
|
||||
|
||||
def __init__(self):
|
||||
self._win32_utils = win32utils.Win32Utils()
|
||||
@ -126,7 +125,7 @@ class PathUtils(object):
|
||||
self.rename(src, os.path.join(dest_dir, fname))
|
||||
|
||||
@_utils.retry_decorator(exceptions=exceptions.OSWinException,
|
||||
error_codes=[ERROR_DIR_IS_NOT_EMPTY])
|
||||
error_codes=[w_const.ERROR_DIR_IS_NOT_EMPTY])
|
||||
def rmtree(self, path):
|
||||
try:
|
||||
shutil.rmtree(path)
|
||||
@ -152,11 +151,12 @@ class PathUtils(object):
|
||||
|
||||
file_attr = self._win32_utils.run_and_check_output(
|
||||
kernel32.GetFileAttributesW,
|
||||
six.text_type(path),
|
||||
path,
|
||||
error_ret_vals=[w_const.INVALID_FILE_ATTRIBUTES],
|
||||
kernel32_lib_func=True)
|
||||
|
||||
return bool(os.path.isdir(path) and (
|
||||
file_attr & self._FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
file_attr & w_const.FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
|
||||
def create_sym_link(self, link, target, target_is_dir=True):
|
||||
"""If target_is_dir is True, a junction will be created.
|
||||
@ -164,15 +164,7 @@ class PathUtils(object):
|
||||
NOTE: Juctions only work on same filesystem.
|
||||
"""
|
||||
|
||||
create_symlink = kernel32.CreateSymbolicLinkW
|
||||
create_symlink.argtypes = (
|
||||
ctypes.c_wchar_p,
|
||||
ctypes.c_wchar_p,
|
||||
ctypes.c_ulong,
|
||||
)
|
||||
create_symlink.restype = ctypes.c_ubyte
|
||||
|
||||
self._win32_utils.run_and_check_output(create_symlink,
|
||||
self._win32_utils.run_and_check_output(kernel32.CreateSymbolicLinkW,
|
||||
link,
|
||||
target,
|
||||
target_is_dir,
|
||||
@ -211,15 +203,15 @@ class PathUtils(object):
|
||||
try:
|
||||
sec_info = self._acl_utils.get_named_security_info(
|
||||
obj_name=path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION)
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION)
|
||||
p_to_free.append(sec_info['pp_sec_desc'].contents)
|
||||
|
||||
access = _acl_utils.EXPLICIT_ACCESS()
|
||||
access = advapi32_def.EXPLICIT_ACCESS()
|
||||
access.grfAccessPermissions = access_rights
|
||||
access.grfAccessMode = access_mode
|
||||
access.grfInheritance = inheritance_flags
|
||||
access.Trustee.TrusteeForm = _acl_utils.TRUSTEE_IS_NAME
|
||||
access.Trustee.TrusteeForm = w_const.TRUSTEE_IS_NAME
|
||||
access.Trustee.pstrName = ctypes.c_wchar_p(trustee_name)
|
||||
|
||||
pp_new_dacl = self._acl_utils.set_entries_in_acl(
|
||||
@ -230,8 +222,8 @@ class PathUtils(object):
|
||||
|
||||
self._acl_utils.set_named_security_info(
|
||||
obj_name=path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
security_info_flags=_acl_utils.DACL_SECURITY_INFORMATION,
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=w_const.DACL_SECURITY_INFORMATION,
|
||||
p_dacl=pp_new_dacl.contents)
|
||||
finally:
|
||||
for p in p_to_free:
|
||||
@ -241,16 +233,16 @@ class PathUtils(object):
|
||||
p_to_free = []
|
||||
|
||||
try:
|
||||
sec_info_flags = _acl_utils.DACL_SECURITY_INFORMATION
|
||||
sec_info_flags = w_const.DACL_SECURITY_INFORMATION
|
||||
sec_info = self._acl_utils.get_named_security_info(
|
||||
obj_name=source_path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=sec_info_flags)
|
||||
p_to_free.append(sec_info['pp_sec_desc'].contents)
|
||||
|
||||
self._acl_utils.set_named_security_info(
|
||||
obj_name=dest_path,
|
||||
obj_type=_acl_utils.SE_FILE_OBJECT,
|
||||
obj_type=w_const.SE_FILE_OBJECT,
|
||||
security_info_flags=sec_info_flags,
|
||||
p_dacl=sec_info['pp_dacl'].contents)
|
||||
finally:
|
||||
|
@ -17,7 +17,6 @@ import collections
|
||||
import ctypes
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
@ -26,9 +25,9 @@ from os_win import _utils
|
||||
from os_win import exceptions
|
||||
from os_win.utils import baseutils
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
|
||||
if sys.platform == 'win32':
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
import contextlib
|
||||
import ctypes
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from oslo_log import log as logging
|
||||
@ -25,13 +24,14 @@ from os_win._i18n import _
|
||||
from os_win import _utils
|
||||
import os_win.conf
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage.initiator import fc_structures as fc_struct
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi.libs import hbaapi as fc_struct
|
||||
|
||||
CONF = os_win.conf.CONF
|
||||
|
||||
if sys.platform == 'win32':
|
||||
hbaapi = ctypes.cdll.LoadLibrary(CONF.os_win.hbaapi_lib_path)
|
||||
hbaapi = w_lib.get_shared_lib_handle(w_lib.HBAAPI)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -50,40 +50,51 @@ class FCUtils(object):
|
||||
def get_fc_hba_count(self):
|
||||
return hbaapi.HBA_GetNumberOfAdapters()
|
||||
|
||||
def _open_adapter(self, adapter_name=None, adapter_wwn=None):
|
||||
if adapter_name:
|
||||
func = hbaapi.HBA_OpenAdapter
|
||||
arg = ctypes.c_char_p(six.b(adapter_name))
|
||||
elif adapter_wwn:
|
||||
func = hbaapi.HBA_OpenAdapterByWWN
|
||||
arg = fc_struct.HBA_WWN(*adapter_wwn)
|
||||
else:
|
||||
err_msg = _("Could not open HBA adapter. "
|
||||
"No HBA name or WWN was specified")
|
||||
raise exceptions.FCException(err_msg)
|
||||
def _open_adapter_by_name(self, adapter_name):
|
||||
handle = self._run_and_check_output(
|
||||
hbaapi.HBA_OpenAdapter,
|
||||
ctypes.c_char_p(six.b(adapter_name)),
|
||||
ret_val_is_err_code=False,
|
||||
error_on_nonzero_ret_val=False,
|
||||
error_ret_vals=[0])
|
||||
return handle
|
||||
|
||||
def _open_adapter_by_wwn(self, adapter_wwn):
|
||||
handle = fc_struct.HBA_HANDLE()
|
||||
hba_wwn = fc_struct.HBA_WWN()
|
||||
hba_wwn.wwn[:] = adapter_wwn
|
||||
|
||||
self._run_and_check_output(
|
||||
hbaapi.HBA_OpenAdapterByWWN,
|
||||
ctypes.byref(handle),
|
||||
hba_wwn)
|
||||
|
||||
handle = self._run_and_check_output(func, arg,
|
||||
ret_val_is_err_code=False,
|
||||
error_on_nonzero_ret_val=False,
|
||||
error_ret_vals=[0])
|
||||
return handle
|
||||
|
||||
def _close_adapter(self, hba_handle):
|
||||
hbaapi.HBA_CloseAdapter(hba_handle)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _get_hba_handle(self, *args, **kwargs):
|
||||
hba_handle = self._open_adapter(*args, **kwargs)
|
||||
def _get_hba_handle(self, adapter_name=None, adapter_wwn=None):
|
||||
if adapter_name:
|
||||
hba_handle = self._open_adapter_by_name(adapter_name)
|
||||
elif adapter_wwn:
|
||||
hba_handle = self._open_adapter_by_wwn(adapter_wwn)
|
||||
else:
|
||||
err_msg = _("Could not open HBA adapter. "
|
||||
"No HBA name or WWN was specified")
|
||||
raise exceptions.FCException(err_msg)
|
||||
|
||||
try:
|
||||
yield hba_handle
|
||||
finally:
|
||||
self._close_adapter(hba_handle)
|
||||
|
||||
def _get_adapter_name(self, adapter_index):
|
||||
buff = (ctypes.c_char * 256)()
|
||||
buff = (ctypes.c_char * w_const.MAX_ISCSI_HBANAME_LEN)()
|
||||
self._run_and_check_output(hbaapi.HBA_GetAdapterName,
|
||||
ctypes.c_uint32(adapter_index),
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
|
||||
return buff.value.decode('utf-8')
|
||||
|
||||
@ -130,8 +141,8 @@ class FCUtils(object):
|
||||
port_attributes = self._get_adapter_port_attributes(
|
||||
hba_handle,
|
||||
port_index)
|
||||
wwnn = self._wwn_array_to_hex_str(port_attributes.NodeWWN)
|
||||
wwpn = self._wwn_array_to_hex_str(port_attributes.PortWWN)
|
||||
wwnn = self._wwn_array_to_hex_str(port_attributes.NodeWWN.wwn)
|
||||
wwpn = self._wwn_array_to_hex_str(port_attributes.PortWWN.wwn)
|
||||
|
||||
hba_port_info = dict(node_name=wwnn,
|
||||
port_name=wwpn)
|
||||
@ -176,8 +187,8 @@ class FCUtils(object):
|
||||
with self._get_hba_handle(adapter_wwn=node_wwn) as hba_handle:
|
||||
fcp_mappings = self._get_target_mapping(hba_handle)
|
||||
for entry in fcp_mappings.Entries:
|
||||
wwnn = self._wwn_array_to_hex_str(entry.FcpId.NodeWWN)
|
||||
wwpn = self._wwn_array_to_hex_str(entry.FcpId.PortWWN)
|
||||
wwnn = self._wwn_array_to_hex_str(entry.FcpId.NodeWWN.wwn)
|
||||
wwpn = self._wwn_array_to_hex_str(entry.FcpId.PortWWN.wwn)
|
||||
mapping = dict(node_name=wwnn,
|
||||
port_name=wwpn,
|
||||
device_name=entry.ScsiId.OSDeviceName,
|
||||
|
@ -18,28 +18,32 @@ import ctypes
|
||||
import functools
|
||||
import inspect
|
||||
import socket
|
||||
import sys
|
||||
import time
|
||||
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from os_win import _utils
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage import diskutils
|
||||
from os_win.utils.storage.initiator import iscsidsc_structures as iscsi_struct
|
||||
from os_win.utils.storage.initiator import iscsierr
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi.errmsg import iscsierr
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi.libs import iscsidsc as iscsi_struct
|
||||
|
||||
if sys.platform == 'win32':
|
||||
iscsidsc = ctypes.windll.iscsidsc
|
||||
iscsidsc = w_lib.get_shared_lib_handle(w_lib.ISCSIDSC)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
ERROR_INSUFFICIENT_BUFFER = 0x7a
|
||||
|
||||
def _get_buff(size, item_type):
|
||||
buff = (ctypes.c_ubyte * size)()
|
||||
return ctypes.cast(buff, ctypes.POINTER(item_type))
|
||||
|
||||
|
||||
def ensure_buff_and_retrieve_items(struct_type=None,
|
||||
def ensure_buff_and_retrieve_items(struct_type,
|
||||
func_requests_buff_sz=True,
|
||||
parse_output=True):
|
||||
# The iscsidsc.dll functions retrieving data accept a buffer, which will
|
||||
@ -47,12 +51,17 @@ def ensure_buff_and_retrieve_items(struct_type=None,
|
||||
# the error code will show it. In this case, the decorator will adjust the
|
||||
# buffer size based on the buffer size or the element count provided by
|
||||
# the function, attempting to call it again.
|
||||
#
|
||||
# We need to provide a buffer large enough to store the retrieved data.
|
||||
# This may be more than the size of the retrieved structures as those
|
||||
# may contain pointers. We're also casting the buffer to the appropriate
|
||||
# type as function parameters are validated.
|
||||
def wrapper(f):
|
||||
@functools.wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
call_args = inspect.getcallargs(f, *args, **kwargs)
|
||||
call_args['element_count'] = ctypes.c_ulong(0)
|
||||
call_args['buff'] = (ctypes.c_ubyte * 0)()
|
||||
call_args['buff'] = _get_buff(0, struct_type)
|
||||
call_args['buff_size'] = ctypes.c_ulong(0)
|
||||
|
||||
while True:
|
||||
@ -66,13 +75,14 @@ def ensure_buff_and_retrieve_items(struct_type=None,
|
||||
else:
|
||||
return ret_val
|
||||
except exceptions.Win32Exception as ex:
|
||||
if (ex.error_code & 0xFFFF) == ERROR_INSUFFICIENT_BUFFER:
|
||||
if (ex.error_code & 0xFFFF ==
|
||||
w_const.ERROR_INSUFFICIENT_BUFFER):
|
||||
if func_requests_buff_sz:
|
||||
buff_size = call_args['buff_size'].value
|
||||
else:
|
||||
buff_size = (ctypes.sizeof(struct_type) *
|
||||
call_args['element_count'].value)
|
||||
call_args['buff'] = (ctypes.c_ubyte * buff_size)()
|
||||
call_args['buff'] = _get_buff(buff_size, struct_type)
|
||||
else:
|
||||
raise
|
||||
return inner
|
||||
@ -93,6 +103,7 @@ retry_decorator = functools.partial(
|
||||
class ISCSIInitiatorUtils(object):
|
||||
_DEFAULT_RESCAN_ATTEMPTS = 3
|
||||
_MS_IQN_PREFIX = "iqn.1991-05.com.microsoft"
|
||||
_DEFAULT_ISCSI_PORT = 3260
|
||||
|
||||
def __init__(self):
|
||||
self._win32utils = win32utils.Win32Utils()
|
||||
@ -110,7 +121,7 @@ class ISCSIInitiatorUtils(object):
|
||||
self._run_and_check_output(
|
||||
iscsidsc.ReportIScsiPersistentLoginsW,
|
||||
ctypes.byref(element_count),
|
||||
ctypes.byref(buff),
|
||||
buff,
|
||||
ctypes.byref(buff_size))
|
||||
|
||||
@ensure_buff_and_retrieve_items(
|
||||
@ -124,15 +135,15 @@ class ISCSIInitiatorUtils(object):
|
||||
iscsidsc.ReportIScsiTargetsW,
|
||||
forced_update,
|
||||
ctypes.byref(element_count),
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
return self._parse_string_list(buff, element_count.value)
|
||||
|
||||
def get_iscsi_initiator(self):
|
||||
"""Returns the initiator node name."""
|
||||
try:
|
||||
buff = (ctypes.c_wchar * (iscsi_struct.MAX_ISCSI_NAME_LEN + 1))()
|
||||
buff = (ctypes.c_wchar * (w_const.MAX_ISCSI_NAME_LEN + 1))()
|
||||
self._run_and_check_output(iscsidsc.GetIScsiInitiatorNodeNameW,
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
return buff.value
|
||||
except exceptions.ISCSIInitiatorAPIException as ex:
|
||||
LOG.info("The ISCSI initiator node name can't be found. "
|
||||
@ -149,7 +160,7 @@ class ISCSIInitiatorUtils(object):
|
||||
self._run_and_check_output(
|
||||
iscsidsc.ReportIScsiInitiatorListW,
|
||||
ctypes.byref(element_count),
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
return self._parse_string_list(buff, element_count.value)
|
||||
|
||||
@staticmethod
|
||||
@ -160,7 +171,7 @@ class ISCSIInitiatorUtils(object):
|
||||
str_list = str_list.split('\x00') if str_list else []
|
||||
return str_list
|
||||
|
||||
@retry_decorator(error_codes=iscsi_struct.ERROR_INSUFFICIENT_BUFFER)
|
||||
@retry_decorator(error_codes=w_const.ERROR_INSUFFICIENT_BUFFER)
|
||||
def _login_iscsi_target(self, target_name, portal=None, login_opts=None,
|
||||
is_persistent=True, initiator_name=None):
|
||||
session_id = iscsi_struct.ISCSI_UNIQUE_SESSION_ID()
|
||||
@ -177,10 +188,9 @@ class ISCSIInitiatorUtils(object):
|
||||
ctypes.c_wchar_p(target_name),
|
||||
False, # IsInformationalSession
|
||||
initiator_name_ref,
|
||||
ctypes.c_ulong(iscsi_struct.ISCSI_ANY_INITIATOR_PORT),
|
||||
ctypes.c_ulong(w_const.ISCSI_ANY_INITIATOR_PORT),
|
||||
portal_ref,
|
||||
iscsi_struct.ISCSI_SECURITY_FLAGS(
|
||||
iscsi_struct.ISCSI_DEFAULT_SECURITY_FLAGS),
|
||||
iscsi_struct.ISCSI_SECURITY_FLAGS(),
|
||||
None, # Security flags / mappings (using default / auto)
|
||||
login_opts_ref,
|
||||
ctypes.c_ulong(0),
|
||||
@ -188,7 +198,7 @@ class ISCSIInitiatorUtils(object):
|
||||
is_persistent,
|
||||
ctypes.byref(session_id),
|
||||
ctypes.byref(connection_id),
|
||||
ignored_error_codes=[iscsierr.ISDSC_TARGET_ALREADY_LOGGED_IN])
|
||||
ignored_error_codes=[w_const.ISDSC_TARGET_ALREADY_LOGGED_IN])
|
||||
return session_id, connection_id
|
||||
|
||||
@ensure_buff_and_retrieve_items(
|
||||
@ -199,7 +209,7 @@ class ISCSIInitiatorUtils(object):
|
||||
iscsidsc.GetIScsiSessionListW,
|
||||
ctypes.byref(buff_size),
|
||||
ctypes.byref(element_count),
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
|
||||
def _get_iscsi_target_sessions(self, target_name, connected_only=True):
|
||||
sessions = self._get_iscsi_sessions()
|
||||
@ -208,8 +218,8 @@ class ISCSIInitiatorUtils(object):
|
||||
and session.TargetNodeName.upper() == target_name.upper()
|
||||
and (session.ConnectionCount > 0 or not connected_only)]
|
||||
|
||||
@retry_decorator(error_codes=(iscsierr.ISDSC_SESSION_BUSY,
|
||||
iscsierr.ISDSC_DEVICE_BUSY_ON_SESSION))
|
||||
@retry_decorator(error_codes=(w_const.ISDSC_SESSION_BUSY,
|
||||
w_const.ISDSC_DEVICE_BUSY_ON_SESSION))
|
||||
@ensure_buff_and_retrieve_items(
|
||||
struct_type=iscsi_struct.ISCSI_DEVICE_ON_SESSION,
|
||||
func_requests_buff_sz=False)
|
||||
@ -220,13 +230,13 @@ class ISCSIInitiatorUtils(object):
|
||||
iscsidsc.GetDevicesForIScsiSessionW,
|
||||
ctypes.byref(session_id),
|
||||
ctypes.byref(element_count),
|
||||
ctypes.byref(buff))
|
||||
buff)
|
||||
|
||||
def _get_iscsi_session_disk_luns(self, session_id):
|
||||
devices = self._get_iscsi_session_devices(session_id)
|
||||
luns = [device.ScsiAddress.Lun for device in devices
|
||||
if (device.StorageDeviceNumber.DeviceType ==
|
||||
iscsi_struct.FILE_DEVICE_DISK)]
|
||||
w_const.FILE_DEVICE_DISK)]
|
||||
return luns
|
||||
|
||||
def _get_iscsi_device_from_session(self, session_id, target_lun):
|
||||
@ -272,7 +282,7 @@ class ISCSIInitiatorUtils(object):
|
||||
def get_target_lun_count(self, target_name):
|
||||
return len(self.get_target_luns(target_name))
|
||||
|
||||
@retry_decorator(error_codes=iscsierr.ISDSC_SESSION_BUSY)
|
||||
@retry_decorator(error_codes=w_const.ISDSC_SESSION_BUSY)
|
||||
def _logout_iscsi_target(self, session_id):
|
||||
self._run_and_check_output(
|
||||
iscsidsc.LogoutIScsiTarget,
|
||||
@ -289,21 +299,37 @@ class ISCSIInitiatorUtils(object):
|
||||
None) # Portal group
|
||||
|
||||
def _remove_static_target(self, target_name):
|
||||
ignored_error_codes = [iscsierr.ISDSC_TARGET_NOT_FOUND]
|
||||
ignored_error_codes = [w_const.ISDSC_TARGET_NOT_FOUND]
|
||||
self._run_and_check_output(iscsidsc.RemoveIScsiStaticTargetW,
|
||||
ctypes.c_wchar_p(target_name),
|
||||
ignored_error_codes=ignored_error_codes)
|
||||
|
||||
def _get_login_opts(self, auth_username, auth_password, auth_type,
|
||||
login_flags=0):
|
||||
def _get_login_opts(self, auth_username=None, auth_password=None,
|
||||
auth_type=None, login_flags=0):
|
||||
if auth_type is None:
|
||||
auth_type = (constants.ISCSI_CHAP_AUTH_TYPE
|
||||
if auth_username and auth_password
|
||||
else constants.ISCSI_NO_AUTH_TYPE)
|
||||
login_opts = iscsi_struct.ISCSI_LOGIN_OPTIONS(Username=auth_username,
|
||||
Password=auth_password,
|
||||
AuthType=auth_type,
|
||||
LoginFlags=login_flags)
|
||||
|
||||
login_opts = iscsi_struct.ISCSI_LOGIN_OPTIONS()
|
||||
|
||||
info_bitmap = 0
|
||||
if auth_username:
|
||||
login_opts.Username = six.b(auth_username)
|
||||
login_opts.UsernameLength = len(auth_username)
|
||||
info_bitmap |= w_const.ISCSI_LOGIN_OPTIONS_USERNAME
|
||||
|
||||
if auth_password:
|
||||
login_opts.Password = six.b(auth_password)
|
||||
login_opts.PasswordLength = len(auth_password)
|
||||
info_bitmap |= w_const.ISCSI_LOGIN_OPTIONS_PASSWORD
|
||||
|
||||
login_opts.AuthType = auth_type
|
||||
info_bitmap |= w_const.ISCSI_LOGIN_OPTIONS_AUTH_TYPE
|
||||
|
||||
login_opts.InformationSpecified = info_bitmap
|
||||
login_opts.LoginFlags = login_flags
|
||||
|
||||
return login_opts
|
||||
|
||||
def _session_on_path_exists(self, target_sessions, portal_addr,
|
||||
@ -354,7 +380,7 @@ class ISCSIInitiatorUtils(object):
|
||||
rescan_attempts=_DEFAULT_RESCAN_ATTEMPTS):
|
||||
portal_addr, portal_port = _utils.parse_server_string(target_portal)
|
||||
portal_port = (int(portal_port)
|
||||
if portal_port else iscsi_struct.DEFAULT_ISCSI_PORT)
|
||||
if portal_port else self._DEFAULT_ISCSI_PORT)
|
||||
|
||||
known_targets = self.get_targets()
|
||||
if target_iqn not in known_targets:
|
||||
@ -370,7 +396,7 @@ class ISCSIInitiatorUtils(object):
|
||||
# If the multipath flag is set, multiple sessions to the same
|
||||
# target may be estabilished. MPIO must be enabled and configured
|
||||
# to claim iSCSI disks, otherwise data corruption can occur.
|
||||
login_flags = (iscsi_struct.ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED
|
||||
login_flags = (w_const.ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED
|
||||
if mpio_enabled else 0)
|
||||
login_opts = self._get_login_opts(auth_username,
|
||||
auth_password,
|
||||
@ -432,8 +458,8 @@ class ISCSIInitiatorUtils(object):
|
||||
raise exceptions.ISCSILunNotAvailable(target_lun=target_lun,
|
||||
target_iqn=target_iqn)
|
||||
|
||||
@retry_decorator(error_codes=(iscsierr.ISDSC_SESSION_BUSY,
|
||||
iscsierr.ISDSC_DEVICE_BUSY_ON_SESSION))
|
||||
@retry_decorator(error_codes=(w_const.ISDSC_SESSION_BUSY,
|
||||
w_const.ISDSC_DEVICE_BUSY_ON_SESSION))
|
||||
def logout_storage_target(self, target_iqn):
|
||||
LOG.debug("Logging out iSCSI target %(target_iqn)s",
|
||||
dict(target_iqn=target_iqn))
|
||||
|
@ -1,189 +0,0 @@
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
#
|
||||
# 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 ctypes
|
||||
import sys
|
||||
|
||||
from os_win.utils.io import ioutils
|
||||
|
||||
if sys.platform == 'win32':
|
||||
iscsidsc = ctypes.windll.iscsidsc
|
||||
|
||||
DEFAULT_ISCSI_PORT = 3260
|
||||
ISCSI_ANY_INITIATOR_PORT = -1
|
||||
ISCSI_ALL_INITIATOR_PORTS = -1
|
||||
ISCSI_DEFAULT_SECURITY_FLAGS = 0
|
||||
MAX_ISCSI_PORTAL_NAME_LEN = 256
|
||||
MAX_ISCSI_PORTAL_ADDRESS_LEN = 256
|
||||
MAX_ISCSI_NAME_LEN = 223
|
||||
MAX_ISCSI_HBANAME_LEN = 256
|
||||
MAX_PATH = 260
|
||||
SENSE_BUFF_SIZE = 18
|
||||
|
||||
PUCHAR = ctypes.POINTER(ctypes.c_ubyte)
|
||||
|
||||
ISCSI_SECURITY_FLAGS = ctypes.c_ulonglong
|
||||
ISCSI_LOGIN_FLAGS = ctypes.c_uint32
|
||||
ISCSI_LOGIN_OPTIONS_INFO_SPECIFIED = ctypes.c_uint32
|
||||
ISCSI_AUTH_TYPES = ctypes.c_int
|
||||
ISCSI_DIGEST_TYPES = ctypes.c_int
|
||||
|
||||
DEVICE_TYPE = ctypes.c_ulong
|
||||
FILE_DEVICE_DISK = 7
|
||||
|
||||
ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED = 2
|
||||
ISCSI_LOGIN_OPTIONS_USERNAME = 0x00000020
|
||||
ISCSI_LOGIN_OPTIONS_PASSWORD = 0x00000040
|
||||
ISCSI_LOGIN_OPTIONS_AUTH_TYPE = 0x00000080
|
||||
|
||||
ERROR_INSUFFICIENT_BUFFER = 122
|
||||
|
||||
|
||||
class GUID(ctypes.Structure):
|
||||
# This is also used in virdisk_structures.py, we should move
|
||||
# common structures to a common module.
|
||||
_fields_ = [("Data1", ctypes.c_ulong),
|
||||
("Data2", ctypes.c_ushort),
|
||||
("Data3", ctypes.c_ushort),
|
||||
("Data4", ctypes.c_byte * 8)]
|
||||
|
||||
|
||||
class ISCSI_TARGET_PORTAL(ctypes.Structure):
|
||||
_fields_ = [('SymbolicName', ctypes.c_wchar * MAX_ISCSI_PORTAL_NAME_LEN),
|
||||
('Address', ctypes.c_wchar * MAX_ISCSI_PORTAL_ADDRESS_LEN),
|
||||
('Socket', ctypes.c_ushort)]
|
||||
|
||||
|
||||
class ISCSI_LOGIN_OPTIONS(ctypes.Structure):
|
||||
_fields_ = [('Version', ctypes.c_ulong),
|
||||
('InformationSpecified', ISCSI_LOGIN_OPTIONS_INFO_SPECIFIED),
|
||||
('LoginFlags', ISCSI_LOGIN_FLAGS),
|
||||
('AuthType', ISCSI_AUTH_TYPES),
|
||||
('HeaderDigest', ISCSI_DIGEST_TYPES),
|
||||
('DataDigest', ISCSI_DIGEST_TYPES),
|
||||
('MaximumConnections', ctypes.c_ulong),
|
||||
('DefaultTime2Wait', ctypes.c_ulong),
|
||||
('DefaultTime2Retain', ctypes.c_ulong),
|
||||
('UsernameLength', ctypes.c_ulong),
|
||||
('PasswordLength', ctypes.c_ulong),
|
||||
('Username', PUCHAR),
|
||||
('Password', PUCHAR)]
|
||||
|
||||
def __init__(self, Username=None, Password=None, AuthType=None,
|
||||
LoginFlags=0):
|
||||
info_bitmap = 0
|
||||
if Username:
|
||||
username_buff = ioutils.IOUtils.get_buffer(len(Username),
|
||||
Username)
|
||||
self.Username = ctypes.cast(username_buff, PUCHAR)
|
||||
self.UsernameLength = len(Username)
|
||||
info_bitmap |= ISCSI_LOGIN_OPTIONS_USERNAME
|
||||
if Password:
|
||||
pwd_buff = ioutils.IOUtils.get_buffer(len(Password),
|
||||
Password)
|
||||
self.Password = ctypes.cast(pwd_buff, PUCHAR)
|
||||
self.PasswordLength = len(Password)
|
||||
info_bitmap |= ISCSI_LOGIN_OPTIONS_PASSWORD
|
||||
if AuthType is not None:
|
||||
self.AuthType = AuthType
|
||||
info_bitmap |= ISCSI_LOGIN_OPTIONS_AUTH_TYPE
|
||||
self.InformationSpecified = info_bitmap
|
||||
self.LoginFlags = LoginFlags
|
||||
|
||||
|
||||
class SCSI_LUN_LIST(ctypes.Structure):
|
||||
_fields_ = [('OSLUN', ctypes.c_ulonglong),
|
||||
('TargetLUN', ctypes.c_ulonglong)]
|
||||
|
||||
|
||||
class ISCSI_UNIQUE_SESSION_ID(ctypes.Structure):
|
||||
_fields_ = [('AdapterUnique', ctypes.c_ulonglong),
|
||||
('AdapterSpecific', ctypes.c_ulonglong)]
|
||||
|
||||
|
||||
class ISCSI_UNIQUE_CONNECTION_ID(ISCSI_UNIQUE_SESSION_ID):
|
||||
pass
|
||||
|
||||
|
||||
class ISCSI_TARGET_MAPPING(ctypes.Structure):
|
||||
_fields_ = [('InitiatorName', ctypes.c_wchar * MAX_ISCSI_HBANAME_LEN),
|
||||
('TargetName', ctypes.c_wchar * (MAX_ISCSI_NAME_LEN + 1)),
|
||||
('OSDeviceName', ctypes.c_wchar * MAX_PATH),
|
||||
('SessionId', ISCSI_UNIQUE_SESSION_ID),
|
||||
('OSBusNumber', ctypes.c_ulong),
|
||||
('OSTargetNumber', ctypes.c_ulong),
|
||||
('LUNCount', ctypes.c_ulong),
|
||||
('LUNList', ctypes.POINTER(SCSI_LUN_LIST))]
|
||||
|
||||
|
||||
PISCSI_TARGET_PORTAL = ctypes.POINTER(ISCSI_TARGET_PORTAL)
|
||||
PISCSI_TARGET_MAPPING = ctypes.POINTER(ISCSI_TARGET_MAPPING)
|
||||
|
||||
|
||||
class PERSISTENT_ISCSI_LOGIN_INFO(ctypes.Structure):
|
||||
_fields_ = [('TargetName', ctypes.c_wchar * (MAX_ISCSI_NAME_LEN + 1)),
|
||||
('IsInformationalSession', ctypes.c_bool),
|
||||
('InitiatorInstance', ctypes.c_wchar * MAX_ISCSI_HBANAME_LEN),
|
||||
('InitiatorPortNumber', ctypes.c_ulong),
|
||||
('TargetPortal', ISCSI_TARGET_PORTAL),
|
||||
('SecurityFlags', ISCSI_SECURITY_FLAGS),
|
||||
('Mappings', PISCSI_TARGET_MAPPING),
|
||||
('LoginOptions', ISCSI_LOGIN_OPTIONS)]
|
||||
|
||||
|
||||
class ISCSI_CONNECTION_INFO(ctypes.Structure):
|
||||
_fields_ = [('ConnectionId', ISCSI_UNIQUE_CONNECTION_ID),
|
||||
('InitiatorAddress', ctypes.c_wchar_p),
|
||||
('TargetAddress', ctypes.c_wchar_p),
|
||||
('InitiatorSocket', ctypes.c_ushort),
|
||||
('TargetSocket', ctypes.c_ushort),
|
||||
('CID', ctypes.c_ubyte * 2)]
|
||||
|
||||
|
||||
class ISCSI_SESSION_INFO(ctypes.Structure):
|
||||
_fields_ = [('SessionId', ISCSI_UNIQUE_SESSION_ID),
|
||||
('InitiatorName', ctypes.c_wchar_p),
|
||||
('TargetName', ctypes.c_wchar_p),
|
||||
('TargetNodeName', ctypes.c_wchar_p),
|
||||
('ISID', ctypes.c_ubyte * 6),
|
||||
('TSID', ctypes.c_ubyte * 2),
|
||||
('ConnectionCount', ctypes.c_ulong),
|
||||
('Connections', ctypes.POINTER(ISCSI_CONNECTION_INFO))]
|
||||
|
||||
|
||||
class SCSI_ADDRESS(ctypes.Structure):
|
||||
_fields_ = [('Length', ctypes.c_ulong),
|
||||
('PortNumber', ctypes.c_ubyte),
|
||||
('PathId', ctypes.c_ubyte),
|
||||
('TargetId', ctypes.c_ubyte),
|
||||
('Lun', ctypes.c_ubyte)]
|
||||
|
||||
|
||||
class STORAGE_DEVICE_NUMBER(ctypes.Structure):
|
||||
_fields_ = [('DeviceType', DEVICE_TYPE),
|
||||
('DeviceNumber', ctypes.c_long),
|
||||
('PartitionNumber', ctypes.c_ulong)]
|
||||
|
||||
|
||||
class ISCSI_DEVICE_ON_SESSION(ctypes.Structure):
|
||||
_fields_ = [('InitiatorName', ctypes.c_wchar * MAX_ISCSI_HBANAME_LEN),
|
||||
('TargetName', ctypes.c_wchar * (MAX_ISCSI_NAME_LEN + 1)),
|
||||
('ScsiAddress', SCSI_ADDRESS),
|
||||
('DeviceInterfaceType', GUID),
|
||||
('DeviceInterfaceName', ctypes.c_wchar * MAX_PATH),
|
||||
('LegacyName', ctypes.c_wchar * MAX_PATH),
|
||||
('StorageDeviceNumber', STORAGE_DEVICE_NUMBER),
|
||||
('DeviceInstance', ctypes.c_ulong)]
|
@ -1,330 +0,0 @@
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
# 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.
|
||||
|
||||
# Error codes and descriptions, as provided by iscsierr.h
|
||||
|
||||
from os_win._i18n import _
|
||||
|
||||
ISDSC_NON_SPECIFIC_ERROR = 0xEFFF0001
|
||||
ISDSC_LOGIN_FAILED = 0xEFFF0002
|
||||
ISDSC_CONNECTION_FAILED = 0xEFFF0003
|
||||
ISDSC_INITIATOR_NODE_ALREADY_EXISTS = 0xEFFF0004
|
||||
ISDSC_INITIATOR_NODE_NOT_FOUND = 0xEFFF0005
|
||||
ISDSC_TARGET_MOVED_TEMPORARILY = 0xEFFF0006
|
||||
ISDSC_TARGET_MOVED_PERMANENTLY = 0xEFFF0007
|
||||
ISDSC_INITIATOR_ERROR = 0xEFFF0008
|
||||
ISDSC_AUTHENTICATION_FAILURE = 0xEFFF0009
|
||||
ISDSC_AUTHORIZATION_FAILURE = 0xEFFF000A
|
||||
ISDSC_NOT_FOUND = 0xEFFF000B
|
||||
ISDSC_TARGET_REMOVED = 0xEFFF000C
|
||||
ISDSC_UNSUPPORTED_VERSION = 0xEFFF000D
|
||||
ISDSC_TOO_MANY_CONNECTIONS = 0xEFFF000E
|
||||
ISDSC_MISSING_PARAMETER = 0xEFFF000F
|
||||
ISDSC_CANT_INCLUDE_IN_SESSION = 0xEFFF0010
|
||||
ISDSC_SESSION_TYPE_NOT_SUPPORTED = 0xEFFF0011
|
||||
ISDSC_TARGET_ERROR = 0xEFFF0012
|
||||
ISDSC_SERVICE_UNAVAILABLE = 0xEFFF0013
|
||||
ISDSC_OUT_OF_RESOURCES = 0xEFFF0014
|
||||
ISDSC_CONNECTION_ALREADY_EXISTS = 0xEFFF0015
|
||||
ISDSC_SESSION_ALREADY_EXISTS = 0xEFFF0016
|
||||
ISDSC_INITIATOR_INSTANCE_NOT_FOUND = 0xEFFF0017
|
||||
ISDSC_TARGET_ALREADY_EXISTS = 0xEFFF0018
|
||||
ISDSC_DRIVER_BUG = 0xEFFF0019
|
||||
ISDSC_INVALID_TEXT_KEY = 0xEFFF001A
|
||||
ISDSC_INVALID_SENDTARGETS_TEXT = 0xEFFF001B
|
||||
ISDSC_INVALID_SESSION_ID = 0xEFFF001C
|
||||
ISDSC_SCSI_REQUEST_FAILED = 0xEFFF001D
|
||||
ISDSC_TOO_MANY_SESSIONS = 0xEFFF001E
|
||||
ISDSC_SESSION_BUSY = 0xEFFF001F
|
||||
ISDSC_TARGET_MAPPING_UNAVAILABLE = 0xEFFF0020
|
||||
ISDSC_ADDRESS_TYPE_NOT_SUPPORTED = 0xEFFF0021
|
||||
ISDSC_LOGON_FAILED = 0xEFFF0022
|
||||
ISDSC_SEND_FAILED = 0xEFFF0023
|
||||
ISDSC_TRANSPORT_ERROR = 0xEFFF0024
|
||||
ISDSC_VERSION_MISMATCH = 0xEFFF0025
|
||||
ISDSC_TARGET_MAPPING_OUT_OF_RANGE = 0xEFFF0026
|
||||
ISDSC_TARGET_PRESHAREDKEY_UNAVAILABLE = 0xEFFF0027
|
||||
ISDSC_TARGET_AUTHINFO_UNAVAILABLE = 0xEFFF0028
|
||||
ISDSC_TARGET_NOT_FOUND = 0xEFFF0029
|
||||
ISDSC_LOGIN_USER_INFO_BAD = 0xEFFF002A
|
||||
ISDSC_TARGET_MAPPING_EXISTS = 0xEFFF002B
|
||||
ISDSC_HBA_SECURITY_CACHE_FULL = 0xEFFF002C
|
||||
ISDSC_INVALID_PORT_NUMBER = 0xEFFF002D
|
||||
ISDSC_OPERATION_NOT_ALL_SUCCESS = 0xAFFF002E
|
||||
ISDSC_HBA_SECURITY_CACHE_NOT_SUPPORTED = 0xEFFF002F
|
||||
ISDSC_IKE_ID_PAYLOAD_TYPE_NOT_SUPPORTED = 0xEFFF0030
|
||||
ISDSC_IKE_ID_PAYLOAD_INCORRECT_SIZE = 0xEFFF0031
|
||||
ISDSC_TARGET_PORTAL_ALREADY_EXISTS = 0xEFFF0032
|
||||
ISDSC_TARGET_ADDRESS_ALREADY_EXISTS = 0xEFFF0033
|
||||
ISDSC_NO_AUTH_INFO_AVAILABLE = 0xEFFF0034
|
||||
ISDSC_NO_TUNNEL_OUTER_MODE_ADDRESS = 0xEFFF0035
|
||||
ISDSC_CACHE_CORRUPTED = 0xEFFF0036
|
||||
ISDSC_REQUEST_NOT_SUPPORTED = 0xEFFF0037
|
||||
ISDSC_TARGET_OUT_OF_RESORCES = 0xEFFF0038
|
||||
ISDSC_SERVICE_DID_NOT_RESPOND = 0xEFFF0039
|
||||
ISDSC_ISNS_SERVER_NOT_FOUND = 0xEFFF003A
|
||||
ISDSC_OPERATION_REQUIRES_REBOOT = 0xAFFF003B
|
||||
ISDSC_NO_PORTAL_SPECIFIED = 0xEFFF003C
|
||||
ISDSC_CANT_REMOVE_LAST_CONNECTION = 0xEFFF003D
|
||||
ISDSC_SERVICE_NOT_RUNNING = 0xEFFF003E
|
||||
ISDSC_TARGET_ALREADY_LOGGED_IN = 0xEFFF003F
|
||||
ISDSC_DEVICE_BUSY_ON_SESSION = 0xEFFF0040
|
||||
ISDSC_COULD_NOT_SAVE_PERSISTENT_LOGIN_DATA = 0xEFFF0041
|
||||
ISDSC_COULD_NOT_REMOVE_PERSISTENT_LOGIN_DATA = 0xEFFF0042
|
||||
ISDSC_PORTAL_NOT_FOUND = 0xEFFF0043
|
||||
ISDSC_INITIATOR_NOT_FOUND = 0xEFFF0044
|
||||
ISDSC_DISCOVERY_MECHANISM_NOT_FOUND = 0xEFFF0045
|
||||
ISDSC_IPSEC_NOT_SUPPORTED_ON_OS = 0xEFFF0046
|
||||
ISDSC_PERSISTENT_LOGIN_TIMEOUT = 0xEFFF0047
|
||||
ISDSC_SHORT_CHAP_SECRET = 0xAFFF0048
|
||||
ISDSC_EVALUATION_PEROID_EXPIRED = 0xEFFF0049
|
||||
ISDSC_INVALID_CHAP_SECRET = 0xEFFF004A
|
||||
ISDSC_INVALID_TARGET_CHAP_SECRET = 0xEFFF004B
|
||||
ISDSC_INVALID_INITIATOR_CHAP_SECRET = 0xEFFF004C
|
||||
ISDSC_INVALID_CHAP_USER_NAME = 0xEFFF004D
|
||||
ISDSC_INVALID_LOGON_AUTH_TYPE = 0xEFFF004E
|
||||
ISDSC_INVALID_TARGET_MAPPING = 0xEFFF004F
|
||||
ISDSC_INVALID_TARGET_ID = 0xEFFF0050
|
||||
ISDSC_INVALID_ISCSI_NAME = 0xEFFF0051
|
||||
ISDSC_INCOMPATIBLE_ISNS_VERSION = 0xEFFF0052
|
||||
ISDSC_FAILED_TO_CONFIGURE_IPSEC = 0xEFFF0053
|
||||
ISDSC_BUFFER_TOO_SMALL = 0xEFFF0054
|
||||
ISDSC_INVALID_LOAD_BALANCE_POLICY = 0xEFFF0055
|
||||
ISDSC_INVALID_PARAMETER = 0xEFFF0056
|
||||
ISDSC_DUPLICATE_PATH_SPECIFIED = 0xEFFF0057
|
||||
ISDSC_PATH_COUNT_MISMATCH = 0xEFFF0058
|
||||
ISDSC_INVALID_PATH_ID = 0xEFFF0059
|
||||
ISDSC_MULTIPLE_PRIMARY_PATHS_SPECIFIED = 0xEFFF005A
|
||||
ISDSC_NO_PRIMARY_PATH_SPECIFIED = 0xEFFF005B
|
||||
ISDSC_DEVICE_ALREADY_PERSISTENTLY_BOUND = 0xEFFF005C
|
||||
ISDSC_DEVICE_NOT_FOUND = 0xEFFF005D
|
||||
ISDSC_DEVICE_NOT_ISCSI_OR_PERSISTENT = 0xEFFF005E
|
||||
ISDSC_DNS_NAME_UNRESOLVED = 0xEFFF005F
|
||||
ISDSC_NO_CONNECTION_AVAILABLE = 0xEFFF0060
|
||||
ISDSC_LB_POLICY_NOT_SUPPORTED = 0xEFFF0061
|
||||
ISDSC_REMOVE_CONNECTION_IN_PROGRESS = 0xEFFF0062
|
||||
ISDSC_INVALID_CONNECTION_ID = 0xEFFF0063
|
||||
ISDSC_CANNOT_REMOVE_LEADING_CONNECTION = 0xEFFF0064
|
||||
ISDSC_RESTRICTED_BY_GROUP_POLICY = 0xEFFF0065
|
||||
ISDSC_ISNS_FIREWALL_BLOCKED = 0xEFFF0066
|
||||
ISDSC_FAILURE_TO_PERSIST_LB_POLICY = 0xEFFF0067
|
||||
ISDSC_INVALID_HOST = 0xEFFF0068
|
||||
|
||||
err_msg_dict = {
|
||||
ISDSC_NON_SPECIFIC_ERROR: _('A non specific error occurred.'),
|
||||
ISDSC_LOGIN_FAILED: _('Login Failed.'),
|
||||
ISDSC_CONNECTION_FAILED: _('Connection Failed.'),
|
||||
ISDSC_INITIATOR_NODE_ALREADY_EXISTS: _('Initiator Node Already Exists.'),
|
||||
ISDSC_INITIATOR_NODE_NOT_FOUND: _('Initiator Node Does Not Exist.'),
|
||||
ISDSC_TARGET_MOVED_TEMPORARILY: _('Target Moved Temporarily.'),
|
||||
ISDSC_TARGET_MOVED_PERMANENTLY: _('Target Moved Permanently.'),
|
||||
ISDSC_INITIATOR_ERROR: _('Initiator Error.'),
|
||||
ISDSC_AUTHENTICATION_FAILURE: _('Authentication Failure.'),
|
||||
ISDSC_AUTHORIZATION_FAILURE: _('Authorization Failure.'),
|
||||
ISDSC_NOT_FOUND: _('Not Found.'),
|
||||
ISDSC_TARGET_REMOVED: _('Target Removed.'),
|
||||
ISDSC_UNSUPPORTED_VERSION: _('Unsupported Version.'),
|
||||
ISDSC_TOO_MANY_CONNECTIONS: _('Too many Connections.'),
|
||||
ISDSC_MISSING_PARAMETER: _('Missing Parameter.'),
|
||||
ISDSC_CANT_INCLUDE_IN_SESSION: _('Can not include in session.'),
|
||||
ISDSC_SESSION_TYPE_NOT_SUPPORTED: _('Session type not supported.'),
|
||||
ISDSC_TARGET_ERROR: _('Target Error.'),
|
||||
ISDSC_SERVICE_UNAVAILABLE: _('Service Unavailable.'),
|
||||
ISDSC_OUT_OF_RESOURCES: _('Out of Resources.'),
|
||||
ISDSC_CONNECTION_ALREADY_EXISTS: _('Connections already exist '
|
||||
'on initiator node.'),
|
||||
ISDSC_SESSION_ALREADY_EXISTS: _('Session Already Exists.'),
|
||||
ISDSC_INITIATOR_INSTANCE_NOT_FOUND: _('Initiator Instance '
|
||||
'Does Not Exist.'),
|
||||
ISDSC_TARGET_ALREADY_EXISTS: _('Target Already Exists.'),
|
||||
ISDSC_DRIVER_BUG: _('The iscsi driver implementation did '
|
||||
'not complete an operation correctly.'),
|
||||
ISDSC_INVALID_TEXT_KEY: _('An invalid key text was encountered.'),
|
||||
ISDSC_INVALID_SENDTARGETS_TEXT: _('Invalid SendTargets response '
|
||||
'text was encountered.'),
|
||||
ISDSC_INVALID_SESSION_ID: _('Invalid Session Id.'),
|
||||
ISDSC_SCSI_REQUEST_FAILED: _('The scsi request failed.'),
|
||||
ISDSC_TOO_MANY_SESSIONS: _('Exceeded max sessions for this initiator.'),
|
||||
ISDSC_SESSION_BUSY: _('Session is busy since a request '
|
||||
'is already in progress.'),
|
||||
ISDSC_TARGET_MAPPING_UNAVAILABLE: _('The target mapping requested '
|
||||
'is not available.'),
|
||||
ISDSC_ADDRESS_TYPE_NOT_SUPPORTED: _('The Target Address type given '
|
||||
'is not supported.'),
|
||||
ISDSC_LOGON_FAILED: _('Logon Failed.'),
|
||||
ISDSC_SEND_FAILED: _('TCP Send Failed.'),
|
||||
ISDSC_TRANSPORT_ERROR: _('TCP Transport Error'),
|
||||
ISDSC_VERSION_MISMATCH: _('iSCSI Version Mismatch'),
|
||||
ISDSC_TARGET_MAPPING_OUT_OF_RANGE: _('The Target Mapping Address passed '
|
||||
'is out of range for the '
|
||||
'adapter configuration.'),
|
||||
ISDSC_TARGET_PRESHAREDKEY_UNAVAILABLE: _('The preshared key for the '
|
||||
'target or IKE identification '
|
||||
'payload is not available.'),
|
||||
ISDSC_TARGET_AUTHINFO_UNAVAILABLE: _('The authentication information for '
|
||||
'the target is not available.'),
|
||||
ISDSC_TARGET_NOT_FOUND: _('The target name is not found or is '
|
||||
'marked as hidden from login.'),
|
||||
ISDSC_LOGIN_USER_INFO_BAD: _('One or more parameters specified in '
|
||||
'LoginTargetIN structure is invalid.'),
|
||||
ISDSC_TARGET_MAPPING_EXISTS: _('Given target mapping already exists.'),
|
||||
ISDSC_HBA_SECURITY_CACHE_FULL: _('The HBA security information cache '
|
||||
'is full.'),
|
||||
ISDSC_INVALID_PORT_NUMBER: _('The port number passed is '
|
||||
'not valid for the initiator.'),
|
||||
ISDSC_OPERATION_NOT_ALL_SUCCESS: _('The operation was not successful '
|
||||
'for all initiators or discovery '
|
||||
'methods.'),
|
||||
ISDSC_HBA_SECURITY_CACHE_NOT_SUPPORTED: _('The HBA security information '
|
||||
'cache is not supported by '
|
||||
'this adapter.'),
|
||||
ISDSC_IKE_ID_PAYLOAD_TYPE_NOT_SUPPORTED: _('The IKE id payload type '
|
||||
'specified is not supported.'),
|
||||
ISDSC_IKE_ID_PAYLOAD_INCORRECT_SIZE: _('The IKE id payload size '
|
||||
'specified is not correct.'),
|
||||
ISDSC_TARGET_PORTAL_ALREADY_EXISTS: _('Target Portal Structure '
|
||||
'Already Exists.'),
|
||||
ISDSC_TARGET_ADDRESS_ALREADY_EXISTS: _('Target Address Structure '
|
||||
'Already Exists.'),
|
||||
ISDSC_NO_AUTH_INFO_AVAILABLE: _('There is no IKE authentication '
|
||||
'information available.'),
|
||||
ISDSC_NO_TUNNEL_OUTER_MODE_ADDRESS: _('There is no tunnel mode outer '
|
||||
'address specified.'),
|
||||
ISDSC_CACHE_CORRUPTED: _('Authentication or tunnel '
|
||||
'address cache is corrupted.'),
|
||||
ISDSC_REQUEST_NOT_SUPPORTED: _('The request or operation '
|
||||
'is not supported.'),
|
||||
ISDSC_TARGET_OUT_OF_RESORCES: _('The target does not have enough '
|
||||
'resources to process the '
|
||||
'given request.'),
|
||||
ISDSC_SERVICE_DID_NOT_RESPOND: _('The initiator service did '
|
||||
'not respond to the request '
|
||||
'sent by the driver.'),
|
||||
ISDSC_ISNS_SERVER_NOT_FOUND: _('The Internet Storage Name Server (iSNS) '
|
||||
'server was not found or is unavailable.'),
|
||||
ISDSC_OPERATION_REQUIRES_REBOOT: _('The operation was successful but '
|
||||
'requires a driver reload or reboot '
|
||||
'to become effective.'),
|
||||
ISDSC_NO_PORTAL_SPECIFIED: _('There is no target portal available '
|
||||
'to complete the login.'),
|
||||
ISDSC_CANT_REMOVE_LAST_CONNECTION: _('Cannot remove the last '
|
||||
'connection for a session.'),
|
||||
ISDSC_SERVICE_NOT_RUNNING: _('The Microsoft iSCSI initiator '
|
||||
'service has not been started.'),
|
||||
ISDSC_TARGET_ALREADY_LOGGED_IN: _('The target has already been '
|
||||
'logged in via an iSCSI session.'),
|
||||
ISDSC_DEVICE_BUSY_ON_SESSION: _('The session cannot be logged out '
|
||||
'since a device on that session is '
|
||||
'currently being used.'),
|
||||
ISDSC_COULD_NOT_SAVE_PERSISTENT_LOGIN_DATA: _('Failed to save persistent '
|
||||
'login information.'),
|
||||
ISDSC_COULD_NOT_REMOVE_PERSISTENT_LOGIN_DATA: _('Failed to remove '
|
||||
'persistent login '
|
||||
'information.'),
|
||||
ISDSC_PORTAL_NOT_FOUND: _('The specified portal was not found.'),
|
||||
ISDSC_INITIATOR_NOT_FOUND: _('The specified initiator '
|
||||
'name was not found.'),
|
||||
ISDSC_DISCOVERY_MECHANISM_NOT_FOUND: _('The specified discovery '
|
||||
'mechanism was not found.'),
|
||||
ISDSC_IPSEC_NOT_SUPPORTED_ON_OS: _('iSCSI does not support IPSEC '
|
||||
'for this version of the OS.'),
|
||||
ISDSC_PERSISTENT_LOGIN_TIMEOUT: _('The iSCSI service timed out waiting '
|
||||
'for all persistent logins to '
|
||||
'complete.'),
|
||||
ISDSC_SHORT_CHAP_SECRET: _('The specified CHAP secret is less than '
|
||||
'96 bits and will not be usable for '
|
||||
'authenticating over non ipsec connections.'),
|
||||
ISDSC_EVALUATION_PEROID_EXPIRED: _('The evaluation period for the '
|
||||
'iSCSI initiator service has '
|
||||
'expired.'),
|
||||
ISDSC_INVALID_CHAP_SECRET: _('CHAP secret given does not conform '
|
||||
'to the standard. Please see system '
|
||||
'event log for more information.'),
|
||||
ISDSC_INVALID_TARGET_CHAP_SECRET:
|
||||
_('Target CHAP secret given is invalid. Maximum size of CHAP secret'
|
||||
'is 16 bytes. Minimum size is 12 bytes if IPSec is not used.'),
|
||||
ISDSC_INVALID_INITIATOR_CHAP_SECRET: _('Initiator CHAP secret given is '
|
||||
'invalid. Maximum size of CHAP '
|
||||
'secret is 16 bytes. Minimum size '
|
||||
'is 12 bytes if IPSec is '
|
||||
'not used.'),
|
||||
ISDSC_INVALID_CHAP_USER_NAME: _('CHAP Username given is invalid.'),
|
||||
ISDSC_INVALID_LOGON_AUTH_TYPE: _('Logon Authentication type '
|
||||
'given is invalid.'),
|
||||
ISDSC_INVALID_TARGET_MAPPING: _('Target Mapping information '
|
||||
'given is invalid.'),
|
||||
ISDSC_INVALID_TARGET_ID: _('Target Id given in '
|
||||
'Target Mapping is invalid.'),
|
||||
ISDSC_INVALID_ISCSI_NAME: _('The iSCSI name specified contains '
|
||||
'invalid characters or is too long.'),
|
||||
ISDSC_INCOMPATIBLE_ISNS_VERSION: _('The version number returned from the '
|
||||
'Internet Storage Name Server (iSNS) '
|
||||
'server is not compatible with this '
|
||||
'version of the iSNS client.'),
|
||||
ISDSC_FAILED_TO_CONFIGURE_IPSEC: _('Initiator failed to configure IPSec '
|
||||
'for the given connection. This could '
|
||||
'be because of low resources.'),
|
||||
ISDSC_BUFFER_TOO_SMALL: _('The buffer given for processing '
|
||||
'the request is too small.'),
|
||||
ISDSC_INVALID_LOAD_BALANCE_POLICY: _('The given Load Balance '
|
||||
'policy is not recognized '
|
||||
'by iScsi initiator.'),
|
||||
ISDSC_INVALID_PARAMETER: _('One or more paramaters '
|
||||
'specified is not valid.'),
|
||||
ISDSC_DUPLICATE_PATH_SPECIFIED: _('Duplicate PathIds were '
|
||||
'specified in the call to '
|
||||
'set Load Balance Policy.'),
|
||||
ISDSC_PATH_COUNT_MISMATCH: _('Number of paths specified in '
|
||||
'Set Load Balance Policy does not '
|
||||
'match the number of paths to the target.'),
|
||||
ISDSC_INVALID_PATH_ID: _('Path Id specified in the call to '
|
||||
'set Load Balance Policy is not valid'),
|
||||
ISDSC_MULTIPLE_PRIMARY_PATHS_SPECIFIED: _('Multiple primary paths '
|
||||
'specified when only one '
|
||||
'primary path is expected.'),
|
||||
ISDSC_NO_PRIMARY_PATH_SPECIFIED: _('No primary path specified when '
|
||||
'at least one is expected.'),
|
||||
ISDSC_DEVICE_ALREADY_PERSISTENTLY_BOUND: _('Device is already a '
|
||||
'persistently bound device.'),
|
||||
ISDSC_DEVICE_NOT_FOUND: _('Device was not found.'),
|
||||
ISDSC_DEVICE_NOT_ISCSI_OR_PERSISTENT: _('The device specified does not '
|
||||
'originate from an iSCSI disk '
|
||||
'or a persistent iSCSI login.'),
|
||||
ISDSC_DNS_NAME_UNRESOLVED: _('The DNS name specified was not resolved.'),
|
||||
ISDSC_NO_CONNECTION_AVAILABLE: _('There is no connection available '
|
||||
'in the iSCSI session to '
|
||||
'process the request.'),
|
||||
ISDSC_LB_POLICY_NOT_SUPPORTED: _('The given Load Balance '
|
||||
'policy is not supported.'),
|
||||
ISDSC_REMOVE_CONNECTION_IN_PROGRESS: _('A remove connection request '
|
||||
'is already in progress for '
|
||||
'this session.'),
|
||||
ISDSC_INVALID_CONNECTION_ID: _('Given connection was not '
|
||||
'found in the session.'),
|
||||
ISDSC_CANNOT_REMOVE_LEADING_CONNECTION: _('The leading connection in '
|
||||
'the session cannot be '
|
||||
'removed.'),
|
||||
ISDSC_RESTRICTED_BY_GROUP_POLICY: _('The operation cannot be performed '
|
||||
'since it does not conform with '
|
||||
'the group policy assigned to '
|
||||
'this computer.'),
|
||||
ISDSC_ISNS_FIREWALL_BLOCKED: _('The operation cannot be performed since '
|
||||
'the Internet Storage Name Server '
|
||||
'(iSNS) firewall exception has '
|
||||
'not been enabled.'),
|
||||
ISDSC_FAILURE_TO_PERSIST_LB_POLICY: _('Failed to persist load '
|
||||
'balancing policy parameters.'),
|
||||
ISDSC_INVALID_HOST: _('The name could not be resolved to an IP Address.'),
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
import ctypes
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
@ -25,9 +24,9 @@ from os_win import _utils
|
||||
from os_win import exceptions
|
||||
from os_win.utils import baseutils
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
|
||||
if sys.platform == 'win32':
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
@ -26,39 +26,67 @@ http://www.microsoft.com/en-us/download/details.aspx?id=34750
|
||||
import ctypes
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import units
|
||||
|
||||
from os_win._i18n import _
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
from os_win.utils.storage.virtdisk import (
|
||||
virtdisk_constants as vdisk_const)
|
||||
from os_win.utils import win32utils
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
from os_win.utils.winapi.libs import virtdisk as vdisk_struct
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
if sys.platform == 'win32':
|
||||
from ctypes import wintypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
virtdisk = ctypes.windll.virtdisk
|
||||
|
||||
from os_win.utils.storage.virtdisk import (
|
||||
virtdisk_structures as vdisk_struct) # noqa
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
virtdisk = w_lib.get_shared_lib_handle(w_lib.VIRTDISK)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
VHD_SIGNATURE = b'conectix'
|
||||
VHDX_SIGNATURE = b'vhdxfile'
|
||||
|
||||
DEVICE_ID_MAP = {
|
||||
constants.DISK_FORMAT_VHD: w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
constants.DISK_FORMAT_VHDX: w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX,
|
||||
}
|
||||
|
||||
VHD_HEADER_SIZE_FIX = 512
|
||||
VHD_BAT_ENTRY_SIZE = 4
|
||||
VHD_DYNAMIC_DISK_HEADER_SIZE = 1024
|
||||
VHD_HEADER_SIZE_DYNAMIC = 512
|
||||
VHD_FOOTER_SIZE_DYNAMIC = 512
|
||||
|
||||
VHDX_BAT_ENTRY_SIZE = 8
|
||||
VHDX_HEADER_OFFSETS = [64 * units.Ki, 128 * units.Ki]
|
||||
VHDX_HEADER_SECTION_SIZE = units.Mi
|
||||
VHDX_LOG_LENGTH_OFFSET = 68
|
||||
VHDX_METADATA_SIZE_OFFSET = 64
|
||||
VHDX_REGION_TABLE_OFFSET = 192 * units.Ki
|
||||
VHDX_BS_METADATA_ENTRY_OFFSET = 48
|
||||
|
||||
VIRTUAL_DISK_DEFAULT_SECTOR_SIZE = 0x200
|
||||
VIRTUAL_DISK_DEFAULT_PHYS_SECTOR_SIZE = 0x200
|
||||
|
||||
CREATE_VIRTUAL_DISK_FLAGS = {
|
||||
constants.VHD_TYPE_FIXED:
|
||||
w_const.CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION,
|
||||
}
|
||||
|
||||
|
||||
class VHDUtils(object):
|
||||
def __init__(self):
|
||||
self._win32_utils = win32utils.Win32Utils()
|
||||
|
||||
self._vhd_info_members = {
|
||||
vdisk_const.GET_VIRTUAL_DISK_INFO_SIZE: 'Size',
|
||||
vdisk_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION:
|
||||
w_const.GET_VIRTUAL_DISK_INFO_SIZE: 'Size',
|
||||
w_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION:
|
||||
'ParentLocation',
|
||||
vdisk_const.GET_VIRTUAL_DISK_INFO_VIRTUAL_STORAGE_TYPE:
|
||||
w_const.GET_VIRTUAL_DISK_INFO_VIRTUAL_STORAGE_TYPE:
|
||||
'VirtualStorageType',
|
||||
vdisk_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE:
|
||||
w_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE:
|
||||
'ProviderSubtype'}
|
||||
|
||||
# Describes the way error handling is performed
|
||||
@ -76,15 +104,17 @@ class VHDUtils(object):
|
||||
return self._win32_utils.run_and_check_output(*args, **kwargs)
|
||||
finally:
|
||||
if cleanup_handle:
|
||||
self._close(cleanup_handle)
|
||||
self._win32_utils.close_handle(cleanup_handle)
|
||||
|
||||
def _open(self, vhd_path,
|
||||
open_flag=None,
|
||||
open_access_mask=vdisk_const.VIRTUAL_DISK_ACCESS_ALL,
|
||||
open_flag=0,
|
||||
open_access_mask=w_const.VIRTUAL_DISK_ACCESS_ALL,
|
||||
open_params=None):
|
||||
device_id = self._get_vhd_device_id(vhd_path)
|
||||
|
||||
vst = vdisk_struct.Win32_VIRTUAL_STORAGE_TYPE(DeviceId=device_id)
|
||||
vst = vdisk_struct.VIRTUAL_STORAGE_TYPE(
|
||||
DeviceId=device_id,
|
||||
VendorId=w_const.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT)
|
||||
handle = wintypes.HANDLE()
|
||||
|
||||
self._run_and_check_output(virtdisk.OpenVirtualDisk,
|
||||
@ -103,24 +133,33 @@ class VHDUtils(object):
|
||||
max_internal_size=0, parent_path=None):
|
||||
new_device_id = self._get_vhd_device_id(new_vhd_path)
|
||||
|
||||
vst = vdisk_struct.Win32_VIRTUAL_STORAGE_TYPE(DeviceId=new_device_id)
|
||||
vst = vdisk_struct.VIRTUAL_STORAGE_TYPE(
|
||||
DeviceId=new_device_id,
|
||||
VendorId=w_const.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT)
|
||||
|
||||
params = vdisk_struct.Win32_CREATE_VIRTUAL_DISK_PARAMETERS(
|
||||
MaximumSize=max_internal_size,
|
||||
ParentPath=parent_path,
|
||||
SourcePath=src_path)
|
||||
params = vdisk_struct.CREATE_VIRTUAL_DISK_PARAMETERS()
|
||||
params.Version = w_const.CREATE_VIRTUAL_DISK_VERSION_2
|
||||
params.Version2.MaximumSize = max_internal_size
|
||||
params.Version2.ParentPath = parent_path
|
||||
params.Version2.SourcePath = src_path
|
||||
params.Version2.PhysicalSectorSizeInBytes = (
|
||||
VIRTUAL_DISK_DEFAULT_PHYS_SECTOR_SIZE)
|
||||
params.Version2.BlockSizeInBytes = (
|
||||
w_const.CREATE_VHD_PARAMS_DEFAULT_BLOCK_SIZE)
|
||||
params.Version2.SectorSizeInBytes = (
|
||||
VIRTUAL_DISK_DEFAULT_SECTOR_SIZE)
|
||||
|
||||
handle = wintypes.HANDLE()
|
||||
create_virtual_disk_flag = (
|
||||
vdisk_const.CREATE_VIRTUAL_DISK_FLAGS.get(new_vhd_type))
|
||||
create_virtual_disk_flag = CREATE_VIRTUAL_DISK_FLAGS.get(
|
||||
new_vhd_type, 0)
|
||||
|
||||
self._run_and_check_output(virtdisk.CreateVirtualDisk,
|
||||
ctypes.byref(vst),
|
||||
ctypes.c_wchar_p(new_vhd_path),
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
create_virtual_disk_flag,
|
||||
None,
|
||||
0,
|
||||
ctypes.byref(params),
|
||||
None,
|
||||
ctypes.byref(handle),
|
||||
@ -142,7 +181,7 @@ class VHDUtils(object):
|
||||
|
||||
def get_vhd_format(self, vhd_path):
|
||||
vhd_format = os.path.splitext(vhd_path)[1][1:].upper()
|
||||
device_id = vdisk_const.DEVICE_ID_MAP.get(vhd_format)
|
||||
device_id = DEVICE_ID_MAP.get(vhd_format)
|
||||
# If the disk format is not recognised by extension,
|
||||
# we attempt to retrieve it by seeking the signature.
|
||||
if not device_id and os.path.exists(vhd_path):
|
||||
@ -156,13 +195,13 @@ class VHDUtils(object):
|
||||
|
||||
def _get_vhd_device_id(self, vhd_path):
|
||||
vhd_format = self.get_vhd_format(vhd_path)
|
||||
return vdisk_const.DEVICE_ID_MAP.get(vhd_format)
|
||||
return DEVICE_ID_MAP.get(vhd_format)
|
||||
|
||||
def _get_vhd_format_by_signature(self, vhd_path):
|
||||
with open(vhd_path, 'rb') as f:
|
||||
# print f.read()
|
||||
# Read header
|
||||
if f.read(8) == vdisk_const.VHDX_SIGNATURE:
|
||||
if f.read(8) == VHDX_SIGNATURE:
|
||||
return constants.DISK_FORMAT_VHDX
|
||||
|
||||
# Read footer
|
||||
@ -170,7 +209,7 @@ class VHDUtils(object):
|
||||
file_size = f.tell()
|
||||
if file_size >= 512:
|
||||
f.seek(-512, 2)
|
||||
if f.read(8) == vdisk_const.VHD_SIGNATURE:
|
||||
if f.read(8) == VHD_SIGNATURE:
|
||||
return constants.DISK_FORMAT_VHD
|
||||
|
||||
def get_vhd_info(self, vhd_path, info_members=None,
|
||||
@ -197,10 +236,10 @@ class VHDUtils(object):
|
||||
vhd_info = {}
|
||||
info_members = info_members or self._vhd_info_members
|
||||
|
||||
open_flag = (vdisk_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS
|
||||
open_flag = (w_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS
|
||||
if not open_parents else 0)
|
||||
open_access_mask = (vdisk_const.VIRTUAL_DISK_ACCESS_GET_INFO |
|
||||
vdisk_const.VIRTUAL_DISK_ACCESS_DETACH)
|
||||
open_access_mask = (w_const.VIRTUAL_DISK_ACCESS_GET_INFO |
|
||||
w_const.VIRTUAL_DISK_ACCESS_DETACH)
|
||||
handle = self._open(
|
||||
vhd_path,
|
||||
open_flag=open_flag,
|
||||
@ -211,13 +250,13 @@ class VHDUtils(object):
|
||||
info = self._get_vhd_info_member(handle, member)
|
||||
vhd_info.update(info)
|
||||
finally:
|
||||
self._close(handle)
|
||||
self._win32_utils.close_handle(handle)
|
||||
|
||||
return vhd_info
|
||||
|
||||
def _get_vhd_info_member(self, vhd_file, info_member):
|
||||
virt_disk_info = vdisk_struct.Win32_GET_VIRTUAL_DISK_INFO_PARAMETERS()
|
||||
virt_disk_info.VERSION = ctypes.c_uint(info_member)
|
||||
virt_disk_info = vdisk_struct.GET_VIRTUAL_DISK_INFO()
|
||||
virt_disk_info.Version = ctypes.c_uint(info_member)
|
||||
|
||||
infoSize = ctypes.sizeof(virt_disk_info)
|
||||
|
||||
@ -226,8 +265,8 @@ class VHDUtils(object):
|
||||
# Note(lpetrut): If the vhd has no parent image, this will
|
||||
# return an error. No need to raise an exception in this case.
|
||||
ignored_error_codes = []
|
||||
if info_member == vdisk_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION:
|
||||
ignored_error_codes.append(vdisk_const.ERROR_VHD_INVALID_TYPE)
|
||||
if info_member == w_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION:
|
||||
ignored_error_codes.append(w_const.ERROR_VHD_INVALID_TYPE)
|
||||
|
||||
self._run_and_check_output(virtdisk.GetVirtualDiskInformation,
|
||||
vhd_file,
|
||||
@ -241,7 +280,7 @@ class VHDUtils(object):
|
||||
def _parse_vhd_info(self, virt_disk_info, info_member):
|
||||
vhd_info = {}
|
||||
vhd_info_member = self._vhd_info_members[info_member]
|
||||
info = getattr(virt_disk_info.VhdInfo, vhd_info_member)
|
||||
info = getattr(virt_disk_info, vhd_info_member)
|
||||
|
||||
if hasattr(info, '_fields_'):
|
||||
for field in info._fields_:
|
||||
@ -258,13 +297,13 @@ class VHDUtils(object):
|
||||
block size and sector size of the vhd.
|
||||
"""
|
||||
size = self.get_vhd_info(vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_SIZE])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_SIZE])
|
||||
return size
|
||||
|
||||
def get_vhd_parent_path(self, vhd_path):
|
||||
vhd_info = self.get_vhd_info(
|
||||
vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_PARENT_LOCATION])
|
||||
parent_path = vhd_info['ParentPath']
|
||||
|
||||
return parent_path if parent_path else None
|
||||
@ -272,23 +311,26 @@ class VHDUtils(object):
|
||||
def get_vhd_type(self, vhd_path):
|
||||
vhd_info = self.get_vhd_info(
|
||||
vhd_path,
|
||||
[vdisk_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE])
|
||||
[w_const.GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE])
|
||||
return vhd_info['ProviderSubtype']
|
||||
|
||||
def merge_vhd(self, vhd_path, delete_merged_image=True):
|
||||
"""Merges a VHD/x image into the immediate next parent image."""
|
||||
open_params = vdisk_struct.Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V1(
|
||||
RWDepth=2)
|
||||
open_params = vdisk_struct.OPEN_VIRTUAL_DISK_PARAMETERS()
|
||||
open_params.Version = w_const.OPEN_VIRTUAL_DISK_VERSION_1
|
||||
open_params.Version1.RWDepth = 2
|
||||
|
||||
handle = self._open(vhd_path,
|
||||
open_params=ctypes.byref(open_params))
|
||||
|
||||
params = vdisk_struct.Win32_MERGE_VIRTUAL_DISK_PARAMETERS(MergeDepth=1)
|
||||
params = vdisk_struct.MERGE_VIRTUAL_DISK_PARAMETERS()
|
||||
params.Version = w_const.MERGE_VIRTUAL_DISK_VERSION_1
|
||||
params.Version1.MergeDepth = 1
|
||||
|
||||
self._run_and_check_output(
|
||||
virtdisk.MergeVirtualDisk,
|
||||
handle,
|
||||
None,
|
||||
0,
|
||||
ctypes.byref(params),
|
||||
None,
|
||||
cleanup_handle=handle)
|
||||
@ -297,17 +339,19 @@ class VHDUtils(object):
|
||||
os.remove(vhd_path)
|
||||
|
||||
def reconnect_parent_vhd(self, child_path, parent_path):
|
||||
open_params = vdisk_struct.Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V2(
|
||||
GetInfoOnly=False)
|
||||
open_params = vdisk_struct.OPEN_VIRTUAL_DISK_PARAMETERS()
|
||||
open_params.Version = w_const.OPEN_VIRTUAL_DISK_VERSION_2
|
||||
open_params.Version2.GetInfoOnly = False
|
||||
|
||||
handle = self._open(
|
||||
child_path,
|
||||
open_flag=vdisk_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
|
||||
open_access_mask=None,
|
||||
open_flag=w_const.OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS,
|
||||
open_access_mask=0,
|
||||
open_params=ctypes.byref(open_params))
|
||||
|
||||
params = vdisk_struct.Win32_SET_VIRTUAL_DISK_INFO_PARAMETERS(
|
||||
ParentFilePath=parent_path)
|
||||
params = vdisk_struct.SET_VIRTUAL_DISK_INFO()
|
||||
params.Version = w_const.SET_VIRTUAL_DISK_INFO_PARENT_PATH
|
||||
params.ParentFilePath = parent_path
|
||||
|
||||
self._run_and_check_output(virtdisk.SetVirtualDiskInformation,
|
||||
handle,
|
||||
@ -350,13 +394,14 @@ class VHDUtils(object):
|
||||
def _resize_vhd(self, vhd_path, new_max_size):
|
||||
handle = self._open(vhd_path)
|
||||
|
||||
params = vdisk_struct.Win32_RESIZE_VIRTUAL_DISK_PARAMETERS(
|
||||
NewSize=new_max_size)
|
||||
params = vdisk_struct.RESIZE_VIRTUAL_DISK_PARAMETERS()
|
||||
params.Version = w_const.RESIZE_VIRTUAL_DISK_VERSION_1
|
||||
params.Version1.NewSize = new_max_size
|
||||
|
||||
self._run_and_check_output(
|
||||
virtdisk.ResizeVirtualDisk,
|
||||
handle,
|
||||
None,
|
||||
0,
|
||||
ctypes.byref(params),
|
||||
None,
|
||||
cleanup_handle=handle)
|
||||
@ -373,7 +418,7 @@ class VHDUtils(object):
|
||||
return self.get_internal_vhd_size_by_file_size(
|
||||
vhd_parent, new_vhd_file_size)
|
||||
|
||||
if vhd_dev_id == vdisk_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD:
|
||||
if vhd_dev_id == w_const.VIRTUAL_STORAGE_TYPE_DEVICE_VHD:
|
||||
func = self._get_internal_vhd_size_by_file_size
|
||||
else:
|
||||
func = self._get_internal_vhdx_size_by_file_size
|
||||
@ -403,14 +448,14 @@ class VHDUtils(object):
|
||||
|
||||
vhd_type = vhd_info['ProviderSubtype']
|
||||
if vhd_type == constants.VHD_TYPE_FIXED:
|
||||
vhd_header_size = vdisk_const.VHD_HEADER_SIZE_FIX
|
||||
vhd_header_size = VHD_HEADER_SIZE_FIX
|
||||
return new_vhd_file_size - vhd_header_size
|
||||
else:
|
||||
bs = vhd_info['BlockSize']
|
||||
bes = vdisk_const.VHD_BAT_ENTRY_SIZE
|
||||
ddhs = vdisk_const.VHD_DYNAMIC_DISK_HEADER_SIZE
|
||||
hs = vdisk_const.VHD_HEADER_SIZE_DYNAMIC
|
||||
fs = vdisk_const.VHD_FOOTER_SIZE_DYNAMIC
|
||||
bes = VHD_BAT_ENTRY_SIZE
|
||||
ddhs = VHD_DYNAMIC_DISK_HEADER_SIZE
|
||||
hs = VHD_HEADER_SIZE_DYNAMIC
|
||||
fs = VHD_FOOTER_SIZE_DYNAMIC
|
||||
|
||||
max_internal_size = (new_vhd_file_size -
|
||||
(hs + ddhs + fs)) * bs // (bes + bs)
|
||||
@ -435,8 +480,8 @@ class VHDUtils(object):
|
||||
|
||||
try:
|
||||
with open(vhd_path, 'rb') as f:
|
||||
hs = vdisk_const.VHDX_HEADER_SECTION_SIZE
|
||||
bes = vdisk_const.VHDX_BAT_ENTRY_SIZE
|
||||
hs = VHDX_HEADER_SECTION_SIZE
|
||||
bes = VHDX_BAT_ENTRY_SIZE
|
||||
|
||||
lss = vhd_info['SectorSize']
|
||||
bs = self._get_vhdx_block_size(f)
|
||||
@ -460,23 +505,22 @@ class VHDUtils(object):
|
||||
|
||||
def _get_vhdx_current_header_offset(self, vhdx_file):
|
||||
sequence_numbers = []
|
||||
for offset in vdisk_const.VHDX_HEADER_OFFSETS:
|
||||
for offset in VHDX_HEADER_OFFSETS:
|
||||
vhdx_file.seek(offset + 8)
|
||||
sequence_numbers.append(struct.unpack('<Q',
|
||||
vhdx_file.read(8))[0])
|
||||
current_header = sequence_numbers.index(max(sequence_numbers))
|
||||
return vdisk_const.VHDX_HEADER_OFFSETS[current_header]
|
||||
return VHDX_HEADER_OFFSETS[current_header]
|
||||
|
||||
def _get_vhdx_log_size(self, vhdx_file):
|
||||
current_header_offset = self._get_vhdx_current_header_offset(vhdx_file)
|
||||
offset = current_header_offset + vdisk_const.VHDX_LOG_LENGTH_OFFSET
|
||||
offset = current_header_offset + VHDX_LOG_LENGTH_OFFSET
|
||||
vhdx_file.seek(offset)
|
||||
log_size = struct.unpack('<I', vhdx_file.read(4))[0]
|
||||
return log_size
|
||||
|
||||
def _get_vhdx_metadata_size_and_offset(self, vhdx_file):
|
||||
offset = (vdisk_const.VHDX_METADATA_SIZE_OFFSET +
|
||||
vdisk_const.VHDX_REGION_TABLE_OFFSET)
|
||||
offset = VHDX_METADATA_SIZE_OFFSET + VHDX_REGION_TABLE_OFFSET
|
||||
vhdx_file.seek(offset)
|
||||
metadata_offset = struct.unpack('<Q', vhdx_file.read(8))[0]
|
||||
metadata_size = struct.unpack('<I', vhdx_file.read(4))[0]
|
||||
@ -484,7 +528,7 @@ class VHDUtils(object):
|
||||
|
||||
def _get_vhdx_block_size(self, vhdx_file):
|
||||
metadata_offset = self._get_vhdx_metadata_size_and_offset(vhdx_file)[1]
|
||||
offset = metadata_offset + vdisk_const.VHDX_BS_METADATA_ENTRY_OFFSET
|
||||
offset = metadata_offset + VHDX_BS_METADATA_ENTRY_OFFSET
|
||||
vhdx_file.seek(offset)
|
||||
file_parameter_offset = struct.unpack('<I', vhdx_file.read(4))[0]
|
||||
|
||||
|
@ -1,79 +0,0 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
# 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.
|
||||
|
||||
from oslo_utils import units
|
||||
|
||||
from os_win import constants
|
||||
|
||||
VHD_SIGNATURE = b'conectix'
|
||||
VHDX_SIGNATURE = b'vhdxfile'
|
||||
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3
|
||||
|
||||
DEVICE_ID_MAP = {
|
||||
constants.DISK_FORMAT_VHD: VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
|
||||
constants.DISK_FORMAT_VHDX: VIRTUAL_STORAGE_TYPE_DEVICE_VHDX,
|
||||
}
|
||||
|
||||
VHD_HEADER_SIZE_FIX = 512
|
||||
VHD_BAT_ENTRY_SIZE = 4
|
||||
VHD_DYNAMIC_DISK_HEADER_SIZE = 1024
|
||||
VHD_HEADER_SIZE_DYNAMIC = 512
|
||||
VHD_FOOTER_SIZE_DYNAMIC = 512
|
||||
|
||||
VHDX_BAT_ENTRY_SIZE = 8
|
||||
VHDX_HEADER_OFFSETS = [64 * units.Ki, 128 * units.Ki]
|
||||
VHDX_HEADER_SECTION_SIZE = units.Mi
|
||||
VHDX_LOG_LENGTH_OFFSET = 68
|
||||
VHDX_METADATA_SIZE_OFFSET = 64
|
||||
VHDX_REGION_TABLE_OFFSET = 192 * units.Ki
|
||||
VHDX_BS_METADATA_ENTRY_OFFSET = 48
|
||||
|
||||
VIRTUAL_DISK_ACCESS_NONE = 0
|
||||
VIRTUAL_DISK_ACCESS_ALL = 0x003f0000
|
||||
VIRTUAL_DISK_ACCESS_CREATE = 0x00100000
|
||||
VIRTUAL_DISK_ACCESS_GET_INFO = 0x80000
|
||||
VIRTUAL_DISK_ACCESS_DETACH = 0x00040000
|
||||
|
||||
VIRTUAL_DISK_DEFAULT_SECTOR_SIZE = 0x200
|
||||
VIRTUAL_DISK_DEFAULT_PHYS_SECTOR_SIZE = 0x200
|
||||
|
||||
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 1
|
||||
OPEN_VIRTUAL_DISK_VERSION_1 = 1
|
||||
OPEN_VIRTUAL_DISK_VERSION_2 = 2
|
||||
|
||||
RESIZE_VIRTUAL_DISK_VERSION_1 = 1
|
||||
|
||||
CREATE_VIRTUAL_DISK_VERSION_2 = 2
|
||||
CREATE_VHD_PARAMS_DEFAULT_BLOCK_SIZE = 0
|
||||
CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION = 1
|
||||
|
||||
CREATE_VIRTUAL_DISK_FLAGS = {
|
||||
constants.VHD_TYPE_FIXED:
|
||||
CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION,
|
||||
}
|
||||
|
||||
MERGE_VIRTUAL_DISK_VERSION_1 = 1
|
||||
|
||||
GET_VIRTUAL_DISK_INFO_SIZE = 1
|
||||
GET_VIRTUAL_DISK_INFO_PARENT_LOCATION = 3
|
||||
GET_VIRTUAL_DISK_INFO_VIRTUAL_STORAGE_TYPE = 6
|
||||
GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE = 7
|
||||
|
||||
SET_VIRTUAL_DISK_INFO_PARENT_PATH = 1
|
||||
|
||||
ERROR_VHD_INVALID_TYPE = 0xC03A001B
|
@ -1,178 +0,0 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
from ctypes import wintypes
|
||||
|
||||
from os_win.utils.storage.virtdisk import (
|
||||
virtdisk_constants as vdisk_const)
|
||||
|
||||
|
||||
class Win32_GUID(ctypes.Structure):
|
||||
_fields_ = [("Data1", wintypes.DWORD),
|
||||
("Data2", wintypes.WORD),
|
||||
("Data3", wintypes.WORD),
|
||||
("Data4", wintypes.BYTE * 8)]
|
||||
|
||||
|
||||
WIN32_VIRTUAL_STORAGE_TYPE_MSFT = Win32_GUID(
|
||||
Data1=0xec984aec,
|
||||
Data2=0xa0f9,
|
||||
Data3=0x47e9,
|
||||
Data4=(wintypes.BYTE * 8)(0x90, 0x1f, 0x71, 0x41,
|
||||
0x5a, 0x66, 0x34, 0x5b))
|
||||
|
||||
|
||||
class Win32_VIRTUAL_STORAGE_TYPE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('DeviceId', wintypes.ULONG),
|
||||
('VendorId', Win32_GUID)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.VendorId = WIN32_VIRTUAL_STORAGE_TYPE_MSFT
|
||||
super(Win32_VIRTUAL_STORAGE_TYPE, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_RESIZE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('NewSize', ctypes.c_ulonglong)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.RESIZE_VIRTUAL_DISK_VERSION_1
|
||||
super(Win32_RESIZE_VIRTUAL_DISK_PARAMETERS, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('RWDepth', ctypes.c_ulong),
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.OPEN_VIRTUAL_DISK_VERSION_1
|
||||
super(Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V1, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V2(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('GetInfoOnly', wintypes.BOOL),
|
||||
('ReadOnly', wintypes.BOOL),
|
||||
('ResiliencyGuid', Win32_GUID)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.OPEN_VIRTUAL_DISK_VERSION_2
|
||||
super(Win32_OPEN_VIRTUAL_DISK_PARAMETERS_V2, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_MERGE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('MergeDepth', ctypes.c_ulong)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.MERGE_VIRTUAL_DISK_VERSION_1
|
||||
super(Win32_MERGE_VIRTUAL_DISK_PARAMETERS, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_CREATE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('UniqueId', Win32_GUID),
|
||||
('MaximumSize', ctypes.c_ulonglong),
|
||||
('BlockSizeInBytes', wintypes.ULONG),
|
||||
('SectorSizeInBytes', wintypes.ULONG),
|
||||
('PhysicalSectorSizeInBytes', wintypes.ULONG),
|
||||
('ParentPath', wintypes.LPCWSTR),
|
||||
('SourcePath', wintypes.LPCWSTR),
|
||||
('OpenFlags', wintypes.DWORD),
|
||||
('ParentVirtualStorageType', Win32_VIRTUAL_STORAGE_TYPE),
|
||||
('SourceVirtualStorageType', Win32_VIRTUAL_STORAGE_TYPE),
|
||||
('ResiliencyGuid', Win32_GUID)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.CREATE_VIRTUAL_DISK_VERSION_2
|
||||
|
||||
# The kwargs can override the defaults specified bellow.
|
||||
self.PhysicalSectorSizeInBytes = (
|
||||
vdisk_const.VIRTUAL_DISK_DEFAULT_PHYS_SECTOR_SIZE)
|
||||
self.BlockSizeInBytes = (
|
||||
vdisk_const.CREATE_VHD_PARAMS_DEFAULT_BLOCK_SIZE)
|
||||
self.SectorSizeInBytes = (
|
||||
vdisk_const.VIRTUAL_DISK_DEFAULT_SECTOR_SIZE)
|
||||
|
||||
super(Win32_CREATE_VIRTUAL_DISK_PARAMETERS, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
class Win32_SIZE(ctypes.Structure):
|
||||
_fields_ = [("VirtualSize", wintypes.ULARGE_INTEGER),
|
||||
("PhysicalSize", wintypes.ULARGE_INTEGER),
|
||||
("BlockSize", wintypes.ULONG),
|
||||
("SectorSize", wintypes.ULONG)]
|
||||
|
||||
|
||||
class Win32_PARENT_LOCATION(ctypes.Structure):
|
||||
_fields_ = [('ParentResolved', wintypes.BOOL),
|
||||
('ParentPath', wintypes.WCHAR * 512)]
|
||||
|
||||
|
||||
class Win32_PHYSICAL_DISK(ctypes.Structure):
|
||||
_fields_ = [("LogicalSectorSize", wintypes.ULONG),
|
||||
("PhysicalSectorSize", wintypes.ULONG),
|
||||
("IsRemote", wintypes.BOOL)]
|
||||
|
||||
|
||||
class Win32_VHD_INFO(ctypes.Union):
|
||||
_fields_ = [("Size", Win32_SIZE),
|
||||
("Identifier", Win32_GUID),
|
||||
("ParentLocation", Win32_PARENT_LOCATION),
|
||||
("ParentIdentifier", Win32_GUID),
|
||||
("ParentTimestamp", wintypes.ULONG),
|
||||
("VirtualStorageType", Win32_VIRTUAL_STORAGE_TYPE),
|
||||
("ProviderSubtype", wintypes.ULONG),
|
||||
("Is4kAligned", wintypes.BOOL),
|
||||
("PhysicalDisk", Win32_PHYSICAL_DISK),
|
||||
("VhdPhysicalSectorSize", wintypes.ULONG),
|
||||
("SmallestSafeVirtualSize",
|
||||
wintypes.ULARGE_INTEGER),
|
||||
("FragmentationPercentage", wintypes.ULONG)]
|
||||
|
||||
|
||||
class Win32_GET_VIRTUAL_DISK_INFO_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [("VERSION", wintypes.UINT),
|
||||
("VhdInfo", Win32_VHD_INFO)]
|
||||
|
||||
|
||||
class Win32_SET_VIRTUAL_DISK_INFO_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('ParentFilePath', wintypes.LPCWSTR)
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.Version = vdisk_const.SET_VIRTUAL_DISK_INFO_PARENT_PATH
|
||||
super(Win32_SET_VIRTUAL_DISK_INFO_PARAMETERS, self).__init__(
|
||||
*args, **kwargs)
|
@ -15,22 +15,18 @@
|
||||
# under the License.
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from os_win import _utils
|
||||
from os_win import exceptions
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import libs as w_lib
|
||||
|
||||
if sys.platform == 'win32':
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32 = w_lib.get_shared_lib_handle(w_lib.KERNEL32)
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
|
||||
|
||||
|
||||
class Win32Utils(object):
|
||||
def __init__(self):
|
||||
@ -99,8 +95,9 @@ class Win32Utils(object):
|
||||
message_buffer = ctypes.c_char_p()
|
||||
|
||||
kernel32.FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
w_const.FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
w_const.FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
w_const.FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
None, error_code, 0, ctypes.byref(message_buffer), 0, None)
|
||||
|
||||
error_message = message_buffer.value
|
||||
@ -128,3 +125,6 @@ class Win32Utils(object):
|
||||
except exceptions.Win32Exception:
|
||||
LOG.exception("Could not deallocate memory. "
|
||||
"There could be a memory leak.")
|
||||
|
||||
def close_handle(self, handle):
|
||||
kernel32.CloseHandle(handle)
|
||||
|
0
os_win/utils/winapi/__init__.py
Normal file
0
os_win/utils/winapi/__init__.py
Normal file
258
os_win/utils/winapi/constants.py
Normal file
258
os_win/utils/winapi/constants.py
Normal file
@ -0,0 +1,258 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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.
|
||||
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
# Windows.h
|
||||
# ----------
|
||||
# winerror.h
|
||||
ERROR_INVALID_HANDLE = 6
|
||||
ERROR_INSUFFICIENT_BUFFER = 122
|
||||
ERROR_DIR_IS_NOT_EMPTY = 145
|
||||
ERROR_PIPE_BUSY = 231
|
||||
ERROR_PIPE_NOT_CONNECTED = 233
|
||||
ERROR_MORE_DATA = 234
|
||||
ERROR_WAIT_TIMEOUT = 258
|
||||
ERROR_IO_PENDING = 997
|
||||
ERROR_NOT_FOUND = 1168
|
||||
ERROR_INVALID_STATE = 5023
|
||||
ERROR_VHD_INVALID_TYPE = 0xC03A001B
|
||||
|
||||
# winbase.h
|
||||
WAIT_FAILED = 0xFFFFFFFF
|
||||
|
||||
FILE_FLAG_OVERLAPPED = 0x40000000
|
||||
|
||||
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
|
||||
|
||||
# FileAPI.h
|
||||
OPEN_EXISTING = 3
|
||||
|
||||
INVALID_FILE_ATTRIBUTES = 4294967295
|
||||
|
||||
# winnt.h
|
||||
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
|
||||
|
||||
FILE_SHARE_READ = 1
|
||||
FILE_SHARE_WRITE = 2
|
||||
GENERIC_READ = 0x80000000
|
||||
GENERIC_WRITE = 0x40000000
|
||||
|
||||
OWNER_SECURITY_INFORMATION = 0x00000001
|
||||
GROUP_SECURITY_INFORMATION = 0x00000002
|
||||
DACL_SECURITY_INFORMATION = 0x00000004
|
||||
SACL_SECURITY_INFORMATION = 0x00000008
|
||||
|
||||
# winioctl.h
|
||||
FILE_DEVICE_DISK = 7
|
||||
|
||||
# handleapi.h
|
||||
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
|
||||
|
||||
# minwindef.h
|
||||
MAX_PATH = 260
|
||||
|
||||
# AccCtrl.h
|
||||
TRUSTEE_IS_NAME = 1
|
||||
# Indicates a file or directory object.
|
||||
SE_FILE_OBJECT = 1
|
||||
# ---------
|
||||
|
||||
# ClusApi.h
|
||||
# ---------
|
||||
CLUSPROP_SYNTAX_NAME = 262147
|
||||
CLUSPROP_SYNTAX_ENDMARK = 0
|
||||
CLUSPROP_SYNTAX_LIST_VALUE_DWORD = 65538
|
||||
CLUSPROP_SYNTAX_LIST_VALUE_ULARGE_INTEGER = 65542
|
||||
|
||||
CLUSAPI_GROUP_MOVE_RETURN_TO_SOURCE_NODE_ON_ERROR = 2
|
||||
CLUSAPI_GROUP_MOVE_QUEUE_ENABLED = 4
|
||||
CLUSAPI_GROUP_MOVE_HIGH_PRIORITY_START = 8
|
||||
|
||||
CLUSTER_OBJECT_TYPE_GROUP = 2
|
||||
|
||||
CLUSTER_CHANGE_GROUP_COMMON_PROPERTY_V2 = 2
|
||||
CLUSTER_CHANGE_GROUP_STATE_V2 = 8
|
||||
|
||||
CLUSGRP_STATUS_WAITING_IN_QUEUE_FOR_MOVE = 4
|
||||
|
||||
CLUS_RESTYPE_NAME_VM = "Virtual Machine"
|
||||
CLUS_RESTYPE_NAME_VM_CONFIG = "Virtual Machine Configuration"
|
||||
|
||||
CLUSREG_NAME_GRP_STATUS_INFORMATION = 'StatusInformation'
|
||||
|
||||
CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES = 0x3000055
|
||||
|
||||
# iscsidsc.h
|
||||
# ----------
|
||||
ISCSI_ANY_INITIATOR_PORT = wintypes.ULONG(-1).value
|
||||
ISCSI_ALL_INITIATOR_PORTS = wintypes.ULONG(-1).value
|
||||
MAX_ISCSI_PORTAL_NAME_LEN = 256
|
||||
MAX_ISCSI_PORTAL_ADDRESS_LEN = 256
|
||||
MAX_ISCSI_NAME_LEN = 223
|
||||
MAX_ISCSI_HBANAME_LEN = 256
|
||||
|
||||
ISCSI_LOGIN_FLAG_MULTIPATH_ENABLED = 2
|
||||
ISCSI_LOGIN_OPTIONS_USERNAME = 0x00000020
|
||||
ISCSI_LOGIN_OPTIONS_PASSWORD = 0x00000040
|
||||
ISCSI_LOGIN_OPTIONS_AUTH_TYPE = 0x00000080
|
||||
|
||||
# iscsierr.h
|
||||
# ----------
|
||||
ISDSC_NON_SPECIFIC_ERROR = 0xEFFF0001
|
||||
ISDSC_LOGIN_FAILED = 0xEFFF0002
|
||||
ISDSC_CONNECTION_FAILED = 0xEFFF0003
|
||||
ISDSC_INITIATOR_NODE_ALREADY_EXISTS = 0xEFFF0004
|
||||
ISDSC_INITIATOR_NODE_NOT_FOUND = 0xEFFF0005
|
||||
ISDSC_TARGET_MOVED_TEMPORARILY = 0xEFFF0006
|
||||
ISDSC_TARGET_MOVED_PERMANENTLY = 0xEFFF0007
|
||||
ISDSC_INITIATOR_ERROR = 0xEFFF0008
|
||||
ISDSC_AUTHENTICATION_FAILURE = 0xEFFF0009
|
||||
ISDSC_AUTHORIZATION_FAILURE = 0xEFFF000A
|
||||
ISDSC_NOT_FOUND = 0xEFFF000B
|
||||
ISDSC_TARGET_REMOVED = 0xEFFF000C
|
||||
ISDSC_UNSUPPORTED_VERSION = 0xEFFF000D
|
||||
ISDSC_TOO_MANY_CONNECTIONS = 0xEFFF000E
|
||||
ISDSC_MISSING_PARAMETER = 0xEFFF000F
|
||||
ISDSC_CANT_INCLUDE_IN_SESSION = 0xEFFF0010
|
||||
ISDSC_SESSION_TYPE_NOT_SUPPORTED = 0xEFFF0011
|
||||
ISDSC_TARGET_ERROR = 0xEFFF0012
|
||||
ISDSC_SERVICE_UNAVAILABLE = 0xEFFF0013
|
||||
ISDSC_OUT_OF_RESOURCES = 0xEFFF0014
|
||||
ISDSC_CONNECTION_ALREADY_EXISTS = 0xEFFF0015
|
||||
ISDSC_SESSION_ALREADY_EXISTS = 0xEFFF0016
|
||||
ISDSC_INITIATOR_INSTANCE_NOT_FOUND = 0xEFFF0017
|
||||
ISDSC_TARGET_ALREADY_EXISTS = 0xEFFF0018
|
||||
ISDSC_DRIVER_BUG = 0xEFFF0019
|
||||
ISDSC_INVALID_TEXT_KEY = 0xEFFF001A
|
||||
ISDSC_INVALID_SENDTARGETS_TEXT = 0xEFFF001B
|
||||
ISDSC_INVALID_SESSION_ID = 0xEFFF001C
|
||||
ISDSC_SCSI_REQUEST_FAILED = 0xEFFF001D
|
||||
ISDSC_TOO_MANY_SESSIONS = 0xEFFF001E
|
||||
ISDSC_SESSION_BUSY = 0xEFFF001F
|
||||
ISDSC_TARGET_MAPPING_UNAVAILABLE = 0xEFFF0020
|
||||
ISDSC_ADDRESS_TYPE_NOT_SUPPORTED = 0xEFFF0021
|
||||
ISDSC_LOGON_FAILED = 0xEFFF0022
|
||||
ISDSC_SEND_FAILED = 0xEFFF0023
|
||||
ISDSC_TRANSPORT_ERROR = 0xEFFF0024
|
||||
ISDSC_VERSION_MISMATCH = 0xEFFF0025
|
||||
ISDSC_TARGET_MAPPING_OUT_OF_RANGE = 0xEFFF0026
|
||||
ISDSC_TARGET_PRESHAREDKEY_UNAVAILABLE = 0xEFFF0027
|
||||
ISDSC_TARGET_AUTHINFO_UNAVAILABLE = 0xEFFF0028
|
||||
ISDSC_TARGET_NOT_FOUND = 0xEFFF0029
|
||||
ISDSC_LOGIN_USER_INFO_BAD = 0xEFFF002A
|
||||
ISDSC_TARGET_MAPPING_EXISTS = 0xEFFF002B
|
||||
ISDSC_HBA_SECURITY_CACHE_FULL = 0xEFFF002C
|
||||
ISDSC_INVALID_PORT_NUMBER = 0xEFFF002D
|
||||
ISDSC_OPERATION_NOT_ALL_SUCCESS = 0xAFFF002E
|
||||
ISDSC_HBA_SECURITY_CACHE_NOT_SUPPORTED = 0xEFFF002F
|
||||
ISDSC_IKE_ID_PAYLOAD_TYPE_NOT_SUPPORTED = 0xEFFF0030
|
||||
ISDSC_IKE_ID_PAYLOAD_INCORRECT_SIZE = 0xEFFF0031
|
||||
ISDSC_TARGET_PORTAL_ALREADY_EXISTS = 0xEFFF0032
|
||||
ISDSC_TARGET_ADDRESS_ALREADY_EXISTS = 0xEFFF0033
|
||||
ISDSC_NO_AUTH_INFO_AVAILABLE = 0xEFFF0034
|
||||
ISDSC_NO_TUNNEL_OUTER_MODE_ADDRESS = 0xEFFF0035
|
||||
ISDSC_CACHE_CORRUPTED = 0xEFFF0036
|
||||
ISDSC_REQUEST_NOT_SUPPORTED = 0xEFFF0037
|
||||
ISDSC_TARGET_OUT_OF_RESORCES = 0xEFFF0038
|
||||
ISDSC_SERVICE_DID_NOT_RESPOND = 0xEFFF0039
|
||||
ISDSC_ISNS_SERVER_NOT_FOUND = 0xEFFF003A
|
||||
ISDSC_OPERATION_REQUIRES_REBOOT = 0xAFFF003B
|
||||
ISDSC_NO_PORTAL_SPECIFIED = 0xEFFF003C
|
||||
ISDSC_CANT_REMOVE_LAST_CONNECTION = 0xEFFF003D
|
||||
ISDSC_SERVICE_NOT_RUNNING = 0xEFFF003E
|
||||
ISDSC_TARGET_ALREADY_LOGGED_IN = 0xEFFF003F
|
||||
ISDSC_DEVICE_BUSY_ON_SESSION = 0xEFFF0040
|
||||
ISDSC_COULD_NOT_SAVE_PERSISTENT_LOGIN_DATA = 0xEFFF0041
|
||||
ISDSC_COULD_NOT_REMOVE_PERSISTENT_LOGIN_DATA = 0xEFFF0042
|
||||
ISDSC_PORTAL_NOT_FOUND = 0xEFFF0043
|
||||
ISDSC_INITIATOR_NOT_FOUND = 0xEFFF0044
|
||||
ISDSC_DISCOVERY_MECHANISM_NOT_FOUND = 0xEFFF0045
|
||||
ISDSC_IPSEC_NOT_SUPPORTED_ON_OS = 0xEFFF0046
|
||||
ISDSC_PERSISTENT_LOGIN_TIMEOUT = 0xEFFF0047
|
||||
ISDSC_SHORT_CHAP_SECRET = 0xAFFF0048
|
||||
ISDSC_EVALUATION_PEROID_EXPIRED = 0xEFFF0049
|
||||
ISDSC_INVALID_CHAP_SECRET = 0xEFFF004A
|
||||
ISDSC_INVALID_TARGET_CHAP_SECRET = 0xEFFF004B
|
||||
ISDSC_INVALID_INITIATOR_CHAP_SECRET = 0xEFFF004C
|
||||
ISDSC_INVALID_CHAP_USER_NAME = 0xEFFF004D
|
||||
ISDSC_INVALID_LOGON_AUTH_TYPE = 0xEFFF004E
|
||||
ISDSC_INVALID_TARGET_MAPPING = 0xEFFF004F
|
||||
ISDSC_INVALID_TARGET_ID = 0xEFFF0050
|
||||
ISDSC_INVALID_ISCSI_NAME = 0xEFFF0051
|
||||
ISDSC_INCOMPATIBLE_ISNS_VERSION = 0xEFFF0052
|
||||
ISDSC_FAILED_TO_CONFIGURE_IPSEC = 0xEFFF0053
|
||||
ISDSC_BUFFER_TOO_SMALL = 0xEFFF0054
|
||||
ISDSC_INVALID_LOAD_BALANCE_POLICY = 0xEFFF0055
|
||||
ISDSC_INVALID_PARAMETER = 0xEFFF0056
|
||||
ISDSC_DUPLICATE_PATH_SPECIFIED = 0xEFFF0057
|
||||
ISDSC_PATH_COUNT_MISMATCH = 0xEFFF0058
|
||||
ISDSC_INVALID_PATH_ID = 0xEFFF0059
|
||||
ISDSC_MULTIPLE_PRIMARY_PATHS_SPECIFIED = 0xEFFF005A
|
||||
ISDSC_NO_PRIMARY_PATH_SPECIFIED = 0xEFFF005B
|
||||
ISDSC_DEVICE_ALREADY_PERSISTENTLY_BOUND = 0xEFFF005C
|
||||
ISDSC_DEVICE_NOT_FOUND = 0xEFFF005D
|
||||
ISDSC_DEVICE_NOT_ISCSI_OR_PERSISTENT = 0xEFFF005E
|
||||
ISDSC_DNS_NAME_UNRESOLVED = 0xEFFF005F
|
||||
ISDSC_NO_CONNECTION_AVAILABLE = 0xEFFF0060
|
||||
ISDSC_LB_POLICY_NOT_SUPPORTED = 0xEFFF0061
|
||||
ISDSC_REMOVE_CONNECTION_IN_PROGRESS = 0xEFFF0062
|
||||
ISDSC_INVALID_CONNECTION_ID = 0xEFFF0063
|
||||
ISDSC_CANNOT_REMOVE_LEADING_CONNECTION = 0xEFFF0064
|
||||
ISDSC_RESTRICTED_BY_GROUP_POLICY = 0xEFFF0065
|
||||
ISDSC_ISNS_FIREWALL_BLOCKED = 0xEFFF0066
|
||||
ISDSC_FAILURE_TO_PERSIST_LB_POLICY = 0xEFFF0067
|
||||
ISDSC_INVALID_HOST = 0xEFFF0068
|
||||
|
||||
|
||||
# virtdisk.h
|
||||
# ----------
|
||||
VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = wintypes.GUID(
|
||||
Data1=0xec984aec,
|
||||
Data2=0xa0f9,
|
||||
Data3=0x47e9,
|
||||
Data4=(wintypes.BYTE * 8)(0x90, 0x1f, 0x71, 0x41,
|
||||
0x5a, 0x66, 0x34, 0x5b))
|
||||
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2
|
||||
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3
|
||||
|
||||
VIRTUAL_DISK_ACCESS_NONE = 0
|
||||
VIRTUAL_DISK_ACCESS_ALL = 0x003f0000
|
||||
VIRTUAL_DISK_ACCESS_CREATE = 0x00100000
|
||||
VIRTUAL_DISK_ACCESS_GET_INFO = 0x80000
|
||||
VIRTUAL_DISK_ACCESS_DETACH = 0x00040000
|
||||
|
||||
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 1
|
||||
OPEN_VIRTUAL_DISK_VERSION_1 = 1
|
||||
OPEN_VIRTUAL_DISK_VERSION_2 = 2
|
||||
|
||||
RESIZE_VIRTUAL_DISK_VERSION_1 = 1
|
||||
|
||||
CREATE_VIRTUAL_DISK_VERSION_2 = 2
|
||||
CREATE_VHD_PARAMS_DEFAULT_BLOCK_SIZE = 0
|
||||
CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION = 1
|
||||
|
||||
MERGE_VIRTUAL_DISK_VERSION_1 = 1
|
||||
|
||||
GET_VIRTUAL_DISK_INFO_SIZE = 1
|
||||
GET_VIRTUAL_DISK_INFO_PARENT_LOCATION = 3
|
||||
GET_VIRTUAL_DISK_INFO_VIRTUAL_STORAGE_TYPE = 6
|
||||
GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE = 7
|
||||
|
||||
SET_VIRTUAL_DISK_INFO_PARENT_PATH = 1
|
0
os_win/utils/winapi/errmsg/__init__.py
Normal file
0
os_win/utils/winapi/errmsg/__init__.py
Normal file
321
os_win/utils/winapi/errmsg/iscsierr.py
Normal file
321
os_win/utils/winapi/errmsg/iscsierr.py
Normal file
@ -0,0 +1,321 @@
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
# 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.
|
||||
|
||||
# Error codes and descriptions, as provided by iscsierr.h
|
||||
|
||||
from os_win._i18n import _
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
|
||||
err_msg_dict = {
|
||||
w_const.ISDSC_NON_SPECIFIC_ERROR:
|
||||
_('A non specific error occurred.'),
|
||||
w_const.ISDSC_LOGIN_FAILED:
|
||||
_('Login Failed.'),
|
||||
w_const.ISDSC_CONNECTION_FAILED:
|
||||
_('Connection Failed.'),
|
||||
w_const.ISDSC_INITIATOR_NODE_ALREADY_EXISTS:
|
||||
_('Initiator Node Already Exists.'),
|
||||
w_const.ISDSC_INITIATOR_NODE_NOT_FOUND:
|
||||
_('Initiator Node Does Not Exist.'),
|
||||
w_const.ISDSC_TARGET_MOVED_TEMPORARILY:
|
||||
_('Target Moved Temporarily.'),
|
||||
w_const.ISDSC_TARGET_MOVED_PERMANENTLY:
|
||||
_('Target Moved Permanently.'),
|
||||
w_const.ISDSC_INITIATOR_ERROR:
|
||||
_('Initiator Error.'),
|
||||
w_const.ISDSC_AUTHENTICATION_FAILURE:
|
||||
_('Authentication Failure.'),
|
||||
w_const.ISDSC_AUTHORIZATION_FAILURE:
|
||||
_('Authorization Failure.'),
|
||||
w_const.ISDSC_NOT_FOUND:
|
||||
_('Not Found.'),
|
||||
w_const.ISDSC_TARGET_REMOVED:
|
||||
_('Target Removed.'),
|
||||
w_const.ISDSC_UNSUPPORTED_VERSION:
|
||||
_('Unsupported Version.'),
|
||||
w_const.ISDSC_TOO_MANY_CONNECTIONS:
|
||||
_('Too many Connections.'),
|
||||
w_const.ISDSC_MISSING_PARAMETER:
|
||||
_('Missing Parameter.'),
|
||||
w_const.ISDSC_CANT_INCLUDE_IN_SESSION:
|
||||
_('Can not include in session.'),
|
||||
w_const.ISDSC_SESSION_TYPE_NOT_SUPPORTED:
|
||||
_('Session type not supported.'),
|
||||
w_const.ISDSC_TARGET_ERROR:
|
||||
_('Target Error.'),
|
||||
w_const.ISDSC_SERVICE_UNAVAILABLE:
|
||||
_('Service Unavailable.'),
|
||||
w_const.ISDSC_OUT_OF_RESOURCES:
|
||||
_('Out of Resources.'),
|
||||
w_const.ISDSC_CONNECTION_ALREADY_EXISTS:
|
||||
_('Connections already exist on initiator node.'),
|
||||
w_const.ISDSC_SESSION_ALREADY_EXISTS:
|
||||
_('Session Already Exists.'),
|
||||
w_const.ISDSC_INITIATOR_INSTANCE_NOT_FOUND:
|
||||
_('Initiator Instance Does Not Exist.'),
|
||||
w_const.ISDSC_TARGET_ALREADY_EXISTS:
|
||||
_('Target Already Exists.'),
|
||||
w_const.ISDSC_DRIVER_BUG:
|
||||
_('The iscsi driver implementation did '
|
||||
'not complete an operation correctly.'),
|
||||
w_const.ISDSC_INVALID_TEXT_KEY:
|
||||
_('An invalid key text was encountered.'),
|
||||
w_const.ISDSC_INVALID_SENDTARGETS_TEXT:
|
||||
_('Invalid SendTargets response text was encountered.'),
|
||||
w_const.ISDSC_INVALID_SESSION_ID:
|
||||
_('Invalid Session Id.'),
|
||||
w_const.ISDSC_SCSI_REQUEST_FAILED:
|
||||
_('The scsi request failed.'),
|
||||
w_const.ISDSC_TOO_MANY_SESSIONS:
|
||||
_('Exceeded max sessions for this initiator.'),
|
||||
w_const.ISDSC_SESSION_BUSY:
|
||||
_('Session is busy since a request is already in progress.'),
|
||||
w_const.ISDSC_TARGET_MAPPING_UNAVAILABLE:
|
||||
_('The target mapping requested is not available.'),
|
||||
w_const.ISDSC_ADDRESS_TYPE_NOT_SUPPORTED:
|
||||
_('The Target Address type given is not supported.'),
|
||||
w_const.ISDSC_LOGON_FAILED:
|
||||
_('Logon Failed.'),
|
||||
w_const.ISDSC_SEND_FAILED:
|
||||
_('TCP Send Failed.'),
|
||||
w_const.ISDSC_TRANSPORT_ERROR:
|
||||
_('TCP Transport Error'),
|
||||
w_const.ISDSC_VERSION_MISMATCH:
|
||||
_('iSCSI Version Mismatch'),
|
||||
w_const.ISDSC_TARGET_MAPPING_OUT_OF_RANGE:
|
||||
_('The Target Mapping Address passed is out of range for the '
|
||||
'adapter configuration.'),
|
||||
w_const.ISDSC_TARGET_PRESHAREDKEY_UNAVAILABLE:
|
||||
_('The preshared key for the target or IKE identification '
|
||||
'payload is not available.'),
|
||||
w_const.ISDSC_TARGET_AUTHINFO_UNAVAILABLE:
|
||||
_('The authentication information for '
|
||||
'the target is not available.'),
|
||||
w_const.ISDSC_TARGET_NOT_FOUND:
|
||||
_('The target name is not found or is '
|
||||
'marked as hidden from login.'),
|
||||
w_const.ISDSC_LOGIN_USER_INFO_BAD:
|
||||
_('One or more parameters specified in '
|
||||
'LoginTargetIN structure is invalid.'),
|
||||
w_const.ISDSC_TARGET_MAPPING_EXISTS:
|
||||
_('Given target mapping already exists.'),
|
||||
w_const.ISDSC_HBA_SECURITY_CACHE_FULL:
|
||||
_('The HBA security information cache '
|
||||
'is full.'),
|
||||
w_const.ISDSC_INVALID_PORT_NUMBER:
|
||||
_('The port number passed is '
|
||||
'not valid for the initiator.'),
|
||||
w_const.ISDSC_OPERATION_NOT_ALL_SUCCESS:
|
||||
_('The operation was not successful '
|
||||
'for all initiators or discovery '
|
||||
'methods.'),
|
||||
w_const.ISDSC_HBA_SECURITY_CACHE_NOT_SUPPORTED:
|
||||
_('The HBA security information '
|
||||
'cache is not supported by '
|
||||
'this adapter.'),
|
||||
w_const.ISDSC_IKE_ID_PAYLOAD_TYPE_NOT_SUPPORTED:
|
||||
_('The IKE id payload type '
|
||||
'specified is not supported.'),
|
||||
w_const.ISDSC_IKE_ID_PAYLOAD_INCORRECT_SIZE:
|
||||
_('The IKE id payload size '
|
||||
'specified is not correct.'),
|
||||
w_const.ISDSC_TARGET_PORTAL_ALREADY_EXISTS:
|
||||
_('Target Portal Structure '
|
||||
'Already Exists.'),
|
||||
w_const.ISDSC_TARGET_ADDRESS_ALREADY_EXISTS:
|
||||
_('Target Address Structure '
|
||||
'Already Exists.'),
|
||||
w_const.ISDSC_NO_AUTH_INFO_AVAILABLE:
|
||||
_('There is no IKE authentication '
|
||||
'information available.'),
|
||||
w_const.ISDSC_NO_TUNNEL_OUTER_MODE_ADDRESS:
|
||||
_('There is no tunnel mode outer '
|
||||
'address specified.'),
|
||||
w_const.ISDSC_CACHE_CORRUPTED:
|
||||
_('Authentication or tunnel '
|
||||
'address cache is corrupted.'),
|
||||
w_const.ISDSC_REQUEST_NOT_SUPPORTED:
|
||||
_('The request or operation '
|
||||
'is not supported.'),
|
||||
w_const.ISDSC_TARGET_OUT_OF_RESORCES:
|
||||
_('The target does not have enough '
|
||||
'resources to process the '
|
||||
'given request.'),
|
||||
w_const.ISDSC_SERVICE_DID_NOT_RESPOND:
|
||||
_('The initiator service did '
|
||||
'not respond to the request '
|
||||
'sent by the driver.'),
|
||||
w_const.ISDSC_ISNS_SERVER_NOT_FOUND:
|
||||
_('The Internet Storage Name Server (iSNS) '
|
||||
'server was not found or is unavailable.'),
|
||||
w_const.ISDSC_OPERATION_REQUIRES_REBOOT:
|
||||
_('The operation was successful but '
|
||||
'requires a driver reload or reboot '
|
||||
'to become effective.'),
|
||||
w_const.ISDSC_NO_PORTAL_SPECIFIED:
|
||||
_('There is no target portal available '
|
||||
'to complete the login.'),
|
||||
w_const.ISDSC_CANT_REMOVE_LAST_CONNECTION:
|
||||
_('Cannot remove the last '
|
||||
'connection for a session.'),
|
||||
w_const.ISDSC_SERVICE_NOT_RUNNING:
|
||||
_('The Microsoft iSCSI initiator '
|
||||
'service has not been started.'),
|
||||
w_const.ISDSC_TARGET_ALREADY_LOGGED_IN:
|
||||
_('The target has already been '
|
||||
'logged in via an iSCSI session.'),
|
||||
w_const.ISDSC_DEVICE_BUSY_ON_SESSION:
|
||||
_('The session cannot be logged out '
|
||||
'since a device on that session is '
|
||||
'currently being used.'),
|
||||
w_const.ISDSC_COULD_NOT_SAVE_PERSISTENT_LOGIN_DATA:
|
||||
_('Failed to save persistent '
|
||||
'login information.'),
|
||||
w_const.ISDSC_COULD_NOT_REMOVE_PERSISTENT_LOGIN_DATA:
|
||||
_('Failed to remove '
|
||||
'persistent login '
|
||||
'information.'),
|
||||
w_const.ISDSC_PORTAL_NOT_FOUND:
|
||||
_('The specified portal was not found.'),
|
||||
w_const.ISDSC_INITIATOR_NOT_FOUND:
|
||||
_('The specified initiator '
|
||||
'name was not found.'),
|
||||
w_const.ISDSC_DISCOVERY_MECHANISM_NOT_FOUND:
|
||||
_('The specified discovery '
|
||||
'mechanism was not found.'),
|
||||
w_const.ISDSC_IPSEC_NOT_SUPPORTED_ON_OS:
|
||||
_('iSCSI does not support IPSEC '
|
||||
'for this version of the OS.'),
|
||||
w_const.ISDSC_PERSISTENT_LOGIN_TIMEOUT:
|
||||
_('The iSCSI service timed out waiting '
|
||||
'for all persistent logins to '
|
||||
'complete.'),
|
||||
w_const.ISDSC_SHORT_CHAP_SECRET:
|
||||
_('The specified CHAP secret is less than '
|
||||
'96 bits and will not be usable for '
|
||||
'authenticating over non ipsec connections.'),
|
||||
w_const.ISDSC_EVALUATION_PEROID_EXPIRED:
|
||||
_('The evaluation period for the '
|
||||
'iSCSI initiator service has '
|
||||
'expired.'),
|
||||
w_const.ISDSC_INVALID_CHAP_SECRET:
|
||||
_('CHAP secret given does not conform '
|
||||
'to the standard. Please see system '
|
||||
'event log for more information.'),
|
||||
w_const.ISDSC_INVALID_TARGET_CHAP_SECRET:
|
||||
_('Target CHAP secret given is invalid. Maximum size of CHAP secret'
|
||||
'is 16 bytes. Minimum size is 12 bytes if IPSec is not used.'),
|
||||
w_const.ISDSC_INVALID_INITIATOR_CHAP_SECRET:
|
||||
_('Initiator CHAP secret given is '
|
||||
'invalid. Maximum size of CHAP '
|
||||
'secret is 16 bytes. Minimum size '
|
||||
'is 12 bytes if IPSec is '
|
||||
'not used.'),
|
||||
w_const.ISDSC_INVALID_CHAP_USER_NAME:
|
||||
_('CHAP Username given is invalid.'),
|
||||
w_const.ISDSC_INVALID_LOGON_AUTH_TYPE:
|
||||
_('Logon Authentication type '
|
||||
'given is invalid.'),
|
||||
w_const.ISDSC_INVALID_TARGET_MAPPING:
|
||||
_('Target Mapping information '
|
||||
'given is invalid.'),
|
||||
w_const.ISDSC_INVALID_TARGET_ID:
|
||||
_('Target Id given in '
|
||||
'Target Mapping is invalid.'),
|
||||
w_const.ISDSC_INVALID_ISCSI_NAME:
|
||||
_('The iSCSI name specified contains '
|
||||
'invalid characters or is too long.'),
|
||||
w_const.ISDSC_INCOMPATIBLE_ISNS_VERSION:
|
||||
_('The version number returned from the '
|
||||
'Internet Storage Name Server (iSNS) '
|
||||
'server is not compatible with this '
|
||||
'version of the iSNS client.'),
|
||||
w_const.ISDSC_FAILED_TO_CONFIGURE_IPSEC:
|
||||
_('Initiator failed to configure IPSec '
|
||||
'for the given connection. This could '
|
||||
'be because of low resources.'),
|
||||
w_const.ISDSC_BUFFER_TOO_SMALL:
|
||||
_('The buffer given for processing '
|
||||
'the request is too small.'),
|
||||
w_const.ISDSC_INVALID_LOAD_BALANCE_POLICY:
|
||||
_('The given Load Balance '
|
||||
'policy is not recognized '
|
||||
'by iScsi initiator.'),
|
||||
w_const.ISDSC_INVALID_PARAMETER:
|
||||
_('One or more paramaters '
|
||||
'specified is not valid.'),
|
||||
w_const.ISDSC_DUPLICATE_PATH_SPECIFIED:
|
||||
_('Duplicate PathIds were '
|
||||
'specified in the call to '
|
||||
'set Load Balance Policy.'),
|
||||
w_const.ISDSC_PATH_COUNT_MISMATCH:
|
||||
_('Number of paths specified in '
|
||||
'Set Load Balance Policy does not '
|
||||
'match the number of paths to the target.'),
|
||||
w_const.ISDSC_INVALID_PATH_ID:
|
||||
_('Path Id specified in the call to '
|
||||
'set Load Balance Policy is not valid'),
|
||||
w_const.ISDSC_MULTIPLE_PRIMARY_PATHS_SPECIFIED:
|
||||
_('Multiple primary paths '
|
||||
'specified when only one '
|
||||
'primary path is expected.'),
|
||||
w_const.ISDSC_NO_PRIMARY_PATH_SPECIFIED:
|
||||
_('No primary path specified when '
|
||||
'at least one is expected.'),
|
||||
w_const.ISDSC_DEVICE_ALREADY_PERSISTENTLY_BOUND:
|
||||
_('Device is already a '
|
||||
'persistently bound device.'),
|
||||
w_const.ISDSC_DEVICE_NOT_FOUND:
|
||||
_('Device was not found.'),
|
||||
w_const.ISDSC_DEVICE_NOT_ISCSI_OR_PERSISTENT:
|
||||
_('The device specified does not '
|
||||
'originate from an iSCSI disk '
|
||||
'or a persistent iSCSI login.'),
|
||||
w_const.ISDSC_DNS_NAME_UNRESOLVED:
|
||||
_('The DNS name specified was not resolved.'),
|
||||
w_const.ISDSC_NO_CONNECTION_AVAILABLE:
|
||||
_('There is no connection available '
|
||||
'in the iSCSI session to '
|
||||
'process the request.'),
|
||||
w_const.ISDSC_LB_POLICY_NOT_SUPPORTED:
|
||||
_('The given Load Balance '
|
||||
'policy is not supported.'),
|
||||
w_const.ISDSC_REMOVE_CONNECTION_IN_PROGRESS:
|
||||
_('A remove connection request '
|
||||
'is already in progress for '
|
||||
'this session.'),
|
||||
w_const.ISDSC_INVALID_CONNECTION_ID:
|
||||
_('Given connection was not '
|
||||
'found in the session.'),
|
||||
w_const.ISDSC_CANNOT_REMOVE_LEADING_CONNECTION:
|
||||
_('The leading connection in '
|
||||
'the session cannot be '
|
||||
'removed.'),
|
||||
w_const.ISDSC_RESTRICTED_BY_GROUP_POLICY:
|
||||
_('The operation cannot be performed '
|
||||
'since it does not conform with '
|
||||
'the group policy assigned to '
|
||||
'this computer.'),
|
||||
w_const.ISDSC_ISNS_FIREWALL_BLOCKED:
|
||||
_('The operation cannot be performed since '
|
||||
'the Internet Storage Name Server '
|
||||
'(iSNS) firewall exception has '
|
||||
'not been enabled.'),
|
||||
w_const.ISDSC_FAILURE_TO_PERSIST_LB_POLICY:
|
||||
_('Failed to persist load '
|
||||
'balancing policy parameters.'),
|
||||
w_const.ISDSC_INVALID_HOST:
|
||||
_('The name could not be resolved to an IP Address.'),
|
||||
}
|
49
os_win/utils/winapi/libs/__init__.py
Normal file
49
os_win/utils/winapi/libs/__init__.py
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 importlib
|
||||
|
||||
from os_win._i18n import _
|
||||
from os_win import exceptions
|
||||
|
||||
|
||||
ADVAPI32 = 'advapi32'
|
||||
CLUSAPI = 'clusapi'
|
||||
HBAAPI = 'hbaapi'
|
||||
ISCSIDSC = 'iscsidsc'
|
||||
KERNEL32 = 'kernel32'
|
||||
VIRTDISK = 'virtdisk'
|
||||
|
||||
libs = [ADVAPI32, CLUSAPI, HBAAPI, ISCSIDSC, KERNEL32, VIRTDISK]
|
||||
|
||||
|
||||
def _get_shared_lib_module(lib_name):
|
||||
if lib_name not in libs:
|
||||
err_msg = _("Unsupported library: %s.")
|
||||
raise exceptions.OSWinException(err_msg % lib_name)
|
||||
|
||||
module = importlib.import_module('os_win.utils.winapi.libs.%s' % lib_name)
|
||||
return module
|
||||
|
||||
|
||||
def register():
|
||||
for lib_name in libs:
|
||||
module = _get_shared_lib_module(lib_name)
|
||||
module.register()
|
||||
|
||||
|
||||
def get_shared_lib_handle(lib_name):
|
||||
module = _get_shared_lib_module(lib_name)
|
||||
return module.lib_handle
|
78
os_win/utils/winapi/libs/advapi32.py
Normal file
78
os_win/utils/winapi/libs/advapi32.py
Normal file
@ -0,0 +1,78 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
lib_handle = None
|
||||
|
||||
|
||||
class TRUSTEE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('pMultipleTrustee', wintypes.PVOID),
|
||||
('MultipleTrusteeOperation', wintypes.INT),
|
||||
('TrusteeForm', wintypes.INT),
|
||||
('TrusteeType', wintypes.INT),
|
||||
('pstrName', wintypes.LPWSTR)
|
||||
]
|
||||
|
||||
|
||||
class EXPLICIT_ACCESS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('grfAccessPermissions', wintypes.DWORD),
|
||||
('grfAccessMode', wintypes.INT),
|
||||
('grfInheritance', wintypes.DWORD),
|
||||
('Trustee', TRUSTEE)
|
||||
]
|
||||
|
||||
|
||||
PEXPLICIT_ACCESS = ctypes.POINTER(EXPLICIT_ACCESS)
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.windll.advapi32
|
||||
|
||||
lib_handle.GetNamedSecurityInfoW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.INT,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID
|
||||
]
|
||||
lib_handle.GetNamedSecurityInfoW.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.SetEntriesInAclW.argtypes = [
|
||||
wintypes.ULONG,
|
||||
PEXPLICIT_ACCESS,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID
|
||||
]
|
||||
lib_handle.SetEntriesInAclW.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.SetNamedSecurityInfoW.argtypes = [
|
||||
wintypes.LPWSTR,
|
||||
wintypes.INT,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID,
|
||||
wintypes.PVOID
|
||||
]
|
||||
lib_handle.SetNamedSecurityInfoW.restype = wintypes.DWORD
|
123
os_win/utils/winapi/libs/clusapi.py
Normal file
123
os_win/utils/winapi/libs/clusapi.py
Normal file
@ -0,0 +1,123 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
lib_handle = None
|
||||
|
||||
|
||||
class NOTIFY_FILTER_AND_TYPE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('dwObjectType', wintypes.DWORD),
|
||||
('FilterFlags', wintypes.LONGLONG)
|
||||
]
|
||||
|
||||
|
||||
PNOTIFY_FILTER_AND_TYPE = ctypes.POINTER(NOTIFY_FILTER_AND_TYPE)
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.windll.clusapi
|
||||
|
||||
lib_handle.CancelClusterGroupOperation.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD
|
||||
]
|
||||
lib_handle.CancelClusterGroupOperation.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.CloseCluster.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.CloseCluster.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CloseClusterGroup.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.CloseClusterGroup.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CloseClusterNode.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.CloseClusterNode.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CloseClusterNotifyPort.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.CloseClusterNotifyPort.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.ClusterGroupControl.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD,
|
||||
wintypes.LPVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.LPVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.LPVOID
|
||||
]
|
||||
lib_handle.ClusterGroupControl.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.GetClusterGroupState.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPWSTR,
|
||||
wintypes.PDWORD
|
||||
]
|
||||
lib_handle.GetClusterGroupState.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.CreateClusterNotifyPortV2.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.HANDLE,
|
||||
PNOTIFY_FILTER_AND_TYPE,
|
||||
wintypes.DWORD,
|
||||
wintypes.PDWORD
|
||||
]
|
||||
lib_handle.CreateClusterNotifyPortV2.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.GetClusterNotifyV2.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
ctypes.POINTER(wintypes.PDWORD),
|
||||
PNOTIFY_FILTER_AND_TYPE,
|
||||
wintypes.PBYTE,
|
||||
wintypes.LPDWORD,
|
||||
wintypes.LPWSTR,
|
||||
wintypes.LPDWORD,
|
||||
wintypes.LPWSTR,
|
||||
wintypes.LPDWORD,
|
||||
wintypes.LPWSTR,
|
||||
wintypes.LPDWORD,
|
||||
wintypes.LPWSTR,
|
||||
wintypes.LPDWORD,
|
||||
wintypes.DWORD
|
||||
]
|
||||
lib_handle.GetClusterNotifyV2.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.MoveClusterGroupEx.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID,
|
||||
wintypes.DWORD
|
||||
]
|
||||
lib_handle.MoveClusterGroupEx.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.OpenCluster.argtypes = [wintypes.LPCWSTR]
|
||||
lib_handle.OpenCluster.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.OpenClusterGroup.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPCWSTR
|
||||
]
|
||||
lib_handle.OpenClusterGroup.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.OpenClusterNode.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPCWSTR
|
||||
]
|
||||
lib_handle.OpenClusterNode.restype = wintypes.HANDLE
|
@ -1,4 +1,4 @@
|
||||
# Copyright 2015 Cloudbase Solutions Srl
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -15,15 +15,25 @@
|
||||
|
||||
import ctypes
|
||||
|
||||
import os_win.conf
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
CONF = os_win.conf.CONF
|
||||
|
||||
lib_handle = None
|
||||
|
||||
HBA_STATUS = ctypes.c_uint32
|
||||
HBA_HANDLE = ctypes.c_uint32
|
||||
HBA_PortType = ctypes.c_uint32
|
||||
HBA_PortSpeed = ctypes.c_uint32
|
||||
HBA_PortState = ctypes.c_uint32
|
||||
HBA_COS = ctypes.c_uint32
|
||||
HBA_WWN = ctypes.c_ubyte * 8
|
||||
HBA_FC4Types = ctypes.c_uint32 * 32
|
||||
HBA_FCPBindingType = ctypes.c_int
|
||||
HBA_FCPBindingType = wintypes.INT
|
||||
|
||||
|
||||
class HBA_WWN(ctypes.Structure):
|
||||
_fields_ = [('wwn', ctypes.c_ubyte * 8)]
|
||||
|
||||
|
||||
class HBA_PortAttributes(ctypes.Structure):
|
||||
@ -34,8 +44,8 @@ class HBA_PortAttributes(ctypes.Structure):
|
||||
('PortState', HBA_PortState),
|
||||
('PortSupportedClassofService', HBA_COS),
|
||||
('PortSupportedFc4Types', HBA_FC4Types),
|
||||
('PortSymbolicName', ctypes.c_char * 256),
|
||||
('OSDeviceName', ctypes.c_char * 256),
|
||||
('PortSymbolicName', wintypes.CHAR * 256),
|
||||
('OSDeviceName', wintypes.CHAR * 256),
|
||||
('PortSupportedSpeed', HBA_PortSpeed),
|
||||
('PortSpeed', HBA_PortSpeed),
|
||||
('PortMaxFrameSize', ctypes.c_uint32),
|
||||
@ -51,7 +61,7 @@ class HBA_FCPId(ctypes.Structure):
|
||||
|
||||
|
||||
class HBA_ScsiId(ctypes.Structure):
|
||||
_fields_ = [('OSDeviceName', ctypes.c_char * 256),
|
||||
_fields_ = [('OSDeviceName', wintypes.CHAR * 256),
|
||||
('ScsiBusNumber', ctypes.c_uint32),
|
||||
('ScsiTargetNumber', ctypes.c_uint32),
|
||||
('ScsiOSLun', ctypes.c_uint32)]
|
||||
@ -75,16 +85,62 @@ def get_target_mapping_struct(entry_count=0):
|
||||
|
||||
|
||||
class HBA_AdapterAttributes(ctypes.Structure):
|
||||
_fields_ = [('Manufacturer', ctypes.c_char * 64),
|
||||
('SerialNumber', ctypes.c_char * 64),
|
||||
('Model', ctypes.c_char * 256),
|
||||
('ModelDescription', ctypes.c_char * 256),
|
||||
_fields_ = [('Manufacturer', wintypes.CHAR * 64),
|
||||
('SerialNumber', wintypes.CHAR * 64),
|
||||
('Model', wintypes.CHAR * 256),
|
||||
('ModelDescription', wintypes.CHAR * 256),
|
||||
('NodeWWN', HBA_WWN),
|
||||
('NodeSymbolicName', ctypes.c_char * 256),
|
||||
('HardwareVersion', ctypes.c_char * 256),
|
||||
('DriverVersion', ctypes.c_char * 256),
|
||||
('OptionROMVersion', ctypes.c_char * 256),
|
||||
('FirmwareVersion', ctypes.c_char * 256),
|
||||
('NodeSymbolicName', wintypes.CHAR * 256),
|
||||
('HardwareVersion', wintypes.CHAR * 256),
|
||||
('DriverVersion', wintypes.CHAR * 256),
|
||||
('OptionROMVersion', wintypes.CHAR * 256),
|
||||
('FirmwareVersion', wintypes.CHAR * 256),
|
||||
('VendorSpecificID', ctypes.c_uint32),
|
||||
('NumberOfPorts', ctypes.c_uint32),
|
||||
('DriverName', ctypes.c_char * 256)]
|
||||
('DriverName', wintypes.CHAR * 256)]
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.cdll.LoadLibrary(CONF.os_win.hbaapi_lib_path)
|
||||
|
||||
lib_handle.HBA_CloseAdapter.argtypes = [HBA_HANDLE]
|
||||
lib_handle.HBA_CloseAdapter.restype = None
|
||||
|
||||
lib_handle.HBA_GetAdapterAttributes.argtypes = [
|
||||
HBA_HANDLE,
|
||||
ctypes.POINTER(HBA_AdapterAttributes)]
|
||||
lib_handle.HBA_GetAdapterAttributes.restype = HBA_STATUS
|
||||
|
||||
lib_handle.HBA_GetAdapterName.argtypes = [
|
||||
ctypes.c_uint32,
|
||||
wintypes.PCHAR
|
||||
]
|
||||
lib_handle.HBA_GetAdapterName.restype = HBA_STATUS
|
||||
|
||||
lib_handle.HBA_GetAdapterPortAttributes.argtypes = [
|
||||
HBA_HANDLE,
|
||||
ctypes.c_uint32,
|
||||
ctypes.POINTER(HBA_PortAttributes)
|
||||
]
|
||||
lib_handle.HBA_GetAdapterPortAttributes.restype = HBA_STATUS
|
||||
|
||||
lib_handle.HBA_GetFcpTargetMapping.argtypes = [
|
||||
HBA_HANDLE,
|
||||
wintypes.PVOID
|
||||
]
|
||||
lib_handle.HBA_GetFcpTargetMapping.restype = HBA_STATUS
|
||||
|
||||
lib_handle.HBA_GetNumberOfAdapters.argtypes = []
|
||||
lib_handle.HBA_GetNumberOfAdapters.restype = ctypes.c_uint32
|
||||
|
||||
lib_handle.HBA_OpenAdapter.argtypes = [wintypes.PCHAR]
|
||||
lib_handle.HBA_OpenAdapter.restype = HBA_HANDLE
|
||||
|
||||
lib_handle.HBA_OpenAdapterByWWN.argtypes = [
|
||||
ctypes.POINTER(HBA_HANDLE),
|
||||
HBA_WWN]
|
||||
lib_handle.HBA_OpenAdapterByWWN.restype = HBA_STATUS
|
||||
|
||||
lib_handle.HBA_RefreshAdapterConfiguration.argtypes = []
|
||||
lib_handle.HBA_RefreshAdapterConfiguration.restype = None
|
267
os_win/utils/winapi/libs/iscsidsc.py
Normal file
267
os_win/utils/winapi/libs/iscsidsc.py
Normal file
@ -0,0 +1,267 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
|
||||
from os_win.utils.winapi import constants as w_const
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
lib_handle = None
|
||||
|
||||
ISCSI_SECURITY_FLAGS = ctypes.c_uint64
|
||||
ISCSI_LOGIN_FLAGS = ctypes.c_uint32
|
||||
ISCSI_LOGIN_OPTIONS_INFO_SPECIFIED = ctypes.c_uint32
|
||||
ISCSI_AUTH_TYPES = wintypes.UINT
|
||||
ISCSI_DIGEST_TYPES = wintypes.UINT
|
||||
DEVICE_TYPE = wintypes.ULONG
|
||||
|
||||
|
||||
class ISCSI_TARGET_PORTAL(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('SymbolicName', wintypes.WCHAR * w_const.MAX_ISCSI_PORTAL_NAME_LEN),
|
||||
('Address', wintypes.WCHAR * w_const.MAX_ISCSI_PORTAL_ADDRESS_LEN),
|
||||
('Socket', wintypes.USHORT)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_TARGET_PORTAL = ctypes.POINTER(ISCSI_TARGET_PORTAL)
|
||||
|
||||
|
||||
class ISCSI_LOGIN_OPTIONS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.ULONG),
|
||||
('InformationSpecified', ISCSI_LOGIN_OPTIONS_INFO_SPECIFIED),
|
||||
('LoginFlags', ISCSI_LOGIN_FLAGS),
|
||||
('AuthType', ISCSI_AUTH_TYPES),
|
||||
('HeaderDigest', ISCSI_DIGEST_TYPES),
|
||||
('DataDigest', ISCSI_DIGEST_TYPES),
|
||||
('MaximumConnections', wintypes.ULONG),
|
||||
('DefaultTime2Wait', wintypes.ULONG),
|
||||
('DefaultTime2Retain', wintypes.ULONG),
|
||||
('UsernameLength', wintypes.ULONG),
|
||||
('PasswordLength', wintypes.ULONG),
|
||||
('Username', wintypes.PSTR),
|
||||
('Password', wintypes.PSTR)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_LOGIN_OPTIONS = ctypes.POINTER(ISCSI_LOGIN_OPTIONS)
|
||||
|
||||
|
||||
class SCSI_LUN_LIST(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('OSLUN', wintypes.ULONG),
|
||||
('TargetLUN', wintypes.ULONGLONG)
|
||||
]
|
||||
|
||||
|
||||
PSCSI_LUN_LIST = ctypes.POINTER(SCSI_LUN_LIST)
|
||||
|
||||
|
||||
class ISCSI_UNIQUE_SESSION_ID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('AdapterUnique', wintypes.ULONGLONG),
|
||||
('AdapterSpecific', wintypes.ULONGLONG)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_UNIQUE_SESSION_ID = ctypes.POINTER(ISCSI_UNIQUE_SESSION_ID)
|
||||
|
||||
|
||||
class ISCSI_UNIQUE_CONNECTION_ID(ISCSI_UNIQUE_SESSION_ID):
|
||||
pass
|
||||
|
||||
|
||||
PISCSI_UNIQUE_CONNECTION_ID = ctypes.POINTER(ISCSI_UNIQUE_CONNECTION_ID)
|
||||
|
||||
|
||||
class ISCSI_TARGET_MAPPING(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('InitiatorName', wintypes.WCHAR * w_const.MAX_ISCSI_HBANAME_LEN),
|
||||
('TargetName', wintypes.WCHAR * (w_const.MAX_ISCSI_NAME_LEN + 1)),
|
||||
('OSDeviceName', wintypes.WCHAR * w_const.MAX_PATH),
|
||||
('SessionId', ISCSI_UNIQUE_SESSION_ID),
|
||||
('OSBusNumber', wintypes.ULONG),
|
||||
('OSTargetNumber', wintypes.ULONG),
|
||||
('LUNCount', wintypes.ULONG),
|
||||
('LUNList', PSCSI_LUN_LIST)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_TARGET_MAPPING = ctypes.POINTER(ISCSI_TARGET_MAPPING)
|
||||
|
||||
|
||||
class PERSISTENT_ISCSI_LOGIN_INFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('TargetName', wintypes.WCHAR * (w_const.MAX_ISCSI_NAME_LEN + 1)),
|
||||
('IsInformationalSession', wintypes.BOOLEAN),
|
||||
('InitiatorInstance', wintypes.WCHAR * w_const.MAX_ISCSI_HBANAME_LEN),
|
||||
('InitiatorPortNumber', wintypes.ULONG),
|
||||
('TargetPortal', ISCSI_TARGET_PORTAL),
|
||||
('SecurityFlags', ISCSI_SECURITY_FLAGS),
|
||||
('Mappings', PISCSI_TARGET_MAPPING),
|
||||
('LoginOptions', ISCSI_LOGIN_OPTIONS)
|
||||
]
|
||||
|
||||
|
||||
PPERSISTENT_ISCSI_LOGIN_INFO = ctypes.POINTER(PERSISTENT_ISCSI_LOGIN_INFO)
|
||||
|
||||
|
||||
class ISCSI_CONNECTION_INFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('ConnectionId', ISCSI_UNIQUE_CONNECTION_ID),
|
||||
('InitiatorAddress', wintypes.PWSTR),
|
||||
('TargetAddress', wintypes.PWSTR),
|
||||
('InitiatorSocket', wintypes.USHORT),
|
||||
('TargetSocket', wintypes.USHORT),
|
||||
('CID', ctypes.c_ubyte * 2)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_CONNECTION_INFO = ctypes.POINTER(ISCSI_CONNECTION_INFO)
|
||||
|
||||
|
||||
class ISCSI_SESSION_INFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('SessionId', ISCSI_UNIQUE_SESSION_ID),
|
||||
('InitiatorName', wintypes.PWSTR),
|
||||
('TargetName', wintypes.PWSTR),
|
||||
('TargetNodeName', wintypes.PWSTR),
|
||||
('ISID', ctypes.c_ubyte * 6),
|
||||
('TSID', ctypes.c_ubyte * 2),
|
||||
('ConnectionCount', wintypes.ULONG),
|
||||
('Connections', PISCSI_CONNECTION_INFO)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_SESSION_INFO = ctypes.POINTER(ISCSI_SESSION_INFO)
|
||||
|
||||
|
||||
class SCSI_ADDRESS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Length', wintypes.ULONG),
|
||||
('PortNumber', ctypes.c_ubyte),
|
||||
('PathId', ctypes.c_ubyte),
|
||||
('TargetId', ctypes.c_ubyte),
|
||||
('Lun', ctypes.c_ubyte)
|
||||
]
|
||||
|
||||
|
||||
class STORAGE_DEVICE_NUMBER(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('DeviceType', DEVICE_TYPE),
|
||||
('DeviceNumber', wintypes.DWORD),
|
||||
('PartitionNumber', wintypes.DWORD)
|
||||
]
|
||||
|
||||
|
||||
class ISCSI_DEVICE_ON_SESSION(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('InitiatorName', wintypes.WCHAR * w_const.MAX_ISCSI_HBANAME_LEN),
|
||||
('TargetName', wintypes.WCHAR * (w_const.MAX_ISCSI_NAME_LEN + 1)),
|
||||
('ScsiAddress', SCSI_ADDRESS),
|
||||
('DeviceInterfaceType', wintypes.GUID),
|
||||
('DeviceInterfaceName', wintypes.WCHAR * w_const.MAX_PATH),
|
||||
('LegacyName', wintypes.WCHAR * w_const.MAX_PATH),
|
||||
('StorageDeviceNumber', STORAGE_DEVICE_NUMBER),
|
||||
('DeviceInstance', wintypes.ULONG)
|
||||
]
|
||||
|
||||
|
||||
PISCSI_DEVICE_ON_SESSION = ctypes.POINTER(ISCSI_DEVICE_ON_SESSION)
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.windll.iscsidsc
|
||||
|
||||
lib_handle.AddIScsiStaticTargetW.argtypes = [
|
||||
wintypes.PWSTR,
|
||||
wintypes.PWSTR,
|
||||
wintypes.ULONG,
|
||||
wintypes.BOOLEAN,
|
||||
PISCSI_TARGET_MAPPING,
|
||||
PISCSI_LOGIN_OPTIONS,
|
||||
wintypes.LPVOID # unused
|
||||
]
|
||||
lib_handle.AddIScsiStaticTargetW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.GetDevicesForIScsiSessionW.argtypes = [
|
||||
PISCSI_UNIQUE_SESSION_ID,
|
||||
wintypes.PULONG,
|
||||
PISCSI_DEVICE_ON_SESSION
|
||||
]
|
||||
lib_handle.GetDevicesForIScsiSessionW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.GetIScsiInitiatorNodeNameW.argtypes = [wintypes.PWCHAR]
|
||||
lib_handle.GetIScsiInitiatorNodeNameW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.GetIScsiSessionListW.argtypes = [
|
||||
wintypes.PULONG,
|
||||
wintypes.PULONG,
|
||||
PISCSI_SESSION_INFO
|
||||
]
|
||||
lib_handle.GetIScsiSessionListW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.LoginIScsiTargetW.argtypes = [
|
||||
wintypes.PWSTR,
|
||||
wintypes.BOOLEAN,
|
||||
wintypes.PWSTR,
|
||||
wintypes.ULONG,
|
||||
PISCSI_TARGET_PORTAL,
|
||||
ISCSI_SECURITY_FLAGS,
|
||||
PISCSI_TARGET_MAPPING,
|
||||
PISCSI_LOGIN_OPTIONS,
|
||||
wintypes.ULONG,
|
||||
wintypes.PCHAR,
|
||||
wintypes.BOOLEAN,
|
||||
PISCSI_UNIQUE_SESSION_ID,
|
||||
PISCSI_UNIQUE_CONNECTION_ID
|
||||
]
|
||||
lib_handle.LoginIScsiTargetW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.LogoutIScsiTarget.argtypes = [PISCSI_UNIQUE_SESSION_ID]
|
||||
lib_handle.LogoutIScsiTarget.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.RemoveIScsiPersistentTargetW.argtypes = [
|
||||
wintypes.PWSTR,
|
||||
wintypes.ULONG,
|
||||
wintypes.PWSTR,
|
||||
PISCSI_TARGET_PORTAL
|
||||
]
|
||||
lib_handle.RemoveIScsiPersistentTargetW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.RemoveIScsiStaticTargetW.argtypes = [wintypes.PWSTR]
|
||||
lib_handle.RemoveIScsiStaticTargetW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.ReportIScsiInitiatorListW.argtypes = [
|
||||
wintypes.PULONG,
|
||||
wintypes.PWCHAR
|
||||
]
|
||||
lib_handle.ReportIScsiInitiatorListW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.ReportIScsiPersistentLoginsW.argtypes = [
|
||||
wintypes.PULONG,
|
||||
PPERSISTENT_ISCSI_LOGIN_INFO,
|
||||
wintypes.PULONG
|
||||
]
|
||||
lib_handle.ReportIScsiPersistentLoginsW.restype = wintypes.ULONG
|
||||
|
||||
lib_handle.ReportIScsiTargetsW.argtypes = [
|
||||
wintypes.BOOLEAN,
|
||||
wintypes.PULONG,
|
||||
wintypes.PWCHAR
|
||||
]
|
||||
lib_handle.ReportIScsiTargetsW.restype = wintypes.ULONG
|
141
os_win/utils/winapi/libs/kernel32.py
Normal file
141
os_win/utils/winapi/libs/kernel32.py
Normal file
@ -0,0 +1,141 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
lib_handle = None
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.windll.kernel32
|
||||
|
||||
lib_handle.CancelIoEx.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPOVERLAPPED
|
||||
]
|
||||
lib_handle.CancelIoEx.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CloseHandle.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.CloseHandle.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CopyFileW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.BOOL
|
||||
]
|
||||
lib_handle.CopyFileW.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.CreateEventW.argtypes = [
|
||||
wintypes.PVOID, # unused
|
||||
wintypes.BOOL,
|
||||
wintypes.BOOL,
|
||||
wintypes.LPCWSTR
|
||||
]
|
||||
lib_handle.CreateEventW.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.CreateFileW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.DWORD,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID, # unused
|
||||
wintypes.DWORD,
|
||||
wintypes.DWORD,
|
||||
wintypes.HANDLE
|
||||
]
|
||||
lib_handle.CreateFileW.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.CreateSymbolicLinkW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.DWORD
|
||||
]
|
||||
lib_handle.CreateSymbolicLinkW.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.FormatMessageA.argtypes = [
|
||||
wintypes.DWORD,
|
||||
wintypes.LPCVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.PVOID
|
||||
]
|
||||
lib_handle.FormatMessageA.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.GetDiskFreeSpaceExW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.PULARGE_INTEGER,
|
||||
wintypes.PULARGE_INTEGER,
|
||||
wintypes.PULARGE_INTEGER
|
||||
]
|
||||
lib_handle.GetDiskFreeSpaceExW.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.GetFileAttributesW.argtypes = [wintypes.LPCWSTR]
|
||||
lib_handle.GetFileAttributesW.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.GetLastError.argtypes = []
|
||||
lib_handle.GetLastError.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.GetTickCount64.argtypes = []
|
||||
lib_handle.GetTickCount64.restype = wintypes.ULONGLONG
|
||||
|
||||
lib_handle.IsProcessorFeaturePresent.argtypes = [wintypes.DWORD]
|
||||
lib_handle.IsProcessorFeaturePresent.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.LocalFree.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.LocalFree.restype = wintypes.HANDLE
|
||||
|
||||
lib_handle.ReadFileEx.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.LPOVERLAPPED,
|
||||
wintypes.LPOVERLAPPED_COMPLETION_ROUTINE
|
||||
]
|
||||
lib_handle.ReadFileEx.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.ResetEvent.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.ResetEvent.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.SetEvent.argtypes = [wintypes.HANDLE]
|
||||
lib_handle.SetEvent.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.SetLastError.argtypes = [wintypes.DWORD]
|
||||
lib_handle.SetLastError.restype = None
|
||||
|
||||
lib_handle.WaitForSingleObjectEx.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.DWORD,
|
||||
wintypes.BOOL
|
||||
]
|
||||
lib_handle.WaitForSingleObjectEx.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.WaitNamedPipeW.argtypes = [
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.DWORD
|
||||
]
|
||||
lib_handle.WaitNamedPipeW.restype = wintypes.BOOL
|
||||
|
||||
lib_handle.WriteFileEx.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.LPCVOID,
|
||||
wintypes.DWORD,
|
||||
wintypes.LPOVERLAPPED,
|
||||
wintypes.LPOVERLAPPED_COMPLETION_ROUTINE
|
||||
]
|
||||
lib_handle.WriteFileEx.restype = wintypes.BOOL
|
248
os_win/utils/winapi/libs/virtdisk.py
Normal file
248
os_win/utils/winapi/libs/virtdisk.py
Normal file
@ -0,0 +1,248 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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 ctypes
|
||||
|
||||
from os_win.utils.winapi import wintypes
|
||||
|
||||
lib_handle = None
|
||||
|
||||
|
||||
class VIRTUAL_STORAGE_TYPE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('DeviceId', wintypes.DWORD),
|
||||
('VendorId', wintypes.GUID)
|
||||
]
|
||||
|
||||
|
||||
PVIRTUAL_STORAGE_TYPE = ctypes.POINTER(VIRTUAL_STORAGE_TYPE)
|
||||
|
||||
|
||||
class _RESIZE_VIRTUAL_DISK_PARAMETERS_V1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('NewSize', wintypes.ULONGLONG)
|
||||
]
|
||||
|
||||
|
||||
# Only V1 is used, we avoid defining an union.
|
||||
class RESIZE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('Version1', _RESIZE_VIRTUAL_DISK_PARAMETERS_V1)
|
||||
]
|
||||
|
||||
|
||||
PRESIZE_VIRTUAL_DISK_PARAMETERS = ctypes.POINTER(
|
||||
RESIZE_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
|
||||
class _OPEN_VIRTUAL_DISK_PARAMETERS_V1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('RWDepth', wintypes.ULONG),
|
||||
]
|
||||
|
||||
|
||||
class _OPEN_VIRTUAL_DISK_PARAMETERS_V2(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('GetInfoOnly', wintypes.BOOL),
|
||||
('ReadOnly', wintypes.BOOL),
|
||||
('ResiliencyGuid', wintypes.GUID)
|
||||
]
|
||||
|
||||
|
||||
class _OPEN_VIRTUAL_DISK_PARAMETERS_U(ctypes.Union):
|
||||
_fields_ = [
|
||||
('Version1', _OPEN_VIRTUAL_DISK_PARAMETERS_V1),
|
||||
('Version2', _OPEN_VIRTUAL_DISK_PARAMETERS_V2)
|
||||
]
|
||||
|
||||
|
||||
class OPEN_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_anonymous_ = ['_parameters']
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('_parameters', _OPEN_VIRTUAL_DISK_PARAMETERS_U)
|
||||
]
|
||||
|
||||
|
||||
POPEN_VIRTUAL_DISK_PARAMETERS = ctypes.POINTER(
|
||||
OPEN_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
|
||||
class _MERGE_VIRTUAL_DISK_PARAMETERS_V1(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('MergeDepth', wintypes.ULONG)
|
||||
]
|
||||
|
||||
|
||||
# Only V1 is used, we avoid defining an union.
|
||||
class MERGE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('Version1', _MERGE_VIRTUAL_DISK_PARAMETERS_V1)
|
||||
]
|
||||
|
||||
|
||||
PMERGE_VIRTUAL_DISK_PARAMETERS = ctypes.POINTER(
|
||||
MERGE_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
|
||||
class _CREATE_VIRTUAL_DISK_PARAMETERS_V2(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('UniqueId', wintypes.GUID),
|
||||
('MaximumSize', wintypes.ULONGLONG),
|
||||
('BlockSizeInBytes', wintypes.ULONG),
|
||||
('SectorSizeInBytes', wintypes.ULONG),
|
||||
('PhysicalSectorSizeInBytes', wintypes.ULONG),
|
||||
('ParentPath', wintypes.LPCWSTR),
|
||||
('SourcePath', wintypes.LPCWSTR),
|
||||
('OpenFlags', wintypes.DWORD),
|
||||
('ParentVirtualStorageType', VIRTUAL_STORAGE_TYPE),
|
||||
('SourceVirtualStorageType', VIRTUAL_STORAGE_TYPE),
|
||||
('ResiliencyGuid', wintypes.GUID)
|
||||
]
|
||||
|
||||
|
||||
# Only V2 is used, we avoid defining an union.
|
||||
class CREATE_VIRTUAL_DISK_PARAMETERS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('Version2', _CREATE_VIRTUAL_DISK_PARAMETERS_V2)
|
||||
]
|
||||
|
||||
|
||||
PCREATE_VIRTUAL_DISK_PARAMETERS = ctypes.POINTER(
|
||||
CREATE_VIRTUAL_DISK_PARAMETERS)
|
||||
|
||||
|
||||
class _VHD_INFO_SIZE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("VirtualSize", wintypes.ULARGE_INTEGER),
|
||||
("PhysicalSize", wintypes.ULARGE_INTEGER),
|
||||
("BlockSize", wintypes.ULONG),
|
||||
("SectorSize", wintypes.ULONG)
|
||||
]
|
||||
|
||||
|
||||
class _VHD_INFO_PARENT_LOCATION(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('ParentResolved', wintypes.BOOL),
|
||||
('ParentPath', wintypes.WCHAR * 512)
|
||||
]
|
||||
|
||||
|
||||
class _VHD_INFO_PHYSICAL_DISK(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("LogicalSectorSize", wintypes.ULONG),
|
||||
("PhysicalSectorSize", wintypes.ULONG),
|
||||
("IsRemote", wintypes.BOOL)
|
||||
]
|
||||
|
||||
|
||||
class _VHD_INFO(ctypes.Union):
|
||||
_fields_ = [
|
||||
("Size", _VHD_INFO_SIZE),
|
||||
("Identifier", wintypes.GUID),
|
||||
("ParentLocation", _VHD_INFO_PARENT_LOCATION),
|
||||
("ParentIdentifier", wintypes.GUID),
|
||||
("ParentTimestamp", wintypes.ULONG),
|
||||
("VirtualStorageType", VIRTUAL_STORAGE_TYPE),
|
||||
("ProviderSubtype", wintypes.ULONG),
|
||||
("Is4kAligned", wintypes.BOOL),
|
||||
("PhysicalDisk", _VHD_INFO_PHYSICAL_DISK),
|
||||
("VhdPhysicalSectorSize", wintypes.ULONG),
|
||||
("SmallestSafeVirtualSize", wintypes.ULARGE_INTEGER),
|
||||
("FragmentationPercentage", wintypes.ULONG)
|
||||
]
|
||||
|
||||
|
||||
class GET_VIRTUAL_DISK_INFO(ctypes.Structure):
|
||||
_anonymous_ = ['_vhdinfo']
|
||||
_fields_ = [
|
||||
("Version", wintypes.UINT),
|
||||
("_vhdinfo", _VHD_INFO)
|
||||
]
|
||||
|
||||
|
||||
PGET_VIRTUAL_DISK_INFO = ctypes.POINTER(GET_VIRTUAL_DISK_INFO)
|
||||
|
||||
|
||||
# Only this version is used, we avoid defining an union.
|
||||
class SET_VIRTUAL_DISK_INFO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Version', wintypes.DWORD),
|
||||
('ParentFilePath', wintypes.LPCWSTR)
|
||||
]
|
||||
|
||||
|
||||
PSET_VIRTUAL_DISK_INFO = ctypes.POINTER(SET_VIRTUAL_DISK_INFO)
|
||||
|
||||
|
||||
def register():
|
||||
global lib_handle
|
||||
lib_handle = ctypes.windll.virtdisk
|
||||
|
||||
lib_handle.CreateVirtualDisk.argtypes = [
|
||||
PVIRTUAL_STORAGE_TYPE,
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.INT,
|
||||
wintypes.PVOID,
|
||||
wintypes.INT,
|
||||
wintypes.ULONG,
|
||||
PCREATE_VIRTUAL_DISK_PARAMETERS,
|
||||
wintypes.LPOVERLAPPED,
|
||||
wintypes.PHANDLE
|
||||
]
|
||||
lib_handle.CreateVirtualDisk.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.GetVirtualDiskInformation.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.PULONG,
|
||||
PGET_VIRTUAL_DISK_INFO,
|
||||
wintypes.PULONG
|
||||
]
|
||||
lib_handle.GetVirtualDiskInformation.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.MergeVirtualDisk.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.INT,
|
||||
PMERGE_VIRTUAL_DISK_PARAMETERS,
|
||||
wintypes.LPOVERLAPPED
|
||||
]
|
||||
lib_handle.MergeVirtualDisk.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.OpenVirtualDisk.argtypes = [
|
||||
PVIRTUAL_STORAGE_TYPE,
|
||||
wintypes.LPCWSTR,
|
||||
wintypes.INT,
|
||||
wintypes.INT,
|
||||
POPEN_VIRTUAL_DISK_PARAMETERS,
|
||||
wintypes.PHANDLE
|
||||
]
|
||||
lib_handle.OpenVirtualDisk.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.ResizeVirtualDisk.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
wintypes.INT,
|
||||
PRESIZE_VIRTUAL_DISK_PARAMETERS,
|
||||
wintypes.LPOVERLAPPED
|
||||
]
|
||||
lib_handle.ResizeVirtualDisk.restype = wintypes.DWORD
|
||||
|
||||
lib_handle.SetVirtualDiskInformation.argtypes = [
|
||||
wintypes.HANDLE,
|
||||
PSET_VIRTUAL_DISK_INFO
|
||||
]
|
||||
lib_handle.SetVirtualDiskInformation.restype = wintypes.DWORD
|
103
os_win/utils/winapi/wintypes.py
Normal file
103
os_win/utils/winapi/wintypes.py
Normal file
@ -0,0 +1,103 @@
|
||||
# Copyright 2017 Cloudbase Solutions Srl
|
||||
# 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.
|
||||
|
||||
# This module contains some common types extracted from ctypes.wintypes
|
||||
# plus some extra ones that we are using throughout os-win.
|
||||
#
|
||||
# In order to avoid portability issues more easily, we avoid using
|
||||
# ctypes.wintypes directly.
|
||||
|
||||
import ctypes
|
||||
import sys
|
||||
|
||||
BYTE = ctypes.c_byte
|
||||
WORD = ctypes.c_ushort
|
||||
DWORD = ctypes.c_ulong
|
||||
|
||||
CHAR = ctypes.c_char
|
||||
WCHAR = ctypes.c_wchar
|
||||
UINT = ctypes.c_uint
|
||||
INT = ctypes.c_int
|
||||
|
||||
DOUBLE = ctypes.c_double
|
||||
FLOAT = ctypes.c_float
|
||||
|
||||
BOOLEAN = BYTE
|
||||
BOOL = ctypes.c_long
|
||||
|
||||
ULONG = ctypes.c_ulong
|
||||
LONG = ctypes.c_long
|
||||
|
||||
USHORT = ctypes.c_ushort
|
||||
SHORT = ctypes.c_short
|
||||
|
||||
LONGLONG = _LARGE_INTEGER = LARGE_INTEGER = ctypes.c_longlong
|
||||
ULONGLONG = _ULARGE_INTEGER = ULARGE_INTEGER = ctypes.c_ulonglong
|
||||
|
||||
LPCOLESTR = LPOLESTR = OLESTR = ctypes.c_wchar_p
|
||||
LPCWSTR = LPWSTR = PWSTR = ctypes.c_wchar_p
|
||||
LPCSTR = LPSTR = PSTR = ctypes.c_char_p
|
||||
LPCVOID = LPVOID = PVOID = ctypes.c_void_p
|
||||
|
||||
HANDLE = ctypes.c_void_p
|
||||
|
||||
LPBOOL = PBOOL = ctypes.POINTER(BOOL)
|
||||
PBOOLEAN = ctypes.POINTER(BOOLEAN)
|
||||
LPBYTE = PBYTE = ctypes.POINTER(BYTE)
|
||||
PCHAR = ctypes.POINTER(CHAR)
|
||||
LPDWORD = PDWORD = ctypes.POINTER(DWORD)
|
||||
PFLOAT = ctypes.POINTER(FLOAT)
|
||||
LPHANDLE = PHANDLE = ctypes.POINTER(HANDLE)
|
||||
LPINT = PINT = ctypes.POINTER(INT)
|
||||
PLARGE_INTEGER = ctypes.POINTER(LARGE_INTEGER)
|
||||
LPLONG = PLONG = ctypes.POINTER(LONG)
|
||||
PLONGLONG = ctypes.POINTER(LONGLONG)
|
||||
PSHORT = ctypes.POINTER(SHORT)
|
||||
LPUINT = PUINT = ctypes.POINTER(UINT)
|
||||
PULARGE_INTEGER = ctypes.POINTER(ULARGE_INTEGER)
|
||||
PULONG = ctypes.POINTER(ULONG)
|
||||
PUSHORT = ctypes.POINTER(USHORT)
|
||||
# Warning: PWCHAR behaves differently than c_wchar_p. Accessing
|
||||
# a PWCHAR structure attribute won't give us back a Python string.
|
||||
PWCHAR = ctypes.POINTER(WCHAR)
|
||||
LPWORD = PWORD = ctypes.POINTER(WORD)
|
||||
|
||||
|
||||
class GUID(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("Data1", ULONG),
|
||||
("Data2", USHORT),
|
||||
("Data3", USHORT),
|
||||
("Data4", BYTE * 8)
|
||||
]
|
||||
|
||||
|
||||
class OVERLAPPED(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('Internal', ULONG),
|
||||
('InternalHigh', ULONG),
|
||||
('Offset', DWORD),
|
||||
('OffsetHigh', DWORD),
|
||||
('hEvent', HANDLE)
|
||||
]
|
||||
|
||||
|
||||
LPOVERLAPPED = ctypes.POINTER(OVERLAPPED)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE = ctypes.WINFUNCTYPE(
|
||||
None, DWORD, DWORD, LPOVERLAPPED)
|
||||
else:
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE = PVOID
|
Loading…
Reference in New Issue
Block a user