Add job management
Change-Id: Id5c8462c9f797f5d506fcacab5736a7768dbd99d
This commit is contained in:
parent
9153b850b2
commit
400f9317ba
@ -19,6 +19,7 @@ import logging
|
||||
|
||||
from dracclient import exceptions
|
||||
from dracclient.resources import bios
|
||||
from dracclient.resources import job
|
||||
from dracclient import utils
|
||||
from dracclient import wsman
|
||||
|
||||
@ -41,6 +42,7 @@ class DRACClient(object):
|
||||
"""
|
||||
self.client = WSManClient(host, username, password, port, path,
|
||||
protocol)
|
||||
self._job_mgmt = job.JobManagement(self.client)
|
||||
self._power_mgmt = bios.PowerManagement(self.client)
|
||||
|
||||
def get_power_state(self):
|
||||
@ -69,6 +71,98 @@ class DRACClient(object):
|
||||
"""
|
||||
self._power_mgmt.set_power_state(target_state)
|
||||
|
||||
def list_jobs(self, only_unfinished=False):
|
||||
"""Returns a list of jobs from the job queue
|
||||
|
||||
:param only_unfinished: indicates whether only unfinished jobs should
|
||||
be returned
|
||||
:returns: a list of Job objects
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
"""
|
||||
return self._job_mgmt.list_jobs(only_unfinished)
|
||||
|
||||
def get_job(self, job_id):
|
||||
"""Returns a job from the job queue
|
||||
|
||||
:param job_id: id of the job
|
||||
:returns: a Job object on successful query, None otherwise
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
"""
|
||||
return self._job_mgmt.get_job(job_id)
|
||||
|
||||
def create_config_job(self, resource_uri, cim_creation_class_name,
|
||||
cim_name, target,
|
||||
cim_system_creation_class_name='DCIM_ComputerSystem',
|
||||
cim_system_name='DCIM:ComputerSystem',
|
||||
reboot=False):
|
||||
"""Creates a config job
|
||||
|
||||
In CIM (Common Information Model), weak association is used to name an
|
||||
instance of one class in the context of an instance of another class.
|
||||
SystemName and SystemCreationClassName are the attributes of the
|
||||
scoping system, while Name and CreationClassName are the attributes of
|
||||
the instance of the class, on which the CreateTargetedConfigJob method
|
||||
is invoked.
|
||||
|
||||
:param: resource_uri: URI of resource to invoke
|
||||
:param: cim_creation_class_name: creation class name of the CIM object
|
||||
:param: cim_name: name of the CIM object
|
||||
:param: target: target device
|
||||
:param: cim_system_creation_class_name: creation class name of the
|
||||
scoping system
|
||||
:param: cim_system_name: name of the scoping system
|
||||
:param: reboot: indicates whether a RebootJob should be also be
|
||||
created or not
|
||||
:returns: id of the created job
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
:raises: DRACUnexpectedReturnValue on return value mismatch
|
||||
"""
|
||||
return self._job_mgmt.create_config_job(
|
||||
resource_uri, cim_creation_class_name, cim_name, target,
|
||||
cim_system_creation_class_name, cim_system_name, reboot)
|
||||
|
||||
def delete_pending_config(
|
||||
self, resource_uri, cim_creation_class_name, cim_name, target,
|
||||
cim_system_creation_class_name='DCIM_ComputerSystem',
|
||||
cim_system_name='DCIM:ComputerSystem'):
|
||||
"""Cancels pending configuration
|
||||
|
||||
Configuration can only be canceled until a config job hasn't been
|
||||
submitted.
|
||||
|
||||
In CIM (Common Information Model), weak association is used to name an
|
||||
instance of one class in the context of an instance of another class.
|
||||
SystemName and SystemCreationClassName are the attributes of the
|
||||
scoping system, while Name and CreationClassName are the attributes of
|
||||
the instance of the class, on which the CreateTargetedConfigJob method
|
||||
is invoked.
|
||||
|
||||
:param: resource_uri: URI of resource to invoke
|
||||
:param: cim_creation_class_name: creation class name of the CIM object
|
||||
:param: cim_name: name of the CIM object
|
||||
:param: target: target device
|
||||
:param: cim_system_creation_class_name: creation class name of the
|
||||
scoping system
|
||||
:param: cim_system_name: name of the scoping system
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
:raises: DRACUnexpectedReturnValue on return value mismatch
|
||||
"""
|
||||
self._job_mgmt.delete_pending_config(
|
||||
resource_uri, cim_creation_class_name, cim_name, target,
|
||||
cim_system_creation_class_name, cim_system_name)
|
||||
|
||||
|
||||
class WSManClient(wsman.Client):
|
||||
"""Wrapper for wsman.Client with return value checking"""
|
||||
|
192
dracclient/resources/job.py
Normal file
192
dracclient/resources/job.py
Normal file
@ -0,0 +1,192 @@
|
||||
#
|
||||
# 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 collections
|
||||
|
||||
from dracclient.resources import uris
|
||||
from dracclient import utils
|
||||
from dracclient import wsman
|
||||
|
||||
Job = collections.namedtuple('Job', ['id', 'name', 'start_time', 'until_time',
|
||||
'message', 'state', 'percent_complete'])
|
||||
|
||||
|
||||
class JobManagement(object):
|
||||
|
||||
def __init__(self, client):
|
||||
"""Creates JobManagement object
|
||||
|
||||
:param client: an instance of WSManClient
|
||||
"""
|
||||
self.client = client
|
||||
|
||||
def list_jobs(self, only_unfinished=False):
|
||||
"""Returns a list of jobs from the job queue
|
||||
|
||||
:param only_unfinished: indicates whether only unfinished jobs should
|
||||
be returned
|
||||
:returns: a list of Job objects
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
"""
|
||||
|
||||
filter_query = None
|
||||
if only_unfinished:
|
||||
filter_query = ('select * from DCIM_LifecycleJob '
|
||||
'where Name != "CLEARALL" and '
|
||||
'JobStatus != "Reboot Completed" and '
|
||||
'JobStatus != "Completed" and '
|
||||
'JobStatus != "Completed with Errors" and '
|
||||
'JobStatus != "Failed"')
|
||||
|
||||
doc = self.client.enumerate(uris.DCIM_LifecycleJob,
|
||||
filter_query=filter_query)
|
||||
|
||||
drac_jobs = utils.find_xml(doc, 'DCIM_LifecycleJob',
|
||||
uris.DCIM_LifecycleJob, find_all=True)
|
||||
|
||||
return [self._parse_drac_job(drac_job) for drac_job in drac_jobs]
|
||||
|
||||
def get_job(self, job_id):
|
||||
"""Returns a job from the job queue
|
||||
|
||||
:param job_id: id of the job
|
||||
:returns: a Job object on successful query, None otherwise
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
"""
|
||||
|
||||
filter_query = ('select * from DCIM_LifecycleJob where InstanceID="%s"'
|
||||
% job_id)
|
||||
|
||||
doc = self.client.enumerate(uris.DCIM_LifecycleJob,
|
||||
filter_query=filter_query)
|
||||
|
||||
drac_job = utils.find_xml(doc, 'DCIM_LifecycleJob',
|
||||
uris.DCIM_LifecycleJob)
|
||||
|
||||
if drac_job:
|
||||
return self._parse_drac_job(drac_job)
|
||||
|
||||
def create_config_job(self, resource_uri, cim_creation_class_name,
|
||||
cim_name, target,
|
||||
cim_system_creation_class_name='DCIM_ComputerSystem',
|
||||
cim_system_name='DCIM:ComputerSystem',
|
||||
reboot=False):
|
||||
"""Creates a config job
|
||||
|
||||
In CIM (Common Information Model), weak association is used to name an
|
||||
instance of one class in the context of an instance of another class.
|
||||
SystemName and SystemCreationClassName are the attributes of the
|
||||
scoping system, while Name and CreationClassName are the attributes of
|
||||
the instance of the class, on which the CreateTargetedConfigJob method
|
||||
is invoked.
|
||||
|
||||
:param: resource_uri: URI of resource to invoke
|
||||
:param: cim_creation_class_name: creation class name of the CIM object
|
||||
:param: cim_name: name of the CIM object
|
||||
:param: target: target device
|
||||
:param: cim_system_creation_class_name: creation class name of the
|
||||
scoping system
|
||||
:param: cim_system_name: name of the scoping system
|
||||
:param: reboot: indicates whether a RebootJob should be also be
|
||||
created or not
|
||||
:returns: id of the created job
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
:raises: DRACUnexpectedReturnValue on return value mismatch
|
||||
"""
|
||||
|
||||
selectors = {'SystemCreationClassName': cim_system_creation_class_name,
|
||||
'SystemName': cim_system_name,
|
||||
'CreationClassName': cim_creation_class_name,
|
||||
'Name': cim_name}
|
||||
|
||||
properties = {'Target': target,
|
||||
'ScheduledStartTime': 'TIME_NOW'}
|
||||
|
||||
if reboot:
|
||||
properties['RebootJobType'] = '3'
|
||||
|
||||
doc = self.client.invoke(resource_uri, 'CreateTargetedConfigJob',
|
||||
selectors, properties,
|
||||
expected_return_value=utils.RET_CREATED)
|
||||
|
||||
query = ('.//{%(namespace)s}%(item)s[@%(attribute_name)s='
|
||||
'"%(attribute_value)s"]' %
|
||||
{'namespace': wsman.NS_WSMAN, 'item': 'Selector',
|
||||
'attribute_name': 'Name',
|
||||
'attribute_value': 'InstanceID'})
|
||||
job_id = doc.find(query).text
|
||||
return job_id
|
||||
|
||||
def delete_pending_config(
|
||||
self, resource_uri, cim_creation_class_name, cim_name, target,
|
||||
cim_system_creation_class_name='DCIM_ComputerSystem',
|
||||
cim_system_name='DCIM:ComputerSystem'):
|
||||
"""Cancels pending configuration
|
||||
|
||||
Configuration can only be canceled until a config job hasn't been
|
||||
submitted.
|
||||
|
||||
In CIM (Common Information Model), weak association is used to name an
|
||||
instance of one class in the context of an instance of another class.
|
||||
SystemName and SystemCreationClassName are the attributes of the
|
||||
scoping system, while Name and CreationClassName are the attributes of
|
||||
the instance of the class, on which the CreateTargetedConfigJob method
|
||||
is invoked.
|
||||
|
||||
:param: resource_uri: URI of resource to invoke
|
||||
:param: cim_creation_class_name: creation class name of the CIM object
|
||||
:param: cim_name: name of the CIM object
|
||||
:param: target: target device
|
||||
:param: cim_system_creation_class_name: creation class name of the
|
||||
scoping system
|
||||
:param: cim_system_name: name of the scoping system
|
||||
:raises: WSManRequestFailure on request failures
|
||||
:raises: WSManInvalidResponse when receiving invalid response
|
||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||
interface
|
||||
:raises: DRACUnexpectedReturnValue on return value mismatch
|
||||
"""
|
||||
|
||||
selectors = {'SystemCreationClassName': cim_system_creation_class_name,
|
||||
'SystemName': cim_system_name,
|
||||
'CreationClassName': cim_creation_class_name,
|
||||
'Name': cim_name}
|
||||
|
||||
properties = {'Target': target}
|
||||
|
||||
self.client.invoke(resource_uri, 'DeletePendingConfiguration',
|
||||
selectors, properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
def _parse_drac_job(self, drac_job):
|
||||
return Job(id=self._get_job_attr(drac_job, 'InstanceID'),
|
||||
name=self._get_job_attr(drac_job, 'Name'),
|
||||
start_time=self._get_job_attr(drac_job, 'JobStartTime'),
|
||||
until_time=self._get_job_attr(drac_job, 'JobUntilTime'),
|
||||
message=self._get_job_attr(drac_job, 'Message'),
|
||||
state=self._get_job_attr(drac_job, 'JobStatus'),
|
||||
percent_complete=self._get_job_attr(drac_job,
|
||||
'PercentComplete'))
|
||||
|
||||
def _get_job_attr(self, drac_job, attr_name):
|
||||
return utils.get_wsman_resource_attr(drac_job, uris.DCIM_LifecycleJob,
|
||||
attr_name)
|
@ -40,5 +40,8 @@ DCIM_ComputerSystem = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2'
|
||||
DCIM_LifecycleJob = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/'
|
||||
'DCIM_LifecycleJob')
|
||||
|
||||
DCIM_RAIDService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/'
|
||||
'DCIM_RAIDService')
|
||||
|
||||
DCIM_SystemView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/'
|
||||
'DCIM_SystemView')
|
||||
|
@ -11,13 +11,17 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import lxml.etree
|
||||
import mock
|
||||
import requests_mock
|
||||
|
||||
import dracclient.client
|
||||
from dracclient import exceptions
|
||||
import dracclient.resources.job
|
||||
from dracclient.resources import uris
|
||||
from dracclient.tests import base
|
||||
from dracclient.tests import utils as test_utils
|
||||
from dracclient import utils
|
||||
|
||||
|
||||
@requests_mock.Mocker()
|
||||
@ -57,6 +61,185 @@ class ClientPowerManagementTestCase(base.BaseTest):
|
||||
self.drac_client.set_power_state, 'foo')
|
||||
|
||||
|
||||
class ClientJobManagementTestCase(base.BaseTest):
|
||||
|
||||
def setUp(self):
|
||||
super(ClientJobManagementTestCase, self).setUp()
|
||||
self.drac_client = dracclient.client.DRACClient(
|
||||
**test_utils.FAKE_ENDPOINT)
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_list_jobs(self, mock_requests):
|
||||
mock_requests.post(
|
||||
'https://1.2.3.4:443/wsman',
|
||||
text=test_utils.JobEnumerations[uris.DCIM_LifecycleJob]['ok'])
|
||||
|
||||
jobs = self.drac_client.list_jobs()
|
||||
|
||||
self.assertEqual(6, len(jobs))
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'enumerate',
|
||||
spec_set=True, autospec=True)
|
||||
def test_list_jobs_only_unfinished(self, mock_enumerate):
|
||||
expected_filter_query = ('select * from DCIM_LifecycleJob '
|
||||
'where Name != "CLEARALL" and '
|
||||
'JobStatus != "Reboot Completed" and '
|
||||
'JobStatus != "Completed" and '
|
||||
'JobStatus != "Completed with Errors" and '
|
||||
'JobStatus != "Failed"')
|
||||
mock_enumerate.return_value = lxml.etree.fromstring(
|
||||
test_utils.JobEnumerations[uris.DCIM_LifecycleJob]['ok'])
|
||||
|
||||
self.drac_client.list_jobs(only_unfinished=True)
|
||||
|
||||
mock_enumerate.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_LifecycleJob,
|
||||
filter_query=expected_filter_query)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'enumerate',
|
||||
spec_set=True, autospec=True)
|
||||
def test_get_job(self, mock_enumerate):
|
||||
expected_filter_query = ('select * from DCIM_LifecycleJob'
|
||||
' where InstanceID="42"')
|
||||
# NOTE: This is the first job in the xml. Filtering the job is the
|
||||
# responsibility of the controller, so not testing it.
|
||||
expected_job = dracclient.resources.job.Job(id='JID_CLEARALL',
|
||||
name='CLEARALL',
|
||||
start_time='TIME_NA',
|
||||
until_time='TIME_NA',
|
||||
message='NA',
|
||||
state='Pending',
|
||||
percent_complete='0')
|
||||
mock_enumerate.return_value = lxml.etree.fromstring(
|
||||
test_utils.JobEnumerations[uris.DCIM_LifecycleJob]['ok'])
|
||||
|
||||
job = self.drac_client.get_job(42)
|
||||
|
||||
mock_enumerate.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_LifecycleJob,
|
||||
filter_query=expected_filter_query)
|
||||
self.assertEqual(expected_job, job)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'enumerate',
|
||||
spec_set=True, autospec=True)
|
||||
def test_get_job_not_found(self, mock_enumerate):
|
||||
expected_filter_query = ('select * from DCIM_LifecycleJob'
|
||||
' where InstanceID="42"')
|
||||
mock_enumerate.return_value = lxml.etree.fromstring(
|
||||
test_utils.JobEnumerations[uris.DCIM_LifecycleJob]['not_found'])
|
||||
|
||||
job = self.drac_client.get_job(42)
|
||||
|
||||
mock_enumerate.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_LifecycleJob,
|
||||
filter_query=expected_filter_query)
|
||||
self.assertIsNone(job)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||
spec_set=True, autospec=True)
|
||||
def test_create_config_job(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'}
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_create_config_job_failed(self, mock_requests):
|
||||
cim_creation_class_name = 'DCIM_BIOSService'
|
||||
cim_name = 'DCIM:BIOSService'
|
||||
target = 'BIOS.Setup.1-1'
|
||||
mock_requests.post(
|
||||
'https://1.2.3.4:443/wsman',
|
||||
text=test_utils.JobInvocations[uris.DCIM_BIOSService][
|
||||
'CreateTargetedConfigJob']['error'])
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.DRACOperationFailed, self.drac_client.create_config_job,
|
||||
uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target)
|
||||
|
||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||
autospec=True)
|
||||
def test_create_config_job_with_reboot(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,
|
||||
'RebootJobType': '3',
|
||||
'ScheduledStartTime': 'TIME_NOW'}
|
||||
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=True)
|
||||
|
||||
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_delete_pending_config(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}
|
||||
mock_invoke.return_value = lxml.etree.fromstring(
|
||||
test_utils.JobInvocations[uris.DCIM_BIOSService][
|
||||
'DeletePendingConfiguration']['ok'])
|
||||
|
||||
self.drac_client.delete_pending_config(
|
||||
uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target)
|
||||
|
||||
mock_invoke.assert_called_once_with(
|
||||
mock.ANY, uris.DCIM_BIOSService, 'DeletePendingConfiguration',
|
||||
expected_selectors, expected_properties,
|
||||
expected_return_value=utils.RET_SUCCESS)
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_delete_pending_config_failed(self, mock_requests):
|
||||
cim_creation_class_name = 'DCIM_BIOSService'
|
||||
cim_name = 'DCIM:BIOSService'
|
||||
target = 'BIOS.Setup.1-1'
|
||||
mock_requests.post(
|
||||
'https://1.2.3.4:443/wsman',
|
||||
text=test_utils.JobInvocations[uris.DCIM_BIOSService][
|
||||
'DeletePendingConfiguration']['error'])
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.DRACOperationFailed,
|
||||
self.drac_client.delete_pending_config, uris.DCIM_BIOSService,
|
||||
cim_creation_class_name, cim_name, target)
|
||||
|
||||
|
||||
@requests_mock.Mocker()
|
||||
class WSManClientTestCase(base.BaseTest):
|
||||
|
||||
|
@ -59,3 +59,27 @@ BIOSInvocations = {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
JobEnumerations = {
|
||||
uris.DCIM_LifecycleJob: {
|
||||
'ok': load_wsman_xml('lifecycle_job-enum-ok'),
|
||||
'not_found': load_wsman_xml('lifecycle_job-enum-not_found'),
|
||||
},
|
||||
}
|
||||
|
||||
JobInvocations = {
|
||||
uris.DCIM_BIOSService: {
|
||||
'CreateTargetedConfigJob': {
|
||||
'ok': load_wsman_xml(
|
||||
'bios_service-invoke-create_targeted_config_job-ok'),
|
||||
'error': load_wsman_xml(
|
||||
'bios_service-invoke-create_targeted_config_job-error'),
|
||||
},
|
||||
'DeletePendingConfiguration': {
|
||||
'ok': load_wsman_xml(
|
||||
'bios_service-invoke-delete_pending_configuration-ok'),
|
||||
'error': load_wsman_xml(
|
||||
'bios_service-invoke-delete_pending_configuration-error'),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService"
|
||||
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/CreateTargetedConfigJobResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:80cf5e1b-b109-4ef5-87c8-5b03ce6ba117</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:e57fa514-2189-1189-8ec1-a36fc6fe83b0</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:CreateTargetedConfigJob_OUTPUT>
|
||||
<n1:Message>Configuration job already created, cannot create another config job on specified target until existing job is completed or is cancelled</n1:Message>
|
||||
<n1:MessageID>BIOS007</n1:MessageID>
|
||||
<n1:ReturnValue>2</n1:ReturnValue>
|
||||
</n1:CreateTargetedConfigJob_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -0,0 +1,28 @@
|
||||
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService"
|
||||
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||
xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/CreateTargetedConfigJobResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:fc2fdae5-6ac2-4338-9b2e-e69b813af829</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:d7d89957-2189-1189-8ec0-a36fc6fe83b0</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:CreateTargetedConfigJob_OUTPUT>
|
||||
<n1:Job>
|
||||
<wsa:EndpointReference>
|
||||
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
|
||||
<wsa:ReferenceParameters>
|
||||
<wsman:ResourceURI>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LifecycleJob</wsman:ResourceURI>
|
||||
<wsman:SelectorSet>
|
||||
<wsman:Selector Name="InstanceID">JID_442507917525</wsman:Selector>
|
||||
<wsman:Selector Name="__cimnamespace">root/dcim</wsman:Selector>
|
||||
</wsman:SelectorSet>
|
||||
</wsa:ReferenceParameters>
|
||||
</wsa:EndpointReference>
|
||||
</n1:Job>
|
||||
<n1:ReturnValue>4096</n1:ReturnValue>
|
||||
</n1:CreateTargetedConfigJob_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -0,0 +1,17 @@
|
||||
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService"
|
||||
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/DeletePendingConfigurationResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:6bd49922-f63b-44d9-abf7-b902f08ec932</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:87a16ea4-2189-1189-8eb5-a36fc6fe83b0</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:DeletePendingConfiguration_OUTPUT>
|
||||
<n1:Message>Configuration job already created, pending data cannot be deleted</n1:Message>
|
||||
<n1:MessageID>BIOS011</n1:MessageID>
|
||||
<n1:ReturnValue>2</n1:ReturnValue>
|
||||
</n1:DeletePendingConfiguration_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -0,0 +1,15 @@
|
||||
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/DeletePendingConfigurationResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:33b4948b-79e6-42ff-8670-19fbb25702c8</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:d578f646-2189-1189-8ebe-a36fc6fe83b0</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<n1:DeletePendingConfiguration_OUTPUT>
|
||||
<n1:Message>The command was successful.</n1:Message>
|
||||
<n1:MessageID>BIOS001</n1:MessageID>
|
||||
<n1:ReturnValue>0</n1:ReturnValue>
|
||||
</n1:DeletePendingConfiguration_OUTPUT>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -0,0 +1,19 @@
|
||||
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||
xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
|
||||
xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
|
||||
xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LifecycleJob">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:2453cc4f-104c-104c-8002-fd0aa2bdb228</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:28c00f71-1051-1051-8003-fcc71555dbe0</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<wsen:EnumerateResponse>
|
||||
<wsman:Items/>
|
||||
<wsen:EnumerationContext/>
|
||||
<wsman:EndOfSequence/>
|
||||
</wsen:EnumerateResponse>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
76
dracclient/tests/wsman_mocks/lifecycle_job-enum-ok.xml
Normal file
76
dracclient/tests/wsman_mocks/lifecycle_job-enum-ok.xml
Normal file
@ -0,0 +1,76 @@
|
||||
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LifecycleJob">
|
||||
<s:Header>
|
||||
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse</wsa:Action>
|
||||
<wsa:RelatesTo>uuid:f3ee3b82-210b-110b-8002-fd0aa2bdb228</wsa:RelatesTo>
|
||||
<wsa:MessageID>uuid:f4327d65-210b-110b-836c-0581b4d9bed4</wsa:MessageID>
|
||||
</s:Header>
|
||||
<s:Body>
|
||||
<wsen:EnumerateResponse>
|
||||
<wsman:Items>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_CLEARALL</n1:InstanceID>
|
||||
<n1:JobStartTime>TIME_NA</n1:JobStartTime>
|
||||
<n1:JobStatus>Pending</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>NA</n1:Message>
|
||||
<n1:MessageID>NA</n1:MessageID>
|
||||
<n1:Name>CLEARALL</n1:Name>
|
||||
<n1:PercentComplete>0</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_001436912645</n1:InstanceID>
|
||||
<n1:JobStartTime>00000101000000</n1:JobStartTime>
|
||||
<n1:JobStatus>Completed</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>Job completed successfully</n1:Message>
|
||||
<n1:MessageID>PR19</n1:MessageID>
|
||||
<n1:Name>ConfigBIOS:BIOS.Setup.1-1</n1:Name>
|
||||
<n1:PercentComplete>100</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_001436960861</n1:InstanceID>
|
||||
<n1:JobStartTime>00000101000000</n1:JobStartTime>
|
||||
<n1:JobStatus>Completed</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>Job completed successfully</n1:Message>
|
||||
<n1:MessageID>PR19</n1:MessageID>
|
||||
<n1:Name>ConfigBIOS:BIOS.Setup.1-1</n1:Name>
|
||||
<n1:PercentComplete>100</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_001436966148</n1:InstanceID>
|
||||
<n1:JobStartTime>00000101000000</n1:JobStartTime>
|
||||
<n1:JobStatus>Completed</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>Job completed successfully</n1:Message>
|
||||
<n1:MessageID>PR19</n1:MessageID>
|
||||
<n1:Name>ConfigBIOS:BIOS.Setup.1-1</n1:Name>
|
||||
<n1:PercentComplete>100</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_001436980372</n1:InstanceID>
|
||||
<n1:JobStartTime>00000101000000</n1:JobStartTime>
|
||||
<n1:JobStatus>Completed</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>Job completed successfully</n1:Message>
|
||||
<n1:MessageID>PR19</n1:MessageID>
|
||||
<n1:Name>ConfigBIOS:BIOS.Setup.1-1</n1:Name>
|
||||
<n1:PercentComplete>100</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
<n1:DCIM_LifecycleJob>
|
||||
<n1:InstanceID>JID_001436981582</n1:InstanceID>
|
||||
<n1:JobStartTime>00000101000000</n1:JobStartTime>
|
||||
<n1:JobStatus>Running</n1:JobStatus>
|
||||
<n1:JobUntilTime>TIME_NA</n1:JobUntilTime>
|
||||
<n1:Message>Job in progress</n1:Message>
|
||||
<n1:MessageID>PR20</n1:MessageID>
|
||||
<n1:Name>ConfigBIOS:BIOS.Setup.1-1</n1:Name>
|
||||
<n1:PercentComplete>34</n1:PercentComplete>
|
||||
</n1:DCIM_LifecycleJob>
|
||||
</wsman:Items>
|
||||
<wsen:EnumerationContext/>
|
||||
<wsman:EndOfSequence/>
|
||||
</wsen:EnumerateResponse>
|
||||
</s:Body>
|
||||
</s:Envelope>
|
@ -40,3 +40,9 @@ def find_xml(doc, item, namespace, find_all=False):
|
||||
if find_all:
|
||||
return doc.findall(query)
|
||||
return doc.find(query)
|
||||
|
||||
|
||||
def get_wsman_resource_attr(doc, resource_uri, attr_name):
|
||||
"""Find an attribute of a resource in an ElementTree object"""
|
||||
|
||||
return find_xml(doc, attr_name, resource_uri).text.strip()
|
||||
|
Loading…
Reference in New Issue
Block a user