Existe um método que permite a configuração de parâmetros específicos de um sistema operacional através da passagem de seus valores ao realizar o deploy de um OVF. Isso é feito por meio do recurso vApp disponibilizado pela VMware, parcialmente (logo mais o motivo ficará explícito). Existem outras facilidades dele, mas nessa postagem somente é mostrado como preparar uma estratégia para que o SUSE Linux Enterprise Server 11 SP3 seja autoconfigurado no âmbito de estrutura básica de rede como IP, máscara, gateway, DNS primário, DNS secundário, NTP, hostname e domínio.
O primeiro passo é habilitar o vApp options na edição da VM. No tree view dessa opção surgirá mais 4 itens: Properties, IP Allocation Policy, OVF Settings e Advanced.
Na opção Advanced clique no botão IP Allocation e marque a opção OVF Environment.
Os parâmetros para o usuário digitar ao realizar o deploy são configurados na janela mostrada abaixo ao clicar no botão Properties.
Veja um exemplo da configuração de um campo do tipo IP.
Na opção OVF Settings marque a opção VMware Tools. Isso permite que obtemos os valores configurados a partir de um XML no contexto de execução do sistema operacional pelo comando vmtoolsd --cmd "info-get guestinfo.ovfenv" no shell.
Veja que o botão View fica bloqueado. Ele só é liberado ao ligar a VM.
Por fim na opção Properties podemos visualizar como será mostrado os campos no deploy do OVF.
Agora se clicarmos no botão View depois de a VM ter sido iniciada ele pode mostrar, por exemplo, o seguinte XML:
É justamente ele que será disponibilizado pela VMware Tools.
Um ponto importante é que podemos testar a configuração em função desses valores até funcionar para distribuir o OVF. Para fazer isso eu desenvolvi o seguinte script em python (a leitura do XML eu achei na postagem do Martin Amdisen):
Caso seja feita a execução dele os valores já serão obtidos e configurados no SLES.
Depois dos testes é necessário preparar a VM para exportar um OVF. Existem alguns pré-requisitos como não ter entradas no /etc/resolv.conf e na tabela de consultas do NTP, mas o principal é garantir que o script seja executado uma única vez no SLES. No meu caso criei um serviço para ser iniciado no runlevel 3 (depois de network) que chama o script em python, exclui ele depois da configuração, desfaz o registro para ele próprio não ser mais executado como serviço para, no final, se auto excluir não deixando rastros no SLES, mas é claro, isso é só uma sugestão.
Para maiores detalhes sugiro os seguintes links:
O primeiro passo é habilitar o vApp options na edição da VM. No tree view dessa opção surgirá mais 4 itens: Properties, IP Allocation Policy, OVF Settings e Advanced.
Na opção Advanced clique no botão IP Allocation e marque a opção OVF Environment.
Os parâmetros para o usuário digitar ao realizar o deploy são configurados na janela mostrada abaixo ao clicar no botão Properties.
Veja um exemplo da configuração de um campo do tipo IP.
Na opção OVF Settings marque a opção VMware Tools. Isso permite que obtemos os valores configurados a partir de um XML no contexto de execução do sistema operacional pelo comando vmtoolsd --cmd "info-get guestinfo.ovfenv" no shell.
Veja que o botão View fica bloqueado. Ele só é liberado ao ligar a VM.
Por fim na opção Properties podemos visualizar como será mostrado os campos no deploy do OVF.
Agora se clicarmos no botão View depois de a VM ter sido iniciada ele pode mostrar, por exemplo, o seguinte XML:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<Environment | |
xmlns="http://schemas.dmtf.org/ovf/environment/1" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:oe="http://schemas.dmtf.org/ovf/environment/1" | |
xmlns:ve="http://www.vmware.com/schema/ovfenv" | |
oe:id="" | |
ve:vCenterId="vm-610"> | |
<PlatformSection> | |
<Kind>VMware ESXi</Kind> | |
<Version>5.1.0</Version> | |
<Vendor>VMware, Inc.</Vendor> | |
<Locale>en</Locale> | |
</PlatformSection> | |
<PropertySection> | |
<Property oe:key="dns1" oe:value="8.8.8.8"/> | |
<Property oe:key="dns2" oe:value="8.8.4.4"/> | |
<Property oe:key="domain" oe:value="yoursite.com"/> | |
<Property oe:key="gateway" oe:value="10.222.21.254"/> | |
<Property oe:key="hostname" oe:value="minidlsss"/> | |
<Property oe:key="ip" oe:value="10.222.21.69"/> | |
<Property oe:key="netmask" oe:value="24"/> | |
<Property oe:key="ntp" oe:value="0.br.pool.ntp.org"/> | |
</PropertySection> | |
<ve:EthernetAdapterSection> | |
<ve:Adapter ve:mac="00:50:56:92:35:01" ve:network="VM Network SSC" ve:unitNumber="7"/> | |
</ve:EthernetAdapterSection> | |
</Environment> |
Um ponto importante é que podemos testar a configuração em função desses valores até funcionar para distribuir o OVF. Para fazer isso eu desenvolvi o seguinte script em python (a leitura do XML eu achei na postagem do Martin Amdisen):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python | |
# Script to set network parameters from 'vmtoolsd --cmd "info-get guestinfo.ovfenv"'. It is designed for SLES 11 SP3 | |
# Author: Willian Antunes | |
# Date of creation: September 03, 2014 | |
import os, sys, time, subprocess, re | |
from xml.dom.minidom import parseString | |
def findXmlSection(dom, sectionName): | |
sections = dom.getElementsByTagName(sectionName) | |
return sections[0] | |
def getPropertyMap(ovfEnv): | |
dom = parseString(ovfEnv) | |
section = findXmlSection(dom, "PropertySection") | |
propertyMap = {} | |
for property in section.getElementsByTagName("Property"): | |
key = property.getAttribute("oe:key") | |
value = property.getAttribute("oe:value") | |
propertyMap[key] = value | |
dom.unlink() | |
return propertyMap | |
print "Issuing the command echo `vmtoolsd --cmd \"info-get guestinfo.ovfenv\"` to get the vApp configuration..." | |
ovfEnv = subprocess.Popen("echo `vmtoolsd --cmd \"info-get guestinfo.ovfenv\"`", shell=True, stdout=subprocess.PIPE).stdout.read() | |
propertyMap = getPropertyMap(ovfEnv) | |
ip = propertyMap["ip"] | |
netmask = propertyMap["netmask"] | |
gateway = propertyMap["gateway"] | |
dns1 = propertyMap["dns1"] | |
dns2 = propertyMap["dns2"] | |
hostname = propertyMap["hostname"] | |
domain = propertyMap["domain"] | |
ntp = propertyMap["ntp"] | |
print "The following properties will be used to set network parameters: " | |
print "--- IP: ", ip | |
print "--- Netmask: ", netmask | |
print "--- Gateway: ", gateway | |
print "--- Preferred DNS server: ", dns1 | |
print "--- Alternate DNS server: ", dns2 | |
print "--- Hostname: ", hostname | |
print "--- domain: ", domain | |
print "--- ntp: ", ntp | |
print "Cleaning up the device list..." | |
# It will prevent the case when the VM has two NICs. Generally it occurs when a new deploy is made | |
print subprocess.Popen("yast2 lan delete id=0 verbose", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("yast2 lan delete id=1 verbose", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "Obtaining device name..." | |
p = subprocess.Popen('yast2 lan list', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
returnCode = p.wait() | |
stdout = p.stdout.read() | |
deviceName = re.search(r'\s.*,', stdout).group().strip()[:-1] | |
print "Device name: ", deviceName | |
print "Configuring NTP parameters..." | |
print subprocess.Popen("yast2 ntp-client add server=%s" % (ntp), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("yast2 ntp-client enable", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "Configuring IP parameters..." | |
print subprocess.Popen("echo \"default %s - -\" > /etc/sysconfig/network/routes" % (gateway), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "Creating the file ifcfg-eth0..." | |
print subprocess.Popen("echo \"BOOTPROTO='static'\" > /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"BROADCAST=''\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"ETHTOOL_OPTIONS=''\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"IPADDR='%s/%s'\" >> /etc/sysconfig/network/ifcfg-eth0" % (ip, netmask), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"MTU=''\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"NAME='%s'\" >> /etc/sysconfig/network/ifcfg-eth0" % (deviceName), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"NETWORK=''\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"REMOTE_IPADDR=''\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"STARTMODE='auto'\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"USERCONTROL='no'\" >> /etc/sysconfig/network/ifcfg-eth0", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "File created!" | |
print "Setting the current NIC to use 'eth0' as its name..." | |
print subprocess.Popen("head -n -1 /etc/udev/rules.d/70-persistent-net.rules | cat > /tmp/70-persistent-net.rules", shell=True, stdout=subprocess.PIPE).stdout.read() | |
netRules = subprocess.Popen("tail -n 1 /etc/udev/rules.d/70-persistent-net.rules", shell=True, stdout=subprocess.PIPE).stdout.read() | |
newNameValue = ", NAME=\"eth0\"" | |
netRulesNew = netRules[:-(len(netRules)-netRules.rindex(','))] + newNameValue | |
# The command bellow will allow python to pass double quotes to the shell | |
netRulesNew = netRulesNew.replace("\"", "\\\"") | |
print subprocess.Popen("echo \"{0}\" >> /tmp/70-persistent-net.rules".format(netRulesNew), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("mv /tmp/70-persistent-net.rules /etc/udev/rules.d/70-persistent-net.rules", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "Configuring DNS parameters..." | |
print subprocess.Popen("sed -i \"s/NETCONFIG_DNS_STATIC_SERVERS=.*/NETCONFIG_DNS_STATIC_SERVERS=\\\"%s %s\\\"/g\" /etc/sysconfig/network/config" % (dns1, dns2), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("head -n -1 /etc/hosts | cat > /tmp/hosts", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"%s %s.%s %s\" >> /tmp/hosts" % (ip, hostname, domain, hostname), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("mv /tmp/hosts /etc/hosts", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"{0}.{1}\" > /etc/HOSTNAME".format(hostname, domain), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"nameserver {0}\" >> /etc/resolv.conf".format(dns1), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print subprocess.Popen("echo \"nameserver {0}\" >> /etc/resolv.conf".format(dns2), shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "Restarting the network service..." | |
print subprocess.Popen("/etc/init.d/network restart", shell=True, stdout=subprocess.PIPE).stdout.read() | |
print "The configuration has been applied" |
Depois dos testes é necessário preparar a VM para exportar um OVF. Existem alguns pré-requisitos como não ter entradas no /etc/resolv.conf e na tabela de consultas do NTP, mas o principal é garantir que o script seja executado uma única vez no SLES. No meu caso criei um serviço para ser iniciado no runlevel 3 (depois de network) que chama o script em python, exclui ele depois da configuração, desfaz o registro para ele próprio não ser mais executado como serviço para, no final, se auto excluir não deixando rastros no SLES, mas é claro, isso é só uma sugestão.
Para maiores detalhes sugiro os seguintes links:
Comentários
Postar um comentário