Criar seus próprios 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 host com suporte

  • Windows 10 e posterior
  • Windows Server 2016 e posterior

Sistema operacional convidado com suporte

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 10 – pré-instalado no Visual Studio 2015 com Atualização 3 e posterior.
  • Um computador com um dos sistemas operacionais host acima 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 no Windows 10 logo depois. Os aplicativos que usam o HVSocket funcionarão em qualquer host e convidado do Widnows 10, mas só poderão ser desenvolvidos com um SDK do Windows posterior à compilação 14290.

Registrar um novo aplicativo

Para usar soquetes do Hyper-V, o aplicativo deve 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 deve 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

Local 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 próprio serviço, crie uma nova chave de registro usando seu próprio 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 será assim:

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

** 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

SOCKET WSAAPI socket(
  _In_ int af,
  _In_ int type,
  _In_ int protocol
);

Para um soquete do Hyper-V:

  • Família de endereços - AF_HYPERV
  • tipo - SOCK_STREAM
  • protocolo - HV_PROTOCOL_RAW

Segue um exemplo de declaração/instanciação:

SOCKET sock = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);

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.

int bind(
  _In_ SOCKET                s,
  _In_ const struct sockaddr *name,
  _In_ int                   namelen
);

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.

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:

struct SOCKADDR_HV
{
     ADDRESS_FAMILY Family;
     USHORT Reserved;
     GUID VmId;
     GUID ServiceId;
};

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 trecho de código do PowerShell.
    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 de 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 é seu 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.
Escutar essa 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()

Concluir a API do WinSock

Referência dos serviços de integração do Hyper-V