Сценарии PowerShell для Hyper-V и WMI. Использование компонента интеграции обмена парами ключ-значение (KVP Exchange integration component). Часть 1 — версия гостевой ОС

Когда Алексей опубликовал вводную заметку о компоненте обмена данными (Data Exchange) из комплекта служб интеграции (Integration Services) Hyper-V, это неожиданно вызвало целый ряд вопросов о том, что же именно можно передавать из родительской системы в ВМ и обратно. Поэтому теперь я собираюсь рассказать об этой возможности подробнее. Официально она называется «Компонент интеграции обмена парами ключ-значение» (Key Value Pair, KVP Exchange Integration Component). Этот компонент реализован в виде службы в гостевой ОС и позволяет передавать некоторую ограниченную информацию из ВМ в родительскую ОС и обратно.

Вначале давайте остановимся только на внутренних (intrinsic) KVP, которые уже существуют по умолчанию в виртуальных машинах с установленными компонентами интеграции. А именно, нам доступны следующие KVP, названия которых довольно понятно описывают их предназначение: FullyQualifiedDomainName, OsName, OsVersion, CSDVersion, OsMajorVersion, OsMinorVersion, OsBuildNumber, OsPlatformID, ServicePackMajor, SuiteMask, ProductType, ProcessorArhitecture.

Для получения текущих значений KVP воспользуемся сценарием PowerShell, а затем рассмотрим, как интерпретировать каждое из них. Сценарий начинается с блока, похожего на функцию. Но это не функция, а фильтр PowerShell, который берет поток XML, называемый в WMI «embedded instance», и конвертирует его в объекты. Чтобы понять, насколько удобен этот маленький фильтр, просто удалите «|Import-CimXml» из последней строки сценария — и увидите XML в необработанном виде.

Как работает сценарий? Давайте на минуту проигнорируем фильтр. Тогда первая строка ($Vm = Get-Wmi...) выглядит вполне обычно: мы получаем объект WMI Msvm_ComputerSystem для ВМ «Server 2008 - Test1». Вторая строка интереснее: мы выполняем ассоциативный запрос (Association query), чтобы получить объект WMI Msvm_KvpExchangeCompoents для этой ВМ. Ассоциации представляют собой вид запросов к WMI, которые следует воспринимать подобно оператору объединения в SQL: «пожалуйста, дайте мне все X, которые соответствуют критерию Y». Третья строка просто берет атрибут GuestIntrinsicExchangeItems объекта Msvm_KvpExchangeCompoents и направляет его по конвейеру на вход фильтра Import-CimXml, описанного выше. А сам фильтр использует запросы XML xpath к каждому узлу «Instance/Property», добавляя его имя и значение к объекту CimObj, а затем возвращает сам объект.

Сценарий PowerShell WMIKVP.ps1

filter Import-CimXml{ $CimXml = [Xml]$_ $CimObj = New-Object -TypeName System.Object foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY")) { $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE } $CimObj}

$Vm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'"

$Kvp = Get-WmiObject -Namespace root\virtualization -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"

$Kvp.GuestIntrinsicExchangeItems | Import-CimXml

Пример вывода сценария WMIKVP.ps1

PS C:\> . 'D:\BlogsDemo\powerShell\Demo\WMIKVP.ps1'

Caption : Data : AUTOBVT-M02LJSS Description : ElementName : Name : FullyQualifiedDomainName Source : 2

Caption : Data : Windows Server (R) 2008 Enterprise Description : ElementName : Name : OSName Source : 2

Caption : Data : 6.0.6001 Description : ElementName : Name : OSVersion Source : 2

Caption : Data : Service Pack 1 Description : ElementName : Name : CSDVersion Source : 2

Caption : Data : 6 Description : ElementName : Name : OSMajorVersion Source : 2

Caption : Data : 0 Description : ElementName : Name : OSMinorVersion Source : 2

Caption : Data : 6001 Description : ElementName : Name : OSBuildNumber Source : 2

Caption : Data : 2 Description : ElementName : Name : OSPlatformId Source : 2

Caption : Data : 1 Description : ElementName : Name : ServicePackMajor Source : 2

Caption : Data : 0 Description : ElementName : Name : ServicePackMinor Source : 2

Caption : Data : 274 Description : ElementName : Name : SuiteMask Source : 2

Caption : Data : 3 Description : ElementName : Name : ProductType Source : 2

Caption : Data : 9 Description : ElementName : Name : ProcessorArchitecture Source : 2

Как же теперь расшифровать полученные значения — такие как SuiteMask? Все эти данные, за исключением «Fully Qualified Domain Name», получаются с помощью функции Windows API GetVersionEx. Но нам интереснее взлянуть на структуру OSVERSIONINFOEX. Она документирует каждое из полученных нами значений. Например, мы получили значение SuiteMask, равное 274 (или 0x112). В соответствии с описанием это значит, что гостевая ОС является изданием Windows Server Enterprise, в ней включена поддержка «Удалённого рабочего стола» (Remote Desktop support) и установлены службы терминалов.

Есть еще много операций, которые можно выполнять с KVP. Например, передать специальные данные из родительского раздела в гостевую ОС или добавить информацию в гостевую ОС и запрашивать ее затем из родительского раздела. Обо всем этом мы поговорим в следующий раз.