Criar seus serviços de integração
A partir da Atualização de Aniversário do Windows 10, qualquer pessoa pode criar aplicativos que se comuniquem entre o host do Hyper-V e suas máquinas virtuais usando soquetes do Hyper-V – um soquete do Windows com uma nova família de endereços e um ponto de extremidade especializado para direcionamento de máquinas virtuais. Todas as comunicações por meio de soquetes do Hyper-V funcionam sem o uso de rede e todos os dados permanecem na mesma memória física. Os aplicativos que usam soquetes do Hyper-V são semelhantes aos serviços de integração do Hyper-V.
Este documento explica como criar um programa simples baseado em soquetes do Hyper-V.
Sistema operacional do host com suporte
- Windows 10 e posterior
- Windows Server 2016 e posterior
Sistema operacional convidado com suporte
- Windows 10 e posterior
- Windows Server 2016 e posterior
- Convidados do Linux com o Linux Integration Services. Confira Máquinas virtuais compatíveis do Linux e do FreeBSD para o Hyper-V no Windows
Observação
um convidado Linux compatível precisa ter suporte de kernel para:
CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y
Funcionalidades e Limitações
- Dá suporte a ações de modo de usuário ou modo de kernel
- Somente o fluxo de dados
- Nenhuma memória de bloco (não é a melhor para backup/vídeo)
Introdução
Requisitos:
- Compilador C/C++. Se você não tiver um, confira Visual Studio Community
- SDK do Windows – pré-instalado no Visual Studio 2015 com Atualização 3 e posterior.
- Um computador com um dos sistemas operacionais host especificados com pelo menos uma máquina virtual. – isso é para testar seu aplicativo.
Observação: a API para soquetes do Hyper-V se tornou publicamente disponível na Atualização de Aniversário do Windows 10. Os aplicativos que usam o HVSocket funcionarão em qualquer host e convidado do Windows 10, mas só podem ser desenvolvidos com um SDK do Windows posterior ao build 14290.
Registrar um novo aplicativo
Para usar soquetes do Hyper-V, o aplicativo precisa ser registrado com o Registro de Host do Hyper-V.
Ao registrar o serviço no Registro, você obtém:
- Gerenciamento de WMI para habilitar, desabilitar e listar os serviços disponíveis
- Permissão para se comunicar diretamente com máquinas virtuais
O PowerShell a seguir registrará um novo aplicativo chamado "Demonstração de Soquete do HV". Ele precisa ser executado como administrador. Instruções manuais abaixo.
$friendlyName = "HV Socket Demo"
# Create a new random GUID. Add it to the services list
$service = New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices" -Name ((New-Guid).Guid)
# Set a friendly name
$service.SetValue("ElementName", $friendlyName)
# Copy GUID to clipboard for later use
$service.PSChildName | clip.exe
Localização e informações do Registro:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\
No local do Registro, você verá vários GUIDs. Esses são nossos serviços nativos.
Informações no Registro por serviço:
Service GUID
ElementName (REG_SZ)
— este é o nome amigável do serviço
Para registrar seu serviço, crie uma chave do Registro usando seu GUID e o nome amigável.
O nome amigável será associado ao seu novo aplicativo. Ele aparecerá nos contadores de desempenho e em outros lugares onde um GUID não é apropriado.
A entrada do Registro tem esta aparência:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\
999E53D4-3D5C-4C3E-8779-BED06EC056E1\
ElementName REG_SZ VM Session Service
YourGUID\
ElementName REG_SZ Your Service Friendly Name
Observação
o GUID de serviço de um convidado Linux usa o protocolo VSOCK, que faz o endereçamento por meio de um svm_cid
e uma svm_port
em vez de um GUID. Para reduzir essa inconsistência com o Windows, o GUID bem conhecido é usado como o modelo de serviço no host, que é convertido para uma porta no convidado. Para personalizar o GUID de serviço, basta alterar os primeiros "00000000" para o número da porta desejado. Ex: "00000ac9" é a porta 2761.
// Hyper-V Socket Linux guest VSOCK template GUID
struct __declspec(uuid("00000000-facb-11e6-bd58-64006a7986d3")) VSockTemplate{};
/*
* GUID example = __uuidof(VSockTemplate);
* example.Data1 = 2761; // 0x00000AC9
*/
Dica: para gerar um GUID no PowerShell e copiá-lo para a área de transferência, execute:
(New-Guid).Guid | clip.exe
Criar um soquete do Hyper-V
No caso mais básico, definir um soquete requer uma família de endereços, um tipo de conexão e um protocolo.
Segue uma definição simples de soquete
// Windows
SOCKET WSAAPI socket(
_In_ int af,
_In_ int type,
_In_ int protocol
);
// Linux guest
int socket(int domain, int type, int protocol);
Para um soquete do Hyper-V:
- Família de endereços –
AF_HYPERV
(Windows) ouAF_VSOCK
(convidado Linux) - tipo -
SOCK_STREAM
- protocolo –
HV_PROTOCOL_RAW
(Windows) ou0
(convidado Linux)
Segue um exemplo de declaração/instanciação:
// Windows
SOCKET sock = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);
// Linux guest
int sock = socket(AF_VSOCK, SOCK_STREAM, 0);
Associar a um soquete do Hyper-V
A associação vincula um soquete às informações de conexão.
A definição da função é copiada abaixo por uma questão de conveniência; leia mais sobre associação aqui.
// Windows
int bind(
_In_ SOCKET s,
_In_ const struct sockaddr *name,
_In_ int namelen
);
// Linux guest
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
Em contraste com o endereço de soquete (sockaddr) para uma família de endereços do protocolo de internet padrão (AF_INET
) que consiste no endereço IP e um número da porta no computador host, o endereço de soquete para AF_HYPERV
usa a ID da máquina virtual e a ID do aplicativo definida acima para estabelecer uma conexão. Se a associação estiver sendo feita em um convidado Linux, AF_VSOCK
usará o svm_cid
e a svm_port
.
Como soquetes do Hyper-V não dependem de uma pilha de rede, TCP/IP, DNS, etc., o ponto de extremidade de soquete necessita de um formato sem IP e sem nome do host que ainda descreve a conexão sem ambiguidade.
Esta é a definição para o endereço de soquete de um soquete do Hyper-V:
// Windows
struct SOCKADDR_HV
{
ADDRESS_FAMILY Family;
USHORT Reserved;
GUID VmId;
GUID ServiceId;
};
// Linux guest
// See include/uapi/linux/vm_sockets.h for more information.
struct sockaddr_vm {
__kernel_sa_family_t svm_family;
unsigned short svm_reserved1;
unsigned int svm_port;
unsigned int svm_cid;
unsigned char svm_zero[sizeof(struct sockaddr) -
sizeof(sa_family_t) -
sizeof(unsigned short) -
sizeof(unsigned int) - sizeof(unsigned int)];
};
Em vez de um IP ou nome de host, pontos de extremidade AF_HYPERV dependem fortemente de dois GUIDs:
ID da VM – essa é a ID exclusiva atribuída por VM. Uma ID da VM pode ser encontrada usando o seguinte snippet do PowerShell.
(Get-VM -Name $VMName).Id
ID de Serviço – GUID, descrito acima, com o qual o aplicativo está registrado no Registro do host do Hyper-V.
Há também um conjunto de caracteres curinga de VMID disponível quando uma conexão não for específica para a máquina virtual.
Caracteres curinga de VMID
Nome | GUID | Descrição |
---|---|---|
HV_GUID_ZERO | 00000000-0000-0000-0000-000000000000 | Ouvintes devem ser vinculados a essa VmId para aceitar conexão de todas as partições. |
HV_GUID_WILDCARD | 00000000-0000-0000-0000-000000000000 | Ouvintes devem ser vinculados a essa VmId para aceitar conexão de todas as partições. |
HV_GUID_BROADCAST | FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF | |
HV_GUID_CHILDREN | 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd | Endereço curinga para os filhos. Os ouvintes devem ser associados a essa VmId para aceitar a conexão de todos os filhos. |
HV_GUID_LOOPBACK | e0e16197-dd56-4a10-9195-5ee7a155a838 | Endereço de loopback. Usar essa VmId conecta à mesma partição que o conector. |
HV_GUID_PARENT | a42e7cda-d03f-480c-9cc2-a4de20abb878 | Endereço do pai. Usar essa VmId conecta à partição pai do connector.* |
* HV_GUID_PARENT
O pai de uma máquina virtual é o respectivo host. O pai de um contêiner é o host do contêiner.
Conectar-se de um contêiner em execução em uma máquina virtual se conectará à VM que hospeda o contêiner.
A escuta nessa VmId aceita a conexão de: (dentro de contêineres): host do contêiner.
(Dentro da VM: host do contêiner / nenhum contêiner): host da VM.
(Fora da VM: host do contêiner / nenhum contêiner): sem suporte.
Comandos de soquete com suporte
Socket() Bind() Connect() Send() Listen() Accept()
Opções de soquete HvSocket
Nome | Tipo | Descrição |
---|---|---|
HVSOCKET_CONNECTED_SUSPEND | ULONG | Quando essa opção de soquete é definida com um valor diferente de zero, os soquetes não se desconectam quando a máquina virtual fica em pausa. |