Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Data Exchange is een integratieservice (ook wel sleutel-waarde-paaruitwisseling of KVP genoemd) die kan worden gebruikt om kleine stukjes informatie te delen tussen een virtuele machine (gast) en de bijbehorende Hyper-V host. Algemene informatie over de virtuele machine en host wordt automatisch gemaakt en opgeslagen als sleutel-waardeparen. U kunt ook uw eigen paren maken om aangepaste gegevens te delen.
Sleutel-waardeparen bestaan uit een 'sleutel' en een 'waarde'. Beide zijn tekenreeksen; er worden geen andere gegevenstypen ondersteund. Wanneer een sleutel-waardepaar wordt gemaakt of gewijzigd, wordt het zichtbaar voor zowel de gast als de host. KVP-gegevens worden verzonden via de Hyper-V VMbus en vereisen geen netwerkverbinding tussen de gast en host.
Zodra deze zijn gemaakt, blijven sleutel-waardeparen behouden totdat ze worden verwijderd. Elke toepassing die sleutel-waardeparen maakt, moet deze verwijderen wanneer deze niet meer nodig zijn. Sleutel-waardeparen worden tijdens livemigratie met de virtuele machine verplaatst.
Windows-gasten
Bij Windows-gasten worden KVP-gegevens opgeslagen in het register onder:
HKLM\SOFTWARE\Microsoft\Virtual Machine
De gegevens zijn ingedeeld in deze subsleutels:
- Virtual Machine\Auto : gegevens die de gast beschrijven. Gemaakt door integratieservice-stuurprogramma's nadat ze zijn geladen. Zichtbaar voor de host als intrinsieke gegevens.
- Virtuele machine\extern : gegevens die vanaf de host naar de gast zijn gepusht door een gebruiker.
- Virtual Machine\Guest – gegevens die op het gast-systeem zijn gemaakt. Zichtbaar voor de host als niet-intrinsieke gegevens.
- Virtual Machine\Guest\Parameter : gegevens die vanaf de host naar de gast zijn gepusht die de host beschrijft.
Het toevoegen van waarden vanuit de gast is net zo eenvoudig als het maken van een nieuwe tekenreekswaarde onder HKLM\SOFTWARE\Microsoft\Virtual Machine\Guest. U moet een beheerder in de gastomgeving zijn om deze locatie te wijzigen. U kunt WMI (PowerShell of andere hulpprogramma's) van de host of een externe computer (met machtigingen) gebruiken om de waarde op te halen.
Zie het artikel Registerelementgroottelimieten (verouderd) voor informatie over limieten voor registergrootten.
Een nieuw sleutel-waardepaar toevoegen aan de gast
In dit voorbeeld is de waarde van Status ingesteld op Ready:
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest"
Set-ItemProperty -Path $regPath -Name "Status" -Value "Ready" -Type String
U kunt dezelfde syntaxis gebruiken om de waarde te wijzigen.
Sleutel-waardeparen opvragen in de gast
De waarde van de externe subsleutel opvragen (gegevens die vanaf de host naar de gast zijn gepusht):
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\External"
Get-ItemProperty -Path $regPath -Name "Name"
Linux-gasten
Linux heeft geen register, dus KVP-items worden opgeslagen in het bestandssysteem. nl-NL: Een daemonproces, hv_kvp_daemon moet actief zijn om de verwerking te beheren. Voor de meeste distributies waarop LIS-stuurprogramma's (Linux Integration Services) of in-kernelstuurprogramma's zijn geïnstalleerd, wordt deze daemon automatisch gestart. In sommige gevallen zijn er mogelijk extra stappen vereist om de daemon te installeren en te starten.
De Linux-integratieservices implementeren gegevensuitwisseling met KVP-pools. Een KVP-pool is een bestand dat is opgeslagen in een specifiek pad. Er zijn vier poolbestanden:
/var/lib/hyperv/.kvp_pool_0
/var/lib/hyperv/.kvp_pool_1
/var/lib/hyperv/.kvp_pool_2
/var/lib/hyperv/.kvp_pool_3
Deze poolbestanden worden toegewezen aan de volgende Windows-registersleutelsets:
- Groep 0:
Virtual Machine\External - Groep 1:
Virtual Machine\Guest - Groep 2:
Virtual Machine\Auto - Groep 3:
Virtual Machine\Guest\Parameter
Opmerking
Zie Linux en FreeBSD Virtual Machines op Hyper-V voor meer informatie over Linux KVP-ondersteuning.
De sleutel-waardepaarinfrastructuur werkt mogelijk niet correct zonder een Linux-software-update. Neem contact op met uw distributieleverancier voor een update als u problemen ondervindt.
Poolstructuur
Elk poolbestand bevat records met deze structuur:
struct kvp_record
{
unsigned char key[ HV_KVP_EXCHANGE_MAK_KEY_SIZE ];
unsigned char value[ HV_KVP_EXCHANGE_MAX_VALUE_SIZE ];
};
Deze grootteconstanten worden gedefinieerd in hyperv.h (een kernelheader die wordt gedistribueerd met de Linux-kernelbronnen).
Waarden uit groep 0 lezen en weergeven
In dit voorbeeld worden KVP-waarden uit pool 0 gelezen en weergegeven.
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "../include/linux/hyperv.h"
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
KVP_RECORD myRecords[200];
void KVPAcquireLock(int fd)
{
struct flock fl = {F_RDLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_0";
int i;
int fd;
int bytesRead;
int numRecords;
fd = open(poolName, O_RDONLY);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-30);
}
KVPAcquireLock(fd);
bytesRead = read(fd, myRecords, sizeof(myRecords));
KVPReleaseLock(fd);
numRecords = bytesRead / sizeof(struct kvp_record);
printf("Number of records : %d\n", numRecords);
for (i = 0; i < numRecords; i++)
{
printf(" Key : %s\n Value: %s\n\n", myRecords[i].key, myRecords[i].value);
}
close(fd);
return 0;
}
Een KVP-item maken in groep 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "../include/linux/hyperv.h"
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
void KVPAcquireWriteLock(int fd)
{
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_1";
int fd;
KVP_RECORD newKvp;
if (3 != argc)
{
printf("Usage: WritePool keyName valueString\n\n");
exit (-5);
}
fd = open(poolName, O_WRONLY);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-30);
}
memset((void *)&newKvp, 0, sizeof(KVP_RECORD));
memcpy(newKvp.key, argv[1], strlen(argv[1]));
memcpy(newKvp.value, argv[2], strlen(argv[2]));
KVPAcquireWriteLock(fd);
write(fd, (void *)&newKvp, sizeof(KVP_RECORD));
KVPReleaseLock(fd);
close(fd);
return 0;
}
Een KVP-item verwijderen uit groep 1
In dit voorbeeld wordt een item verwijderd.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <uapi/linux/hyperv.h>
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
void KVPAcquireWriteLock(int fd)
{
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int find_record_offset(int fd, char *key)
{
int bytesRead;
int offset = 0;
int retval = -1;
KVP_RECORD kvpRec;
while (1)
{
lseek(fd, offset, SEEK_SET);
bytesRead = read(fd, &kvpRec, sizeof(KVP_RECORD));
if (0 == bytesRead)
{
break;
}
if (0 == strcmp(key, (const char *) kvpRec.key))
{
retval = offset;
break;
}
offset += sizeof(KVP_RECORD);
}
return retval;
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_1";
int fd;
int exitVal = -1;
int bytesRead;
int bytesWritten;
int offset_to_delete;
int offset_last_record;
KVP_RECORD kvpRec;
if (2 != argc)
{
printf("Usage: WritePool keyName valueString\n\n");
exit (-5);
}
fd = open(poolName, O_RDWR, 0644);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-10);
}
KVPAcquireWriteLock(fd);
offset_to_delete = find_record_offset(fd, argv[1]);
if (offset_to_delete < 0)
{
exitVal = -15;
goto cleanup2;
}
offset_last_record = lseek(fd, -sizeof(KVP_RECORD), SEEK_END);
if (offset_last_record < 0)
{
exitVal = -20;
goto cleanup2;
}
if (offset_last_record != offset_to_delete)
{
lseek(fd, offset_last_record, SEEK_SET);
bytesRead = read(fd, &kvpRec, sizeof(KVP_RECORD));
lseek(fd, offset_to_delete, SEEK_SET);
bytesWritten = write(fd, &kvpRec, sizeof(KVP_RECORD));
}
ftruncate(fd, offset_last_record);
exitVal = 0;
cleanup2:
KVPReleaseLock(fd);
cleanup1:
close(fd);
return exitVal;
}
Werken met sleutel-waardeparen van de host met WMI
In de volgende voorbeelden wordt de WMI v2-naamruimte gebruikt. Voor WMI v1 (oudere versies) verwijdert u het \v2 segment uit het pad naar de naamruimte.
Opmerking
Als u Windows 8 of Windows 8.1 gebruikt, installeert u Client Hyper-V om de naamruimten op te halen.
Lees de waarde van de host
In dit voorbeeld wordt de waarde van de sleutel opgehaald van een virtuele machine Status met de naam Vm1:
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName = 'Vm1'}
$vm.GetRelated("Msvm_KvpExchangeComponent").GuestExchangeItems | % { \
$GuestExchangeItemXml = ([XML]$_).SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Name']/VALUE[child::text() = 'Status']")
if ($GuestExchangeItemXml -ne $null)
{
$GuestExchangeItemXml.SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Data']/VALUE/child::text()" ).Value
}
}
Sleutel-waardeparen van de host toevoegen of wijzigen
Als u een sleutel-waardepaar van de host wilt toevoegen, haalt u exemplaren van zowel de beheerservice als de VM op en maakt u een nieuw exemplaar van Msvm_KvpExchangeDataItem. Wanneer u het nieuwe exemplaar maakt, specificeert u de Name, Data en Source (deze moeten 0 zijn). Bel dan AddKvpItems.
Het opvragen van door de host gemaakte sleutel-waardeparen is vergelijkbaar met gast-query's, maar vereist een extra associatiehop naar Msvm_KvpExchangeComponentSettingData. Het wijzigen en verwijderen van waarden werkt op dezelfde manier: geef dezelfde sleutelnaam op en roep de juiste Modify of Remove methode aan.
Belangrijk
In de onderstaande voorbeelden wordt de v2-naamruimte gebruikt. Als u Windows Server 2008 of Windows Server 2008 R2 gebruikt, verwijdert u het \v2 segment.
Een nieuw sleutel-waardepaar toevoegen
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = "Data"
$kvpDataItem.Source = 0
$VmMgmt.AddKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))
Sleutel-waardeparen op de host opvragen
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
($vm.GetRelated("Msvm_KvpExchangeComponent")[0] ).GetRelated("Msvm_KvpExchangeComponentSettingData").HostExchangeItems | % { \
$GuestExchangeItemXml = ([XML]$_).SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Name']/VALUE[child::text() = 'Name2']")
if ($GuestExchangeItemXml -ne $null)
{
$GuestExchangeItemXml.SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Data']/VALUE/child::text()" ).Value
}
}
Een sleutel-waardepaar wijzigen
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = "Data2"
$kvpDataItem.Source = 0
$VmMgmt.ModifyKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))
Een sleutel-waardepaar verwijderen
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = [String]::Empty
$kvpDataItem.Source = 0
$VmMgmt.RemoveKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))