# -*- mode: ruby -*-
# vi: set ft=ruby :
# Size of the cluster created by Vagrant
num_instances = 3

# VM Basename
instance_name_prefix="calico-mesos"

# Version of mesos to install from official mesos repo
mesos_version = "1.0.0"

# Download URL for Mesos DNS.
mesos_dns_url = "https://github.com/mesosphere/mesos-dns/releases/download/v0.5.0/mesos-dns-v0.5.0-linux-amd64"

# The calicoctl download URL.
calicoctl_url = "https://github.com/projectcalico/calico-containers/releases/download/v0.22.0/calicoctl"

# The version of the calico docker images to install.  This is used to pre-load
# the calico/node and calico/node-libnetwork images which slows down the
# install process, but speeds up the tutorial.
#
# This version should match the version required by calicoctl installed from
# calicoctl_url.
calico_node_ver = "v0.22.0"
calico_libnetwork_ver = "v0.9.0"

# Script to write out the Calico environment file.
$write_calico_env=<<SCRIPT
cat <<EOF > /etc/sysconfig/calico
ETCD_AUTHORITY=${1}:2379
ETCD_SCHEME=http
ETCD_CA_FILE=""
ETCD_CERT_FILE=""
ETCD_KEY_FILE=""
EOF
SCRIPT

# Script to write out the Mesos DNS config file.
$write_mesos_dns_config=<<SCRIPT
cat <<EOF > /etc/sysconfig/mesos-dns
{
  "zk": "",
  "masters": ["${1}:5050"],
  "refreshSeconds": 5,
  "ttl": 60,
  "domain": "mesos",
  "port": 53,
  "resolvers": ["8.8.8.8"],
  "timeout": 5,
  "httpon": true,
  "dsnon": true,
  "httpport": 8123,
  "externalon": true,
  "listener": "0.0.0.0",
  "SOAMname": "root.ns1.mesos",
  "SOARname": "ns1.mesos",
  "SOARefresh": 60,
  "SOARetry":   600,
  "SOAExpire":  86400,
  "SOAMinttl": 60,
  "IPSources": ["netinfo", "mesos", "host"]
}
EOF
SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = 'centos/7'
  config.ssh.insert_key = false

  # The vagrant centos:7 box has a bug where it automatically tries to sync /home/vagrant/sync using rsync, so disable it:
  # https://github.com/mitchellh/vagrant/issues/6154#issuecomment-135949010
  config.vm.synced_folder ".", "/home/vagrant/sync", disabled: true

  config.vm.provider :virtualbox do |vbox|
    # On VirtualBox, we don't have guest additions or a functional vboxsf
    # in CoreOS, so tell Vagrant that so it can be smarter.
    vbox.functional_vboxsf = false
    vbox.check_guest_additions = false
    vbox.memory = 2048
    vbox.cpus = 2
  end

  config.vm.provider :vsphere do |vsphere, override|
    # The following section sets login credentials for the vagrant-vsphere
    # plugin to allow use of this Vagrant script in vSphere.
    # This is not recommended for demo purposes, only internal testing.
    override.vm.box_url = 'file://dummy.box'
    vsphere.host =                  ENV['VSPHERE_HOSTNAME']
    vsphere.compute_resource_name = ENV['VSPHERE_COMPUTE_RESOURCE_NAME']
    vsphere.template_name =         ENV['VSPHERE_TEMPLATE_NAME']
    vsphere.user =                  ENV['VSPHERE_USER']
    vsphere.password =              ENV['VSPHERE_PASSWORD']
    vsphere.insecure=true
    vsphere.customization_spec_name = 'vagrant-vsphere'
  end

  master_ip = "172.24.197.101"

  # Set up each box
  (1..num_instances).each do |i|
    vm_name = "%s-%02d" % [instance_name_prefix, i]
    config.vm.define vm_name do |host|
      # Provision the FQDN
      host.vm.hostname = vm_name

      # Assign IP and prepend IP/hostname pair to /etc/hosts for correct FQDN IP resolution
      ip = "172.24.197.#{i+100}"
      host.vm.network :private_network, ip: ip

      # Selinux => permissive
      host.vm.provision :shell, inline: "setenforce permissive"

      # Install docker here, as otherwise it will run 'yum update' and unexpectedly ugrade mesos
      host.vm.provision :docker

      # Add official Mesos Repos and install Mesos.
      host.vm.provision :shell, inline: "sudo rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-3.noarch.rpm"
      host.vm.provision :shell, inline: "yum -y install --enablerepo=mesosphere-unstable mesos-#{mesos_version}"

      # Write out the Calico environment file.
      host.vm.provision :shell, inline: $write_calico_env, args: "#{master_ip}"

      # Master
      if i == 1
        host.vm.provision :shell, inline: "yum -y install mesosphere-zookeeper etcd"

        # Zookeeper
        host.vm.provision :shell, inline: "systemctl start zookeeper"

        # Mesos-Master
        host.vm.provision :shell, inline: "sh -c 'echo #{master_ip} > /etc/mesos-master/hostname'"
        host.vm.provision :shell, inline: "sh -c 'echo #{ip} > /etc/mesos-master/ip'"
        host.vm.provision :shell, inline: "systemctl start mesos-master"

        # Marathon
        host.vm.provision "file", source: "units/marathon.service", destination: "/tmp/marathon.service"
        host.vm.provision :shell, inline: "mv /tmp/marathon.service /usr/lib/systemd/system/marathon.service"
        host.vm.provision :shell, inline: "systemctl start marathon"

        # etcd
        host.vm.provision :shell, inline: "sh -c 'echo ETCD_LISTEN_CLIENT_URLS=\"http://0.0.0.0:2379\" >> /etc/etcd/etcd.conf'"
        host.vm.provision :shell, inline: "sh -c 'echo ETCD_ADVERTISE_CLIENT_URLS=\"http://#{master_ip}:2379\" >> /etc/etcd/etcd.conf'"
        host.vm.provision :shell, inline: "systemctl enable etcd.service"
        host.vm.provision :shell, inline: "systemctl start etcd.service"

        # Mesos-dns
        host.vm.provision :shell, inline: "curl -o /usr/bin/mesos-dns -L #{mesos_dns_url}", :privileged => true
        host.vm.provision :shell, inline: "chmod +x /usr/bin/mesos-dns"
        host.vm.provision :shell, inline: $write_mesos_dns_config, args: "#{master_ip}"
        host.vm.provision "file", source: "units/mesos-dns.service", destination: "/tmp/mesos-dns.service"
        host.vm.provision :shell, inline: "mv /tmp/mesos-dns.service /usr/lib/systemd/system/mesos-dns.service"
        host.vm.provision :shell, inline: "systemctl start mesos-dns"
      end

      # Configure all hosts to use Mesos DNS.  Do this after configuring Mesos DNS
      # but before starting Calico on the agent because restarting network services
      # also resets IP forwarding.
      host.vm.provision :shell, inline: "sh -c 'echo DNS1=#{master_ip} >> /etc/sysconfig/network-scripts/ifcfg-eth1'"
      host.vm.provision :shell, inline: "sh -c 'echo PEERDNS=yes >> /etc/sysconfig/network-scripts/ifcfg-eth1'"
      host.vm.provision :shell, inline: "systemctl restart network"

      # Provision with docker, and download the calico-node docker image
      host.vm.provision :docker, images: [
	        "calico/node-libnetwork:#{calico_libnetwork_ver}",
	        "calico/node:#{calico_node_ver}",
      ]

      # Configure docker to use etcd on master as its datastore
      host.vm.provision :shell, inline: "mkdir -p /usr/lib/systemd/system/docker.service.d"
      host.vm.provision "file", source: "units/docker.service.d/docker.conf", destination: "/tmp/docker.conf"
      host.vm.provision :shell, inline: "mv /tmp/docker.conf /usr/lib/systemd/system/docker.service.d/docker.conf"
      host.vm.provision :shell, inline: "systemctl daemon-reload"
      host.vm.provision :shell, inline: "systemctl restart docker.service"

      # Install calicoctl
      host.vm.provision :shell, inline: "curl -o /usr/bin/calicoctl -L #{calicoctl_url}", :privileged => true
      host.vm.provision :shell, inline: "chmod +x /usr/bin/calicoctl"

      # Install the Calico service files and start the Calico services.
      ["calico", "calico-libnetwork"].each do |service_name|
        host.vm.provision "file", source: "units/#{service_name}.service", destination: "/tmp/#{service_name}.service"
        host.vm.provision :shell, inline: "mv /tmp/#{service_name}.service /usr/lib/systemd/system/#{service_name}.service"
        host.vm.provision :shell, inline: "systemctl start #{service_name}"
      end

      if i == 1
        # Master specific stuff.
        # Setup marathon-lb
        host.vm.provision :docker, images: ["robbrockbank/marathon-lb:ip-per-task"]
        host.vm.provision "file", source: "units/marathon-lb.service", destination: "/tmp/marathon-lb.service"
        host.vm.provision :shell, inline: "sh -c 'echo MARATHON_IP=#{master_ip} > /etc/sysconfig/marathon-lb'"
        host.vm.provision :shell, inline: "mv /tmp/marathon-lb.service /usr/lib/systemd/system/marathon-lb.service"
        host.vm.provision :shell, inline: "systemctl start marathon-lb"
      else
        # Configure and start mesos-slave
        host.vm.provision :shell, inline: "sh -c 'echo zk://#{master_ip}:2181/mesos > /etc/mesos/zk'"
        # NOTE: Saving the IP below is used for demo purposes to workaround DNS hostname
        # resolution when visiting the Mesos Master UI agent sandboxes.
        host.vm.provision :shell, inline: "sh -c 'echo #{ip} > /etc/mesos-slave/ip'"
        host.vm.provision :shell, inline: "sh -c 'echo #{ip} > /etc/mesos-slave/hostname'"
        host.vm.provision :shell, inline: "sh -c 'echo mesos,docker > /etc/mesos-slave/containerizers'"
        host.vm.provision :shell, inline: "systemctl start mesos-slave.service"
      end
    end
  end
end
