Vagrant on erittäin kätevä työkalu kehitys- ja testausympäristöjen rakentamiseen. Sillä voidaan helposti ja toistettavasti luoda virtuaalikoneita, joiden asetukset säädetään halutunlaisiksi provisioning-vaiheessa esimerkiksi skripteillä (shell, powershell) tai konfiguraationhallintatyökaluilla kuten Puppetilla. Vagrantin taustalla on yleensä käytössä Oraclen Virtuabox, mutta myös muita virtualisointialustoja tuetaan ns. providerien avulla.

Vagrantilla luodut virtuaalikoneen on myös helppo verkottaa keskenään. Vagrant toimiikin siten hyvin palvelinympäristöjen testauksessa; hyvänä esimerkkinä käy puppet-ipa -moduuli, jossa Vagrantilla luodaan FreeIPA multi-master -palvelinympäristö sekä useita asiakaskoneita eri käyttöjärjestelmillä. Toinen hyvä esimerkki on puppet-bacula -moduuli, jossa Vagrantilla luodaan täydellinen Bacula-varmuuskopiointiympäristö.

Koska virtuaalikoneet asentuvat ja konfiguroituvat automaattisesti, voidaan ne tuhota ja rakentaa uudelleen jos ne pääsevät soseutumaan. Lisäksi kullakin kehittäjällä tai sysadminilla voi olla oma testiympäristönsä, jonka rikkominen ei vaikuta kehenkään muuhun, saati tuotannossa oleviin palveluihin, millä onkin todistetusti stressiä alentava vaikutus. Vagrant onkin hyvä ottaa esimerkiksi työnkulun osaksi esimerkiksi Puppet-moduuleja kehitettäessä - etenkin silloin, kun moduulit ovat erityisen monimutkaisia, kuten yllä mainitut puppet-ipa tai puppet-bacula.

Vagrant luo virtuaalikoneita ns. boxeista eli virtuaalikonekuvista. Vaikka julkisia boxeja onkin saatavilla suuri määrä, on toisinaan tarpeen luoda myös omia boxeja. Työkaluna tähän käytetään Packeria, jonka käyttöä voi helpottaa valmiilla Boxcutter-templateita.

Esimerkiksi Windows-boxin luonti WIndows Server 2012r2:n evaluointiversion pohjalta 64-bittisessä Linuxissa onnistuu melko helposti. Ensin asennetaan Packer:

$ wget https://releases.hashicorp.com/packer/1.1.3/packer_1.1.3_linux_amd64.zip
 $ unzip packer_1.1.3_linux_amd64.zip
 $ chown john:john packer
 $ chmod 755 packer
 $ mv packer /usr/local/bin
Nyt packer on asennettu. Packerin versionumero epäilemättä vaihtuu ajan saatossa, mutta tällä hetkellä tämä 1.1.3 on uusin versio. Seuraavaksi ladataan Windowsin Boxcutter-tiedosto:
$ git clone https://github.com/boxcutter/windows boxcutter-windows
 $ cd boxcutter-windows
Tässä hakemistossa on lukuisia Packerin json-muotoisia template-tiedostoja. Kustakin templatesta voidaan luoda boxeja eri Vagrant providereille (esim. Virtualbox ja VMWare).
Tämän jälkeen Windows-boxin luonti onkin hyvin suoraviivaista:
$ make virtualbox/eval-win2012r2-standard
Lopputuloksena syntyy Vagrant box:
$ ls box/virtualbox
 eval-win2012r2-standard-nocm-1.0.4.box
Tähän boxiin voidaan sitten viitata Vagrantfile-tiedostossa. Tästä lisää myöhemmin.

Edellisessä artikkelissa rakennettiin Packerilla ja Boxcutter-templateilla Windows box Vagrant-käyttöön. Tässä artikkelissa näytetään, miten Vagrantilla rakennetaan varsinaisia Windows-virtuaalikoneita.

Vagrantia ohjataan Vagrantfile-tiedostolla, joka usein sijaitsee projektin (esim. Puppet-moduuli) päähakemistossa. Jopa hyvin yksinkertainen Vagrantfile riittää Windows-virtuaalikoneen pystyttämiseen:

# -*- mode: ruby -*-
 # vi: set ft=ruby :
 
 Vagrant.configure("2") do |config|
 config.vm.define "win2012r2" do |box|
 box.vm.box = "mwrock/Windows2012R2"
 box.vm.box_version = "0.6.1"
 box.vm.hostname = "windows2012r2a"
 box.vm.network "private_network", ip: "192.168.31.101"
 box.vm.provider "virtualbox" do |vb|
 # Poistetaan Virtualboxin konsolinäkymä käytöstä
 vb.gui = false
 vb.memory = 2048
 end
 end
 end

Yllä käytetään erästä julkista Windows 2012r2 boxia. Aivan yhtä hyvin voitaisiin käyttää aiemmassa artikkelissa Packerilla luotua boxia tähän tapaan:

box.vm.box = "/home/samuli/opt/boxcutter-windows/box/virtualbox/eval-win2012r2-standard-nocm-1.0.4.box"

Kun Vagrantfile on luotu, rakennetaan virtuaalikone:

$ vagrant up
 Bringing machine 'win2012r2' up with 'virtualbox' provider...
 ==> win2012r2: Importing base box 'mwrock/Windows2012R2'...
 ==> win2012r2: Matching MAC address for NAT networking...
 ==> win2012r2: Checking if box 'mwrock/Windows2012R2' is up to date...
 ==> win2012r2: Setting the name of the VM: vagrant-win2012r2_win2012r2_1516105136632_99055
 ==> win2012r2: Clearing any previously set forwarded ports...
 ==> win2012r2: Clearing any previously set network interfaces...
 ==> win2012r2: Preparing network interfaces based on configuration...
 win2012r2: Adapter 1: nat
 win2012r2: Adapter 2: hostonly
 ==> win2012r2: Forwarding ports...
 win2012r2: 3389 (guest) => 3389 (host) (adapter 1)
 win2012r2: 5985 (guest) => 55985 (host) (adapter 1)
 win2012r2: 5986 (guest) => 55986 (host) (adapter 1)
 win2012r2: 22 (guest) => 2222 (host) (adapter 1)
 ==> win2012r2: Running 'pre-boot' VM customizations...
 ==> win2012r2: Booting VM...
 ==> win2012r2: Waiting for machine to boot. This may take a few minutes...
 win2012r2: WinRM address: 127.0.0.1:55985
 win2012r2: WinRM username: vagrant
 win2012r2: WinRM execution_time_limit: PT2H
 win2012r2: WinRM transport: negotiate
 ==> win2012r2: Machine booted and ready!
 Sorry, don't know how to check guest version of Virtualbox Guest Additions on this platform. Stopping installation.
 ==> win2012r2: Checking for guest additions in VM...
 ==> win2012r2: Setting hostname...
 ==> win2012r2: Configuring and enabling network interfaces...
 ==> win2012r2: Mounting shared folders...
 win2012r2: /vagrant => /home/samuli/opt/vagrant-win2012r2

Virtuaalikone on nyt käytettävissä:

$ vagrant status
 Current machine states:
 
 win2012r2 running (virtualbox)
 
 The VM is running. To stop this VM, you can run `vagrant halt` to
 shut it down forcefully, or you can run `vagrant suspend` to simply
 suspend the virtual machine. In either case, to restart it again,
 simply run `vagrant up`.

Teoriassa koneeseen pitäisi pystyä nyt yhdistämään "vagrant rdp"-komennolla. Näin ei kuitenkaan ole, kuten on helppo todeta:

$ vagrant rdp
 ==> win2012r2: Detecting RDP info...
 win2012r2: Address: 127.0.0.1:3389
 win2012r2: Username: vagrant
 ==> win2012r2: Vagrant will now launch your RDP client with the connection parameters
 ==> win2012r2: above. If the connection fails, verify that the information above is
 ==> win2012r2: correct. Additionally, make sure the RDP server is configured and
 ==> win2012r2: running in the guest machine (it is disabled by default on Windows).
 ==> win2012r2: Also, verify that the firewall is open to allow RDP connections.

Vagrant jumittaa tässä pisteessä ilman mitään ilmiselvää syytä ja tilanteen saa purettua vain CTRL-C -komennolla.

Ongelman aiheuttaa se, että "vagrant rdp" ei osaa hyväksyä virtuaalikoneen RDP-palvelimen julkista avainta, joten ongelman voi kiertää yhdistämällä virtuaalikoneeseen ensin käsin. Olettaen, että käytetään Linuxia, kannattaa asentaa Vagrant-käyttöön xfreerdp. Sen asentaminen lähdekoodista on melko suoraviivaista, mutta se löytyy monien Linux-jakelujen pakettivarastoista suoraankin.

Yhdistäminen Vagrant-virtuaalikoneeseen onnistuu helposti, koska oletuksena Windows-virtuaalikoneen portti 3389 välitetään isäntäkoneen porttiin 3389:

$ xfreerdp /u:vagrant /p:vagrant /v:127.0.0.1
 [14:45:39:912] [7041:7042] [INFO][com.freerdp.client.common.cmdline] - loading channelEx cliprdr
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - @ WARNING: CERTIFICATE NAME MISMATCH! @
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - The hostname used for this connection (127.0.0.1:3389) 
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - does not match the name given in the certificate:
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - Common Name (CN):
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - windows2012r2a
 [14:45:39:933] [7041:7042] [ERROR][com.freerdp.crypto] - A valid certificate for the wrong name should NOT be trusted!
 Certificate details:
 Subject: CN = windows2012r2a
 Issuer: CN = windows2012r2a
 Thumbprint: 6e:b7:b8:e2:b3:ab:3d:13:eb:9b:aa:66:8f:4f:7c:70:
 32:a9:49:33
 The above X.509 certificate could not be verified, possibly because you do not have the CA certificate in your certificate store, or the certificate has expired. Please look at the OpenSSL documentation on how to add a private CA to the store.

Xfreerdp:n varoituksista ei tässä yhteydessä kannata välittää, vaan vastata "Y(es)":

Do you trust the above certificate? (Y/T/N) Y

Tämän jälkeen "vagrant rdp" toimii niinkuin kuuluukin, eli avaa suoraan RDP-ikkunan ajettaessa "vagrant rdp".

Kun virtuaalikonetta ei enää tarvita, voidaan se sammuttaa:

$ vagrant halt
 ==> win2012r2: Attempting graceful shutdown of VM...

Jos kone halutaan tuhota kokonaan, käytetään "vagrant destroy"-komentoa:

$ vagrant destroy
 win2012r2: Are you sure you want to destroy the 'win2012r2' VM? [y/N] y
 ==> win2012r2: Destroying VM and associated drives...

Kone voidaan tuhoamisen jälkeen uudelleenrakentaa puhtaalta pöydältä ajamalla "vagrant up"-komento.

Vagrantin shell-provisioner tukee suoraan Powershell-skriptejä. Toisin sanoen Windows-virtuaalikoneen asetuksia voi muokata Powershellillä ilman, että tarvitsee rakentaa uusi virtuaalikonekuva. Tyypillinen esimerkki on Windows liittäminen konfiguraationhallintajärjestelmään kuten Puppetiin.

Vagrantin dokumentaatiossa mainitaan, että Powershell-skriptille voi välittää parametreja powershell_args -valinnalla joko merkkijonona (string) tai listana (array). Esimerkkejä etenkin Powershell-provisioinnista on kuitenkin heikosti, mistä syystä tämäkin blogipostaus on kirjoitettu. Otetaan esimerkkinä skripti bootstrap_windows.ps1, joka liittää Windows-virtuaalikoneen olemassa olevaan Puppetserveriin. Sitä käytetään käsin Powershellistä seuraavasti:

> .bootstrap_windows.ps1 -certName win2012r2.local
 -ServerName puppet.local
 -puppetServerAddress 192.168.137.10

Rivinvaihdot on lisätty selvyyden vuoksi.

Jos bootstrap_windows.ps1 skripti halutaan ajaa suoraan Vagrantissa, tehdään se seuraavasti:

# -*- mode: ruby -*-
 # vi: set ft=ruby :
 
 Vagrant.configure("2") do |config|
 
 config.vm.define "win2012r2" do |box|
 box.vm.box = "mwrock/Windows2012R2"
 box.vm.box_version = "0.6.1"
 box.vm.hostname = "windows2012r2a"
 box.vm.network "private_network", ip: "192.168.31.101"
 box.vm.provider "virtualbox" do |vb|
 vb.gui = false
 vb.memory = 2048
 end
 box.vm.provision "shell" do |s|
 s.path = "bootstrap_windows.ps1"
 s.args = ["-certName", "win2012r2.local",
 "-ServerName", "puppet.local",
 "-puppetServerAddress", "192.168.31.1"]
 end
 end
 end

Huomaa, miten kukin parametri ja parametrin arvo on lisätty listaan erillisenä merkkijonona; syystä tai toisesta esimerkiksi "-certName win2012r2.local" ei toimi.

menucross-circle