
class vmware::server {

    package { "VMware-server":
	ensure  => installed,
    }

    service { "vmware":
	ensure    => running,
	enable    => true,
	hasstatus => true,
	start     => "pkill 'vmnet-' ; /sbin/service vmware stop ; rm -f /etc/vmware/not_configured ; /sbin/service vmware start && sleep 5",
	stop      => "pkill 'vmnet-' ; /sbin/service vmware stop",
	require   => [ Package["VMware-server"],
		       Exec["vmware-config.pl"], ],
    }

    # seems that vmware init script fails if pid files are missing for vmnet
    # processes, so kill them by force first
    exec { "vmware-config.pl":
	command     => "pkill 'vmnet-' ; perl /usr/bin/vmware-config.pl --default EULA_AGREED=yes && rm -f /etc/vmware/not_configured",
	path        => "/bin:/usr/bin:/sbin:/usr/sbin",
        environment => [ "PAGER=/bin/cat", ],
	unless      => "test ! -f /etc/vmware/not_configured -a -f /lib/modules/$kernelrelease/misc/vmci.ko",
        require     => Package["VMware-server"],
	notify      => Service["vmware"],
    }

    if $vmware_serial {
	exec { "vmware-set-serial":
	    command => "/usr/lib/vmware/bin/vmware-vmx --new-sn ${vmware_serial}",
	    path    => "/bin:/usr/bin:/sbin:/usr/sbin",
	    user    => root,
	    creates => "/etc/vmware/license.vs.1.0-00",
	    require => Package["VMware-server"],
	    before  => Exec["vmware-config.pl"],
	}
    }

    if $vmware_admin_group {
        file { "/etc/vmware/ssl/rui.key":
	    ensure  => present,
	    mode    => 0640,
	    owner   => root,
	    group   => $vmware_admin_group,
	    require => [ Service["vmware"],
                         Class["puppet::client"], ],
	    notify  => Exec["restart-vmware-mgmt"],
        }
        exec { "restart-vmware-mgmt":
            command     => "/etc/init.d/vmware-mgmt restart && sleep 10",
            path        => "/bin:/usr/bin:/sbin:/usr/sbin",
            user        => root,
            refreshonly => true,
        }

        exec { "vmware-admin-add-${vmware_admin_group}":
            command => "/usr/bin/vmware-vim-cmd vimsvc/auth/entity_permission_add 'vim.Folder:ha-folder-root' '${vmware_admin_group}' 'true' 'Admin' 'true'",
            path    => "/bin:/usr/bin:/sbin:/usr/sbin",
            user    => root,
            unless  => "/usr/bin/vmware-vim-cmd vimsvc/auth/entity_permissions 'vim.Folder:ha-folder-root' | egrep 'principal|roleId' | cut -d= -f2 | sed -e 'N;s/\\n/ /' | fgrep -- -1 | grep '\"${vmware_admin_group}\"'",
            require => Service["vmware"],
        }
    }

}


# Install custom VMware support scripts
#
class vmware::server::scripts {

    include socat::package

    define vmware::server::scripts::file {
	file { "/usr/local/sbin/${name}":
	    ensure => present,
	    source => "puppet:///modules/vmware/scripts/${name}",
	    mode   => 0755,
	    owner  => root,
	    group  => root,
	}
    }

    file { "/usr/local/lib/vmware.sh":
	ensure => present,
	source => "puppet:///modules/vmware/scripts/vmware.sh",
	mode   => 0644,
	owner  => root,
	group  => root,
    }

    vmware::server::scripts::file { "vmware-console": }
    vmware::server::scripts::file { "vmware-list": }
    vmware::server::scripts::file { "vmware-register": }
    vmware::server::scripts::file { "vmware-start": }
    vmware::server::scripts::file { "vmware-stop": }
    vmware::server::scripts::file { "vmware-suspend": }
    vmware::server::scripts::file { "vmware-unregister": }

}


# Create /vmfs directory hierarcy.
#
# === Depencies
#
#   * Package["VMware-server"]
#
class vmware::server::vmfs {

    include vmware::server

    file { "/vmfs":
	ensure  => directory,
	mode    => 0755,
	owner   => root,
	group   => root,
	require => Package["VMware-server"],
    }
    file { "/vmfs/volumes":
	ensure  => directory,
	mode    => 0755,
	owner   => root,
	group   => root,
	require => File["/vmfs"],
    }

}


# Modify VMware datastores.
#
# === Parameters
#
#   $name:
#       Datastore name.
#   $type:
#       Filesystem type of datastore.
#   $options:
#       Filesystem mount options.
#
# === Sample usage
#
# vmware::server::datastore { "ds-001":
#     device  => "its1:/export/vmware/ds-001",
#     options => "hard,intr,rw,nosuid,nodev,tcp,rsize=1048576,wsize=1048576",
# }
#
define vmware::server::datastore($device, $type = "auto", $options = "defaults") {

    include vmware::server::vmfs

    case $vmware_admin_group {
        "":      { $real_vmware_admin_group = "root" }
        default: { $real_vmware_admin_group = $vmware_admin_group }
    }

    if $type == "auto" {
        $server = regsubst($device, '^([a-zA-Z0-9\-]+):(/.+)$', '\1')
	if $server == $device {
	    $fstype = $type
	    if $device == regsubst($device, '^(/dev/).+$', '\1') {
		$mountopts = "bind"
	    }
	} else {
	    $fstype = "nfs"
	    $path = regsubst($device, '^([a-zA-Z0-9\-]+):(/.+)$', '\2')
	}
    }

    if !$mountopts {
	$mountopts = $options
    }

    file { "/vmfs/volumes/${name}":
	ensure  => directory,
	mode    => $fstype ? {
            nfs     => 0755,
            default => 0775,
        },
	owner   => root,
	group   => $fstype ? {
            nfs     => "root",
            default => $real_vmware_admin_group,
        },
	require => File["/vmfs/volumes"],
    }

    mount { "/vmfs/volumes/${name}":
	ensure  => mounted,
	device  => "${device}",
	fstype  => "${fstype}",
	options => "${mountopts}",
	require => File["/vmfs/volumes/${name}"],
    }

    exec { "vmware-create-datastore-${name}":
	command => $fstype ? {
	    nfs     => "vmware-vim-cmd hostsvc/datastore/nas_create ${name} ${server} ${path} 0",
	    default => "vmware-vim-cmd hostsvc/datastore/localds_create ${name} /vmfs/volumes/${name}",
	},
	path    => "/bin:/usr/bin:/sbin:/usr/sbin",
	user    => root,
	unless  => "vmware-vim-cmd hostsvc/datastore/summary ${name}",
	require => [ Mount["/vmfs/volumes/${name}"],
		     Service["vmware"], ],
	notify  => Exec["vmware-refresh-datastore-${name}"],
    }

    exec { "vmware-refresh-datastore-${name}":
	command     => "vmware-vim-cmd hostsvc/datastore/refresh ${name}",
	path        => "/bin:/usr/bin:/sbin:/usr/sbin",
	user        => root,
	refreshonly => true,
    }

}


# Modify VMware bridge interfaces.
#
# === Parameters
#
#   $name:
#       vmnet device name.
#   $description:
#       Interface description.
#   $device:
#       Physical network device to bridge.
#   $ensure:
#	Set to present to enable bridge and absent to disable it.
#
# === Sample usage
#
# vmware::server::bridge { "vmnet0":
#     ensure      => present,
#     device      => "eth0",
#     description => "Bunker",
# }
#
define vmware::server::bridge($description, $device, $ensure = "present") {

    $vmnet = regsubst($name, '^vmnet([0-9]+)$', '\1')
    if $vmnet == $name {
	fail("Invalid vmnet device name.")
    }

    service { "${name}-bridge":
	ensure   => $ensure ? {
	    "present" => running,
	    "absent"  => stopped,
	},
	pattern  => "/usr/bin/vmnet-bridge -d .* -n ${vmnet}",
	start    => "/usr/bin/vmnet-bridge -d /var/run/vmnet-bridge-${vmnet}.pid -n ${vmnet} -i ${device}",
	stop     => "pkill -f '/usr/bin/vmnet-bridge -d .* -n ${vmnet}'",
	provider => base,
	require  => Exec["vmware-config.pl"],
    }

    vmware_config { "VNET_${vmnet}_NAME":
	ensure  => $ensure ? {
	    absent  => absent,
	    present => "${description}",
	},
	require => Exec["vmware-config.pl"],
    }
    vmware_config { "VNET_${vmnet}_INTERFACE":
	ensure  => $ensure ? {
	    absent  => absent,
	    present => "${device}",
	},
	notify  => Service["${name}-bridge"],
	require => Exec["vmware-config.pl"],
    }

}
