diff --git a/dracclient/client.py b/dracclient/client.py
index 74decc3..df18ea1 100644
--- a/dracclient/client.py
+++ b/dracclient/client.py
@@ -468,7 +468,8 @@ class DRACClient(object):
cim_system_creation_class_name='DCIM_ComputerSystem',
cim_system_name='DCIM:ComputerSystem',
reboot=False,
- start_time='TIME_NOW'):
+ start_time='TIME_NOW',
+ realtime=False):
"""Creates a configuration job.
In CIM (Common Information Model), weak association is used to name an
@@ -492,6 +493,8 @@ class DRACClient(object):
means execute immediately or None which means
the job will not execute until
schedule_job_execution is called
+ :param realtime: Indicates if reatime mode should be used.
+ Valid values are True and False.
:returns: id of the created job
:raises: WSManRequestFailure on request failures
:raises: WSManInvalidResponse when receiving invalid response
@@ -508,7 +511,8 @@ class DRACClient(object):
cim_system_creation_class_name=cim_system_creation_class_name,
cim_system_name=cim_system_name,
reboot=reboot,
- start_time=start_time)
+ start_time=start_time,
+ realtime=realtime)
def create_nic_config_job(
self,
@@ -785,7 +789,7 @@ class DRACClient(object):
return self._raid_mgmt.delete_virtual_disk(virtual_disk)
def commit_pending_raid_changes(self, raid_controller, reboot=False,
- start_time='TIME_NOW'):
+ start_time='TIME_NOW', realtime=False):
"""Applies all pending changes on a RAID controller
...by creating a config job.
@@ -798,6 +802,8 @@ class DRACClient(object):
means execute immediately or None which means
the job will not execute until
schedule_job_execution is called
+ :param realtime: Indicates if reatime mode should be used.
+ Valid values are True and False.
:returns: id of the created job
:raises: WSManRequestFailure on request failures
:raises: WSManInvalidResponse when receiving invalid response
@@ -811,7 +817,8 @@ class DRACClient(object):
cim_name='DCIM:RAIDService',
target=raid_controller,
reboot=reboot,
- start_time=start_time)
+ start_time=start_time,
+ realtime=realtime)
def abandon_pending_raid_changes(self, raid_controller):
"""Deletes all pending changes on a RAID controller
@@ -830,6 +837,14 @@ class DRACClient(object):
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target=raid_controller)
+ def is_realtime_supported(self, raid_controller):
+ """Find if controller supports realtime or not
+
+ :param raid_controller: ID of RAID controller
+ :returns: True or False
+ """
+ return self._raid_mgmt.is_realtime_supported(raid_controller)
+
def list_cpus(self):
"""Returns the list of CPUs
diff --git a/dracclient/resources/job.py b/dracclient/resources/job.py
index 26bf85c..0ad67ae 100644
--- a/dracclient/resources/job.py
+++ b/dracclient/resources/job.py
@@ -117,7 +117,8 @@ class JobManagement(object):
cim_system_creation_class_name='DCIM_ComputerSystem',
cim_system_name='DCIM:ComputerSystem',
reboot=False,
- start_time='TIME_NOW'):
+ start_time='TIME_NOW',
+ realtime=False):
"""Creates a config job
In CIM (Common Information Model), weak association is used to name an
@@ -142,6 +143,8 @@ class JobManagement(object):
but will not start execution until
schedule_job_execution is called with the returned
job id.
+ :param realtime: Indicates if reatime mode should be used.
+ Valid values are True and False. Default value is False.
:returns: id of the created job
:raises: WSManRequestFailure on request failures
:raises: WSManInvalidResponse when receiving invalid response
@@ -157,7 +160,10 @@ class JobManagement(object):
properties = {'Target': target}
- if reboot:
+ if realtime:
+ properties['RealTime'] = '1'
+
+ if not realtime and reboot:
properties['RebootJobType'] = '3'
if start_time is not None:
diff --git a/dracclient/resources/raid.py b/dracclient/resources/raid.py
index b5701af..732b6b5 100644
--- a/dracclient/resources/raid.py
+++ b/dracclient/resources/raid.py
@@ -34,6 +34,11 @@ RAID_LEVELS = {
REVERSE_RAID_LEVELS = dict((v, k) for (k, v) in RAID_LEVELS.items())
+RAID_CONTROLLER_IS_REALTIME = {
+ '1': True,
+ '0': False
+}
+
DISK_RAID_STATUS = {
'0': 'unknown',
'1': 'ready',
@@ -110,7 +115,8 @@ class PhysicalDisk(PhysicalDiskTuple):
RAIDController = collections.namedtuple(
'RAIDController', ['id', 'description', 'manufacturer', 'model',
- 'primary_status', 'firmware_version', 'bus'])
+ 'primary_status', 'firmware_version', 'bus',
+ 'supports_realtime'])
VirtualDiskTuple = collections.namedtuple(
'VirtualDisk',
@@ -191,7 +197,10 @@ class RAIDManagement(object):
'PrimaryStatus')],
firmware_version=self._get_raid_controller_attr(
drac_controller, 'ControllerFirmwareVersion'),
- bus=self._get_raid_controller_attr(drac_controller, 'Bus'))
+ bus=self._get_raid_controller_attr(drac_controller, 'Bus'),
+ supports_realtime=RAID_CONTROLLER_IS_REALTIME[
+ self._get_raid_controller_attr(
+ drac_controller, 'RealtimeCapability')])
def _get_raid_controller_attr(self, drac_controller, attr_name):
return utils.get_wsman_resource_attr(
@@ -763,3 +772,18 @@ class RAIDManagement(object):
return {'is_reboot_required': is_reboot_required,
'commit_required_ids': controllers}
+
+ def is_realtime_supported(self, raid_controller_fqdd):
+ """Find if controller supports realtime or not
+
+ :param raid_controller_fqdd: ID of RAID controller
+ :returns: True or False
+ """
+ drac_raid_controllers = self.list_raid_controllers()
+ realtime_controller = [cnt.id for cnt in drac_raid_controllers
+ if cnt.supports_realtime]
+
+ if raid_controller_fqdd in realtime_controller:
+ return True
+
+ return False
diff --git a/dracclient/tests/test_job.py b/dracclient/tests/test_job.py
index 4dcbc56..051b847 100644
--- a/dracclient/tests/test_job.py
+++ b/dracclient/tests/test_job.py
@@ -342,7 +342,34 @@ class ClientJobManagementTestCase(base.BaseTest):
job_id = self.drac_client.create_config_job(
uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target,
- reboot=True)
+ reboot=True, realtime=False)
+
+ mock_invoke.assert_called_once_with(
+ mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
+ expected_selectors, expected_properties,
+ expected_return_value=utils.RET_CREATED)
+ self.assertEqual('JID_442507917525', job_id)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
+ autospec=True)
+ def test_create_config_job_with_realtime(self, mock_invoke):
+ cim_creation_class_name = 'DCIM_BIOSService'
+ cim_name = 'DCIM:BIOSService'
+ target = 'BIOS.Setup.1-1'
+ expected_selectors = {'CreationClassName': cim_creation_class_name,
+ 'Name': cim_name,
+ 'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'DCIM:ComputerSystem'}
+ expected_properties = {'Target': target,
+ 'ScheduledStartTime': 'TIME_NOW',
+ 'RealTime': '1'}
+ mock_invoke.return_value = lxml.etree.fromstring(
+ test_utils.JobInvocations[uris.DCIM_BIOSService][
+ 'CreateTargetedConfigJob']['ok'])
+
+ job_id = self.drac_client.create_config_job(
+ uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target,
+ reboot=False, realtime=True)
mock_invoke.assert_called_once_with(
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
diff --git a/dracclient/tests/test_raid.py b/dracclient/tests/test_raid.py
index 5fbf60c..ced71cc 100644
--- a/dracclient/tests/test_raid.py
+++ b/dracclient/tests/test_raid.py
@@ -124,8 +124,8 @@ class ClientRAIDManagementTestCase(base.BaseTest):
model='PERC H710 Mini',
primary_status='ok',
firmware_version='21.3.0-0009',
- bus='1')
-
+ bus='1',
+ supports_realtime=True)
mock_requests.post(
'https://1.2.3.4:443/wsman',
text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok'])
@@ -597,25 +597,28 @@ class ClientRAIDManagementTestCase(base.BaseTest):
'create_config_job', spec_set=True, autospec=True)
def test_commit_pending_raid_changes(self, mock_requests,
mock_create_config_job):
- self.drac_client.commit_pending_raid_changes('controller')
+ self.drac_client.commit_pending_raid_changes('controller',
+ realtime=False)
mock_create_config_job.assert_called_once_with(
mock.ANY, resource_uri=uris.DCIM_RAIDService,
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller', reboot=False,
- start_time='TIME_NOW')
+ start_time='TIME_NOW', realtime=False)
@mock.patch.object(dracclient.resources.job.JobManagement,
'create_config_job', spec_set=True, autospec=True)
def test_commit_pending_raid_changes_with_reboot(self, mock_requests,
mock_create_config_job):
- self.drac_client.commit_pending_raid_changes('controller', reboot=True)
+ self.drac_client.commit_pending_raid_changes('controller',
+ reboot=True,
+ realtime=False)
mock_create_config_job.assert_called_once_with(
mock.ANY, resource_uri=uris.DCIM_RAIDService,
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller', reboot=True,
- start_time='TIME_NOW')
+ start_time='TIME_NOW', realtime=False)
@mock.patch.object(dracclient.resources.job.JobManagement,
'create_config_job', spec_set=True, autospec=True)
@@ -624,13 +627,14 @@ class ClientRAIDManagementTestCase(base.BaseTest):
mock_create_config_job):
timestamp = '20140924140201'
self.drac_client.commit_pending_raid_changes('controller',
- start_time=timestamp)
+ start_time=timestamp,
+ realtime=False)
mock_create_config_job.assert_called_once_with(
mock.ANY, resource_uri=uris.DCIM_RAIDService,
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller', reboot=False,
- start_time=timestamp)
+ start_time=timestamp, realtime=False)
@mock.patch.object(dracclient.resources.job.JobManagement,
'create_config_job', spec_set=True, autospec=True)
@@ -640,13 +644,31 @@ class ClientRAIDManagementTestCase(base.BaseTest):
timestamp = '20140924140201'
self.drac_client.commit_pending_raid_changes('controller',
reboot=True,
- start_time=timestamp)
+ start_time=timestamp,
+ realtime=False)
mock_create_config_job.assert_called_once_with(
mock.ANY, resource_uri=uris.DCIM_RAIDService,
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller', reboot=True,
- start_time=timestamp)
+ start_time=timestamp, realtime=False)
+
+ @mock.patch.object(dracclient.resources.job.JobManagement,
+ 'create_config_job', spec_set=True, autospec=True)
+ def test_commit_pending_raid_changes_with_realtime(
+ self, mock_requests,
+ mock_create_config_job):
+ timestamp = '20140924140201'
+ self.drac_client.commit_pending_raid_changes('controller',
+ reboot=False,
+ start_time=timestamp,
+ realtime=True)
+
+ mock_create_config_job.assert_called_once_with(
+ mock.ANY, resource_uri=uris.DCIM_RAIDService,
+ cim_creation_class_name='DCIM_RAIDService',
+ cim_name='DCIM:RAIDService', target='controller', reboot=False,
+ start_time=timestamp, realtime=True)
@mock.patch.object(dracclient.resources.job.JobManagement,
'delete_pending_config', spec_set=True, autospec=True)
@@ -659,6 +681,17 @@ class ClientRAIDManagementTestCase(base.BaseTest):
cim_creation_class_name='DCIM_RAIDService',
cim_name='DCIM:RAIDService', target='controller')
+ @mock.patch.object(dracclient.resources.job.JobManagement,
+ 'delete_pending_config', spec_set=True, autospec=True)
+ def test_abandon_pending_raid_changes_realtime(self, mock_requests,
+ mock_delete_pending_config):
+ self.drac_client.abandon_pending_raid_changes('controller')
+
+ mock_delete_pending_config.assert_called_once_with(
+ mock.ANY, resource_uri=uris.DCIM_RAIDService,
+ cim_creation_class_name='DCIM_RAIDService',
+ cim_name='DCIM:RAIDService', target='controller')
+
@mock.patch.object(dracclient.client.WSManClient,
'wait_until_idrac_is_ready', spec_set=True,
autospec=True)
@@ -1153,3 +1186,35 @@ class ClientRAIDManagementTestCase(base.BaseTest):
results = self.drac_client.change_physical_disk_state(mode)
self.assertFalse(results["is_reboot_required"])
self.assertEqual(len(results["commit_required_ids"]), 0)
+
+ @mock.patch.object(dracclient.client.WSManClient,
+ 'wait_until_idrac_is_ready', spec_set=True,
+ autospec=True)
+ def test_is_realtime_supported_with_realtime_controller(
+ self,
+ mock_requests,
+ mock_wait_until_idrac_is_ready):
+ expected_raid_controller = 'RAID.Integrated.1-1'
+
+ mock_requests.post(
+ 'https://1.2.3.4:443/wsman',
+ text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok'])
+
+ self.assertTrue(
+ self.drac_client.is_realtime_supported(expected_raid_controller))
+
+ @mock.patch.object(dracclient.client.WSManClient,
+ 'wait_until_idrac_is_ready', spec_set=True,
+ autospec=True)
+ def test_is_realtime_supported_with_non_realtime_controller(
+ self,
+ mock_requests,
+ mock_wait_until_idrac_is_ready):
+ expected_raid_controller = 'AHCI.Integrated.1-1'
+
+ mock_requests.post(
+ 'https://1.2.3.4:443/wsman',
+ text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok'])
+
+ self.assertFalse(
+ self.drac_client.is_realtime_supported(expected_raid_controller))
diff --git a/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml b/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml
index 2188685..069a0d8 100644
--- a/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml
+++ b/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml
@@ -43,6 +43,7 @@
0
1
PERC H710 Mini
+ 1
1
5B083FE0D2D0F200
1
@@ -82,6 +83,7 @@
0
1
BOSS-S1
+ 0
1
5B083FE0D2D0F201
1