# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2" 

NETWORK = "192.168.56."
NETMASK = "255.255.255.0"

# Put the MAIN ip <-> NCDOM domain below to host /etc/hosts
MAIN = NETWORK+"10"
NCDOM = "nextcloud.test"

# VM machines configuration
HOSTS = [
    #VM_NAME                    IP_ADDRESS            RAM(mb)        CPU         BOX                       GROUP
  { :hostname => "db1",         :ip => NETWORK+"11",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "db_servers",      }, #:guestport => 3306, :hostport => 13306 }, #:user => ""  :pass => ""  },
  #{ :hostname => "db2",         :ip => NETWORK+"12",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "db_servers",      }, #:guestport => 3306, :hostport => 23306 }, #:user => ""  :pass => ""  },
  #{ :hostname => "db3",         :ip => NETWORK+"13",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "db_servers",      }, #:guestport => 3306, :hostport => 33306 }, #:user => ""  :pass => ""  },
  #{ :hostname => "lbsql1",      :ip => NETWORK+"19",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "db_lbal_servers", :state => "MASTER",  :priority => 101, :vip => NETWORK+"20" },
  #{ :hostname => "lbsql2",      :ip => NETWORK+"18",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "db_lbal_servers", :state => "BACKUP",  :priority => 100, :vip => NETWORK+"20" },
  #{ :hostname => "redis",       :ip => NETWORK+"21",  :ram =>  512,  :cpu => 1,  :box => "centos/7",       :group => "redis_servers"    },
  #{ :hostname => "redis2",      :ip => NETWORK+"22",  :ram =>  512,  :cpu => 1,  :box => "centos/7",       :group => "redis_servers"    },
  #{ :hostname => "gl",          :ip => NETWORK+"31",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "gluster_servers"  },
  #{ :hostname => "gl2",         :ip => NETWORK+"32",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "gluster_servers"  },
  { :hostname => "web.test",    :ip => NETWORK+"41",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "web_servers",     :ipdb => NETWORK+"20", :redis_vip => NETWORK+"40", :priority => 101 },
  #{ :hostname => "web2.test",   :ip => NETWORK+"42",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "web_servers",     :ipdb => NETWORK+"20", :redis_vip => NETWORK+"40", :priority => 100 },
  { :hostname => "lb.test",     :ip => NETWORK+"51",  :ram => 1024,  :cpu => 1,  :box => "ubuntu/focal64", :group => "lbal_servers",    :state => "MASTER",  :priority => 101 },
  #{ :hostname => "lb2.test",    :ip => NETWORK+"52",  :ram =>  512,  :cpu => 1,  :box => "ubuntu/focal64", :group => "lbal_servers",    :state => "BACKUP",  :priority => 100 },
  #{ :hostname => "prome",       :ip => NETWORK+"61",  :ram =>  512,  :cpu => 1,  :box => "centos/7",       :group => "monitor_servers"  },
  #{ :hostname => "node",        :ip => NETWORK+"62",  :ram =>  512,  :cpu => 1,  :box => "centos/7",       :group => "monitor_servers"  },
  #{ :hostname => "grafa",       :ip => NETWORK+"63",  :ram =>  512,  :cpu => 1,  :box => "centos/7",       :group => "monitor_servers"  },
  #{ :hostname => "essai1.test", :ip => NETWORK+"98",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "test_servers",    :priority => 101, :vip => NETWORK+"100" },
  #{ :hostname => "essai2.test", :ip => NETWORK+"99",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "test_servers",    :priority => 100, :vip => NETWORK+"100" },
  #{ :hostname => "web.test",    :ip => NETWORK+"41",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "web_servers"      },
  #{ :hostname => "web2.test",   :ip => NETWORK+"42",  :ram => 1024,  :cpu => 1,  :box => "centos/7",       :group => "web_servers"      },
]

# Defined ansible playbook
vagrant_root = File.expand_path(File.dirname(__FILE__))
# If empty, will skip the ansible provisioner block
ansible_playbook = "provisioning/ansible/playbook.yml"
# Ansible inventory. The path supports nested directories or a single file
ansible_inventory_path = "provisioning/ansible/hosts"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  if Vagrant.has_plugin?("vagrant-hostmanager")
    config.vm.box_check_update = false 
    # To enable the hostmanager plugin
    config.hostmanager.enabled           = true
    # To enable add records to host /etc/hosts
    config.hostmanager.manage_host       = false
    # To enable add records to guest /etc/hosts
    config.hostmanager.manage_guest      = true
    # Not use private ip addresses for the hosts file, set to false
    config.hostmanager.ignore_private_ip = false
    config.hostmanager.include_offline   = false
  end

  # Create groups to be used in ansible inventory
  groups = {"all" => []}
  HOSTS.each do |cfg|
    if ! groups.has_key?(cfg[:group])
      groups[cfg[:group]] = [cfg[:hostname]]
    else
      groups[cfg[:group]].push(cfg[:hostname])
    end
    groups["all"].push(cfg[:hostname])
  end

  # Create inventory for ansible provision
  # The inventory will hold servers details and groups per each server.
  if File.dirname(ansible_inventory_path) != "."
    Dir.mkdir(File.dirname(ansible_inventory_path)) unless Dir.exist?(File.dirname(ansible_inventory_path))
  end
  File.delete(ansible_inventory_path) if File.exist?(ansible_inventory_path)
  File.open(ansible_inventory_path, 'w') do |f|
    HOSTS.each do |cfg|
      ssh_key = vagrant_root+"/.vagrant/machines/"+cfg[:hostname]+"/virtualbox/private_key"
      f.write "#{cfg[:hostname]} ansible_host=#{cfg[:ip]} ansible_ssh_private_key_file=#{ssh_key}\n"
    end
    groups.keys.each_with_index do |g, index|
      f.write "\n"
      f.write "[#{g}]\n"
      groups[g].each do |h| 
        f.write "#{h}"
        network = NETWORK+"0/24"
        f.write " network_allowed="+network
        if g == "lbal_servers"
          HOSTS.each do |cfg|
            if cfg[:hostname] == h
              priority = (cfg[:priority].to_s || "UNKNOWN" )
              state = (cfg[:state].to_s || "UNKNOWN" )           
              f.write " ssl_name="+NCDOM+" keepalived_vip="+MAIN+" keepalived_priority="+priority+" keepalived_state="+state
            end
          end
        end
        if g == "web_servers"
          HOSTS.each do |cfg|
            if cfg[:hostname] == h
              ipdb = (cfg[:ipdb].to_s || "" )
              priority = (cfg[:priority].to_s || "UNKNOWN" )
              redis = (cfg[:redis_vip].to_s || "UNKNOWN" )
              if groups.count("web_servers") > 2
                f.write " nc_global_name="+NCDOM+" db_host="+ipdb+" redis_host="+redis+" keepalived_vip="+redis+" keepalived_priority="+priority
              else
                f.write " nc_global_name="+NCDOM+" db_host="+ipdb
              end
            end
          end
        end
        if g == "db_lbal_servers"
          HOSTS.each do |cfg|
            if cfg[:hostname] == h
              priority = (cfg[:priority].to_s || "UNKNOWN" )
              state = (cfg[:state].to_s || "UNKNOWN" )
              vip = (cfg[:vip].to_s || "UNKNOWN" )
              f.write " keepalived_vip="+vip+" keepalived_priority="+priority+" keepalived_state="+state
            end
          end
        end
        if g == "test_servers"
          HOSTS.each do |cfg|
            if cfg[:hostname] == h
              priority = (cfg[:priority].to_s || "UNKNOWN" )
              vip = (cfg[:vip].to_s || "UNKNOWN" )
              f.write " keepalived_vip="+vip+" keepalived_priority="+priority
            end
          end
        end
        f.write "\n"
      end
    end
  end

  # VM DEFINITIONS

  HOSTS.each_with_index do |server, index|
    config.vm.define server[:hostname] do |conf|
      conf.vm.box = server[:box]
      conf.vm.hostname = server[:hostname]
      conf.vm.boot_timeout = 360
      # Set system options
      cpu = server[:cpu] ? server[:cpu] : 1;
      memory = server[:ram] ? server[:ram] : 512;
      name = server[:hostname] ? server[:hostname] : "linux";
      conf.vm.provider "virtualbox" do |vbox|
        vbox.cpus   = cpu.to_s
        vbox.memory = memory.to_s
        vbox.name   = name
      end
      # Set network options
      netmask = server[:netmask] || NETMASK
      conf.vm.network :private_network, ip: server[:ip], netmask: netmask
      # Set port forwarding if defined
      if !server[:port_guest].nil? && !server[:port_host].nil?
        conf.vm.network "forwarded_port", guest: server[:port_guest], host: server[:port_host]
      end
      # Set synced folders if defined
      if !server[:folder_guest].nil? && !server[:folder_host].nil?
        conf.vm.synced_folder server[:folder_host], server[:folder_guest]
      end 
      # Set common provision
      conf.vm.provision "shell" do |s|
        s.path = "provisioning/bash/common.sh"
        s.args = [server[:box]]
      end     
      # Provision nodes with Ansible.
      # The index used here in order to execute the provision just after all
      # the servers are up and running.
      if index == HOSTS.size - 1
        if ansible_playbook != ""
          conf.vm.provision :ansible do |ansible|
            ansible.limit = "all"
            ansible.compatibility_mode = "2.0"
            ansible.inventory_path = ansible_inventory_path
            ansible.playbook = ansible_playbook
            ansible.become = true
            #ansible.verbose = "vvvv"
          end
        end
      end      
    end
  end

# VM PROVISIONING

#  #Prometheus
#  config.vm.define "prometheus" do |prometheus|
#    prometheus.vm.box = 'centos/7'
#    prometheus.vm.hostname = "prometheus"
#    prometheus.vm.network :private_network, ip: "192.168.56.41"
#    prometheus.vm.provision "shell", path: "provisioning/install/Centos_7.sh"
#
#    #Provision prometheus-grafana with Ansible
#    prometheus.vm.provision "ansible" do |ansible|
#       ansible.compatibility_mode = "2.0"
#       ansible.playbook="provisioning/ansible/prometheus.yml"
#       ansible.become = true
#       ansible.extra_vars = {
#         ansible_python_interpreter: "/usr/bin/python2",
#       }
#    end
#  end
#
#  #Node Exporter
#  config.vm.define "node" do |node|
#    node.vm.box = 'centos/7'
#    node.vm.hostname = "nodexporter"
#    node.vm.network :private_network, ip: "192.168.56.42"
#    node.vm.provision "shell", path: "provisioning/install/Centos_7.sh"
#
#    #Provision prometheus-grafana with Ansible
#    node.vm.provision "ansible" do |ansible|
#       ansible.compatibility_mode = "2.0"
#       ansible.playbook="provisioning/ansible/node_exporter.yml"
#       ansible.become = true
#       ansible.extra_vars = { 
#         ansible_python_interpreter: "/usr/bin/python2",
#       }
#    end 
#  end
#
#  #Grafana
#  config.vm.define "grafana" do |grafana|
#    grafana.vm.box = 'centos/7'
#    grafana.vm.hostname = "grafana"
#    grafana.vm.network :private_network, ip: "192.168.56.43"
#    grafana.vm.provision "shell", path: "provisioning/install/Centos_7.sh"
#
#    #Provision prometheus-grafana with Ansible
#    grafana.vm.provision "ansible" do |ansible|
#       ansible.compatibility_mode = "2.0"
#       ansible.playbook="provisioning/ansible/grafana.yml"
#       ansible.become = true
#       ansible.extra_vars = { 
#         ansible_python_interpreter: "/usr/bin/python2",
#       }
#    end 
#  end 

  #end
end
