Notas

Notas

Instalei o Ubuntu 18.04 no Hyper-V em um host Windows 10 e expus funcionalidades em algumas portas, que estão disponíveis para outros programas em execução no host ao acessar http://vm-ip-number:port(ou seja http://192.168.0.1:12345,). Funciona muito bem.

Eu gostaria de usar um nome em vez do número IP da VM para conectar-se a ela (por todos os motivos usuais, pois isso estará nos arquivos de configuração). Para servidores Linux ou MacOS completos, eu deixaria o host se anunciar usando o zeroconf, mas algumas pesquisas indicaram que isso não funciona bem para o Windows 10 além dos limites da VM.

Outra abordagem pode ser fazer com que o Hyper-V atribua à VM um nome fornecido por mim, que estará disponível quando a VM estiver ativa, mas não estou familiarizado o suficiente com o Hyper-V para saber se isso é possível ou não. Instalar ferramentas adicionais apenas para isso no convidado é aceitável, no host somente se necessário.

Tudo que eu quero é poder http://my-own-nameacessar a VM durante a execução sem codificar o número IP em qualquer lugar.

Sugestões?

Responder1

O seguinte script do PowerShell gerará um hostsarquivo que contém os endereços IP e nomes de VM para todas as VMs em execução:

get-vm | Get-VMNetworkAdapter | ? IPAddresses -ne $null | % {Write-Output "$($_.ipaddresses[0]) $($_.VMName)"} | Set-Content -Path ".\hosts"

Alguns pontos a serem observados:

  • O script precisa ser executado como administrador.

  • ODefinir conteúdo O comando precisa de um parâmetro Path melhor, pois atualmente ele substituirá o hostsarquivo na pasta atual.

  • Se você não deseja que o hostsarquivo seja sobrescrito, mas anexado, use Adicionar conteúdo comando em vez disso. Dessa forma, você pode começar a partir de um hostsarquivo inicial e apenas anexar a ele.

  • O Saída de gravação comando gera a primeira entrada no ipaddressescampo. Se IPv4 e IPv6 estiverem habilitados, a lista conterá duas entradas, onde a primeira entrada geralmente é IPv4.

Um hostsarquivo de exemplo que foi gerado para minha VM em execução por este script:

172.17.223.121 Windows10Test

(Provavelmente é melhor evitar espaços em branco nos nomes das VMs, ou será necessário mais trabalho no script.)

Responder2

Adicione o endereço IP no arquivo HOSTS do Windows. O caminho completo é C:\Windows\System32\drivers\etc\hosts. Execute o Bloco de Notas (ou qualquer editor de texto) como administrador e abra esse arquivo com Ctrl+ O. Em seguida, adicione o endereço IP. O formato será o endereço IP e depois o nome do convidado. Aqui está um exemplo:

# This is a comment
# 127.0.0.1 localhost loopback
# ::1 localhost

192.168.0.1 myguest

Para mais informações, leiaWikipédia: hosts (arquivo).

Responder3

Encontrei uma maneira de conectar por nome a VMs convidadas de outras VMs convidadas ou do host, usando nomes que são gerenciados automaticamente pelo Hyper-V, como segue:

  1. Conecte o convidado ao switch padrão (este é o padrão para uma nova VM).
  2. Defina o endereço IP como DHCP no convidado (este é o padrão para uma nova VM).
  3. Defina o nome do computador/nome do host no sistema operacional convidado para algo exclusivo, por exemplo myfirstvm. O sufixo DNS não importa.
  4. De outra VM ou do host, tente entrar em contato com <host_name>.mshome.net, por exemplo, se você definir o nome do host como myfirstvm, tente fazer ping myfirstvm.mshome.netdo host.

Explicação:

No meu sistema encontrei um arquivo no mesmo diretório do hostsarquivo chamado hosts.ics. Parecia conter entradas para todos os meus convidados anexadas aDefault Switch e uma entrada para o sistema básico, mas todos com o sufixo mshome.net. Acredito que os adaptadores de rede conectados ao switch padrão usam o recurso Compartilhamento de conexão com a Internet, que cria e mantém esse hosts.icsarquivo automaticamente. Quando o seu convidado inicializa, ele solicita um endereço IP por DHCP e tenta registrar-se no servidor DNS integrado ao Hyper-V. Acredito que o Hyper-V pega o nome que o convidado tenta cadastrar e armazena neste hosts.icsarquivo com um novo sufixo mshome.net. Se duas de suas VMs convidadas tentarem registrar o mesmo nome, esse processo será interrompido.

Não tenho certeza se este é um recurso novo ou sempre esteve aqui. Encontrado no Windows 11 Pro, Hyper-V 10.0.22000.1

Responder4

Este script do PowerShell se baseiaLucas Schlathera resposta (https://superuser.com/a/1485949/280673) para esta pergunta.

A diferença mais importante é que ele não substitui todo o arquivo hosts pelos endereços IP das suas VMs, mas em vez disso anexa novas entradas se houver novas VMs e substitui os endereços de entradas pré-existentes. Isso deve eliminar a necessidade de fazer backups e preservar outras entradas no arquivo hosts que você possa ter feito para desenvolvimento local ou outros fins.

#Requires -RunAsAdministrator

# Based on: https://superuser.com/a/1485949

Write-Host "Fix entries for local HyperV VMs in hosts file."

Set-StrictMode -Version 3.0
$ErrorActionPreference = "Stop"
$hostsFile = "${env:SystemRoot}/System32/drivers/etc/hosts"

$hostsFileContentOriginal = (Get-Content $hostsFile)
$hostsFileContent = $hostsFileContentOriginal

Write-Debug "Original hosts file content:"
Write-Debug ($hostsFileContent | Out-String)
Write-Debug "`n`n"

foreach ($vm in (Get-VM | Get-VMNetworkAdapter))
{
   $vmName = $($vm.VMName)
   $vmNameSanitized = $vm.VMName.ToLower() -replace '[. ]',''
   $hostName = "${vmNameSanitized}.local"
   Write-Verbose "Porcessing $vm."
   if (0 -lt $vm.IPAddresses.Length)
   {
      Write-Verbose "VM ${vmname} has IP addresses, updating hosts file."
      $address = $vm.IPAddresses[0]
      Write-Verbose "Selected IP Address for ${vmname}: $address."
      Write-Debug "All IP Addresses for ${vmname}: $($vm.IPAddresses)."

      $vmPreviouslyAddedToHostsFile = $hostsFileContent -match ".*$hostName.*"
      if($vmPreviouslyAddedToHostsFile)
      {
         Write-Verbose "VM $vmName already present in hosts, updating entry."
         # # Regex explanation
         # - `([^\d]*)` is a grouping `()` of 0 or more of the character group `[]*` that contains no digits `^\d`.
         # - `(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})` is a grouping `()` of 4 collections of 1 to 3 digits `\d{1,3}`, separated by a dot `\.`, which should match an ipv4 address.
         # - `(\s+$hostName.*)` is a grouping `()` that matches 1 or more spaces `\s+`, followed by the content of the hostname variable `$hostName`, followed by 0 or more of any characters `.*`.
         # # Substitution expression explanation
         # `${n}` is used to access the n-th (1 indexed) grouping from the regex.
         # Because we want to access the `$address` variable we can't use literal strings `''` but have to use normal strings instead `""`.
         # This results in having to escape the `$` character when doing the group substitution access.
         # # Caveat emptor
         # This only works for ipv4 addresses as written.
         # If you want to support ipv6 addresses, consider using `([a-f0-9:]+:+)+[a-f0-9]+` from https://stackoverflow.com/a/37355379 .
         # It will fail in interesting ways if the entry is commented out and there are digits in the comment in a position preceding the address.
         $hostsFileContent = $hostsFileContent -replace "([^\d]*)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+$hostName.*)","`${1}$address`${3}" -join "`r`n"
      }
      else
      {
         Write-Verbose "VM $vmName not previously in hosts, appending entry."
         $hostsFileContent += "$address $hostName" -join "`r`n"
      }
   }
   else
   {
      Write-Verbose "VM ${vmname} doesn't have IP addresses, skipping."
   }
}

$originalAsString = ($hostsFileContentOriginal | Out-String)
$updatedAsString = ($hostsFileContent | Out-String)

Write-Debug "`n`nUpdated hosts file content:"
Write-Debug "$updatedAsString"

if($originalAsString -ne $updatedAsString)
{
   Write-Host "There are new addresses for VMs, updtating hosts file."

   # $datestring = (Get-Date -Format "o") -replace '[:\-]','-'
   # $backupHostsFile = "$hostsFile.${datestring}.bak"
   # Write-Verbose "Backing up hosts file to $backupHostsFile."
   # Copy-Item $hostsFile $backupHostsFile

   # Write-Verbose "Setting new hosts file content."

   Set-Content -Path $hostsfile -Value $hostsFileContent -Encoding UTF8
}
else
{
   Write-Host "No new VMs or addresses, exiting."
}

Notas

Dependendo da sua VM, pode ser necessário instalar pacotes adicionais dentro da VM, por exemplohypervno arch, antes de descobrir o IP atribuído à VM do HyperV e do PowerShell. Isso provavelmente variará entre os diferentes sistemas operacionais, então você provavelmente terá que procurar um guia para o seu sistema (ou postar uma nova pergunta) se não conseguir obter o endereço do host.

Saí da seção de backup e apenas comentei, para facilitar a experimentação e a iteração no script. Também para tornar mais fácil fazer backups se eles forem desejados em um local mais sensato (não há necessidade de backups se nenhuma alteração estiver sendo feita, portanto, não os faça antes de as alterações serem gravadas).

Também coloquei o comentário de como funciona a regex para substituição do endereço no código, ao invés de fora aqui no corpo do post. Isso é para tornar mais fácil seguir o código caso a referência a esta postagem seja perdida após alguma cópia e colagem e, esperançosamente, seja útil caso alguém queira fazer alterações nele.

informação relacionada