feat: Intel AMT driver over WS-Management (0.1.0)

An `amt` driver (napalm_amt.AmtDriver), a ManagementControllerDriver for the
management controller of Intel vPro machines, with its own lean WS-Management
client (requests + ElementTree, HTTP Digest, ports 16992/16993).

It reads the machine's identity, hardware with the SMBIOS system UUID, firmware
(AMT with build, BIOS), power state and the hardware event log, reports what AMT
listens on (plain HTTP or TLS, KVM incl. port 5900, IDE-R), and switches the
machine's power. AMT cannot be reset over WS-Management, so there is no
reboot_host. Discovery recognises AMT by its ports and its Server header.

Tested against Intel's published AMT 12 recordings (go-wsman-messages,
Apache-2.0, see NOTICE). `python -m napalm_amt.record` records a real AMT
read-only; the first test devices are two Lenovo ThinkCentre M910x.
This commit is contained in:
christianmanivong committed 2026-10-18 14:55:32 +02:00
commit 0052ba7884
61 files changed
+4303

No files matched your search

View File
Whitespace-only changes.
+142
View File
@@ -0,0 +1,142 @@
"""Shared helpers: an Intel AMT WS-Management service served from the recorded responses."""
import re
import xml.etree.ElementTree as ET
from pathlib import Path
import pytest
import responses
FIXTURES = Path(__file__).parent / "fixtures"
DMT = FIXTURES / "dmt-wsman-messages"
HOST = "amt.example.net"
URL = f"http://{HOST}:16992/wsman"
_SOAP = "http://www.w3.org/2003/05/soap-envelope"
_ADDRESSING = "http://schemas.xmlsoap.org/ws/2004/08/addressing"
_WSMAN = "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
_ENUMERATION = "http://schemas.xmlsoap.org/ws/2004/09/enumeration"
def load(name: str, fixtures: Path = DMT) -> str:
return (fixtures / name).read_text()
def _end_of_sequence(resource_uri: str) -> str:
"""The last, empty page of an enumeration."""
return (
f'<?xml version="1.0" encoding="UTF-8"?>'
f'<a:Envelope xmlns:a="{_SOAP}" xmlns:b="{_ADDRESSING}" xmlns:c="{_WSMAN}" '
f'xmlns:g="{_ENUMERATION}"><a:Header>'
f"<b:Action>{_ENUMERATION}/PullResponse</b:Action>"
f"<c:ResourceURI>{resource_uri}</c:ResourceURI></a:Header>"
f"<a:Body><g:PullResponse><g:Items/><g:EndOfSequence/></g:PullResponse></a:Body>"
f"</a:Envelope>"
)
def _enumerate_response(resource_uri: str, context: str) -> str:
return (
f'<?xml version="1.0" encoding="UTF-8"?>'
f'<a:Envelope xmlns:a="{_SOAP}" xmlns:b="{_ADDRESSING}" xmlns:c="{_WSMAN}" '
f'xmlns:g="{_ENUMERATION}"><a:Header>'
f"<b:Action>{_ENUMERATION}/EnumerateResponse</b:Action>"
f"<c:ResourceURI>{resource_uri}</c:ResourceURI></a:Header>"
f"<a:Body><g:EnumerateResponse><g:EnumerationContext>{context}</g:EnumerationContext>"
f"</g:EnumerateResponse></a:Body></a:Envelope>"
)
class Request:
"""One WS-Management request as the mock received it."""
def __init__(self, body: bytes | str):
self.xml = body.decode() if isinstance(body, bytes) else body
root = ET.fromstring(self.xml)
self.action = root.findtext(f"{{{_SOAP}}}Header/{{{_ADDRESSING}}}Action") or ""
self.resource_uri = root.findtext(f"{{{_SOAP}}}Header/{{{_WSMAN}}}ResourceURI") or ""
self.resource = self.resource_uri.rsplit("/", 1)[-1]
self.operation = self.action.rsplit("/", 1)[-1]
self.context = root.findtext(f".//{{{_ENUMERATION}}}EnumerationContext")
self.body = root.find(f"{{{_SOAP}}}Body")
header = root.find(f"{{{_SOAP}}}Header")
self.selectors = {s.get("Name"): s.text for s in header.iter(f"{{{_WSMAN}}}Selector")}
class AmtServer:
"""Answer WS-Management requests from ``<Resource>.<operation>.xml`` files.
``Get`` -> ``<Resource>.get.xml``, ``Pull`` -> ``<Resource>.pull.xml`` (a page without
``EndOfSequence`` is followed by an empty last page), a method -> ``<Resource>.<Method>.xml``.
A resource without a file is answered with the fault for an unknown resource URI, as
AMT does. ``override(resource, operation, status, body)`` replaces one answer.
"""
def __init__(self, rsps, fixtures: Path = DMT, url: str = URL):
self.fixtures = fixtures
self.requests: list[Request] = []
self.overrides: dict[tuple[str, str], tuple[int, str]] = {}
self._finished: set[str] = set()
rsps.add_callback(responses.POST, re.compile(re.escape(url)), callback=self._handle)
def override(self, resource: str, operation: str, status: int, body: str) -> None:
self.overrides[(resource, operation)] = (status, body)
def calls(self, operation: str | None = None) -> list[Request]:
return [r for r in self.requests if operation is None or r.operation == operation]
def _file(self, name: str) -> tuple[int, str]:
path = self.fixtures / name
if not path.exists():
return 400, load("fault_destination_unreachable.xml")
return 200, path.read_text()
def _handle(self, request):
req = Request(request.body)
self.requests.append(req)
status, text = self._answer(req)
return status, {"Content-Type": "application/soap+xml;charset=UTF-8"}, text
def _answer(self, req: Request) -> tuple[int, str]:
if (req.resource, req.operation) in self.overrides:
return self.overrides[(req.resource, req.operation)]
if req.operation == "Get":
return self._file(f"{req.resource}.get.xml")
if req.operation == "Enumerate":
if not (self.fixtures / f"{req.resource}.pull.xml").exists():
return self._file(f"{req.resource}.pull.xml")
return 200, _enumerate_response(req.resource_uri, f"ctx-{req.resource}")
if req.operation == "Pull":
if req.resource in self._finished:
return 200, _end_of_sequence(req.resource_uri)
status, text = self._file(f"{req.resource}.pull.xml")
if "EndOfSequence" not in text:
self._finished.add(req.resource)
return status, text
return self._file(f"{req.resource}.{req.operation}.xml")
@pytest.fixture
def amt():
"""A mocked AMT on http://amt.example.net:16992 answering from the DMT recordings."""
with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
yield AmtServer(rsps)
def instances(name: str, fixtures: Path = DMT) -> list[dict]:
"""The instances in a recorded Get or Pull response, as the transport returns them."""
from napalm_amt.wsman import to_instance
body = ET.fromstring(load(name, fixtures)).find(f"{{{_SOAP}}}Body")
page = body.find(f"{{{_ENUMERATION}}}PullResponse")
if page is not None:
return [to_instance(item) for item in page.findall(f"{{{_ENUMERATION}}}Items/*")]
return [to_instance(body[0])]
def patched(name: str, old: str, new: str, count: int = -1) -> str:
"""A recorded response with ``old`` replaced; fails when ``old`` is not in it."""
text = load(name)
assert old in text, f"{old!r} not in {name}"
return text.replace(old, new, count)
@@ -0,0 +1,48 @@
<?xml version= "1.0" encoding= "UTF-8"?>
<a:Envelope xmlns:a= "http://www.w3.org/2003/05/soap-envelope" xmlns:b= "http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c= "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:d= "http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:e= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:f= "http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:g= "http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:h= "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_EthernetPortSettings"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>4</b:RelatesTo>
<b:Action a:mustUnderstand= "true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-0000000002E8</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_EthernetPortSettings</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:AMT_EthernetPortSettings>
<h:DHCPEnabled>true</h:DHCPEnabled>
<h:DefaultGateway>192.168.6.1</h:DefaultGateway>
<h:ElementName>Intel(r) AMT Ethernet Port Settings</h:ElementName>
<h:InstanceID>Intel(r) AMT Ethernet Port Settings 0</h:InstanceID>
<h:IpSyncEnabled>true</h:IpSyncEnabled>
<h:LinkIsUp>true</h:LinkIsUp>
<h:LinkPolicy>1</h:LinkPolicy>
<h:LinkPolicy>14</h:LinkPolicy>
<h:MACAddress>00-be-43-d8-22-a4</h:MACAddress>
<h:PhysicalConnectionType>0</h:PhysicalConnectionType>
<h:PrimaryDNS>192.168.6.1</h:PrimaryDNS>
<h:SharedDynamicIP>true</h:SharedDynamicIP>
<h:SharedMAC>true</h:SharedMAC>
<h:SharedStaticIp>false</h:SharedStaticIp>
<h:SubnetMask>255.255.255.0</h:SubnetMask>
</h:AMT_EthernetPortSettings>
<h:AMT_EthernetPortSettings>
<h:ConsoleTcpMaxRetransmissions>5</h:ConsoleTcpMaxRetransmissions>
<h:DHCPEnabled>true</h:DHCPEnabled>
<h:ElementName>Intel(r) AMT Ethernet Port Settings</h:ElementName>
<h:InstanceID>Intel(r) AMT Ethernet Port Settings 1</h:InstanceID>
<h:LinkControl>2</h:LinkControl>
<h:LinkIsUp>false</h:LinkIsUp>
<h:LinkPreference>2</h:LinkPreference>
<h:MACAddress>00-00-00-00-00-00</h:MACAddress>
<h:PhysicalConnectionType>3</h:PhysicalConnectionType>
<h:SharedMAC>true</h:SharedMAC>
<h:WLANLinkProtectionLevel>1</h:WLANLinkProtectionLevel>
</h:AMT_EthernetPortSettings>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-00000000007B</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings</c:ResourceURI>
</a:Header>
<a:Body>
<g:EnumerateResponse>
<g:EnumerationContext>14000000-0000-0000-0000-000000000000</g:EnumerationContext>
</g:EnumerateResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,39 @@
<?xml version= "1.0" encoding= "UTF-8"?>
<a:Envelope xmlns:a= "http://www.w3.org/2003/05/soap-envelope" xmlns:b= "http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c= "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:d= "http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:e= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:f= "http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:g= "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand= "true">http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-0000000002E4</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings</c:ResourceURI>
</a:Header>
<a:Body>
<g:AMT_GeneralSettings>
<g:AMTNetworkEnabled>1</g:AMTNetworkEnabled>
<g:DDNSPeriodicUpdateInterval>1440</g:DDNSPeriodicUpdateInterval>
<g:DDNSTTL>900</g:DDNSTTL>
<g:DDNSUpdateByDHCPServerEnabled>true</g:DDNSUpdateByDHCPServerEnabled>
<g:DDNSUpdateEnabled>false</g:DDNSUpdateEnabled>
<g:DHCPSyncRequiresHostname>1</g:DHCPSyncRequiresHostname>
<g:DHCPv6ConfigurationTimeout>0</g:DHCPv6ConfigurationTimeout>
<g:DigestRealm>Digest:F3EB554784E729164447A89F60B641C5</g:DigestRealm>
<g:DomainName>Test Domain Name</g:DomainName>
<g:ElementName>Intel(r) AMT: General Settings</g:ElementName>
<g:HostName>Test Host Name</g:HostName>
<g:HostOSFQDN>Test Host OS FQDN</g:HostOSFQDN>
<g:IdleWakeTimeout>1</g:IdleWakeTimeout>
<g:InstanceID>Intel(r) AMT: General Settings</g:InstanceID>
<g:NetworkInterfaceEnabled>true</g:NetworkInterfaceEnabled>
<g:PingResponseEnabled>true</g:PingResponseEnabled>
<g:PowerSource>0</g:PowerSource>
<g:PreferredAddressFamily>0</g:PreferredAddressFamily>
<g:PresenceNotificationInterval>0</g:PresenceNotificationInterval>
<g:PrivacyLevel>0</g:PrivacyLevel>
<g:RmcpPingResponseEnabled>true</g:RmcpPingResponseEnabled>
<g:SharedFQDN>true</g:SharedFQDN>
<g:ThunderboltDockEnabled>0</g:ThunderboltDockEnabled>
<g:WsmanOnlyMode>false</g:WsmanOnlyMode>
</g:AMT_GeneralSettings>
</a:Body>
</a:Envelope>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>9</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog/GetRecordsResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000002722</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog</c:ResourceURI>
</a:Header>
<a:Body>
<g:GetRecords_OUTPUT>
<g:IterationIdentifier>3</g:IterationIdentifier>
<g:NoMoreRecords>true</g:NoMoreRecords>
<g:RecordArray>Y8iYZf8GbwVoEP8mYaoKAAAAAAAA</g:RecordArray>
<g:RecordArray>IgYBZf8PbwJoAf8iAEAHAAAAAAAA</g:RecordArray>
<g:RecordArray>IgYBZf8PbwJoAf8iAEAHAAAAAAAA</g:RecordArray>
<g:ReturnValue>0</g:ReturnValue>
</g:GetRecords_OUTPUT>
</a:Body>
</a:Envelope>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>10</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog/PositionToFirstRecordResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000002723</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog</c:ResourceURI>
</a:Header>
<a:Body>
<g:PositionToFirstRecord_OUTPUT>
<g:IterationIdentifier>1</g:IterationIdentifier>
<g:ReturnValue>0</g:ReturnValue>
</g:PositionToFirstRecord_OUTPUT>
</a:Body>
</a:Envelope>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_RedirectionService"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>5</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-0000000028B5</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_RedirectionService</c:ResourceURI>
</a:Header>
<a:Body>
<g:AMT_RedirectionService>
<g:CreationClassName>AMT_RedirectionService</g:CreationClassName>
<g:ElementName>Intel(r) AMT Redirection Service</g:ElementName>
<g:EnabledState>32771</g:EnabledState>
<g:ListenerEnabled>true</g:ListenerEnabled>
<g:Name>Intel(r) AMT Redirection Service</g:Name>
<g:SystemCreationClassName>CIM_ComputerSystem</g:SystemCreationClassName>
<g:SystemName>Intel(r) AMT</g:SystemName>
</g:AMT_RedirectionService>
</a:Body>
</a:Envelope>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns="http://www.w3.org/2003/05/soap-envelope">
<Header>
<a:Action>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService/GetUuid</a:Action>
<a:To>/wsman</a:To>
<w:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService</w:ResourceURI>
<a:MessageID>1</a:MessageID>
<a:ReplyTo>
<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
</a:ReplyTo>
<w:OperationTimeout>PT60S</w:OperationTimeout>
</Header>
<Body>
<h:GetUuid_OUTPUT xmlns:h="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService"><UUID>E67jVdK/u2EXoIiu3XA36g==</UUID></h:GetUuid_OUTPUT>
</Body>
</Envelope>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>0</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000332</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService</c:ResourceURI>
</a:Header>
<a:Body>
<g:AMT_SetupAndConfigurationService>
<g:CreationClassName>AMT_SetupAndConfigurationService</g:CreationClassName>
<g:ElementName>Intel(r) AMT Setup and Configuration Service</g:ElementName>
<g:EnabledState>5</g:EnabledState>
<g:Name>Intel(r) AMT Setup and Configuration Service</g:Name>
<g:PasswordModel>1</g:PasswordModel>
<g:ProvisioningMode>1</g:ProvisioningMode>
<g:ProvisioningServerOTP>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</g:ProvisioningServerOTP>
<g:ProvisioningState>2</g:ProvisioningState>
<g:RequestedState>12</g:RequestedState>
<g:SystemCreationClassName>CIM_ComputerSystem</g:SystemCreationClassName>
<g:SystemName>Intel(r) AMT</g:SystemName>
<g:ZeroTouchConfigurationEnabled>true</g:ZeroTouchConfigurationEnabled>
</g:AMT_SetupAndConfigurationService>
</a:Body>
</a:Envelope>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TLSSettingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>8</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000002915</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/amt-schema/1/AMT_TLSSettingData</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:AMT_TLSSettingData>
<h:AcceptNonSecureConnections>false</h:AcceptNonSecureConnections>
<h:ElementName>Intel(r) AMT 802.3 TLS Settings</h:ElementName>
<h:Enabled>false</h:Enabled>
<h:InstanceID>Intel(r) AMT 802.3 TLS Settings</h:InstanceID>
<h:MutualAuthentication>false</h:MutualAuthentication>
</h:AMT_TLSSettingData>
<h:AMT_TLSSettingData>
<h:AcceptNonSecureConnections>true</h:AcceptNonSecureConnections>
<h:ElementName>Intel(r) AMT LMS TLS Settings</h:ElementName>
<h:Enabled>false</h:Enabled>
<h:InstanceID>Intel(r) AMT LMS TLS Settings</h:InstanceID>
<h:MutualAuthentication>false</h:MutualAuthentication>
</h:AMT_TLSSettingData>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope" xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd" xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_AssociatedPowerManagementService" xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000007A95</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_AssociatedPowerManagementService</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_AssociatedPowerManagementService>
<h:AvailableRequestedPowerStates>10</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>8</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>5</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>11</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>4</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>7</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>14</h:AvailableRequestedPowerStates>
<h:AvailableRequestedPowerStates>12</h:AvailableRequestedPowerStates>
<h:PowerState>2</h:PowerState>
<h:ServiceProvided>
<b:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:Address>
<b:ReferenceParameters>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService</c:ResourceURI>
<c:SelectorSet>
<c:Selector Name="CreationClassName">CIM_PowerManagementService</c:Selector>
<c:Selector Name="Name">Intel(r) AMT Power Management Service</c:Selector>
<c:Selector Name="SystemCreationClassName">CIM_ComputerSystem</c:Selector>
<c:Selector Name="SystemName">Intel(r) AMT</c:Selector>
</c:SelectorSet>
</b:ReferenceParameters>
</h:ServiceProvided>
<h:UserOfService>
<b:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:Address>
<b:ReferenceParameters>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</c:ResourceURI>
<c:SelectorSet>
<c:Selector Name="CreationClassName">CIM_ComputerSystem</c:Selector>
<c:Selector Name="Name">ManagedSystem</c:Selector>
</c:SelectorSet>
</b:ReferenceParameters>
</h:UserOfService>
</h:CIM_AssociatedPowerManagementService>
</g:Items>
<g:EndOfSequence/>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BIOSElement"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E39</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BIOSElement</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_BIOSElement>
<h:ElementName>Primary BIOS</h:ElementName>
<h:Manufacturer>Intel Corp.</h:Manufacturer>
<h:Name>Primary BIOS</h:Name>
<h:OperationalStatus>0</h:OperationalStatus>
<h:PrimaryBIOS>true</h:PrimaryBIOS>
<h:ReleaseDate>
<i:Datetime>2020-08-10T00:00:00Z</i:Datetime>
</h:ReleaseDate>
<h:SoftwareElementID>QNCFLX70.0054.2020.0810.2227</h:SoftwareElementID>
<h:SoftwareElementState>2</h:SoftwareElementState>
<h:TargetOperatingSystem>66</h:TargetOperatingSystem>
<h:Version>QNCFLX70.0054.2020.0810.2227</h:Version>
</h:CIM_BIOSElement>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Card"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E77</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Card</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_Card>
<h:CanBeFRUed>true</h:CanBeFRUed>
<h:CreationClassName>CIM_Card</h:CreationClassName>
<h:ElementName>Managed System Base Board</h:ElementName>
<h:Manufacturer>Intel Corporation</h:Manufacturer>
<h:Model>NUC9V7QNB</h:Model>
<h:OperationalStatus>0</h:OperationalStatus>
<h:PackageType>9</h:PackageType>
<h:SerialNumber>KNQN0221020W</h:SerialNumber>
<h:Tag>CIM_Card</h:Tag>
<h:Version>K47180-402</h:Version>
</h:CIM_Card>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chassis"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E7B</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chassis</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_Chassis>
<h:ChassisPackageType>0</h:ChassisPackageType>
<h:CreationClassName>CIM_Chassis</h:CreationClassName>
<h:ElementName>Managed System Chassis</h:ElementName>
<h:Manufacturer>Intel(R) Client Systems</h:Manufacturer>
<h:Model>NUC9V7QNX</h:Model>
<h:OperationalStatus>0</h:OperationalStatus>
<h:PackageType>3</h:PackageType>
<h:SerialNumber>JRQN0243007J</h:SerialNumber>
<h:Tag>CIM_Chassis</h:Tag>
<h:Version>K47174-402</h:Version>
</h:CIM_Chassis>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chip"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E7F</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chip</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:EnumerationContext>D4020000-0000-0000-0000-000000000000</g:EnumerationContext>
<g:Items>
<h:CIM_Chip>
<h:CanBeFRUed>true</h:CanBeFRUed>
<h:CreationClassName>CIM_Chip</h:CreationClassName>
<h:ElementName>Managed System Processor Chip</h:ElementName>
<h:Manufacturer>Intel(R) Corporation</h:Manufacturer>
<h:OperationalStatus>0</h:OperationalStatus>
<h:Tag>CPU 0</h:Tag>
<h:Version>Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz</h:Version>
</h:CIM_Chip>
</g:Items>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystemPackage"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-0000000000BF</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystemPackage</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_ComputerSystemPackage>
<h:Antecedent>
<b:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:Address>
<b:ReferenceParameters>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Chassis</c:ResourceURI>
<c:SelectorSet>
<c:Selector Name="CreationClassName">CIM_Chassis</c:Selector>
<c:Selector Name="Tag">CIM_Chassis</c:Selector>
</c:SelectorSet>
</b:ReferenceParameters>
</h:Antecedent>
<h:Dependent>
<b:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:Address>
<b:ReferenceParameters>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem</c:ResourceURI>
<c:SelectorSet>
<c:Selector Name="CreationClassName">CIM_ComputerSystem</c:Selector>
<c:Selector Name="Name">ManagedSystem</c:Selector>
</c:SelectorSet>
</b:ReferenceParameters>
</h:Dependent>
<h:PlatformGUID>13AEE355D2BFBB6117A088AEDD7037EA</h:PlatformGUID>
</h:CIM_ComputerSystemPackage>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_KVMRedirectionSAP"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E6F</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_KVMRedirectionSAP</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_KVMRedirectionSAP>
<h:CreationClassName>CIM_KVMRedirectionSAP</h:CreationClassName>
<h:ElementName>KVM Redirection Service Access Point</h:ElementName>
<h:EnabledState>6</h:EnabledState>
<h:KVMProtocol>4</h:KVMProtocol>
<h:Name>KVM Redirection Service Access Point</h:Name>
<h:RequestedState>5</h:RequestedState>
<h:SystemCreationClassName>CIM_ComputerSystem</h:SystemCreationClassName>
<h:SystemName>ManagedSystem</h:SystemName>
</h:CIM_KVMRedirectionSAP>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_MediaAccessDevice"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E72</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_MediaAccessDevice</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_MediaAccessDevice>
<h:Capabilities>4</h:Capabilities>
<h:CreationClassName>CIM_MediaAccessDevice</h:CreationClassName>
<h:DeviceID>MEDIA DEV 0</h:DeviceID>
<h:ElementName>Managed System Media Access Device</h:ElementName>
<h:EnabledDefault>2</h:EnabledDefault>
<h:EnabledState>0</h:EnabledState>
<h:MaxMediaSize>960197124</h:MaxMediaSize>
<h:OperationalStatus>0</h:OperationalStatus>
<h:RequestedState>12</h:RequestedState>
<h:Security>2</h:Security>
<h:SystemCreationClassName>CIM_ComputerSystem</h:SystemCreationClassName>
<h:SystemName>ManagedSystem</h:SystemName>
</h:CIM_MediaAccessDevice>
<h:CIM_MediaAccessDevice>
<h:Capabilities>4</h:Capabilities>
<h:CreationClassName>CIM_MediaAccessDevice</h:CreationClassName>
<h:DeviceID>MEDIA DEV 1</h:DeviceID>
<h:ElementName>Managed System Media Access Device</h:ElementName>
<h:EnabledDefault>2</h:EnabledDefault>
<h:EnabledState>0</h:EnabledState>
<h:MaxMediaSize>500107862</h:MaxMediaSize>
<h:OperationalStatus>0</h:OperationalStatus>
<h:RequestedState>12</h:RequestedState>
<h:Security>2</h:Security>
<h:SystemCreationClassName>CIM_ComputerSystem</h:SystemCreationClassName>
<h:SystemName>ManagedSystem</h:SystemName>
</h:CIM_MediaAccessDevice>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PhysicalMemory"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E82</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PhysicalMemory</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_PhysicalMemory>
<h:BankLabel>BANK 0</h:BankLabel>
<h:Capacity>17179869184</h:Capacity>
<h:ConfiguredMemoryClockSpeed>2400</h:ConfiguredMemoryClockSpeed>
<h:CreationClassName>CIM_PhysicalMemory</h:CreationClassName>
<h:ElementName>Managed System Memory Chip</h:ElementName>
<h:FormFactor>13</h:FormFactor>
<h:IsSpeedInMhz>true</h:IsSpeedInMhz>
<h:Manufacturer>859B</h:Manufacturer>
<h:MaxMemorySpeed>2400</h:MaxMemorySpeed>
<h:MemoryType>26</h:MemoryType>
<h:PartNumber>CT16G4SFD824A.M16FE </h:PartNumber>
<h:SerialNumber>E0E8D670</h:SerialNumber>
<h:Speed>0</h:Speed>
<h:Tag>9876543210</h:Tag>
</h:CIM_PhysicalMemory>
<h:CIM_PhysicalMemory>
<h:BankLabel>BANK 2</h:BankLabel>
<h:Capacity>17179869184</h:Capacity>
<h:ConfiguredMemoryClockSpeed>2400</h:ConfiguredMemoryClockSpeed>
<h:CreationClassName>CIM_PhysicalMemory</h:CreationClassName>
<h:ElementName>Managed System Memory Chip</h:ElementName>
<h:FormFactor>13</h:FormFactor>
<h:IsSpeedInMhz>true</h:IsSpeedInMhz>
<h:Manufacturer>859B</h:Manufacturer>
<h:MaxMemorySpeed>2400</h:MaxMemorySpeed>
<h:MemoryType>26</h:MemoryType>
<h:PartNumber>CT16G4SFD824A.M16FE </h:PartNumber>
<h:SerialNumber>E0E8D070</h:SerialNumber>
<h:Speed>0</h:Speed>
<h:Tag>9876543210 (#1)</h:Tag>
</h:CIM_PhysicalMemory>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>0</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService/RequestPowerStateChangeResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-0000000003B8</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_PowerManagementService</c:ResourceURI>
</a:Header>
<a:Body>
<g:RequestPowerStateChange_OUTPUT>
<g:ReturnValue>0</g:ReturnValue>
</g:RequestPowerStateChange_OUTPUT>
</a:Body>
</a:Envelope>
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Processor"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E8B</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Processor</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_Processor>
<h:CPUStatus>1</h:CPUStatus>
<h:CreationClassName>CIM_Processor</h:CreationClassName>
<h:CurrentClockSpeed>2400</h:CurrentClockSpeed>
<h:DeviceID>CPU 0</h:DeviceID>
<h:ElementName>Managed System CPU</h:ElementName>
<h:EnabledState>2</h:EnabledState>
<h:ExternalBusClockSpeed>100</h:ExternalBusClockSpeed>
<h:Family>198</h:Family>
<h:HealthState>0</h:HealthState>
<h:MaxClockSpeed>8300</h:MaxClockSpeed>
<h:OperationalStatus>0</h:OperationalStatus>
<h:OtherFamilyDescription></h:OtherFamilyDescription>
<h:RequestedState>12</h:RequestedState>
<h:Role>Central</h:Role>
<h:Stepping>13</h:Stepping>
<h:SystemCreationClassName>CIM_ComputerSystem</h:SystemCreationClassName>
<h:SystemName>ManagedSystem</h:SystemName>
<h:UpgradeMethod>52</h:UpgradeMethod>
</h:CIM_Processor>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://schemas.xmlsoap.org/ws/2004/09/enumeration"
xmlns:h="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity"
xmlns:i="http://schemas.dmtf.org/wbem/wscim/1/common"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000E9A</b:MessageID>
<c:ResourceURI>http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_SoftwareIdentity</c:ResourceURI>
</a:Header>
<a:Body>
<g:PullResponse>
<g:Items>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Flash</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Netstack</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>AMTApps</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>AMT</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Sku</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>16392</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>VendorID</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>8086</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Build Number</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>1579</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Recovery Version</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Recovery Build Num</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>1579</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>Legacy Mode</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>False</h:VersionString>
</h:CIM_SoftwareIdentity>
<h:CIM_SoftwareIdentity>
<h:InstanceID>AMT FW Core Version</h:InstanceID>
<h:IsEntity>true</h:IsEntity>
<h:VersionString>12.0.67</h:VersionString>
</h:CIM_SoftwareIdentity>
</g:Items>
<g:EndOfSequence></g:EndOfSequence>
</g:PullResponse>
</a:Body>
</a:Envelope>
+30
View File
@@ -0,0 +1,30 @@
# Intel AMT 12.0.67 (build 1579) on an Intel NUC9 (NUC9V7QNB, i7-9850H), as published in
# Intel's go-wsman-messages (Apache-2.0), pkg/wsman/wsmantesting/responses, commit 00402b9.
# Some values there were replaced by placeholders (AMT_GeneralSettings: "Test Host Name").
#
# file request
AMT_GeneralSettings.get.xml Get AMT_GeneralSettings
AMT_GeneralSettings.enumerate.xml Enumerate AMT_GeneralSettings (shape of every EnumerateResponse)
AMT_EthernetPortSettings.pull.xml Enumerate + Pull AMT_EthernetPortSettings
AMT_SetupAndConfigurationService.get.xml Get AMT_SetupAndConfigurationService
AMT_SetupAndConfigurationService.GetUuid.xml Invoke AMT_SetupAndConfigurationService.GetUuid
AMT_TLSSettingData.pull.xml Enumerate + Pull AMT_TLSSettingData
AMT_RedirectionService.get.xml Get AMT_RedirectionService
AMT_MessageLog.PositionToFirstRecord.xml Invoke AMT_MessageLog.PositionToFirstRecord
AMT_MessageLog.GetRecords.xml Invoke AMT_MessageLog.GetRecords
IPS_KVMRedirectionSettingData.get.xml Get IPS_KVMRedirectionSettingData
CIM_KVMRedirectionSAP.pull.xml Enumerate + Pull CIM_KVMRedirectionSAP
CIM_SoftwareIdentity.pull.xml Enumerate + Pull CIM_SoftwareIdentity
CIM_BIOSElement.pull.xml Enumerate + Pull CIM_BIOSElement
CIM_Chassis.pull.xml Enumerate + Pull CIM_Chassis
CIM_Card.pull.xml Enumerate + Pull CIM_Card
CIM_ComputerSystemPackage.pull.xml Enumerate + Pull CIM_ComputerSystemPackage
CIM_Processor.pull.xml Enumerate + Pull CIM_Processor
CIM_Chip.pull.xml Enumerate + Pull CIM_Chip (first page: a context, no EndOfSequence)
CIM_PhysicalMemory.pull.xml Enumerate + Pull CIM_PhysicalMemory
CIM_MediaAccessDevice.pull.xml Enumerate + Pull CIM_MediaAccessDevice
CIM_AssociatedPowerManagementService.pull.xml Enumerate + Pull CIM_AssociatedPowerManagementService
CIM_PowerManagementService.RequestPowerStateChange.xml Invoke CIM_PowerManagementService.RequestPowerStateChange
#
# Written by hand after DSP0226 (WS-Management) section 14, not recorded:
fault_destination_unreachable.xml the fault for a resource URI the service does not know
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope"
xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:c="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
xmlns:d="http://schemas.xmlsoap.org/ws/2005/02/trust"
xmlns:e="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:f="http://schemas.dmtf.org/wbem/wsman/1/cimbinding.xsd"
xmlns:g="http://intel.com/wbem/wscim/1/ips-schema/1/IPS_KVMRedirectionSettingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>0</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-00000000028D</b:MessageID>
<c:ResourceURI>http://intel.com/wbem/wscim/1/ips-schema/1/IPS_KVMRedirectionSettingData</c:ResourceURI>
</a:Header>
<a:Body>
<g:IPS_KVMRedirectionSettingData>
<g:BackToBackFbMode>false</g:BackToBackFbMode>
<g:DefaultScreen>0</g:DefaultScreen>
<g:ElementName>Intel(r) KVM Redirection Settings</g:ElementName>
<g:EnabledByMEBx>true</g:EnabledByMEBx>
<g:InstanceID>Intel(r) KVM Redirection Settings</g:InstanceID>
<g:Is5900PortEnabled>false</g:Is5900PortEnabled>
<g:OptInPolicy>true</g:OptInPolicy>
<g:OptInPolicyTimeout>300</g:OptInPolicyTimeout>
<g:RFBPassword></g:RFBPassword>
<g:SessionTimeout>3</g:SessionTimeout>
</g:IPS_KVMRedirectionSettingData>
</a:Body>
</a:Envelope>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<a:Envelope xmlns:a="http://www.w3.org/2003/05/soap-envelope" xmlns:b="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:g="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
<a:Header>
<b:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</b:To>
<b:RelatesTo>1</b:RelatesTo>
<b:Action a:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/fault</b:Action>
<b:MessageID>uuid:00000000-8086-8086-8086-000000000001</b:MessageID>
</a:Header>
<a:Body>
<a:Fault>
<a:Code>
<a:Value>a:Sender</a:Value>
<a:Subcode>
<a:Value>b:DestinationUnreachable</a:Value>
</a:Subcode>
</a:Code>
<a:Reason>
<a:Text xml:lang="en-US">No route can be determined to reach the destination role defined by the WS-Addressing To.</a:Text>
</a:Reason>
<a:Detail>
<g:FaultDetail>http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/InvalidResourceURI</g:FaultDetail>
</a:Detail>
</a:Fault>
</a:Body>
</a:Envelope>
View File
Whitespace-only changes.
+100
View File
@@ -0,0 +1,100 @@
"""CPUs, DIMMs and drives of the managed machine, from the recorded NUC9."""
import pytest
from napalm_amt.parsers import parse_cpus, parse_drives, parse_memory
from ..conftest import instances
def test_cpus_take_the_model_from_the_chip():
cpus = parse_cpus(instances("CIM_Processor.pull.xml"), instances("CIM_Chip.pull.xml"))
assert cpus == [
{
"socket": "CPU 0",
"model": "Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz",
"cores": None,
"threads": None,
"status": "OK",
}
]
@pytest.mark.parametrize(
("cpu_status", "status"),
[("1", "OK"), ("4", "OK"), ("2", "Warning"), ("3", "Critical"), ("0", ""), ("", "")],
)
def test_cpu_status_follows_cpustatus(cpu_status, status):
(cpu,) = parse_cpus([{"DeviceID": "CPU 0", "CPUStatus": cpu_status}], [])
assert cpu["status"] == status
assert cpu["model"] == ""
def test_memory():
dimms = parse_memory(instances("CIM_PhysicalMemory.pull.xml"))
assert dimms[0] == {
"slot": "BANK 0",
"size_bytes": 17179869184,
"type": "DDR4",
"speed_mts": 2400,
"part_number": "CT16G4SFD824A.M16FE",
"serial_number": "E0E8D670",
"status": "",
}
assert [d["slot"] for d in dimms] == ["BANK 0", "BANK 2"]
@pytest.mark.parametrize(
("code", "name"),
[("24", "DDR3"), ("26", "DDR4"), ("29", "LPDDR3"), ("34", "DDR5"), ("2", ""), ("", "")],
)
def test_memory_type_follows_smbios(code, name):
(dimm,) = parse_memory([{"BankLabel": "BANK 0", "MemoryType": code}])
assert dimm["type"] == name
def test_memory_without_a_configured_speed_falls_back_to_the_maximum():
(dimm,) = parse_memory(
[{"BankLabel": "A", "ConfiguredMemoryClockSpeed": "0", "MaxMemorySpeed": "2133"}]
)
assert dimm["speed_mts"] == 2133
def test_memory_slot_falls_back_to_the_tag():
(dimm,) = parse_memory([{"Tag": "ChannelA-DIMM0", "Capacity": "8589934592"}])
assert dimm["slot"] == "ChannelA-DIMM0"
assert dimm["size_bytes"] == 8589934592
def test_drives_size_is_in_kilobytes_of_1000():
drives = parse_drives(instances("CIM_MediaAccessDevice.pull.xml"))
# 500107862 KB is the classic 500 GB disk (976773168 sectors of 512 bytes).
assert drives == [
{
"slot": "MEDIA DEV 0",
"model": "",
"serial_number": "",
"size_bytes": 960197124000,
"media": "",
"protocol": "",
"status": "",
},
{
"slot": "MEDIA DEV 1",
"model": "",
"serial_number": "",
"size_bytes": 500107862000,
"media": "",
"protocol": "",
"status": "",
},
]
@pytest.mark.parametrize(
("operational", "status"), [("2", "OK"), ("3", "Warning"), ("6", "Critical"), ("0", "")]
)
def test_drive_status_follows_operational_status(operational, status):
(drive,) = parse_drives([{"DeviceID": "MEDIA DEV 0", "OperationalStatus": operational}])
assert drive["status"] == status
assert drive["size_bytes"] is None
+75
View File
@@ -0,0 +1,75 @@
"""AMT's hardware event log (AMT_MessageLog records), from the recorded NUC9."""
import base64
import pytest
from napalm_amt.parsers import parse_event_record
from ..conftest import instances
def _records():
(out,) = instances("AMT_MessageLog.GetRecords.xml")
return out["RecordArray"]
def test_failed_logins_are_critical():
entry = parse_event_record(_records()[0], "1")
assert entry == {
"id": "1",
"timestamp": 1704511587.0,
"severity": "Critical",
"message": "Intel(r) ME: Authentication failed 10 times. The system may be under attack.",
}
def test_bios_progress_is_ok():
entry = parse_event_record(_records()[1], "2")
assert entry["severity"] == "OK"
assert entry["message"] == "BIOS: PCI resource configuration"
assert entry["timestamp"] == 1694565922.0
def _record(sensor_type, offset, severity, entity, data=(0,) * 8, timestamp=1700000000):
raw = (
timestamp.to_bytes(4, "little")
+ bytes([0xFF, sensor_type, 0x6F, offset, 0x68, severity, 0xFF, entity, 0])
+ bytes(data)
)
return base64.b64encode(raw).decode()
@pytest.mark.parametrize(
("severity", "expected"),
[
(0, "OK"),
(1, "OK"),
(2, "OK"),
(4, "OK"),
(8, "Warning"),
(16, "Critical"),
(32, "Critical"),
],
)
def test_severity(severity, expected):
assert parse_event_record(_record(37, 0, severity, 34), "1")["severity"] == expected
def test_firmware_error():
entry = parse_event_record(_record(15, 0, 16, 34, (0, 1, 0, 0, 0, 0, 0, 0)), "1")
assert entry["message"] == ("BIOS: No system memory is physically installed in the system.")
def test_unknown_sensor_type_is_named():
entry = parse_event_record(_record(200, 0, 2, 2), "1")
assert entry["message"] == "Unknown: sensor type 200"
def test_no_timestamp_is_none():
assert parse_event_record(_record(30, 0, 16, 34, timestamp=0), "1")["timestamp"] is None
def test_a_short_or_broken_record_is_skipped():
assert parse_event_record("AAAA", "1") is None
assert parse_event_record("not base64!", "1") is None
+63
View File
@@ -0,0 +1,63 @@
"""AMT's own network ports (AMT_EthernetPortSettings), from the recorded NUC9."""
from napalm_amt.parsers import parse_ethernet_ports
from ..conftest import instances
def test_the_wired_port_is_kept_and_the_unused_wireless_one_dropped():
# The NUC9 lists a wireless port without a MAC address: there is no WLAN card.
ports = parse_ethernet_ports(instances("AMT_EthernetPortSettings.pull.xml"))
assert ports == [
{
"name": "wired",
"mac_address": "00:be:43:d8:22:a4",
"link_up": True,
"dhcp": True,
"shared_ip": True,
"ip": "",
"prefix_length": None,
}
]
def test_a_static_address_with_its_mask():
(port,) = parse_ethernet_ports(
[
{
"InstanceID": "Intel(r) AMT Ethernet Port Settings 0",
"MACAddress": "6C-4B-90-12-34-56",
"LinkIsUp": "true",
"DHCPEnabled": "false",
"SharedStaticIp": "false",
"IPAddress": "172.22.8.61",
"SubnetMask": "255.255.255.0",
"PhysicalConnectionType": "0",
}
]
)
assert port["mac_address"] == "6c:4b:90:12:34:56"
assert (port["ip"], port["prefix_length"]) == ("172.22.8.61", 24)
assert port["dhcp"] is False
assert port["shared_ip"] is False
def test_a_wireless_port_with_a_card_is_named_wireless():
ports = parse_ethernet_ports(
[
{
"InstanceID": "Intel(r) AMT Ethernet Port Settings 1",
"MACAddress": "a0-88-69-01-02-03",
"PhysicalConnectionType": "3",
"LinkIsUp": "false",
},
]
)
assert [(p["name"], p["link_up"]) for p in ports] == [("wireless", False)]
def test_an_invalid_mask_gives_no_prefix():
(port,) = parse_ethernet_ports(
[{"MACAddress": "00-be-43-d8-22-a4", "IPAddress": "10.0.0.5", "SubnetMask": "255.0.255.0"}]
)
assert port["prefix_length"] is None
+73
View File
@@ -0,0 +1,73 @@
"""The machine's power state and what AMT accepts, from the recorded NUC9."""
import pytest
from napalm_amt.parsers import POWER_REQUESTS, accepted_actions, parse_power_state
from ..conftest import instances
def test_power_state_of_a_running_machine():
(service,) = instances("CIM_AssociatedPowerManagementService.pull.xml")
assert parse_power_state(service) == {
"state": "On",
"available": [10, 8, 5, 11, 4, 7, 14, 12],
}
@pytest.mark.parametrize(
("code", "state"),
[
("2", "On"),
("8", "Off"),
("6", "Off"),
("13", "Off"),
# Asleep or hibernating: the OS is not running, On wakes it.
("3", "Off"),
("4", "Off"),
("7", "Off"),
("99", ""),
("", ""),
],
)
def test_power_state_codes(code, state):
assert parse_power_state({"PowerState": code})["state"] == state
def test_a_single_available_state_is_a_list():
assert parse_power_state({"PowerState": "8", "AvailableRequestedPowerStates": "2"})[
"available"
] == [2]
def test_running_machine_accepts_what_amt_offers_except_on():
assert accepted_actions("On", [10, 8, 5, 11, 4, 7, 14, 12]) == [
"GracefulShutdown",
"ForceOff",
"GracefulRestart",
"ForceRestart",
"PowerCycle",
]
def test_without_graceful_states_amt_offers_no_graceful_actions():
# AMT lists the graceful states only where the host can honour them.
assert accepted_actions("On", [10, 8, 5]) == ["ForceOff", "ForceRestart", "PowerCycle"]
def test_machine_that_is_off_accepts_on_only():
assert accepted_actions("Off", [2]) == ["On"]
assert accepted_actions("Off", []) == ["On"]
def test_unknown_state_accepts_nothing():
assert accepted_actions("", [2, 8, 10]) == []
def test_power_requests_cover_every_role_action():
from napalm_device_types.models import POWER_ACTIONS
assert set(POWER_REQUESTS) == set(POWER_ACTIONS)
assert POWER_REQUESTS["On"] == 2
assert POWER_REQUESTS["ForceOff"] == 8
assert POWER_REQUESTS["ForceRestart"] == 10
+97
View File
@@ -0,0 +1,97 @@
"""What AMT listens on: plain HTTP or TLS, the KVM console and IDE/USB redirection."""
import pytest
from napalm_amt.parsers import parse_management_protocols
from ..conftest import instances
def _protocols(**overrides):
args = {
"tls_settings": instances("AMT_TLSSettingData.pull.xml"),
"redirection": instances("AMT_RedirectionService.get.xml")[0],
"kvm_settings": instances("IPS_KVMRedirectionSettingData.get.xml")[0],
"kvm_saps": instances("CIM_KVMRedirectionSAP.pull.xml"),
}
args.update(overrides)
return parse_management_protocols(**args)
def test_amt_without_tls_listens_on_plain_http():
assert _protocols() == {
"ipmi": {"enabled": False, "port": 623},
"ssh": {"enabled": False, "port": 22},
"http": {"enabled": True, "port": 16992},
"https": {"enabled": False, "port": 16993},
"snmp": {"enabled": False, "port": 161},
# KVM is enabled (MEBx), offline until someone connects; over the redirection
# port, as the standard VNC port 5900 is off.
"kvm": {"enabled": True, "port": 16994},
# IDE-R/USB-R and SOL are both on (EnabledState 32771).
"virtual_media": {"enabled": True, "port": 16994},
}
def test_amt_with_tls_listens_on_16993_and_redirects_over_tls():
tls = [
{
"InstanceID": "Intel(r) AMT 802.3 TLS Settings",
"Enabled": "true",
"AcceptNonSecureConnections": "false",
}
]
protocols = _protocols(tls_settings=tls)
assert protocols["https"] == {"enabled": True, "port": 16993}
assert protocols["http"] == {"enabled": False, "port": 16992}
assert protocols["kvm"]["port"] == 16995
assert protocols["virtual_media"]["port"] == 16995
def test_tls_that_still_accepts_plain_connections_keeps_http_open():
tls = [
{
"InstanceID": "Intel(r) AMT 802.3 TLS Settings",
"Enabled": "true",
"AcceptNonSecureConnections": "true",
}
]
assert _protocols(tls_settings=tls)["http"]["enabled"] is True
def test_the_lms_tls_setting_is_local_and_ignored():
tls = [{"InstanceID": "Intel(r) AMT LMS TLS Settings", "Enabled": "true"}]
assert _protocols(tls_settings=tls)["https"]["enabled"] is False
def test_kvm_on_the_standard_vnc_port():
kvm = {**instances("IPS_KVMRedirectionSettingData.get.xml")[0], "Is5900PortEnabled": "true"}
assert _protocols(kvm_settings=kvm)["kvm"] == {"enabled": True, "port": 5900}
@pytest.mark.parametrize("sap_state", ["3", "4"])
def test_kvm_disabled(sap_state):
saps = [{"EnabledState": sap_state}]
assert _protocols(kvm_saps=saps)["kvm"]["enabled"] is False
def test_kvm_disabled_in_mebx():
kvm = {**instances("IPS_KVMRedirectionSettingData.get.xml")[0], "EnabledByMEBx": "false"}
assert _protocols(kvm_settings=kvm)["kvm"]["enabled"] is False
def test_kvm_unknown_without_any_data():
assert _protocols(kvm_settings={}, kvm_saps=[])["kvm"]["enabled"] is False
@pytest.mark.parametrize(
("state", "enabled"),
[("32768", False), ("32769", True), ("32770", False), ("32771", True), ("", False)],
)
def test_virtual_media_is_ide_redirection(state, enabled):
assert _protocols(redirection={"EnabledState": state})["virtual_media"]["enabled"] is enabled
def test_redirection_listener_off_closes_virtual_media():
redirection = {"EnabledState": "32771", "ListenerEnabled": "false"}
assert _protocols(redirection=redirection)["virtual_media"]["enabled"] is False
+98
View File
@@ -0,0 +1,98 @@
"""The machine's identity and AMT's firmware, from the recorded NUC9 (AMT 12.0.67)."""
import pytest
from napalm_amt.parsers import (
parse_firmware,
parse_platform_guid,
parse_software_identity,
parse_system_identity,
uuid_from_base64,
)
from ..conftest import instances
def test_software_identity_gives_the_amt_version_with_its_build():
identity = parse_software_identity(instances("CIM_SoftwareIdentity.pull.xml"))
assert identity["amt"] == "12.0.67.1579"
assert identity["flash"] == "12.0.67"
def test_software_identity_without_build_keeps_the_version():
identity = parse_software_identity([{"InstanceID": "AMT", "VersionString": "11.8.50"}])
assert identity["amt"] == "11.8.50"
def test_software_identity_of_nothing_is_empty():
assert parse_software_identity([]) == {"amt": "", "flash": ""}
def test_platform_guid_is_the_smbios_uuid():
# AMT sends the SMBIOS UUID's bytes as stored; the first three groups are
# little-endian, as dmidecode and Intel's own console decode them.
(package,) = instances("CIM_ComputerSystemPackage.pull.xml")
assert parse_platform_guid(package["PlatformGUID"]) == "55e3ae13-bfd2-61bb-17a0-88aedd7037ea"
def test_get_uuid_and_platform_guid_agree():
(out,) = instances("AMT_SetupAndConfigurationService.GetUuid.xml")
assert uuid_from_base64(out["UUID"]) == "55e3ae13-bfd2-61bb-17a0-88aedd7037ea"
@pytest.mark.parametrize("guid", ["", "zz", "13AEE355", "0" * 32, "F" * 32])
def test_platform_guid_placeholders_and_garbage_are_empty(guid):
assert parse_platform_guid(guid) == ""
def test_system_identity_comes_from_the_chassis():
identity = parse_system_identity(
instances("CIM_Chassis.pull.xml"), instances("CIM_Card.pull.xml")
)
assert identity == {
"manufacturer": "Intel(R) Client Systems",
"model": "NUC9V7QNX",
"serial_number": "JRQN0243007J",
"board_model": "NUC9V7QNB",
"board_serial": "KNQN0221020W",
}
def test_system_identity_falls_back_to_the_board_for_placeholders():
chassis = [
{
"Manufacturer": "Default string",
"Model": "To Be Filled By O.E.M.",
"SerialNumber": "Default string",
}
]
card = [{"Manufacturer": "LENOVO", "Model": "3102", "SerialNumber": "L1HF8AB01XY"}]
identity = parse_system_identity(chassis, card)
assert identity["manufacturer"] == "LENOVO"
assert identity["model"] == "3102"
assert identity["serial_number"] == "L1HF8AB01XY"
def test_system_identity_of_nothing_is_empty():
assert parse_system_identity([], []) == {
"manufacturer": "",
"model": "",
"serial_number": "",
"board_model": "",
"board_serial": "",
}
def test_firmware_lists_amt_and_the_bios():
firmware = parse_firmware(
parse_software_identity(instances("CIM_SoftwareIdentity.pull.xml")),
instances("CIM_BIOSElement.pull.xml"),
)
assert firmware == [
{"name": "Intel AMT", "version": "12.0.67.1579", "updateable": None},
{"name": "BIOS", "version": "QNCFLX70.0054.2020.0810.2227", "updateable": None},
]
def test_firmware_skips_what_is_unknown():
assert parse_firmware({"amt": "", "flash": ""}, []) == []
+45
View File
@@ -0,0 +1,45 @@
"""What netOrk's discovery scores the driver on.
netOrk lowercases the page (title, Server header, body) and matches each rule's pattern as
a substring; a port that answers adds its PortSpec weight. AMT names itself in its
``Server`` header on every answer, also the 401 of a page that needs a login.
"""
from napalm_device_types.base import rules_max_weight
from napalm_amt import AmtDriver
def _score(text: str) -> float:
text = " ".join(text.lower().split())
return sum(rule.weight for rule in AmtDriver.HTTP_FINGERPRINT if rule.pattern in text)
def test_amt_ports_are_probed():
assert {(s.scheme, s.port) for s in AmtDriver.PORT_SPECS} == {("http", 16992), ("https", 16993)}
def test_server_header_is_recognised():
assert _score("Intel(R) Active Management Technology 11.8.50.3399") >= 10.0
def test_web_ui_landing_page_is_recognised():
page = (
"<html><head><title>Intel&reg; Active Management Technology</title></head>"
"<body>Log On</body></html>"
)
assert _score(page) >= 10.0
def test_other_pages_score_nothing():
assert _score("<title>Loading...</title> Web Switch nginx") == 0.0
def test_an_answering_amt_port_with_its_header_is_a_confident_match():
# One of the two ports answers (16992 without TLS, 16993 with); with the header the
# normalised score must reach netOrk's "high" (0.7).
port = max(s.weight for s in AmtDriver.PORT_SPECS)
total = sum(s.weight for s in AmtDriver.PORT_SPECS) + rules_max_weight(
AmtDriver.HTTP_FINGERPRINT
)
assert (port + _score("Intel(R) Active Management Technology 11.8")) / total >= 0.7
+327
View File
@@ -0,0 +1,327 @@
"""The driver end to end against the recorded NUC9 (AMT 12.0.67), served over mocked HTTP."""
import pytest
import requests
import responses
from napalm.base.exceptions import ConnectionException
from napalm_device_types import ManagementControllerDriver
from napalm_amt import AmtDriver
from .conftest import HOST, URL, load, patched
@pytest.fixture
def driver(amt):
d = AmtDriver(HOST, "admin", "P@ssw0rd")
d.open()
yield d
d.close()
def test_is_a_management_controller():
assert issubclass(AmtDriver, ManagementControllerDriver)
assert AmtDriver.ROLE == "management_controller"
assert AmtDriver.DRIVER_NAME == "amt"
assert AmtDriver.default_port == 16992
def test_does_not_offer_a_controller_reset():
# AMT cannot be restarted over WS-Management; the role method stays absent so
# netOrk does not offer it.
assert not hasattr(AmtDriver, "reboot_host")
def test_tls_follows_the_port():
assert AmtDriver(HOST, "u", "p").transport.url == f"http://{HOST}:16992/wsman"
tls = AmtDriver(HOST, "u", "p", optional_args={"port": 16993, "verify_ssl": False})
assert tls.transport.url == f"https://{HOST}:16993/wsman"
assert tls.transport.session.verify is False
# --- connection ------------------------------------------------------------------------
def test_open_reads_the_general_settings(amt):
d = AmtDriver(HOST, "admin", "P@ssw0rd")
d.open()
assert [r.resource for r in amt.requests] == ["AMT_GeneralSettings"]
assert d.is_alive() == {"is_alive": True}
def test_open_with_wrong_credentials_fails():
with responses.RequestsMock() as rsps:
rsps.add(
responses.POST,
URL,
status=401,
headers={"WWW-Authenticate": 'Digest realm="Digest:0", nonce="n", qop="auth"'},
)
with pytest.raises(ConnectionException, match="credentials"):
AmtDriver(HOST, "admin", "wrong", optional_args={"retries": 0}).open()
def test_open_without_an_answer_fails():
with responses.RequestsMock() as rsps:
rsps.add(responses.POST, URL, body=requests.ConnectionError("refused"))
with pytest.raises(ConnectionException):
AmtDriver(HOST, "admin", "pw", optional_args={"retries": 0}).open()
def test_is_alive_asks_amt(driver, amt):
amt.override("AMT_GeneralSettings", "Get", 500, "<html>gone</html>")
assert driver.is_alive() == {"is_alive": False}
def test_is_alive_before_open_is_false():
assert AmtDriver(HOST, "u", "p").is_alive() == {"is_alive": False}
# --- NAPALM getters --------------------------------------------------------------------
def test_facts(driver):
assert driver.get_facts() == {
"uptime": -1.0,
"vendor": "Intel(R) Client Systems",
"model": "NUC9V7QNX",
"hostname": "Test Host Name",
"fqdn": "Test Host Name.Test Domain Name",
"os_version": "12.0.67.1579",
"serial_number": "JRQN0243007J",
"interface_list": ["wired"],
}
def test_facts_without_an_amt_hostname_use_the_address(amt):
amt.override(
"AMT_GeneralSettings",
"Get",
200,
patched(
"AMT_GeneralSettings.get.xml",
"<g:HostName>Test Host Name</g:HostName>",
"<g:HostName></g:HostName>",
),
)
d = AmtDriver(HOST, "admin", "pw")
d.open()
facts = d.get_facts()
assert facts["hostname"] == HOST
assert facts["fqdn"] == HOST
def test_interfaces(driver):
assert driver.get_interfaces() == {
"wired": {
"is_up": True,
"is_enabled": True,
"description": "Intel AMT, wired, DHCP, shares the host's IP address",
"last_flapped": -1.0,
"speed": -1.0,
"mtu": -1,
"mac_address": "00:be:43:d8:22:a4",
}
}
def test_interfaces_ip_without_an_address_is_empty(driver):
# In DHCP mode the NUC9 reports no address of its own.
assert driver.get_interfaces_ip() == {}
def test_interfaces_ip_with_a_static_address(amt):
pull = patched(
"AMT_EthernetPortSettings.pull.xml",
"<h:DHCPEnabled>true</h:DHCPEnabled>",
"<h:DHCPEnabled>false</h:DHCPEnabled><h:IPAddress>172.22.8.61</h:IPAddress>",
1,
)
amt.override("AMT_EthernetPortSettings", "Pull", 200, pull)
d = AmtDriver(HOST, "admin", "pw")
d.open()
assert d.get_interfaces_ip() == {"wired": {"ipv4": {"172.22.8.61": {"prefix_length": 24}}}}
assert "static" in d.get_interfaces()["wired"]["description"]
def test_environment_is_empty(driver):
# AMT on a client platform reports no temperatures, fans or power supplies.
assert driver.get_environment() == {
"fans": {},
"temperature": {},
"power": {},
"cpu": {},
"memory": {},
}
# --- role methods ----------------------------------------------------------------------
def test_power_state(driver):
assert driver.get_power_state() == {
"state": "On",
"actions": [
"GracefulShutdown",
"ForceOff",
"GracefulRestart",
"ForceRestart",
"PowerCycle",
],
}
def test_set_power_state_asks_amt_for_the_cim_state(driver, amt):
driver.set_power_state("ForceOff")
(request,) = amt.calls("RequestPowerStateChange")
assert "<h:PowerState>8</h:PowerState>" in request.xml
assert '<Selector Name="Name">ManagedSystem</Selector>' in request.xml
def test_set_power_state_refuses_an_unknown_action(driver):
with pytest.raises(ValueError):
driver.set_power_state("Explode")
def test_set_power_state_refuses_on_for_a_running_machine(driver, amt):
with pytest.raises(RuntimeError, match="not accepted"):
driver.set_power_state("On")
assert amt.calls("RequestPowerStateChange") == []
def test_set_power_state_reports_amt_refusing(driver, amt):
amt.override(
"CIM_PowerManagementService",
"RequestPowerStateChange",
200,
patched(
"CIM_PowerManagementService.RequestPowerStateChange.xml",
"<g:ReturnValue>0</g:ReturnValue>",
"<g:ReturnValue>2</g:ReturnValue>",
),
)
with pytest.raises(RuntimeError, match="refused.*2"):
driver.set_power_state("ForceRestart")
def test_set_power_state_accepts_a_started_job(driver, amt):
amt.override(
"CIM_PowerManagementService",
"RequestPowerStateChange",
200,
patched(
"CIM_PowerManagementService.RequestPowerStateChange.xml",
"<g:ReturnValue>0</g:ReturnValue>",
"<g:ReturnValue>4096</g:ReturnValue>",
),
)
driver.set_power_state("PowerCycle")
def test_hardware_inventory(driver):
inventory = driver.get_hardware_inventory()
assert {k: v for k, v in inventory.items() if not isinstance(v, list)} == {
"manufacturer": "Intel(R) Client Systems",
"model": "NUC9V7QNX",
"serial_number": "JRQN0243007J",
"system_uuid": "55e3ae13-bfd2-61bb-17a0-88aedd7037ea",
}
assert [c["model"] for c in inventory["cpus"]] == ["Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz"]
assert len(inventory["memory"]) == 2
assert len(inventory["drives"]) == 2
assert inventory["power_supplies"] == []
assert inventory["nics"] == [
{"name": "wired", "mac_address": "00:be:43:d8:22:a4", "speed_mbps": None, "link_up": True}
]
def test_hardware_inventory_survives_a_class_amt_lacks(driver, amt):
# Older AMT versions know fewer CIM classes; a missing one leaves its part empty.
amt.override(
"CIM_MediaAccessDevice", "Enumerate", 400, load("fault_destination_unreachable.xml")
)
inventory = driver.get_hardware_inventory()
assert inventory["drives"] == []
assert len(inventory["memory"]) == 2
def test_event_log_newest_first(driver, amt):
log = driver.get_event_log()
assert [e["id"] for e in log] == ["1", "2", "3"]
assert log[0]["severity"] == "Critical"
assert log[0]["timestamp"] > log[1]["timestamp"]
(position,) = amt.calls("PositionToFirstRecord")
(records,) = amt.calls("GetRecords")
assert "<h:IterationIdentifier>1</h:IterationIdentifier>" in records.xml
def test_event_log_limit(driver):
assert len(driver.get_event_log(limit=1)) == 1
def test_event_log_empty(driver, amt):
amt.override(
"AMT_MessageLog",
"PositionToFirstRecord",
200,
patched(
"AMT_MessageLog.PositionToFirstRecord.xml",
"<g:ReturnValue>0</g:ReturnValue>",
"<g:ReturnValue>2</g:ReturnValue>",
),
)
assert driver.get_event_log() == []
assert amt.calls("GetRecords") == []
def test_event_log_reads_on_until_no_more_records(driver, amt):
first_page = patched(
"AMT_MessageLog.GetRecords.xml",
"<g:NoMoreRecords>true</g:NoMoreRecords>",
"<g:NoMoreRecords>false</g:NoMoreRecords>",
)
pages = iter([first_page, load("AMT_MessageLog.GetRecords.xml")])
original = amt._answer
def answer(req):
if req.operation == "GetRecords":
return 200, next(pages)
return original(req)
amt._answer = answer
log = driver.get_event_log()
assert len(log) == 6
second = amt.calls("GetRecords")[1]
assert "<h:IterationIdentifier>3</h:IterationIdentifier>" in second.xml
def test_firmware_inventory(driver):
assert driver.get_firmware_inventory() == [
{"name": "Intel AMT", "version": "12.0.67.1579", "updateable": None},
{"name": "BIOS", "version": "QNCFLX70.0054.2020.0810.2227", "updateable": None},
]
def test_management_protocols(driver):
protocols = driver.get_management_protocols()
assert protocols["http"] == {"enabled": True, "port": 16992}
assert protocols["https"] == {"enabled": False, "port": 16993}
assert protocols["kvm"] == {"enabled": True, "port": 16994}
def test_reads_are_cached_per_connection(driver, amt):
driver.get_facts()
driver.get_hardware_inventory()
before = len(amt.requests)
driver.get_facts()
assert len(amt.requests) == before
driver.close()
driver.open()
driver.get_facts()
assert len(amt.requests) > before
def test_getters_before_open_raise():
with pytest.raises(ConnectionException):
AmtDriver(HOST, "u", "p").get_facts()
+118
View File
@@ -0,0 +1,118 @@
"""Recording fixtures from a real AMT: every read the driver makes, nothing that changes it."""
import pytest
import responses
from napalm_amt.record import READS, main, record
from napalm_amt.wsman import WsmanTransport
from .conftest import DMT, HOST, AmtServer
def test_records_every_read_under_the_fixture_names(amt, tmp_path):
record(WsmanTransport(HOST, "admin", "pw"), tmp_path)
names = sorted(p.name for p in tmp_path.iterdir())
assert "AMT_GeneralSettings.get.xml" in names
assert "CIM_PhysicalMemory.pull.xml" in names
assert "AMT_SetupAndConfigurationService.GetUuid.xml" in names
assert "AMT_MessageLog.GetRecords.xml" in names
assert "COMMANDS.txt" in names
assert (tmp_path / "CIM_PhysicalMemory.pull.xml").read_text() == (
DMT / "CIM_PhysicalMemory.pull.xml"
).read_text()
def test_a_second_page_gets_its_own_file(amt, tmp_path):
record(WsmanTransport(HOST, "admin", "pw"), tmp_path)
# CIM_Chip answers in two pages (the second is the mock's empty last page).
assert (tmp_path / "CIM_Chip.pull.xml").exists()
assert (tmp_path / "CIM_Chip.pull.2.xml").exists()
def test_never_switches_power_or_writes(amt, tmp_path):
record(WsmanTransport(HOST, "admin", "pw"), tmp_path)
operations = {r.operation for r in amt.requests}
assert operations <= {
"Get",
"Enumerate",
"Pull",
"GetUuid",
"PositionToFirstRecord",
"GetRecords",
}
def test_a_class_amt_lacks_is_recorded_as_its_fault(amt, tmp_path):
amt.override(
"CIM_MediaAccessDevice",
"Enumerate",
400,
(DMT / "fault_destination_unreachable.xml").read_text(),
)
record(WsmanTransport(HOST, "admin", "pw"), tmp_path)
assert (
"DestinationUnreachable" in (tmp_path / "CIM_MediaAccessDevice.enumerate.xml").read_text()
)
assert "CIM_MediaAccessDevice" in (tmp_path / "COMMANDS.txt").read_text()
def test_the_provisioning_otp_is_redacted(amt, tmp_path):
record(WsmanTransport(HOST, "admin", "pw"), tmp_path)
text = (tmp_path / "AMT_SetupAndConfigurationService.get.xml").read_text()
assert "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" not in text
assert "<g:ProvisioningServerOTP>REDACTED</g:ProvisioningServerOTP>" in text
def test_every_read_names_a_known_class():
from napalm_amt.wsman import resource_uri
for resource, _operation in READS:
resource_uri(resource)
def test_main_reads_the_password_from_a_file(tmp_path, monkeypatch):
secret = tmp_path / "pw"
secret.write_text("P@ssw0rd\n")
out = tmp_path / "out"
with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
AmtServer(rsps)
assert (
main(
[
HOST,
"--user",
"admin",
"--password-file",
str(secret),
"--out",
str(out),
"--no-landing-page",
]
)
== 0
)
assert (out / "AMT_GeneralSettings.get.xml").exists()
def test_main_without_a_password_fails(tmp_path, monkeypatch):
monkeypatch.delenv("AMT_PASSWORD", raising=False)
with pytest.raises(SystemExit):
main([HOST, "--out", str(tmp_path)])
def test_landing_page_with_its_headers_is_kept(tmp_path):
with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps:
AmtServer(rsps)
rsps.add(
responses.GET,
f"http://{HOST}:16992/",
status=200,
headers={"Server": "Intel(R) Active Management Technology 11.8.50.3399"},
body="<html><title>Intel&reg; Active Management Technology</title></html>",
)
secret = tmp_path / "pw"
secret.write_text("pw")
main([HOST, "--password-file", str(secret), "--out", str(tmp_path / "out")])
page = (tmp_path / "out" / "landing_page.txt").read_text()
assert "Server: Intel(R) Active Management Technology 11.8.50.3399" in page
assert "<title>Intel&reg; Active Management Technology</title>" in page
+293
View File
@@ -0,0 +1,293 @@
"""The WS-Management client: envelopes, Digest auth, enumeration, methods and faults."""
import pytest
import requests
import responses
from napalm_amt.wsman import (
WsmanAuthError,
WsmanError,
WsmanFault,
WsmanTransport,
resource_uri,
)
from .conftest import HOST, URL, Request, load, patched
def _transport(**kwargs) -> WsmanTransport:
return WsmanTransport(HOST, "admin", "P@ssw0rd", **kwargs)
# --- resource URIs ---------------------------------------------------------------------
@pytest.mark.parametrize(
("resource", "uri"),
[
("AMT_GeneralSettings", "http://intel.com/wbem/wscim/1/amt-schema/1/AMT_GeneralSettings"),
(
"IPS_KVMRedirectionSettingData",
"http://intel.com/wbem/wscim/1/ips-schema/1/IPS_KVMRedirectionSettingData",
),
("CIM_Processor", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Processor"),
],
)
def test_resource_uri_follows_the_class_prefix(resource, uri):
assert resource_uri(resource) == uri
def test_resource_uri_refuses_an_unknown_prefix():
with pytest.raises(ValueError):
resource_uri("Win32_Processor")
def test_url_is_plain_http_on_16992_and_tls_on_16993():
assert _transport().url == f"http://{HOST}:16992/wsman"
assert _transport(port=16993).url == f"https://{HOST}:16993/wsman"
assert _transport(port=8443, tls=True).url == f"https://{HOST}:8443/wsman"
# --- reading ---------------------------------------------------------------------------
def test_get_returns_the_instance_as_a_dict(amt):
settings = _transport().get("AMT_GeneralSettings")
assert settings["HostName"] == "Test Host Name"
assert settings["AMTNetworkEnabled"] == "1"
request = amt.calls("Get")[0]
assert request.action == "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get"
assert request.resource_uri == resource_uri("AMT_GeneralSettings")
def test_enumerate_pulls_every_instance(amt):
items = _transport().enumerate("CIM_PhysicalMemory")
assert [i["BankLabel"] for i in items] == ["BANK 0", "BANK 2"]
assert [r.operation for r in amt.requests] == ["Enumerate", "Pull"]
assert amt.calls("Pull")[0].context == "ctx-CIM_PhysicalMemory"
def test_enumerate_follows_the_context_until_end_of_sequence(amt):
# CIM_Chip's first page carries a context and no EndOfSequence: pull again.
items = _transport().enumerate("CIM_Chip")
assert [i["Version"] for i in items] == ["Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz"]
assert [r.operation for r in amt.requests] == ["Enumerate", "Pull", "Pull"]
assert amt.calls("Pull")[1].context == "D4020000-0000-0000-0000-000000000000"
def test_repeated_elements_become_lists(amt):
(service,) = _transport().enumerate("CIM_AssociatedPowerManagementService")
assert service["PowerState"] == "2"
assert service["AvailableRequestedPowerStates"] == ["10", "8", "5", "11", "4", "7", "14", "12"]
def test_nested_elements_become_dicts(amt):
(bios,) = _transport().enumerate("CIM_BIOSElement")
assert bios["ReleaseDate"] == {"Datetime": "2020-08-10T00:00:00Z"}
def test_an_empty_element_is_an_empty_string(amt):
kvm = _transport().get("IPS_KVMRedirectionSettingData")
assert kvm["RFBPassword"] == ""
def test_invoke_returns_the_output_parameters(amt):
out = _transport().invoke("AMT_SetupAndConfigurationService", "GetUuid")
assert out == {"UUID": "E67jVdK/u2EXoIiu3XA36g=="}
request = amt.calls("GetUuid")[0]
assert request.action == (
"http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService/GetUuid"
)
assert (
request.body.find(
"{http://intel.com/wbem/wscim/1/amt-schema/1/AMT_SetupAndConfigurationService}"
"GetUuid_INPUT"
)
is not None
)
def test_invoke_sends_the_input_parameters_in_order(amt):
_transport().invoke(
"AMT_MessageLog", "GetRecords", [("IterationIdentifier", "1"), ("MaxReadRecords", "390")]
)
body = amt.calls("GetRecords")[0].body
ns = "{http://intel.com/wbem/wscim/1/amt-schema/1/AMT_MessageLog}"
params = body.find(f"{ns}GetRecords_INPUT")
assert [(p.tag.removeprefix(ns), p.text) for p in params] == [
("IterationIdentifier", "1"),
("MaxReadRecords", "390"),
]
def test_invoke_accepts_raw_xml_for_references(amt):
ref = "<h:ManagedElement><Address>x</Address></h:ManagedElement>"
_transport().invoke(
"CIM_PowerManagementService", "RequestPowerStateChange", [("PowerState", "8")], raw=ref
)
xml = amt.calls("RequestPowerStateChange")[0].xml
assert "<h:PowerState>8</h:PowerState><h:ManagedElement>" in xml
def test_selectors_go_into_the_header(amt):
_transport().get("AMT_GeneralSettings", selectors={"InstanceID": "Intel(r) AMT: General"})
assert amt.calls("Get")[0].selectors == {"InstanceID": "Intel(r) AMT: General"}
def test_values_are_escaped(amt):
_transport().invoke("AMT_MessageLog", "GetRecords", [("Tag", "<a&b>")])
assert "&lt;a&amp;b&gt;" in amt.calls("GetRecords")[0].xml
def test_message_ids_differ_per_request(amt):
transport = _transport()
transport.get("AMT_GeneralSettings")
transport.get("AMT_GeneralSettings")
ids = [r.xml.split("<a:MessageID>")[1].split("<")[0] for r in amt.requests]
assert len(set(ids)) == 2
# --- errors ----------------------------------------------------------------------------
def test_a_fault_raises_with_its_subcode_and_reason(amt):
with pytest.raises(WsmanFault) as excinfo:
_transport().get("AMT_NoSuchClass")
fault = excinfo.value
assert fault.subcode == "DestinationUnreachable"
assert "No route can be determined" in fault.reason
assert fault.detail.endswith("/InvalidResourceURI")
assert isinstance(fault, WsmanError)
def test_an_unknown_class_in_an_enumeration_raises_the_fault(amt):
with pytest.raises(WsmanFault):
_transport().enumerate("CIM_NoSuchClass")
def test_a_method_returning_an_error_code_raises(amt):
amt.override(
"AMT_MessageLog",
"PositionToFirstRecord",
200,
patched(
"AMT_MessageLog.PositionToFirstRecord.xml",
"<g:ReturnValue>0</g:ReturnValue>",
"<g:ReturnValue>2</g:ReturnValue>",
),
)
with pytest.raises(WsmanError, match="ReturnValue 2"):
_transport().invoke("AMT_MessageLog", "PositionToFirstRecord")
def test_a_method_may_be_allowed_an_error_code(amt):
amt.override(
"AMT_MessageLog",
"PositionToFirstRecord",
200,
patched(
"AMT_MessageLog.PositionToFirstRecord.xml",
"<g:ReturnValue>0</g:ReturnValue>",
"<g:ReturnValue>2</g:ReturnValue>",
),
)
out = _transport().invoke("AMT_MessageLog", "PositionToFirstRecord", check=False)
assert out["ReturnValue"] == "2"
def test_wrong_credentials_raise_an_auth_error():
with responses.RequestsMock() as rsps:
rsps.add(
responses.POST,
URL,
status=401,
headers={"WWW-Authenticate": 'Digest realm="Digest:0", nonce="n", qop="auth"'},
)
with pytest.raises(WsmanAuthError):
_transport(retries=0).get("AMT_GeneralSettings")
def test_a_non_soap_error_raises():
with responses.RequestsMock() as rsps:
rsps.add(responses.POST, URL, status=500, body="<html>busy</html>")
with pytest.raises(WsmanError, match="HTTP 500"):
_transport(retries=0).get("AMT_GeneralSettings")
def test_a_connection_error_is_retried_then_raised():
with responses.RequestsMock() as rsps:
rsps.add(responses.POST, URL, body=requests.ConnectionError("refused"))
rsps.add(responses.POST, URL, body=load("AMT_GeneralSettings.get.xml"))
assert _transport(retries=1).get("AMT_GeneralSettings")["HostName"] == "Test Host Name"
with responses.RequestsMock() as rsps:
rsps.add(responses.POST, URL, body=requests.ConnectionError("refused"))
with pytest.raises(WsmanError, match="refused"):
_transport(retries=0).get("AMT_GeneralSettings")
# --- Digest authentication -------------------------------------------------------------
def test_digest_challenge_is_answered():
"""AMT accepts only HTTP Digest; the first request draws the challenge."""
seen = []
def handle(request):
seen.append(request.headers.get("Authorization"))
if not request.headers.get("Authorization"):
return (
401,
{
"WWW-Authenticate": 'Digest realm="Digest:F3EB554784E729164447A89F60B641C5", '
'nonce="dGVzdG5vbmNl", stale="false", qop="auth"'
},
"",
)
return 200, {}, load("AMT_GeneralSettings.get.xml")
with responses.RequestsMock() as rsps:
rsps.add_callback(responses.POST, URL, callback=handle)
assert _transport().get("AMT_GeneralSettings")["HostName"] == "Test Host Name"
assert seen[0] is None
assert seen[1].startswith("Digest ")
assert 'username="admin"' in seen[1]
assert 'uri="/wsman"' in seen[1]
assert 'qop="auth"' in seen[1] or "qop=auth" in seen[1]
def test_request_is_a_soap_post():
with responses.RequestsMock() as rsps:
rsps.add(responses.POST, URL, body=load("AMT_GeneralSettings.get.xml"))
_transport().get("AMT_GeneralSettings")
sent = rsps.calls[0].request
assert sent.headers["Content-Type"].startswith("application/soap+xml")
request = Request(sent.body)
assert request.resource == "AMT_GeneralSettings"
# --- recording -------------------------------------------------------------------------
def test_recorder_sees_every_raw_answer(amt):
seen = []
transport = _transport()
transport.recorder = lambda resource, operation, content: seen.append(
(resource, operation, content[:5])
)
transport.enumerate("CIM_PhysicalMemory")
transport.invoke("AMT_SetupAndConfigurationService", "GetUuid")
assert [(r, o) for r, o, _ in seen] == [
("CIM_PhysicalMemory", "Enumerate"),
("CIM_PhysicalMemory", "Pull"),
("AMT_SetupAndConfigurationService", "GetUuid"),
]
assert all(c == b"<?xml" for _, _, c in seen)
def test_recorder_sees_faults_too(amt):
seen = []
transport = _transport()
transport.recorder = lambda resource, operation, content: seen.append(operation)
with pytest.raises(WsmanFault):
transport.get("AMT_NoSuchClass")
assert seen == ["Get"]