From 703241117f67434b63637a93da9203ee29456f71 Mon Sep 17 00:00:00 2001 From: Gardouille Date: Thu, 10 Dec 2015 10:03:08 +0100 Subject: [PATCH] Start from the previous Proxmox Puppet module: https://git.101010.fr/puppet/proxmox --- CHANGELOG.md | 133 +++++++++ Gemfile | 7 + README.md | 278 ++++++++++++++++++ Rakefile | 18 ++ lib/facter/is_proxmox.rb | 7 + lib/facter/is_pve_kernel.rb | 19 ++ lib/facter/vznetmask.rb | 29 ++ lib/facter/vznetwork.rb | 35 +++ manifests/hypervisor.pp | 82 ++++++ manifests/hypervisor/cluster.pp | 52 ++++ manifests/hypervisor/config.pp | 56 ++++ manifests/hypervisor/group.pp | 74 +++++ manifests/hypervisor/install.pp | 78 +++++ manifests/hypervisor/preconfig.pp | 75 +++++ manifests/hypervisor/service.pp | 45 +++ manifests/hypervisor/user.pp | 59 ++++ manifests/init.pp | 23 ++ manifests/params.pp | 73 +++++ manifests/vm.pp | 46 +++ manifests/vm/openvz.pp | 41 +++ metadata.json | 20 ++ spec/classes/init_spec.rb | 7 + spec/spec_helper.rb | 1 + templates/hypervisor/proxmox_modules.conf.erb | 7 + templates/hypervisor/pveproxy_default.erb | 8 + templates/hypervisor/vz.conf.erb | 56 ++++ templates/vm/openzv_interfaces.erb | 12 + templates/vm/openzv_interfaces.tail.erb | 15 + tests/add_user.pp | 1 + tests/group_management.pp | 8 + tests/hypervisor.pp | 1 + tests/hypervisor_kvm_only.pp | 4 + tests/init.pp | 12 + 33 files changed, 1382 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 Gemfile create mode 100644 README.md create mode 100644 Rakefile create mode 100644 lib/facter/is_proxmox.rb create mode 100644 lib/facter/is_pve_kernel.rb create mode 100644 lib/facter/vznetmask.rb create mode 100644 lib/facter/vznetwork.rb create mode 100644 manifests/hypervisor.pp create mode 100644 manifests/hypervisor/cluster.pp create mode 100644 manifests/hypervisor/config.pp create mode 100644 manifests/hypervisor/group.pp create mode 100644 manifests/hypervisor/install.pp create mode 100644 manifests/hypervisor/preconfig.pp create mode 100644 manifests/hypervisor/service.pp create mode 100644 manifests/hypervisor/user.pp create mode 100644 manifests/init.pp create mode 100644 manifests/params.pp create mode 100644 manifests/vm.pp create mode 100644 manifests/vm/openvz.pp create mode 100644 metadata.json create mode 100644 spec/classes/init_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 templates/hypervisor/proxmox_modules.conf.erb create mode 100644 templates/hypervisor/pveproxy_default.erb create mode 100644 templates/hypervisor/vz.conf.erb create mode 100644 templates/vm/openzv_interfaces.erb create mode 100644 templates/vm/openzv_interfaces.tail.erb create mode 100644 tests/add_user.pp create mode 100644 tests/group_management.pp create mode 100644 tests/hypervisor.pp create mode 100644 tests/hypervisor_kvm_only.pp create mode 100644 tests/init.pp diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b8bfed1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,133 @@ + +--------------------------------------- + +### 0.2.4 + +##### Features +* Latest release for Proxmox 3.x. Please be careful with the next release! + +##### Changes +* Upgrade pve-kernel-3.10.0-13-pve and pve-kernel-2.6.32-43 to the last version. + +--------------------------------------- + +### 0.2.3 - 2015/06/01 + +##### Features +* New fact is_pve_kernel check if the running kernel is a PVE. + +##### Changes +* Some installation's instructions only run if running a PVE kernel (test the new is_pve_kernel fact). +* Use the stdlib function 'ensure_packages' to install recommended packages instead of 'if ! defined'. +* Upgrade pve-kernel-3.10.0-9-pve and pve-kernel-2.6.32-39 to the last version. +* Correct puppet-lint warnings. + +##### Bugfixes +* #14 The module no longer automatically reboot nodes after kernel upgrade, show a warning message instead. + +--------------------------------------- + +### 0.2.2 - 2015/03/25 + +##### Features +* A new subclass to automates the creation of a cluster from the master and join from other nodes. + +##### Changes +* Update README.md. +* Upgrade pve-kernel-3.10.0-8-pve and pve-kernel-2.6.32-37 to the last version. +* Puppet-lint +* Add a case for 'kvm' VM doesn't do anything right now, wait for specific (packages, config, …). + +##### Bugfixes +* (#11) Add a new fact to get a valid netmask for OpenVZ's virtual interfaces (venet). +* (#11) Use the new fact vznetmask_venet0_0 to add the route in interfaces.tail file. + +--------------------------------------- +### 0.2.1 - 2015/02/03 + +##### Features +* Manage the main OpenVZ's configuration file (/etc/vz/vz.conf). +* Add vz service management. + +##### Changes +* The network management for an OpenVZ CT now works for all Debian family and not only Debian >=7. +* Modification in OpenVZ's configuration file notify the 'vz' service. +* Set an option to manage iptables modules in OpenVZ configuration. +* Correct puppet-lint warnings. + +--------------------------------------- +### 0.2.0 - 2015/01/27 + +#### Summary +This release introduce a new subclasse for OpenVZ CT (network management): + + include proxmox::vm + +It's also provide a array of kernel modules added at the boot start. + +##### Features +* (#2) Add an array and a file to load additionnal modules. +* (#9) Add a puppetlabs-firewall rule. +* (#3) Add a new class and subclass: proxmox::vm::openvz to manage OpenVZ CT. +* (#3) Add a new fact to calculate venet's network with /24 instead of /32.) +* Add many modules (mainly for iptables) to load at startup (sea README.md). + +##### Bugfixes +* Correct module's dependencies. +* Run the proxmox::hypervisor::group only if PVE is installed. + +##### Changes +* README.md: Add examples, a table of contents, information about proxmox::vm::openvz (#3). +* Correct indentation, double quote, ... + +--------------------------------------- + +### 0.1.0 - 2015/01/15 + +This release introduce new defined types: + + proxmox::hypervisor::group { 'sysadmin': + role => 'Administrator', + users => [ 'root@pam', 'test@pve' ], + } + + proxmox::hypervisor::user { 'toto@pve': + group => 'sysadmin', + } + +And also directly jump to 0.1.0, the module allow to manage a simple Proxmox hypervisor right now. + +##### Changes +* Add a variable to choose to keep PVE enterprise repo for the subscribers. +* (#4) Add an access control list for PveProxy. +* (#4) Add a new class to manage Proxmox's service (proxmox::hypervisor::service). +* (#6) Add a new defined type to manage groups for PVE WebGUI. +* (#7) Add a new defined type to manage users for PVE WebGUI. +* Update the README.md file for (#6) group and (#7) user defined types. +* Add a test for (#6) group and (#7) user defined types. + +--------------------------------------- + +### 0.0.2 - 2015/01/08 + +New functionality release, Proxmox installation now working :) + +##### Changes +* (#1) Possibility to choose between newer kernel that only supports KVM or a ~2.6.32 that supports both KVM and OpenVZ. +* (#1) Install the Virtual Environment and it's works with 2 puppet run. +* Add new test (hypervisor_kvm_only). +* Add a fact to check if Proxmox is "available". +* Add a new class: proxmox::hypervisor::config for some tiny configurations. +* Remove the subscription message in the web gui. +* Add operatingsystem_support information in the metadata.json (to correct the error in Metadata Quality). +* Correct wtfpl into WTFPL to be recognized by SPDX (Metadata Quality). +* Correct indentation, double quote, ... + +--------------------------------------- + +### 0.0.1 - 2015/01/07 + +Initial release. + +##### Changes +* Only prepare the system for Proxmox installation (proxmox::hypervisor::preconfig) diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..7bd34cd --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +source 'https://rubygems.org' + +puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3'] +gem 'puppet', puppetversion +gem 'puppetlabs_spec_helper', '>= 0.1.0' +gem 'puppet-lint', '>= 0.3.2' +gem 'facter', '>= 1.7.0' diff --git a/README.md b/README.md new file mode 100644 index 0000000..40fdcf7 --- /dev/null +++ b/README.md @@ -0,0 +1,278 @@ +# proxmox + +#### Table of Contents + +1. [Overview](#overview) +2. [Module Description](#module-description) +3. [Setup](#setup) + * [What Proxmox affects](#what-proxmox-affects) + * [Beginning with Proxmox](#beginning-with-proxmox) +4. [Usage](#usage) + * [Hypervisor](#hypervisor) + * [VM](#vm) +5. [Reference](#reference) + * [Classes](#classes) + * [Defined types](#defined-types) + * [Parameters](#parameters) +6. [Other notes](#other-notes) +7. [Limitations](#limitations) +8. [Development](#development) +9. [License](#license) + +## Overview + +The proxmox module provide a simple way to manage Proxmox hypervisor and OpenVZ network's configuration with Puppet. + +## Module Description + +The proxmox module automates installing Proxmox on Debian systems. + +## Setup + +### What Proxmox affects: + +* Package/service/configuration files for Proxmox. +* A new `sources.list` file for Proxmox. +* Proxmox's cluster (master and nodes). +* System repository +* The static table lookup for hostnames `hosts`. +* Users and group permissions for WebGUI. +* WebGUI's service (pveproxy). +* Kernel modules loaded at the boot time. +* OpenVZ's configuration file. +* OpenVZ's service. +* OpenVZ CT network's configuration. + +### Beginning with Proxmox + +To begin using proxmox module with default parameters, declare the hypervisor's class with `include proxmox::hypervisor`. + +## Usage + +### Hypervisor + +``` +include proxmox::hypervisor +``` +**Note**: The module will NOT automatically reboot the system on the PVE Kernel. You will need to reboot it manually and start again the puppet agent. + +#### KVM only + +If you will use only KVM you can have a most recent kernel with: +``` +class { 'proxmox::hypervisor': + kvm_only => true, +} +``` + +#### Disable additionnal modules +Disable all additionnal modules load at the boot time: +``` +class { 'proxmox::hypervisor': + pve_modules_list => [ '' ], +} +``` + +#### Create a cluster full KVM (for Ceph) +``` +node "pve_node" { + # Install an hypervisor full KVM + class { 'proxmox::hypervisor': + pveproxy_allow => '127.0.0.1,192.168.0.0/24', + kvm_only => true, + cluster_master_ip => '192.168.0.201', + cluster_name => 'DeepThought', + } + # Access to PVE Webgui + proxmox::hypervisor::group { 'sysadmin': role => "Administrator", users => [ 'marvin@pam', 'arthur@pam' ] } + + # SSH authorized keys between all nodes without passphrase (the module generate a key if not present) + ssh_authorized_key { 'hyper01': + ensure => present, + key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDQxnLaBlnujnByt3V7YLZv1+PTjREJ3hphZFdCVNs9ebED55/kEAPmtJzcq2OL7qk8PajvhpB7efuZAatKeCdhILpFBKRrCo/q3MsQUSyaHbrGKs8Kkpz0EBHp1Tgpd8i1+kF1EzVPqT/euNcI6cA3fyMrvdgTI25BwFt93A6bBpf4We7A0l0Ba2nCAs5ekWyKKLh54GO7KBHlMmIzboYpxwgnFcbb9UhuyUz2J6PSC0K+P+hdMXY4dFk/lPMEXLgve/TTPYpgDxgxWMUaobCanwBWcXkZ4MdJw2Qs6TQ0v+cOxX3ogr78w69naGB3joJ4ll31WA+Uo0mcZU3ylFj3', + type => 'ssh-rsa', + user => 'root', + options => 'from="192.168.0.201"', + } + ssh_authorized_key { 'hyper02': + ensure => present, + key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQCxJeQ1R1rhPoig4jZLA8/Haru3nhVMgvDgO7nIqpwuPkDrheINVHOAd+DyQF0I2MtAjzg9gKfyix/cJ0cWMbd6/FdSVJ39dGYtNG9/YwTBcQiYwT0xS4NgJHzKrYE9PH2HEmjTmzcDeZ/u+IZjhO3Kyy9yZKcOhwV6fD+mzjQb4S2zsy67R/aoySbZjuoZYHrBrfjc66WbPbLtsFXIXuk46N376Y5sX37Bj17HhDEdP/lc9v939SswW1RZ2t1mVAjsMdsyBULDZk5av6Uj//YT1KuZBmBWkp7nPp1yt2ANPPGAnEW3oYjzXJd56Xtf3d0nbHOdHvMmIiV9fZyRUATd', + type => 'ssh-rsa', + user => 'root', + options => 'from="192.168.0.202"', + } + + # Verify the authenticity of each hosts (/etc/ssh/ssh_host_{rsa,ecdsa}_key.pub) + sshkey { 'hyper01': + ensure => present, + host_aliases => [ 'hyper01.domain.org', '192.168.42.201' ], + key => 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ3TC6B3+eVbohjk662FwM/1YUCjMwMT9lmZcNcfllF9Vm082lMXtKix20elUCK9yJDpPWvzFiqdyhgqPAeCNt4=', + target => '/root/.ssh/known_hosts', + type => 'ecdsa-sha2-nistp256', + } + sshkey { 'hyper02': + ensure => present, + host_aliases => [ 'hyper02.domain.org', '192.168.42.202' ], + key => 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEqUpnig3DIQVZEr3LxJCVEF/fl4n1s8LNuUUaLRueCW2ygzNBOv2m7O42K/Ok7aa4kjGaXbnneYXMw3wBULJ1U=' + target => '/root/.ssh/known_hosts', + type => 'ecdsa-sha2-nistp256', + } + + # If you don't have a DNS service, i recommend to have an entry for each nodes in the hosts file + host { 'hyper01': + name => "hyper01.${::domain}", + ensure => present, + ip => '192.168.42.201', + host_aliases => 'hyper01', + } + host { 'hyper02': + name => "hyper02.${::domain}", + ensure => present, + ip => '192.168.42.202', + host_aliases => 'hyper02', + } +} + +node /hyper0[12]/ inherits "pve_node" { + +} + +``` +Will create a Cluster Proxmox with name "Deepthought", the master will be "hyper01". You also can manage all ssh ressources (and host) manually on each nodes. + +### VM + +Only OpenVZ is supported right now but the vm's class will check-it by it self: +``` +include proxmox::vm +``` + +#### proxmox::vm::openvz + +Automatically call by the `proxmox::vm` class, it will manage network configuration, but only few configurations are possible: +* Only one Virtual Ethernet device (aka veth) and it will work with **DHCP**. +* If a veth is available, it will be the main network's interface (set the default gateway throught eth0). +* If a veth is available, only one Virtual Network device (aka venet) as chance to work (the first one), because all others routes will be flushed. +* If there are only venet: no changes. + +## Reference + +### Classes + +* `proxmox`: Main class, do nothing right now. + +* `proxmox::hypervisor`: Install the Proxmox hypervisor on the system. + +* `proxmox::vm`: Manage virtual machines and containers. + +### Defined types + +* `proxmox::hypervisor::group`: Manage groups for Proxmox WebGUI and set permissions. + +``` +proxmox::hypervisor::group { 'sysadmin': + role => "Administrator", + users => [ 'user1@pam', 'toto@pve' ], +} +``` + +* `proxmox::hypervisor::user`: Manage user for Proxmox WebGUI. + +``` +proxmox::hypervisor::user { 'marvin': + group => 'sysadmin', +} +``` + + Mainly used by the `proxmox::hypervisor::group` defined type to create the group, permissions and also create/add the users to a group. Because to add a user to a group via this defined type, the group should already exist. + +### Parameters + +#### proxmox::hypervisor + +* `ve_pkg_ensure`: What to set the Virtual Environnment package to. Can be 'present', 'absent' or 'version'. Defaults to 'present'. +* `ve_pkg_name`: The list of VirtualEnvironnment packages. Can be an array [ 'proxmox-ve-2.6.32', 'ksm-control-daemon', 'vzprocps', 'open-iscsi', 'bootlogd', 'pve-firmware' ]. +* `kvm_only`: If set to 'true', Puppet will install a newer kernel compatible only with KVM. Accepts 'true' or 'false'. Defaults to 'false'. +* `kernel_kvm_pkg_name`: The list of packages to install the newer kernel. Can be an array [ 'pve-kernel-3.10.0-13-pve', '...' ]. +* `kernel_pkg_name`: The list of packages to install a kernel compatible with both KVM and OpenVZ. Can be an array [ 'pve-kernel-2.6.32-43-pve', '...' ]. +* `rec_pkg_name`: The list of recommended and usefull packages for Proxmox. Can be an array [ 'ntp', 'ssh', 'lvm2', 'bridge-utils' ]. +* `old_pkg_ensure`: What to set useless packages (non recommended, previous kernel, ...). Can be 'present' or 'absent'. Defaults to 'absent'. +* `old_pkg_name`: The list of useless packages. Can be an array [ 'acpid', 'linux-image-amd64', 'linux-base', 'linux-image-3.2.0-4-amd64' ]. +* `pve_enterprise_repo_ensure`: Choose to keep the PVE enterprise repository. Can be 'present' or 'absent'. Defaults to 'absent'. +* `pveproxy_default_path`: Path of the configuration file read by the PveProxy service. Defaults to '/etc/default/pveproxy'. +* `pveproxy_default_content`: Template file use to generate the previous configuration file. Default to 'proxmox/hypervisor/pveproxy_default.erb'. +* `pveproxy_allow`: Can be ip addresses, range or network; separated by a comma (example: '192.168.0.0/24,10.10.0.1-10.10.0.5'). Defaults to '127.0.0.1'. +* `pveproxy_deny`: Unauthorized IP addresses. Can be 'all' or ip addresses, range or network; separated by a comma. Defaults to 'all'. +* `pveproxy_policy`: The policy access. Can be 'allow' or 'deny'. Defaults to 'deny'. +* `pveproxy_service_name`: WebGUI's service name (replace Apache2 since v3.0). Defaults to 'pveproxy'. +* `pveproxy_service_manage`: If set to 'true', Puppet will manage the WebGUI's service. Can be 'true' or 'false'. Defaults to 'true'. +* `pveproxy_service_enabled`: If set to 'true', Puppet will ensure the WebGUI's service is running. Can be 'true' or 'false'. Defaults to 'true'. +* `pve_modules_list`: The list of additionnal modules to load at boot time. +* `pve_modules_file_path`: The configuration file that will contain the modules list. Defaults to '/etc/modules-load.d/proxmox.conf'. +* `pve_modules_file_content`: Template file used to generate the previous configuration file. Defaults to 'proxmox/hypervisor/proxmox_modules.conf.erb'. +* `vz_config_file_path`: Path of the main OpenVZ's configuration file. Defaults to '/etc/vz/vz.conf'. +* `vz_config_file_tpl`: Template file use to generate the OpenVZ's configuration file. Defaults to 'proxmox/hypervisor/vz.conf.erb'. +* `vz_iptables_modules`: If set to 'true', OpenVZ will share a list of iptables modules to the containers. Can be 'true' or 'false'. Defaults to 'true'. +* `vz_service_name`: The OpenVZ's service name. Defaults to 'vz'. +* `vz_service_manage`: If set to 'true', Puppet will manage the OpenVZ's service. Can be 'true' or 'false'. Defaults to 'true'. +* `vz_service_enabled`: If set to 'true', Puppet will ensure the OpenVZ's service is running. Can be 'true' or 'false'. Defaults to 'true'. +* `labs_firewall_rule`: If set to 'true', Puppet will set a iptable rule to allow WebGUI and VNC's port access. Can be 'true' or 'false'. Defaults to 'false'. +* `cluster_master_ip`: The ip address of the "master" node that will create the cluster. Must be an IP address. Defaults to 'undef'. +* `cluster_name`: The cluster's name. Defaults to 'undef'. + +#### proxmox::vm +* `vm_interfaces_path`: The main network configuration's file. Defaults to '/etc/network/interfaces'. +* `vm_interfaces_content`: Template file used to generate the previous configuration file. Defaults to 'proxmox/vm/openvz_interfaces.erb'. +* `vm_interfaces_tail_path`: A second network configuration file that will be concatenated in the main. Defaults to '/etc/network/interfaces.tail'. +* `vm_interfaces_tail_content`: Template file used to generate the previous configuration file. Defaults to 'proxmox/vm/openzv_interfaces.tail.erb'. +* `network_service_name`: Network's service name. Defaults to 'networking'. +* `network_service_manage`: If set to 'true', Puppet will manage the network's service. Can be 'true' or 'false'. Defaults to 'true'. +* `network_service_enabled`: If set to 'true', Puppet will ensure the network's service is running. Can be 'true' or 'false'. Defaults to 'true'. + +Other notes +----------- +By default `proxmox::hypervisor` comes with several modules kernel load at boot time. Mainly iptables's modules to allow it in the OpenVZ CT. + +The default modules list: +* `iptable_filter` +* `iptable_mangle` +* `iptable_nat` +* `ipt_length` (=xt_length) +* `ipt_limit` (=xt_limit) +* `ipt_LOG` +* `ipt_MASQUERADE` +* `ipt_multiport` (=xt_multiport) +* `ipt_owner` (=xt_owner) +* `ipt_recent` (=xt_recent) +* `ipt_REDIRECT` +* `ipt_REJECT` +* `ipt_state` (=xt_state) +* `ipt_TCPMSS` (=xt_TCPMSS) +* `ipt_tcpmss` (=xt_tcpmss) +* `ipt_TOS` +* `ipt_tos` +* `ip_conntrack` (=nf_conntrack) +* `ip_nat_ftp` (=nf_nat_ftp) +* `xt_iprange` +* `xt_comment` +* `ip6table_filter` +* `ip6table_mangle` +* `ip6t_REJECT' ` + +See [hypervisor usage](#hypervisor) if you want to disable it or [parameters](#parameters) if you want to edit this list. + +Limitations +----------- + +This module will only work on Debian 7.x versions. + +Development +----------- + +Free to send contributions, fork it, ... + +License +------- + +WTFPL (http://wtfpl.org/) + diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..d1e11f7 --- /dev/null +++ b/Rakefile @@ -0,0 +1,18 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Validate manifests, templates, and ruby files" +task :validate do + Dir['manifests/**/*.pp'].each do |manifest| + sh "puppet parser validate --noop #{manifest}" + end + Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| + sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ + end + Dir['templates/**/*.erb'].each do |template| + sh "erb -P -x -T '-' #{template} | ruby -c" + end +end diff --git a/lib/facter/is_proxmox.rb b/lib/facter/is_proxmox.rb new file mode 100644 index 0000000..53ee880 --- /dev/null +++ b/lib/facter/is_proxmox.rb @@ -0,0 +1,7 @@ +#is_proxmox.rb + +Facter.add("is_proxmox") do + setcode do + FileTest.exists?("/etc/pve/") + end +end diff --git a/lib/facter/is_pve_kernel.rb b/lib/facter/is_pve_kernel.rb new file mode 100644 index 0000000..5e99d9e --- /dev/null +++ b/lib/facter/is_pve_kernel.rb @@ -0,0 +1,19 @@ +# Fact: is_pve_kernel +# +# Purpose: Returns true if the system runs a PVE kernel. +# +# +require 'facter' + +Facter.add(:is_pve_kernel) do + setcode do + + pve = if Facter.value(:kernelrelease) =~ /^*pve/ + 'true' + else + 'false' + end + + end + +end diff --git a/lib/facter/vznetmask.rb b/lib/facter/vznetmask.rb new file mode 100644 index 0000000..cdc6bfb --- /dev/null +++ b/lib/facter/vznetmask.rb @@ -0,0 +1,29 @@ +# Fact: vznetmask +# +# Purpose: +# Get netmasks for Virtual Network aka venet in OpenVZ CT, for available +# network networks +# +# Resolution: +# Uses `facter/util/ip` to enumerate interfaces and return their information. +# +require 'facter/util/ip' +require 'ipaddr' + +Facter::Util::IP.get_interfaces.each do |interface| + Facter.add("vznetmask_" + Facter::Util::IP.alphafy(interface)) do + setcode do + if interface =~ /^venet*/ + + netmask = Facter::Util::IP.get_interface_value(interface, "netmask") + if netmask == "255.255.255.255" + # It's not possible to modify the netmask from WebGUI, so it's mainly set to /32 + # http://openvz.org/Venet#Adding_IP_address_to_a_container + netmask = "255.255.255.0" + end + + end + netmask + end + end +end diff --git a/lib/facter/vznetwork.rb b/lib/facter/vznetwork.rb new file mode 100644 index 0000000..6e7cde1 --- /dev/null +++ b/lib/facter/vznetwork.rb @@ -0,0 +1,35 @@ +# Fact: vznetwork +# +# Purpose: +# Get networks for Virtual Network aka venet in OpenVZ CT, for available +# network networks +# +# Resolution: +# Uses `facter/util/ip` to enumerate interfaces and return their information. +# +require 'facter/util/ip' +require 'ipaddr' + +Facter::Util::IP.get_interfaces.each do |interface| + Facter.add("vznetwork_" + Facter::Util::IP.alphafy(interface)) do + setcode do + if interface =~ /^venet*/ + + ipaddress = Facter::Util::IP.get_interface_value(interface, "ipaddress") + netmask = Facter::Util::IP.get_interface_value(interface, "netmask") + if netmask == "255.255.255.255" + # It's not possible to modify the netmask from WebGUI, so it's mainly set to /32 + # http://openvz.org/Venet#Adding_IP_address_to_a_container + netmask = "255.255.255.0" + end + + if ipaddress && netmask + ip = IPAddr.new(ipaddress, Socket::AF_INET) + subnet = IPAddr.new(netmask, Socket::AF_INET) + ip.mask(subnet.to_s).to_s + end + + end + end + end +end diff --git a/manifests/hypervisor.pp b/manifests/hypervisor.pp new file mode 100644 index 0000000..7580b51 --- /dev/null +++ b/manifests/hypervisor.pp @@ -0,0 +1,82 @@ +# == Class: proxmox::hypervisor +# +# Manage the Proxmox hypervisor. +# +# === Parameters +# +# Document parameters here. +# +# [*sample_parameter*] +# Explanation of what this parameter affects and what it defaults to. +# e.g. "Specify one or more upstream ntp servers as an array." +# +# === Variables +# +# Here you should define a list of variables that this module would require. +# +# [*sample_variable*] +# Explanation of how this variable affects the funtion of this class and if it +# has a default. e.g. "The parameter enc_ntp_servers must be set by the +# External Node Classifier as a comma separated list of hostnames." (Note, +# global variables should not be used in preference to class parameters as of +# Puppet 2.6.) +# +# === Examples +# +# class { '::proxmox::hypervisor': +# kvm_only => true, +# } +# +# === Authors +# +# Gardouille +# +# === Copyright +# +# WTFPL +# +class proxmox::hypervisor ( + $ve_pkg_ensure = $proxmox::params::ve_pkg_ensure, + $ve_pkg_name = $proxmox::params::ve_pkg_name, + $kvm_only = $proxmox::params::kvm_only, + $kernel_kvm_pkg_name = $proxmox::params::kernel_kvm_pkg_name, + $kernel_pkg_name = $proxmox::params::kernel_pkg_name, + $rec_pkg_name = $proxmox::params::rec_pkg_name, + $old_pkg_ensure = $proxmox::params::old_pkg_ensure, + $old_pkg_name = $proxmox::params::old_pkg_name, + $pve_enterprise_repo_ensure = $proxmox::params::pve_enterprise_repo_ensure, + $pveproxy_default_path = $proxmox::params::pveproxy_default_path, + $pveproxy_default_content = $proxmox::params::pveproxy_default_content, + $pveproxy_allow = $proxmox::params::pveproxy_allow, + $pveproxy_deny = $proxmox::params::pveproxy_deny, + $pveproxy_policy = $proxmox::params::pveproxy_policy, + $pveproxy_service_name = $proxmox::params::pveproxy_service_name, + $pveproxy_service_manage = $proxmox::params::pveproxy_service_manage, + $pveproxy_service_enabled = $proxmox::params::pveproxy_service_enabled, + $pve_modules_list = $proxmox::params::pve_modules_list, + $pve_modules_file_path = $proxmox::params::pve_modules_file_path, + $pve_modules_file_content = $proxmox::params::pve_modules_file_content, + $vz_config_file_path = $proxmox::params::vz_config_file_path, + $vz_config_file_tpl = $proxmox::params::vz_config_file_tpl, + $vz_iptables_modules = $proxmox::params::vz_iptables_modules, + $vz_service_name = $proxmox::params::vz_service_name, + $vz_service_manage = $proxmox::params::vz_service_manage, + $vz_service_enabled = $proxmox::params::vz_service_enabled, + $labs_firewall_rule = $proxmox::params::labs_firewall_rule, + $cluster_master_ip = undef, + $cluster_name = undef, +) inherits proxmox::params { + + include '::proxmox::hypervisor::preconfig' + include '::proxmox::hypervisor::install' + include '::proxmox::hypervisor::config' + include '::proxmox::hypervisor::service' + include '::proxmox::hypervisor::cluster' + + Class['proxmox::hypervisor::preconfig'] -> + Class['proxmox::hypervisor::install'] -> + Class['proxmox::hypervisor::config'] -> + Class['proxmox::hypervisor::service'] -> + Class['proxmox::hypervisor::cluster'] + +} # Public class: proxmox::hypervisor diff --git a/manifests/hypervisor/cluster.pp b/manifests/hypervisor/cluster.pp new file mode 100644 index 0000000..61f27a4 --- /dev/null +++ b/manifests/hypervisor/cluster.pp @@ -0,0 +1,52 @@ +# == Class: proxmox::hypervisor::cluster +# +# Manage the Proxmox cluster. +# +class proxmox::hypervisor::cluster +{ + + File { + owner => root, + group => root, + mode => 644, + } + + Exec { + path => [ '/bin', '/sbin', '/usr/bin', '/usr/sbin' ], + logoutput => 'on_failure', + } + + ## Quoted boolean value because can't return "true" boolean with personal fact + if $::is_proxmox == 'true' and $proxmox::hypervisor::cluster_master_ip != undef and $proxmox::hypervisor::cluster_name != undef { + # Ensure the root user got an ssh-key + exec { 'create ssh-key for root': + command => 'ssh-keygen -t rsa -f /root/.ssh/id_rsa -b 2048 -N "" -q', + creates => '/root/.ssh/id_rsa.pub', + } + + # Test if this node should be the master or a node + ## has_interface_with needs double quoted string for the argument ! + if has_interface_with('ipaddress', "${proxmox::hypervisor::cluster_master_ip}") { + + # Create the cluster on this node + exec { "Create ${proxmox::hypervisor::cluster_name} cluster on ${proxmox::hypervisor::cluster_master_ip}": + command => "pvecm create ${proxmox::hypervisor::cluster_name}", + onlyif => 'uname -r | grep -- "-pve"', + creates => '/etc/pve/cluster.conf', + } + } + else { + + # Connect this node to the cluster + exec { "Connect to ${proxmox::hypervisor::cluster_name} cluster": + command => "pvecm add ${proxmox::hypervisor::cluster_master_ip}", + onlyif => 'uname -r | grep -- "-pve"', + creates => '/etc/pve/cluster.conf', + } + } + } + + + #notify { "Master IP: ${proxmox::hypervisor::cluster_master_ip} and Cluster name: ${proxmox::hypervisor::cluster_name}": } + +} # Private class: proxmox::hypervisor::cluster diff --git a/manifests/hypervisor/config.pp b/manifests/hypervisor/config.pp new file mode 100644 index 0000000..6046ace --- /dev/null +++ b/manifests/hypervisor/config.pp @@ -0,0 +1,56 @@ +# == Class: proxmox::hypervisor::config +# +# Some tiny configurations for Proxmox +# +class proxmox::hypervisor::config { + + File { + owner => root, + group => root, + mode => 644, + } + + Exec { + path => [ '/bin', '/sbin', '/usr/bin', '/usr/sbin' ], + logoutput => 'on_failure', + } + + + ## Quoted boolean value because can't return "true" boolean with personal fact + if $::is_proxmox == 'true' { + + # Pveproxy access control list + file { $proxmox::hypervisor::pveproxy_default_path: + ensure => present, + content => template($proxmox::hypervisor::pveproxy_default_content), + notify => Service[$proxmox::hypervisor::pveproxy_service_name], + } + -> + + # Remove the Subscription message + exec { 'remove_subscription_message': + command => 'rm -f /usr/share/pve-manager/ext4/pvemanagerlib.js.bak; sed -i".bak" -r -e "s/if \(data.status !== \'Active\'\) \{/if (false) {/" /usr/share/pve-manager/ext4/pvemanagerlib.js', + onlyif => 'grep "if (data.status !== \'Active\') {" /usr/share/pve-manager/ext4/pvemanagerlib.js', + } + + ## OpenVZ configuration + file { $proxmox::hypervisor::vz_config_file_path: + ensure => present, + content => template($proxmox::hypervisor::vz_config_file_tpl), + notify => Service[$proxmox::hypervisor::vz_service_name], + } + + } + + if $proxmox::hypervisor::labs_firewall_rule == true { + + firewall { '100 accept proxmox': + proto => 'tcp', + action => 'accept', + port => ['8006', '5900'] + } + + } + + +} # Private class: proxmox::hypervisor::config diff --git a/manifests/hypervisor/group.pp b/manifests/hypervisor/group.pp new file mode 100644 index 0000000..ec76946 --- /dev/null +++ b/manifests/hypervisor/group.pp @@ -0,0 +1,74 @@ +# == Define: proxmox::hypervisor::group +# +# Manage groups and permissions to access the PVE ressources +# +# === Parameters +# +# [*group*] +# _default_: +$title+, the title/name of the ressource +# +# Is the group's name. +# +# [*role*] +# _default_: +undef+ +# +# [*acl_path*] +# _default_: +/+ +# +# The objects in Proxmox form a tree, virtual machines (/vms/$vmid), storage +# (/storage/$storageid) or ressource (/pool/$poolname). The role for this +# group will be applied on this path. +# +# [*permission_file*] +# _default_: +/etc/pve/user.cfg+ +# +# The file where group's informations are stored. +# +# [*users*] +# _default_: +undef+ +# +# The user list members of this group. A user will be created if not exist. +# +define proxmox::hypervisor::group ( $group = $title, $acl_path = '/', $permission_file = '/etc/pve/user.cfg', $users = '', $role ) { + + File { + owner => root, + group => www-data, + mode => 0640, + } + + Exec { + path => ['/bin','/sbin','/usr/bin','/usr/sbin'], + logoutput => 'on_failure', + } + + # Manage group only if Proxmox is available + if $::is_proxmox == 'true' { + + # Create the group in Proxmox + exec { "create_${group}_group": + command => "pveum groupadd ${group}", + unless => "grep '^group:${group}' ${permission_file}", + } + -> + # Define the permission + exec { "add_${group}_permission": + command => "pveum aclmod ${acl_path} -group ${group} -role ${role}", + unless => "grep '@${group}' ${permission_file}", + } + -> + # Create user(s) and add it to this group + proxmox::hypervisor::user { $users: + group => $group, + } + + # The permissions file + if ! defined(File[$permission_file]) { + file { $permission_file: + ensure => present, + } + } + + } + +} # Public ressource: proxmox::hypervisor::group diff --git a/manifests/hypervisor/install.pp b/manifests/hypervisor/install.pp new file mode 100644 index 0000000..89e2bbe --- /dev/null +++ b/manifests/hypervisor/install.pp @@ -0,0 +1,78 @@ +# == Class: proxmox::hypervisor::install +# +# Install Proxmox and inform the user he needs to reboot the system on the PVE kernel +# +class proxmox::hypervisor::install { + + Exec { + path => [ '/bin', '/sbin', '/usr/bin', '/usr/sbin' ], + logoutput => 'on_failure', + } + + # If the system already run a PVE kernel + ## Quoted boolean value because can't return "true" boolean with personal fact + if $::is_pve_kernel == 'true' { + + # Installation of Virtual Environnment + package { $proxmox::hypervisor::ve_pkg_name: + ensure => $proxmox::hypervisor::ve_pkg_ensure, + } -> + + # Remove useless packages (such as the standard kernel, acpid, ...) + package { $proxmox::hypervisor::old_pkg_name: + ensure => $proxmox::hypervisor::old_pkg_ensure, + notify => Exec['update_grub'], + } + + # Ensure that some recommended packages are present on the system + ensure_packages( $proxmox::hypervisor::rec_pkg_name ) + + } + else { # If the system run on a standard Debian Kernel + + # To avoid unwanted reboot (kernel update for example), the PVE kernel is + # installed only if the system run on a standard Debian. + # You will need to update your PVE kernel manually. + + # Installation of the PVE Kernel + if $proxmox::hypervisor::kvm_only == true { + notify { 'Please REBOOT': + message => "Need to REBOOT the system on the new PVE kernel (${proxmox::hypervisor::kernel_kvm_pkg_name}) ...", + loglevel => warning, + } + -> + package { $proxmox::hypervisor::kernel_kvm_pkg_name: + ensure => $proxmox::hypervisor::ve_pkg_ensure, + notify => Exec['update_grub'], + } + } + else { + notify { 'Please REBOOT': + message => "Need to REBOOT the system on the new PVE kernel (${proxmox::hypervisor::kernel_pkg_name}) ...", + loglevel => warning, + } + -> + package { $proxmox::hypervisor::kernel_pkg_name: + ensure => $proxmox::hypervisor::ve_pkg_ensure, + notify => Exec['update_grub','grub_reboot'], + } + # The kernel that allow KVM + OpenVZ is older than the standard Debian's + # kernel, so grub reboot must be used + } + + } + + # Ensure the grub is update + exec { 'update_grub': + command => 'update-grub', + refreshonly => true, + } + + # Choose a different line in the grub + exec { 'grub_reboot': + command => 'grub-reboot 2', + refreshonly => true, + } + + +} # Private class: proxmox::hypervisor::install diff --git a/manifests/hypervisor/preconfig.pp b/manifests/hypervisor/preconfig.pp new file mode 100644 index 0000000..9b582c5 --- /dev/null +++ b/manifests/hypervisor/preconfig.pp @@ -0,0 +1,75 @@ +# == Class: proxmox::hypervisor::preconfig +# +# Before installing Proxmox some modifications have to be applied on the system +# +class proxmox::hypervisor::preconfig { + + File { + owner => root, + group => root, + mode => 644, + } + + # Hostname should be resolvable via /etc/hosts + #/files/etc/hosts/2 + #/files/etc/hosts/2/ipaddr = '214.938.839.123' + #/files/etc/hosts/2/canonical = 'hypervisor.domain.tld' + #/files/etc/hosts/2/alias[1] = 'hypervisor' + #/files/etc/hosts/1/ipaddr = '127.0.0.1' + #/files/etc/hosts/1/canonical = 'localhost' + augeas { $::fqdn: + context => '/files/etc/hosts', + changes => [ + #"ins ipaddr ${::ipaddress}", + "set 02/ipaddr ${::ipaddress}", + "set *[ipaddr = '${::ipaddress}']/canonical ${::fqdn}", + "set *[ipaddr = '${::ipaddress}']/alias[1] ${::hostname}", + "set *[ipaddr = '127.0.0.1']/canonical localhost", + "rm *[ipaddr = '127.0.1.1']", + ], + onlyif => "match *[ipaddr = '${::ipaddress}'] size == 0", + } + -> + # Remove Enterprise repository (need a subscription) + file { '/etc/apt/sources.list.d/pve-enterprise.list': + ensure => $proxmox::hypervisor::pve_enterprise_repo_ensure, + notify => Exec[apt_update], + } + -> + # Add the standard repository (~community) + apt::source {'proxmox': + ensure => present, + location => 'http://download.proxmox.com/debian', + release => $::lsbdistcodename, + repos => 'pve-no-subscription', + include_src => false, + key => '9887F95A', + key_server => 'keyserver.ubuntu.com', + } + + # Set the grub default to saved to be able to use grub-set-default during + # the installation + if ! defined(Augeas['grub_default']) { + augeas { 'grub_default': + context => '/files/etc/default/grub', + changes => [ + 'set GRUB_DEFAULT saved', + ], + } + } + + if ! defined(File['/etc/modules-load.d']) { + file { '/etc/modules-load.d': + ensure => directory, + } + } + + $values = [ 'v1', 'v2' ] + + file { $proxmox::hypervisor::pve_modules_file_path: + ensure => present, + content => template($proxmox::hypervisor::pve_modules_file_content), + require => File['/etc/modules-load.d'], + } + +} # Private class: proxmox::hypervisor::preconfig diff --git a/manifests/hypervisor/service.pp b/manifests/hypervisor/service.pp new file mode 100644 index 0000000..9d14980 --- /dev/null +++ b/manifests/hypervisor/service.pp @@ -0,0 +1,45 @@ +# == Class: proxmox::hypervisor::service +# +# Manage Proxmox services +# +class proxmox::hypervisor::service { + + + if $proxmox::hypervisor::pveproxy_service_enabled == true { + $pveproxy_service_ensure = 'running' + } else { + $pveproxy_service_ensure = 'stopped' + } + + if $proxmox::hypervisor::vz_service_enabled == true { + $vz_service_ensure = 'running' + } else { + $vz_service_ensure = 'stopped' + } + + + if $::is_proxmox == 'true' { + + if $proxmox::hypervisor::pveproxy_service_manage == true { + service { $proxmox::hypervisor::pveproxy_service_name: + ensure => $pveproxy_service_ensure, + enable => $proxmox::hypervisor::pveproxy_service_enabled, + hasstatus => false, + hasrestart => true, + } + } + + if $proxmox::hypervisor::vz_service_manage == true { + service { $proxmox::hypervisor::vz_service_name: + ensure => $vz_service_ensure, + enable => $proxmox::hypervisor::pveproxy_service_enabled, + hasstatus => true, + hasrestart => true, + } + } + + } + + + +} # Private class: proxmox::hypervisor::service diff --git a/manifests/hypervisor/user.pp b/manifests/hypervisor/user.pp new file mode 100644 index 0000000..e4529aa --- /dev/null +++ b/manifests/hypervisor/user.pp @@ -0,0 +1,59 @@ +# == Define: proxmox::hypervisor::user +# +# Manage users allowed to WebGUI +# +# === Parameters +# +# [*user*] +# _default_: +$title+, the title/name of the ressource +# +# Is the username. +# +# [*group*] +# _default_: +undef+ +# +# The group list for the user. +# +# [*permission_file*] +# _default_: +/etc/pve/user.cfg+ +# +# The file where group's informations are stored. +# +define proxmox::hypervisor::user ( $user = $title, $group = '', $permission_file = '/etc/pve/user.cfg' ) { + + Exec { + path => ['/bin','/sbin','/usr/bin','/usr/sbin'], + logoutput => 'on_failure', + } + + # Manage user only if Proxmox is available + if $::is_proxmox == 'true' { + + ## Work with an if/else test because the user must be create before adding + # it to a group ... + + # If a group was set + if empty($group) == false { + # Create the user in Proxmox + exec { "add_${user}_user": + command => "pveum useradd ${user}", + unless => "grep '^user:${user}' ${permission_file}", + } + -> + # Then add this user to a group + exec { "add_${user}_to_${group}": + command => "pveum usermod ${user} -group ${group}", + # The grep command should return 2 lines (minium) that match the pattern + unless => "test `grep '${user}' -c ${permission_file}` -ge 2", + } + } + else { + # Create the user in Proxmox + exec { "add_${user}_user": + command => "pveum useradd ${user}", + unless => "grep '^user:${user}' ${permission_file}", + } + } + } + +} # Public ressource: proxmox::hypervisor::user diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 0000000..930acd5 --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,23 @@ +# == Class: proxmox +# +# This class do nothing right now. +# Please use proxmox::hypervisor to manage proxmox. +# +# === Examples +# +# class { 'proxmox': +# } +# +# === Authors +# +# Gardouille +# +# === Copyright +# +# WTFPL +# +class proxmox { + + + +} # Public class: proxmox diff --git a/manifests/params.pp b/manifests/params.pp new file mode 100644 index 0000000..835ceee --- /dev/null +++ b/manifests/params.pp @@ -0,0 +1,73 @@ +# == Class: proxmox::params +# +class proxmox::params { + case $::osfamily { + 'Debian': { + if $::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '7.0') >= 0 { + # Virtual Environment packages + $ve_pkg_ensure = 'present' + $ve_pkg_name = [ 'proxmox-ve-2.6.32', 'ksm-control-daemon', 'vzprocps', 'open-iscsi', 'bootlogd', 'pve-firmware' ] + + # PVE Kernel + $kvm_only = false + $kernel_kvm_pkg_name = [ 'pve-kernel-3.10.0-13-pve' ] + $kernel_pkg_name = [ 'pve-kernel-2.6.32-43' ] + + # Recommended packages + $rec_pkg_name = [ 'ntp', 'ssh', 'lvm2', 'bridge-utils' ] + + # Old useless packages + $old_pkg_ensure = 'absent' + $old_pkg_name = [ 'acpid', 'linux-image-amd64', 'linux-base', 'linux-image-3.2.0-4-amd64' ] + + # Manage PVE Enterprise repository (need a subscription) + $pve_enterprise_repo_ensure = 'absent' + + # Pveproxy access restriction + $pveproxy_default_path = '/etc/default/pveproxy' + $pveproxy_default_content = 'proxmox/hypervisor/pveproxy_default.erb' + $pveproxy_allow = '127.0.0.1' + $pveproxy_deny = 'all' + $pveproxy_policy = 'allow' + $pveproxy_service_name = 'pveproxy' + $pveproxy_service_manage = true + $pveproxy_service_enabled = true + + # Manage additionnals modules + $pve_modules_list = [ 'iptable_filter', 'iptable_mangle', 'iptable_nat', 'ipt_length', 'ipt_limit', 'ipt_LOG', 'ipt_MASQUERADE', 'ipt_multiport', 'ipt_owner', 'ipt_recent', 'ipt_REDIRECT', 'ipt_REJECT', 'ipt_state', 'ipt_TCPMSS', 'ipt_tcpmss', 'ipt_TOS', 'ipt_tos', 'ip_conntrack', 'ip_nat_ftp', 'xt_iprange', 'xt_comment', 'ip6table_filter', 'ip6table_mangle', 'ip6t_REJECT' ] + $pve_modules_file_path = '/etc/modules-load.d/proxmox.conf' + $pve_modules_file_content = 'proxmox/hypervisor/proxmox_modules.conf.erb' + + # OpenVZ configuration + $vz_config_file_path = '/etc/vz/vz.conf' + $vz_config_file_tpl = 'proxmox/hypervisor/vz.conf.erb' + $vz_iptables_modules = true + $vz_service_name = 'vz' + $vz_service_manage = true + $vz_service_enabled = true + + # Firewall + $labs_firewall_rule = false + + } + + ## VM - OpenVZ + # Network + $vm_interfaces_path = '/etc/network/interfaces' + $vm_interfaces_content = 'proxmox/vm/openzv_interfaces.erb' + $vm_interfaces_tail_path = '/etc/network/interfaces.tail' + $vm_interfaces_tail_content = 'proxmox/vm/openzv_interfaces.tail.erb' + $network_service_name = 'networking' + $network_service_manage = true + $network_service_enabled = true + + } + default: { + fail("Proxmox Virtual Environment only works with Debian system; And the OpenVZ configuration has been tested only with Debian family; So osfamily (${::osfamily}) or lsbdistid (${::lsbdistid}) is unsupported") + + } + + } + + +} # Private class: proxmox::params diff --git a/manifests/vm.pp b/manifests/vm.pp new file mode 100644 index 0000000..068b905 --- /dev/null +++ b/manifests/vm.pp @@ -0,0 +1,46 @@ +# == Class: proxmox::vm +# +# Manage Virtual Machines/VM (only OpenVZ right now) +# +# === Parameters +# +# +# +# === Variables +# +# +# === Examples +# +# include proxmox::vm +# +# === Authors +# +# Gardouille +# +# Copyright +# +# WTFPL +# +class proxmox::vm ( + $vm_interfaces_path = $proxmox::params::vm_interfaces_path, + $vm_interfaces_content = $proxmox::params::vm_interfaces_content, + $vm_interfaces_tail_path = $proxmox::params::vm_interfaces_tail_path, + $vm_interfaces_tail_content = $proxmox::params::vm_interfaces_tail_content, + $network_service_name = $proxmox::params::network_service_name, + $network_service_manage = $proxmox::params::network_service_manage, + $network_service_enabled = $proxmox::params::network_service_enabled, +) inherits proxmox::params { + + case $::virtual { + 'openvz': { + include proxmox::vm::openvz + } + 'kvm': { + } + default: { + fail(" => ${::virtual} <= virtual machines type is not yet supported.") + } + + } + +} # Public class: proxmox::vm diff --git a/manifests/vm/openvz.pp b/manifests/vm/openvz.pp new file mode 100644 index 0000000..f5cd154 --- /dev/null +++ b/manifests/vm/openvz.pp @@ -0,0 +1,41 @@ +# == Class: proxmox::vm::openvz +# +# Manage OpenVZ virtual machines (CT aka Containers) +# +class proxmox::vm::openvz { + + File { + owner => root, + group => root, + mode => 0644, + } + + # Test if a virtual interface is available + ## has_interface_with needs double quoted string for the argument ! + if has_interface_with("eth0") { + + ## has_interface_with needs double quoted string for the argument ! + if has_interface_with("venet0_0") { # Virtual network available too? + + # Need to configure eth0 in an interfaces.tail file because + # the main interfaces file is auto-generated by PVE (for venet config) + file { $proxmox::vm::vm_interfaces_tail_path: + ensure => present, + content => template($proxmox::vm::vm_interfaces_tail_content), + } + + } + else { # Only virtual interface is available + + # If eth0 is the only interface, push it's configuration in the standard interfaces file + file { $proxmox::vm::vm_interfaces_path: + ensure => present, + content => template($proxmox::vm::vm_interfaces_content), + } + + } # fi + } # fi; don't need any additionnal network configuration + + + +} # Private class: proxmox::vm::openvz diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..6c6d78a --- /dev/null +++ b/metadata.json @@ -0,0 +1,20 @@ +{ + "name": "gardouille-proxmox", + "version": "0.2.3", + "author": "Gardouille", + "summary": "Manage Proxmox hypervisor and KVM virtual machines or OpenVZ containers.", + "license": "WTFPL", + "source": "https://git.101010.fr/puppet/proxmox", + "project_page": "https://git.101010.fr/puppet/proxmox", + "issues_url": "https://git.101010.fr/puppet/proxmox/issues", + "description": "Proxmox module", + "operatingsystem_support": [ + { + "operatingsystem":"Debian" + } + ], + "dependencies": [ + {"name":"puppetlabs/stdlib","version_requirement":"4.x"}, + {"name":"puppetlabs/apt","version_requirement":">=1.1.0 <2.0.0"} + ] +} diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb new file mode 100644 index 0000000..a0a2221 --- /dev/null +++ b/spec/classes/init_spec.rb @@ -0,0 +1,7 @@ +require 'spec_helper' +describe 'proxmox' do + + context 'with defaults for all parameters' do + it { should contain_class('proxmox') } + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..2c6f566 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/templates/hypervisor/proxmox_modules.conf.erb b/templates/hypervisor/proxmox_modules.conf.erb new file mode 100644 index 0000000..206de38 --- /dev/null +++ b/templates/hypervisor/proxmox_modules.conf.erb @@ -0,0 +1,7 @@ +#file generated by puppet +#Don't edit, please see https://forge.puppetlabs.com/gardouille/proxmox + +## Load additonnal modules for Proxmox +<% @pve_modules_list.each do |val| -%> +<%= val %> +<% end -%> diff --git a/templates/hypervisor/pveproxy_default.erb b/templates/hypervisor/pveproxy_default.erb new file mode 100644 index 0000000..b1c7fcd --- /dev/null +++ b/templates/hypervisor/pveproxy_default.erb @@ -0,0 +1,8 @@ +#file generated by puppet +#Don't edit, please see https://forge.puppetlabs.com/gardouille/proxmox + +# Access control list (Apache2 like) +ALLOW_FROM="<%= scope.lookupvar('proxmox::hypervisor::pveproxy_allow') %>" +DENY_FROM="<%= scope.lookupvar('proxmox::hypervisor::pveproxy_deny') %>" +POLICY="<%= scope.lookupvar('proxmox::hypervisor::pveproxy_policy') %>" + diff --git a/templates/hypervisor/vz.conf.erb b/templates/hypervisor/vz.conf.erb new file mode 100644 index 0000000..52a9588 --- /dev/null +++ b/templates/hypervisor/vz.conf.erb @@ -0,0 +1,56 @@ +## Global parameters +VIRTUOZZO=yes +LOCKDIR=/var/lib/vz/lock +DUMPDIR=/var/lib/vz/dump +VE0CPUUNITS=1000 + +## Logging parameters +LOGGING=yes +LOGFILE=/var/log/vzctl.log +LOG_LEVEL=0 +VERBOSE=0 + +## Disk quota parameters +DISK_QUOTA=yes +VZFASTBOOT=no + +# Disable module loading. If set, vz initscript does not load any modules. +#MODULES_DISABLED=yes + +# The name of the device whose IP address will be used as source IP for CT. +# By default automatically assigned. +#VE_ROUTE_SRC_DEV="eth0" + +# Controls which interfaces to send ARP requests and modify ARP tables on. +NEIGHBOUR_DEVS=detect + +## Fail if there is another machine in the network with the same IP +ERROR_ON_ARPFAIL="no" + +## Template parameters +TEMPLATE=/var/lib/vz/template + +## Defaults for containers +VE_ROOT=/var/lib/vz/root/$VEID +VE_PRIVATE=/var/lib/vz/private/$VEID + +## Filesystem layout for new CTs: either simfs (default) or ploop +#VE_LAYOUT=ploop + +## Load vzwdog module +VZWDOG="no" + +## IPv4 iptables kernel modules to be enabled in CTs by default +<% if scope.lookupvar('proxmox::hypervisor::vz_iptables_modules') == true -%> +IPTABLES="ipt_REJECT ipt_recent ipt_owner ipt_REDIRECT ipt_tos ipt_TOS ipt_LOG ip_conntrack ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ipt_state iptable_nat ip_nat_ftp" +<% else -%> +IPTABLES="" +<% end -%> +## IPv4 iptables kernel modules to be loaded by init.d/vz script +IPTABLES_MODULES="$IPTABLES" + +## Enable IPv6 +IPV6="yes" + +## IPv6 ip6tables kernel modules +IP6TABLES="ip6_tables ip6table_filter ip6table_mangle ip6t_REJECT" diff --git a/templates/vm/openzv_interfaces.erb b/templates/vm/openzv_interfaces.erb new file mode 100644 index 0000000..a953e51 --- /dev/null +++ b/templates/vm/openzv_interfaces.erb @@ -0,0 +1,12 @@ +# file generated by puppet +# Don't edit, please see https://forge.puppetlabs.com/gardouille/proxmox + +# Auto generated lo interface +auto lo +iface lo inet loopback + +# The main network interface +auto eth0 +iface eth0 inet dhcp + + diff --git a/templates/vm/openzv_interfaces.tail.erb b/templates/vm/openzv_interfaces.tail.erb new file mode 100644 index 0000000..9e8335e --- /dev/null +++ b/templates/vm/openzv_interfaces.tail.erb @@ -0,0 +1,15 @@ +# file generated by puppet +# Don't edit, please see https://forge.puppetlabs.com/gardouille/proxmox + +# The main network interface +auto eth0 +iface eth0 inet dhcp + # Need to delete routes creates for venet interfaces + up ip route flush table main + # Add the default gateway throught eth0 + # <%= scope.lookupvar('::ipaddress_eth0') %> + up ip route add default dev eth0 + up ip route add <%= scope.lookupvar('::network_eth0') %>/<%= scope.lookupvar('::netmask_eth0') %> dev eth0 protocol kernel src <%= scope.lookupvar('::ipaddress_eth0') %> + up ip route add <%= scope.lookupvar('::vznetwork_venet0_0') %>/<%= scope.lookupvar('::vznetmask_venet0_0') %> dev venet0 + down ip route del default dev eth0 + down ip route del <%= scope.lookupvar('::vznetwork_venet0_0') %>/<%= scope.lookupvar('::vznetmask_venet0_0') %> dev venet0 diff --git a/tests/add_user.pp b/tests/add_user.pp new file mode 100644 index 0000000..adaa4b9 --- /dev/null +++ b/tests/add_user.pp @@ -0,0 +1 @@ +proxmox::hypervisor::user { 'zaphod@pam': group => 'sysadmin', } diff --git a/tests/group_management.pp b/tests/group_management.pp new file mode 100644 index 0000000..74a7977 --- /dev/null +++ b/tests/group_management.pp @@ -0,0 +1,8 @@ +proxmox::hypervisor::group { 'sysadmin': + role => 'Administrator', + users => [ 'user1@pam', 'toto@pve' ], +} +proxmox::hypervisor::group { 'audit': + role => 'PVEAuditor', + users => [ 'user2@pam' ], +} diff --git a/tests/hypervisor.pp b/tests/hypervisor.pp new file mode 100644 index 0000000..dca5dbf --- /dev/null +++ b/tests/hypervisor.pp @@ -0,0 +1 @@ +include proxmox::hypervisor diff --git a/tests/hypervisor_kvm_only.pp b/tests/hypervisor_kvm_only.pp new file mode 100644 index 0000000..d63dfd1 --- /dev/null +++ b/tests/hypervisor_kvm_only.pp @@ -0,0 +1,4 @@ +class { 'proxmox::hypervisor': + kvm_only => true, +} + diff --git a/tests/init.pp b/tests/init.pp new file mode 100644 index 0000000..d0b7ebd --- /dev/null +++ b/tests/init.pp @@ -0,0 +1,12 @@ +# The baseline for module testing used by Puppet Labs is that each manifest +# should have a corresponding test manifest that declares that class or defined +# type. +# +# Tests are then run by using puppet apply --noop (to check for compilation +# errors and view a log of events) or by fully applying the test in a virtual +# environment (to compare the resulting system state to the desired state). +# +# Learn more about module testing here: +# http://docs.puppetlabs.com/guides/tests_smoke.html +# +include proxmox