diff --git a/dracclient/client.py b/dracclient/client.py
index f3ff34f..3b42d80 100644
--- a/dracclient/client.py
+++ b/dracclient/client.py
@@ -339,6 +339,27 @@ class DRACClient(object):
"""
return self._job_mgmt.get_job(job_id)
+ def delete_jobs(self, job_ids=['JID_CLEARALL']):
+ """Deletes the given jobs, or all jobs if none specified
+
+ :param job_ids: a list of job ids to delete. Clearing all the
+ jobs may be accomplished using the keyword JID_CLEARALL
+ as the job_id, or JID_CLEARALL_FORCE if a job is in
+ Scheduled state and there is another job for the same
+ component in Completed or Failed state,
+ (http://en.community.dell.com/techcenter/extras/m/white_papers/20444501/download)
+ Deletion of each job id will be attempted, even if there
+ are errors in deleting any in the list.
+ :raises: WSManRequestFailure on request failures
+ :raises: WSManInvalidResponse when receiving invalid response
+ :raises: DRACOperationFailed on error reported back by the iDRAC
+ interface. There will be one message for each job_id
+ that had a failure in the exception.
+ :raises: DRACUnexpectedReturnValue on non-success
+ """
+
+ return self._job_mgmt.delete_jobs(job_ids)
+
def create_config_job(self,
resource_uri,
cim_creation_class_name,
diff --git a/dracclient/resources/job.py b/dracclient/resources/job.py
index 875775e..f161fa8 100644
--- a/dracclient/resources/job.py
+++ b/dracclient/resources/job.py
@@ -249,6 +249,43 @@ class JobManagement(object):
job_id = doc.find(query).text
return job_id
+ def delete_jobs(self, job_ids=['JID_CLEARALL']):
+ """Deletes the given jobs, or all jobs if none specified
+
+ :raises: WSManRequestFailure on request failures
+ :raises: WSManInvalidResponse when receiving invalid response
+ :raises: DRACOperationFailed on error reported back by the iDRAC
+ interface
+ :raises: DRACUnexpectedReturnValue on non-success
+ """
+
+ selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'idrac',
+ 'CreationClassName': 'DCIM_JobService',
+ 'Name': 'JobService'}
+
+ if job_ids is None:
+ return
+
+ messages = []
+
+ for job_id in job_ids:
+ properties = {'JobID': job_id}
+
+ try:
+ self.client.invoke(
+ uris.DCIM_JobService,
+ 'DeleteJobQueue',
+ selectors,
+ properties,
+ expected_return_value=utils.RET_SUCCESS)
+ except exceptions.DRACOperationFailed as dof:
+ for message in dof.args:
+ messages.append(message + " " + job_id)
+
+ if len(messages):
+ raise exceptions.DRACOperationFailed(drac_messages=messages)
+
def delete_pending_config(
self, resource_uri, cim_creation_class_name, cim_name, target,
cim_system_creation_class_name='DCIM_ComputerSystem',
diff --git a/dracclient/tests/test_job.py b/dracclient/tests/test_job.py
index a4456bb..4dcbc56 100644
--- a/dracclient/tests/test_job.py
+++ b/dracclient/tests/test_job.py
@@ -103,6 +103,129 @@ class ClientJobManagementTestCase(base.BaseTest):
filter_query=expected_filter_query)
self.assertIsNone(job)
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_all(self, mock_invoke):
+ expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'idrac',
+ 'CreationClassName': 'DCIM_JobService',
+ 'Name': 'JobService'}
+ expected_properties = {'JobID': 'JID_CLEARALL'}
+
+ self.drac_client.delete_jobs()
+
+ mock_invoke.assert_called_once_with(
+ mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue',
+ expected_selectors, expected_properties,
+ expected_return_value=utils.RET_SUCCESS)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_force(self, mock_invoke):
+ expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'idrac',
+ 'CreationClassName': 'DCIM_JobService',
+ 'Name': 'JobService'}
+ expected_properties = {'JobID': 'JID_CLEARALL_FORCE'}
+
+ self.drac_client.delete_jobs(['JID_CLEARALL_FORCE'])
+
+ mock_invoke.assert_called_once_with(
+ mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue',
+ expected_selectors, expected_properties,
+ expected_return_value=utils.RET_SUCCESS)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_one(self, mock_invoke):
+ expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'idrac',
+ 'CreationClassName': 'DCIM_JobService',
+ 'Name': 'JobService'}
+ expected_properties = {'JobID': 'JID_442507917525'}
+
+ self.drac_client.delete_jobs(['JID_442507917525'])
+
+ mock_invoke.assert_called_once_with(
+ mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue',
+ expected_selectors, expected_properties,
+ expected_return_value=utils.RET_SUCCESS)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_multi(self, mock_invoke):
+ expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem',
+ 'SystemName': 'idrac',
+ 'CreationClassName': 'DCIM_JobService',
+ 'Name': 'JobService'}
+
+ self.drac_client.delete_jobs(['JID_442507917525',
+ 'JID_442507917526'])
+
+ calls_expected = [
+ mock.call(mock.ANY,
+ uris.DCIM_JobService,
+ 'DeleteJobQueue',
+ expected_selectors,
+ {'JobID': 'JID_442507917525'},
+ expected_return_value=utils.RET_SUCCESS),
+ mock.call(mock.ANY,
+ uris.DCIM_JobService,
+ 'DeleteJobQueue',
+ expected_selectors,
+ {'JobID': 'JID_442507917526'},
+ expected_return_value=utils.RET_SUCCESS)]
+ mock_invoke.assert_has_calls(calls_expected)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_none(self, mock_invoke):
+ self.drac_client.delete_jobs(None)
+ self.assertFalse(mock_invoke.called)
+
+ @mock.patch.object(dracclient.client.WSManClient, 'invoke',
+ spec_set=True, autospec=True)
+ def test_delete_jobs_empty_list(self, mock_invoke):
+ self.drac_client.delete_jobs([])
+ self.assertFalse(mock_invoke.called)
+
+ @requests_mock.Mocker()
+ @mock.patch.object(dracclient.client.WSManClient,
+ 'wait_until_idrac_is_ready', spec_set=True,
+ autospec=True)
+ def test_delete_job_not_found(
+ self, mock_requests,
+ mock_wait_until_idrac_is_ready):
+ mock_requests.post(
+ 'https://1.2.3.4:443/wsman',
+ text=test_utils.JobService[uris.DCIM_JobService][
+ 'DeleteJobQueue']['error'])
+ self.assertRaises(
+ exceptions.DRACOperationFailed,
+ self.drac_client.delete_jobs,
+ ['JID_1234'])
+
+ @requests_mock.Mocker()
+ @mock.patch.object(dracclient.client.WSManClient,
+ 'wait_until_idrac_is_ready', spec_set=True,
+ autospec=True)
+ def test_delete_some_jobs_not_found(
+ self, mock_requests,
+ mock_wait_until_idrac_is_ready):
+ mock_requests.post(
+ 'https://1.2.3.4:443/wsman',
+ [{'text': test_utils.JobService[uris.DCIM_JobService][
+ 'DeleteJobQueue']['error']},
+ {'text': test_utils.JobService[uris.DCIM_JobService][
+ 'DeleteJobQueue']['ok']}])
+
+ self.assertRaises(
+ exceptions.DRACOperationFailed,
+ self.drac_client.delete_jobs,
+ ['JID_1234', 'JID_442507917525'])
+
+ self.assertEqual(mock_requests.call_count, 2)
+
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
spec_set=True, autospec=True)
def test_create_config_job(self, mock_invoke):
@@ -115,6 +238,7 @@ class ClientJobManagementTestCase(base.BaseTest):
'SystemName': 'DCIM:ComputerSystem'}
expected_properties = {'Target': target,
'ScheduledStartTime': 'TIME_NOW'}
+
mock_invoke.return_value = lxml.etree.fromstring(
test_utils.JobInvocations[uris.DCIM_BIOSService][
'CreateTargetedConfigJob']['ok'])
diff --git a/dracclient/tests/utils.py b/dracclient/tests/utils.py
index 8eef943..c23efad 100644
--- a/dracclient/tests/utils.py
+++ b/dracclient/tests/utils.py
@@ -34,6 +34,7 @@ def load_wsman_xml(name):
return xml_body
+
WSManEnumerations = {
'context': [
load_wsman_xml('wsman-enum_context-1'),
@@ -135,6 +136,17 @@ JobInvocations = {
}
}
+JobService = {
+ uris.DCIM_JobService: {
+ 'DeleteJobQueue': {
+ 'ok': load_wsman_xml(
+ 'job_service-delete-job-id-ok'),
+ 'error': load_wsman_xml(
+ 'job_service-delete-job-id-error'),
+ }
+ }
+}
+
iDracCardEnumerations = {
uris.DCIM_iDRACCardEnumeration: {
'ok': load_wsman_xml('idraccard_enumeration-enum-ok')
diff --git a/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml b/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml
new file mode 100644
index 0000000..1723f51
--- /dev/null
+++ b/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml
@@ -0,0 +1,21 @@
+
+
+ http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
+
+ http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueueResponse
+
+ uuid:bd334a80-bd6f-4fc9-88cc-9c9cb79d41e8
+
+ uuid:ce21f862-70ac-10ac-b40d-64b5b4da6618
+
+
+
+
+ Invalid Job ID
+ SUP011
+ 2
+
+
+
\ No newline at end of file
diff --git a/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml b/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml
new file mode 100644
index 0000000..319225a
--- /dev/null
+++ b/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml
@@ -0,0 +1,21 @@
+
+
+ http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
+
+ http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueueResponse
+
+ uuid:5f1b62ee-19d4-4679-b083-477086856c79
+
+ uuid:07b2e831-70ae-10ae-b56f-64b5b4da6618
+
+
+
+
+ The specified job was deleted
+ SUP020
+ 0
+
+
+
\ No newline at end of file