Ruby
vagrant

VagrantFileをちょっとだけわかりやすくする

More than 1 year has passed since last update.

概要

vagrantfileがrubyで動いているという話。
rubyで動いてるなら、関数とか使えるんじゃ…と思って使ったら動いたというお話。

産物

# -*- mode: ruby -*-
# vi: set ft=ruby :
def VMconf(config ,hostname ,ip:nil ,cpu:1 ,cpulimit:100 ,memory:1024 ,customCode:nil, **var)
  config.vm.define hostname do |vh|
    if ip == nil then
      vh.vm.hostname = hostname
      vh.vm.network "private_network",type: "dhcp", virtualbox__intnet: "VMNet_Vagrant", auto_config: true
    else
      vh.vm.hostname = hostname
      vh.vm.network "private_network",ip: ip, virtualbox__intnet: "VMNet_Vagrant", auto_config: true
    end
    config.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.cpus = cpu.to_s
      vb.memory = memory.to_s
      vb.customize [
          "modifyvm", :id,
          "--cpuexecutioncap", cpulimit.to_s,
          "--groups", "/Vagrant/Vpractice"
      ]
      vb.linked_clone = true
    end

#   yum update とかの共通処理があれば追加
#    config.vm.provision :shell, :path => "./common_setup.sh",:privileged => true
    if customCode != nil then
      customCode.call(config,vh)
    end
  end
end

def DumpPack(config)
  config.vm.provision "shell",inline: <<SCRIPT
    yum install tcpdump -y
    echo "SELINUX=permissive" > /etc/sysconfig/selinux
    setenforce 0
SCRIPT
end

def WebKit(config)
  config.vm.provision :shell,inline: <<SCRIPT
    yum install httpd -y
    echo '<http><body><h1>' > /var/www/html/index.html
    hostname >> /var/www/html/index.html
    echo '</h1></body></html>' >> /var/www/html/index.html
    service httpd start
    chkconfig httpd on

    iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
    service iptables save
SCRIPT
end

def HostOnlyInterface(vmhandle,ip)
  vmhandle.vm.network "private_network",
  name:"VirtualBox Host-Only Ethernet Adapter #1",
  ip: ip,
  netmask: "255.255.255.0",
  auto_config: true
end

fuga_scripts = ::Kernel.lambda{ |config,vmhandle|
#  DumpPack(config)  # ダンプする場合に使う
  WebKit(config)
  HostOnlyInterface(vmhandle,"172.16.0.12")
}

  box = "CentOS6.9_min_customed"
  Vagrant.configure(2) do |config|
    config.vm.box = box
    VMconf(config, "hoge", :ip=>"192.168.254.130", :cpu=>2, :cpulimit=>50, :memory=>8192)
    VMconf(config, "fuga", :ip=>"192.168.254.131", :customcode=>fuga_scripts)
end

このコードでできたこと

簡単なVMなら一行で定義できる

# VCPUx2、CPU制限50%、メモリ8GBのVM"hogehoge1"を作る。 eth1には192.168.254.140を割り当てる
VMconf(config, "hogehoge1", :ip=>"192.168.254.140", :cpu=>2, :cpulimit=>50, :memory=>8192)

# VM"hogehoge2"を作る。VCPUx1で使用率制限なし、メモリ1GB、eth1はDHCP。
VMconf(config, "hogehoge2")

機能を関数にまとめて使いまわせる

# httpサーバのタネ作る関数
def WebKit(config)
  config.vm.provision :shell,inline: <<SCRIPT
    yum install httpd -y
    echo '<http><body><h1>' > /var/www/html/index.html
    hostname >> /var/www/html/index.html
    echo '</h1></body></html>' >> /var/www/html/index.html
    service httpd start
    chkconfig httpd on

    iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
    service iptables save
SCRIPT
end

# ホストオンリーアダプタを追加する関数
def HostOnlyInterface(vmhandle,ip)
  vmhandle.vm.network "private_network",
  name:"VirtualBox Host-Only Ethernet Adapter #1",
  ip: ip,
  netmask: "255.255.255.0",
  auto_config: true
end

###----これより上は使いまわせる。別ファイル化しても良いかも。----###

# 各VM用の関数を定義。
fuga1_scripts = ::Kernel.lambda{ |config,vmhandle|
  WebKit(config)
  HostOnlyInterface(vmhandle,"172.16.0.11")
}
fuga2_scripts = ::Kernel.lambda{ |config,vmhandle|
  WebKit(config)
  HostOnlyInterface(vmhandle,"172.16.0.12")
}
~~ 中略 ~~
# 作ったラムダ関数を渡す。
VMconf(config, "fugafuga1", :customcode=>fuga1_scripts)
VMconf(config, "fugafuga2", :customcode=>fuga2_scripts)

このコードのダメなところ

IPに関しては事前準備が必要

  • 「VMNet_Vagrant」という内部ネットワークがVirtualBoxに存在する
  • 「VMNet_Vagrant」内部ネットワーク内でDHCPが利用可能

これが前提になってしまっている。
vagrant connectで繋ぐからそんなの要らない! って人は下記部分を削除する必要がある。

  if ip == nil then
    vh.vm.hostname = hostname
    vh.vm.network "private_network",type: "dhcp", virtualbox__intnet: "VMNet_Vagrant", auto_config: true
  else
    vh.vm.hostname = hostname
    vh.vm.network "private_network",ip: ip, virtualbox__intnet: "VMNet_Vagrant", auto_config: true
  end

その他、ダメなところはコメントで募集中です。(良いところも募集中です)