├── .gitignore ├── Template-Cloud-Functions.yml ├── templates ├── RHEL │ ├── ifcfg-rhel.j2 │ ├── firstboot-rhel.sh.j2 │ ├── cloud-set-guest-sshkey-rhel.j2 │ ├── cloud-run-userdata-rhel.j2 │ └── cloud-set-guest-password-rhel.j2 ├── Generic │ ├── motd.j2 │ ├── motd-datapipe.j2 │ ├── cloud-set-guest-sshkey │ ├── cloud-set-rhn-systemid │ ├── cloud-common-functions.j2 │ ├── cloud-set-guest-password │ └── cloud-get-userdata ├── upstart │ ├── firstboot.upstart.j2 │ ├── run-userdata.upstart.j2 │ ├── set-guest-sshkey.upstart.j2 │ └── set-guest-password.upstart.j2 ├── systemd │ ├── run-userdata.systemd.j2 │ ├── firstboot.systemd.j2 │ ├── set-guest-sshkey.systemd.j2 │ └── set-guest-password.systemd.j2 ├── FreeBSD │ ├── firstboot-rc.j2 │ ├── cloud-userdata-rc.j2 │ ├── cloud-sshkey-rc.j2 │ ├── cloud-password-rc.j2 │ ├── cloud-set-guest-sshkey-freebsd.j2 │ ├── firstboot-freebsd.j2 │ ├── cloud-run-userdata-freebsd.j2 │ └── cloud-set-guest-password-freebsd.j2 ├── Debian │ ├── ifcfg-debian.j2 │ ├── cloud-set-guest-sshkey-debian.j2 │ ├── firstboot-debian.sh.j2 │ ├── cloud-run-userdata-debian.j2 │ └── cloud-set-guest-password-debian.j2 ├── SLES │ ├── cloud-set-guest-sshkey-sles.j2 │ └── cloud-set-guest-password-sles.j2 └── Ubuntu │ ├── cloud-set-guest-sshkey-ubuntu.j2 │ └── cloud-set-guest-password-ubuntu.j2 ├── Template-Test-Init-System.yml ├── Template-Packages-FreeBSD.yml ├── Template-Packages-SUSE.yml ├── Template-Networking.yml ├── Readme.md ├── Test-Init.yml ├── Template-Clean-Logs.yml ├── Template-Packages-RHEL.yml ├── .kitchen.yml ├── Template-Cloud-Firstboot.yml ├── Template-Cloud-Userdata.yml ├── hosts ├── Template-Packages-Debian.yml ├── Template-Cloud-SSH-Key.yml ├── Template-Cloud-Password.yml ├── Template.yml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .kitchen/ 2 | .kitchen.local.yml 3 | hosts 4 | -------------------------------------------------------------------------------- /Template-Cloud-Functions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add cloud-common-functions script 3 | template: src=templates/Generic/cloud-common-functions.j2 dest=/usr/share/cloudstack/cloudstack-common-functions mode=0755 -------------------------------------------------------------------------------- /templates/RHEL/ifcfg-rhel.j2: -------------------------------------------------------------------------------- 1 | TYPE=Ethernet 2 | DEVICE={{adapter_name.stdout}} 3 | NAME={{adapter_name.stdout}} 4 | BOOTPROTO=dhcp 5 | DEFROUTE=yes 6 | PEERDNS=yes 7 | PEERROUTES=yes 8 | IPV4_FAILURE_FATAL=yes 9 | IPV6INIT=no 10 | ONBOOT=yes 11 | NM_CONTROLLED=yes 12 | -------------------------------------------------------------------------------- /templates/Generic/motd.j2: -------------------------------------------------------------------------------- 1 | ___ _ _ __ _ _ 2 | / __\ | ___ _ _ __| / _\ |_ __ _ ___| | __ 3 | / / | |/ _ \| | | |/ _` \ \| __/ _` |/ __| |/ / 4 | / /___| | (_) | |_| | (_| |\ \ || (_| | (__| < 5 | \____/|_|\___/ \__,_|\__,_\__/\__\__,_|\___|_|\_\ 6 | 7 | -------------------------------------------------------------------------------- /templates/upstart/firstboot.upstart.j2: -------------------------------------------------------------------------------- 1 | # cloudstack-set-guest-sshkey 2 | 3 | description "Initial setup of instance." 4 | 5 | start on (startup and 6 | started networking and 7 | starting ssh) 8 | 9 | task 10 | exec /usr/share/cloudstack/cloudstack-firstboot start 11 | -------------------------------------------------------------------------------- /templates/upstart/run-userdata.upstart.j2: -------------------------------------------------------------------------------- 1 | # cloudstack-set-guest-sshkey 2 | 3 | description "run userdata from CloudStack metadata" 4 | 5 | start on (startup and 6 | started networking and 7 | starting ssh) 8 | 9 | task 10 | exec /usr/share/cloudstack/cloudstack-run-userdata start 11 | -------------------------------------------------------------------------------- /templates/upstart/set-guest-sshkey.upstart.j2: -------------------------------------------------------------------------------- 1 | # cloudstack-set-guest-sshkey 2 | 3 | description "set root sshkeys from CloudStack metadata" 4 | 5 | start on (startup and 6 | started networking and 7 | starting ssh) 8 | 9 | task 10 | exec /usr/share/cloudstack/cloudstack-set-guest-sshkey start -------------------------------------------------------------------------------- /templates/upstart/set-guest-password.upstart.j2: -------------------------------------------------------------------------------- 1 | # cloudstack-set-guest-password 2 | 3 | description "set root password from CloudStack metadata" 4 | 5 | start on (startup and 6 | started networking and 7 | starting ssh) 8 | 9 | task 10 | exec /usr/share/cloudstack/cloudstack-set-guest-password start -------------------------------------------------------------------------------- /templates/systemd/run-userdata.systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudStack User Data 3 | After=network.target 4 | 5 | [Service] 6 | Type=oneshot 7 | ExecStart=/usr/share/cloudstack/cloudstack-run-userdata start 8 | 9 | [Install] 10 | WantedBy=multi-user.target 11 | 12 | # This service file runs the cloudstack userdata 13 | -------------------------------------------------------------------------------- /templates/systemd/firstboot.systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudStack First Boot 3 | After=network.target 4 | Before=sshd.service 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/usr/share/cloudstack/cloudstack-firstboot 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | 13 | # This service file runs the firstboot-cloudstack 14 | -------------------------------------------------------------------------------- /templates/FreeBSD/firstboot-rc.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # PROVIDE: cloudstack_firstboot 3 | # REQUIRE: DAEMON networking 4 | # BEFORE: LOGIN 5 | # KEYWORD: nojail 6 | 7 | . /etc/rc.subr 8 | 9 | name=cloudstack_firstboot 10 | rcvar=cloudstack_firstboot_enable 11 | 12 | command="/usr/share/cloudstack/${name}" 13 | 14 | load_rc_config $name 15 | run_rc_command "$1" -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-userdata-rc.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # PROVIDE: cloudstack_run_userdata 3 | # REQUIRE: DAEMON networking 4 | # BEFORE: LOGIN 5 | # KEYWORD: nojail 6 | 7 | . /etc/rc.subr 8 | 9 | name=cloudstack_run_userdata 10 | rcvar=cloudstack_run_userdata_enable 11 | 12 | command="/usr/share/cloudstack/${name}" 13 | 14 | load_rc_config $name 15 | run_rc_command "$1" -------------------------------------------------------------------------------- /templates/Generic/motd-datapipe.j2: -------------------------------------------------------------------------------- 1 | _____ _______ _____ _____ _____ ______ 2 | | __ \ /\|__ __|/\ | __ \_ _| __ \| ____| 3 | | | | | / \ | | / \ | |__) || | | |__) | |__ 4 | | | | |/ /\ \ | | / /\ \ | ___/ | | | ___/| __| 5 | | |__| / ____ \| |/ ____ \| | _| |_| | | |____ 6 | |_____/_/ \_\_/_/ \_\_| |_____|_| |______| 7 | 8 | 9 | -------------------------------------------------------------------------------- /templates/Debian/ifcfg-debian.j2: -------------------------------------------------------------------------------- 1 | # This file describes the network interfaces available on your system 2 | # and how to activate them. For more information, see interfaces(5). 3 | 4 | # The loopback network interface 5 | auto lo 6 | iface lo inet loopback 7 | 8 | # The primary network interface 9 | auto {{adapter_name.stdout}} 10 | iface {{adapter_name.stdout}} inet dhcp 11 | -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-sshkey-rc.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # PROVIDE: cloudstack_set_guest_sshkey 3 | # REQUIRE: DAEMON networking 4 | # BEFORE: LOGIN 5 | # KEYWORD: nojail 6 | 7 | . /etc/rc.subr 8 | 9 | name=cloudstack_set_guest_sshkey 10 | rcvar=cloudstack_set_guest_sshkey_enable 11 | 12 | command="/usr/share/cloudstack/${name}" 13 | 14 | load_rc_config $name 15 | run_rc_command "$1" -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-password-rc.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # PROVIDE: cloudstack_set_guest_password 3 | # REQUIRE: DAEMON networking 4 | # BEFORE: LOGIN 5 | # KEYWORD: nojail 6 | 7 | . /etc/rc.subr 8 | 9 | name=cloudstack_set_guest_password 10 | rcvar=cloudstack_set_guest_password_enable 11 | 12 | command="/usr/share/cloudstack/${name}" 13 | 14 | load_rc_config $name 15 | run_rc_command "$1" -------------------------------------------------------------------------------- /templates/systemd/set-guest-sshkey.systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudStack Guest SSH Key Reset 3 | After=network.target local-fs.target 4 | Before=sshd.service 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/usr/share/cloudstack/cloudstack-set-guest-sshkey start 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | 13 | # This service file runs the cloudstack-set-guest-password 14 | -------------------------------------------------------------------------------- /templates/systemd/set-guest-password.systemd.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudStack Guest Password Reset 3 | After=network.target local-fs.target 4 | Before=sshd.service 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/usr/share/cloudstack/cloudstack-set-guest-password start 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | 13 | # This service file runs the cloudstack-set-guest-password 14 | -------------------------------------------------------------------------------- /Template-Test-Init-System.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test for systemd 3 | stat: path=/etc/systemd/system get_md5=no 4 | register: systemd 5 | 6 | - name: test for upstart 7 | stat: path=/lib/init/upstart-job get_md5=no 8 | register: upstart 9 | 10 | - name: test for FreeBSD 11 | when: ansible_os_family == "FreeBSD" 12 | stat: path=/etc/rc.conf get_md5=no 13 | register: fbsd 14 | 15 | # - debug: var=systemd 16 | # ignore_errors: true 17 | # - debug: var=upstart 18 | # ignore_errors: true 19 | # - debug: var=fbsd 20 | # ignore_errors: true -------------------------------------------------------------------------------- /Template-Packages-FreeBSD.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install "core" packages (FreeBSD) 3 | when: ansible_os_family == "FreeBSD" 4 | pkgng: name={{ item }} state=present 5 | with_items: 6 | - vim 7 | - screen 8 | - tmux 9 | - curl 10 | - wget 11 | - lynx 12 | - links 13 | - sudo 14 | - bash 15 | - git 16 | - rsyslog 17 | - rsync 18 | - nmap 19 | - netcat 20 | - bind-tools 21 | - htop 22 | - linux_base-c6 23 | - name: update packages (FreeBSD) 24 | when: ansible_os_family == "FreeBSD" 25 | command: pkg upgrade -y -------------------------------------------------------------------------------- /Template-Packages-SUSE.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install "core" packages (SUSE) 3 | when: ansible_os_family == "Suse" 4 | zypper: name={{ item }} state=latest 5 | with_items: 6 | - vim 7 | - screen 8 | - tmux 9 | - curl 10 | - wget 11 | - lynx 12 | - links 13 | - sudo 14 | - git 15 | - rsyslog 16 | - rsync 17 | - nmap 18 | - netcat-openbsd 19 | - strace 20 | - bind-utils 21 | - iotop 22 | - name: update system (SUSE) 23 | when: ansible_os_family == "Suse" 24 | command: zypper update -y 25 | - name: set timezone to UTC (SUSE) 26 | when: ansible_os_family == "Suse" 27 | shell: "rm -f /etc/localtime && ln -s /usr/share/zoneinfo/UTC /etc/localtime" 28 | -------------------------------------------------------------------------------- /Template-Networking.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: register primary network adapter name 3 | when: ansible_os_family != "FreeBSD" 4 | shell: "ip link | grep UP | grep -v LOOPBACK | awk -F':' '{print $2}' | tr -d ' '" 5 | register: adapter_name 6 | 7 | - name: setup networking (RHEL) 8 | when: ansible_os_family == "RedHat" 9 | template: src=templates/RHEL/ifcfg-rhel.j2 dest=/etc/sysconfig/network-scripts/ifcfg-{{adapter_name.stdout}} mode=0644 10 | 11 | - name: remove udev network naming (RHEL) 12 | when: ansible_os_family == "RedHat" 13 | file: path=/etc/udev/rules.d/70-persistent-net.rules state=absent 14 | 15 | - name: setup networking (Debian) 16 | when: ansible_os_family == "Debian" 17 | template: src=templates/Debian/ifcfg-debian.j2 dest=/etc/network/interfaces mode=0644 -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | CloudStack-Template 2 | =================== 3 | 4 | ## Ansible Playbook for creating CloudStack templates 5 | 6 | These plays have been tested and work against: 7 | * Red Hat Enterprise Linux (and derivatives [Scientific/Centos/Oracle]) 8 | * 5 9 | * 6 10 | * 7 11 | * Debian Linux 12 | * 6 13 | * 7 14 | * Ubuntu Linux 15 | * 10.04 LTS 16 | * 12.04 LTS 17 | * 14.04 LTS 18 | 19 | To execute the Playbook, you need to have Ansible installed on the local workstation. Instructions for installing Ansible are available [here](http://docs.ansible.com/intro_installation.html). 20 | 21 | Once Ansible is installed, you will need to modify the hosts file to reflect the IP addresses, passwords, and possibly SSH ports needed to connect to the instance and perform the configuration. 22 | 23 | The Playbook is executed by having this directory as your current working directory and executing: ansible-playbook -i ./hosts ./Template.yml 24 | 25 | ### What this Playbook provides 26 | 27 | This playbook: 28 | * installs a suite of standard packages across all distributions, including curl, wget, lynx, screen, and tmux. 29 | * sets up new init scripts (which work under init and upstart. systemd support is coming soon.) for SSH keys, passwords, and user data execution. 30 | * sets up a new Firstboot script to set up networking, hostsfile, and set the hostname according to DHCP 31 | * cleans out old log files 32 | * cleans out old ssh host keys 33 | * sets a MOTD splash 34 | -------------------------------------------------------------------------------- /Test-Init.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - name: create directory to store cloudstack client scripts 5 | file: state=directory mode=0755 path=/usr/share/cloudstack 6 | 7 | - name: register init system variables 8 | include: Template-Test-Init-System.yml 9 | 10 | - name: setup common functions for init scripts 11 | include: Template-Cloud-Functions.yml 12 | 13 | - name: setup cloudstack-set-guest-password 14 | include: Template-Cloud-Password.yml 15 | - name: setup cloudstack-set-guest-sshkey 16 | include: Template-Cloud-SSH-Key.yml 17 | - name: setup cloudstack-run-userdata 18 | include: Template-Cloud-Userdata.yml 19 | - name: setup cloudstack-firstboot 20 | include: Template-Cloud-Firstboot.yml 21 | 22 | - name: register upstart services 23 | when: upstart.stat.exists == true and systemd.stat.exists == false 24 | shell: initctl reload-configuration 25 | - name: register systemd services 26 | when: upstart.stat.exists == false and systemd.stat.exists == true 27 | shell: systemctl daemon-reload 28 | 29 | - name: enable cloudstack-password service 30 | service: name=cloudstack-set-guest-password enabled=yes 31 | - name: enable cloudstack-sshkey service 32 | service: name=cloudstack-set-guest-sshkey enabled=yes 33 | - name: enable cloudstack-userdata service 34 | service: name=cloudstack-run-userdata enabled=yes 35 | # - name: enable firstboot-cloudstack service 36 | # service: name=cloudstack-firstboot enabled=yes 37 | -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-set-guest-sshkey-freebsd.j2: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | # FreeBSD 3 | # Modify this line to specify the user (default is root) 4 | user=root 5 | 6 | WGET=/usr/local/bin/wget 7 | 8 | keys_received=0 9 | file_count=0 10 | 11 | . /usr/share/cloudstack/cloudstack-common-functions 12 | find_lease 13 | 14 | SSHKEY_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 15 | 16 | if [ -n $SSHKEY_SERVER_IP ]; then 17 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 18 | 19 | publickey=$($WGET -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 20 | 21 | if [ $? -eq 0 ]; then 22 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 23 | keys_received=1 24 | fi 25 | else 26 | logger -t "cloud" "Could not find ssh key server IP in $LEASE_FILE" 27 | fi 28 | 29 | # did we find the keys anywhere? 30 | if [ "$keys_received" == "0" ] 31 | then 32 | logger -t "cloud" "Failed to get ssh keys from any server" 33 | exit 1 34 | fi 35 | 36 | 37 | 38 | # set ssh public key 39 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 40 | sshdir=$homedir/.ssh 41 | authorized=$sshdir/authorized_keys 42 | 43 | 44 | if [ ! -e $sshdir ] 45 | then 46 | mkdir $sshdir 47 | fi 48 | 49 | if [ ! -e $authorized ] 50 | then 51 | touch $authorized 52 | fi 53 | 54 | #cat $authorized|grep -v "$publickey" > $authorized 55 | #echo "$publickey" >> $authorized 56 | #To support user copied ssh keys 57 | if [ `grep -c "$publickey" $authorized` == 0 ] 58 | then 59 | echo "$publickey" >> $authorized 60 | fi 61 | 62 | exit 0 63 | 64 | -------------------------------------------------------------------------------- /Template-Clean-Logs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: clean old logs 3 | file: path={{ item }} state=absent 4 | with_items: 5 | - /var/log/auth.log 6 | - /var/log/boot 7 | - /var/log/boot.log 8 | - /var/log/btmp 9 | - /var/log/daemon.log 10 | - /var/log/debug 11 | - /var/log/dmesg 12 | - /var/log/dpkg.log 13 | - /var/log/faillog 14 | - /var/log/kern.log 15 | - /var/log/lastlog 16 | - /var/log/lpr.log 17 | - /var/log/mail.err 18 | - /var/log/mail.info 19 | - /var/log/mail.log 20 | - /var/log/mail.warn 21 | - /var/log/maillog 22 | - /var/log/messages 23 | - /var/log/pycentral.log 24 | - /var/log/secure 25 | - /var/log/syslog 26 | - /var/log/udev 27 | - /var/log/ufw.log 28 | - /var/log/user.log 29 | - /var/log/wtmp 30 | - /var/log/yum.log 31 | - /var/spool/mail/root 32 | - /root/* 33 | - /home/* 34 | - /root/.history 35 | - /root/.bash_history 36 | - name: clean really old logs 37 | shell: rm -Rf {{ item }} 38 | with_items: 39 | - /var/log/*old 40 | - /var/log/*0 41 | - /var/log/*.? 42 | - /var/log/user.log.? 43 | - /var/log/kern.log.? 44 | - /var/log/auth.log.? 45 | - /var/log/daemon.log.? 46 | - /var/log/upstart/* 47 | - /var/log/sa/* 48 | - /var/log/dmesg* 49 | - /var/log/*-201* 50 | - /var/log/*gz 51 | - /var/log/*bz? 52 | ignore_errors: true 53 | 54 | - name: recreate required logs 55 | file: path={{ item }} state=touch 56 | with_items: 57 | - /var/log/messages 58 | - /var/log/syslog 59 | - /var/log/lastlog 60 | 61 | - name: clean yum cache 62 | when: ansible_os_family == "RedHat" 63 | shell: yum clean all -------------------------------------------------------------------------------- /Template-Packages-RHEL.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install EPEL (RHEL 5) 3 | when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 5 4 | shell: rpm -Uvh http://mirror.pnl.gov/epel/5/i386/epel-release-5-4.noarch.rpm 5 | ignore_errors: true 6 | - name: install EPEL (RHEL 6) 7 | when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 6 8 | yum: name=http://mirror.pnl.gov/epel/6/i386/epel-release-6-8.noarch.rpm state=present 9 | - name: install EPEL (RHEL 7) 10 | when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 7 11 | yum: name=http://mirror.pnl.gov/epel/7/x86_64/e/epel-release-7-5.noarch.rpm state=present 12 | - name: install "core" packages (RHEL) 13 | when: ansible_os_family == "RedHat" 14 | yum: name={{ item }} state=latest 15 | with_items: 16 | - openssh-clients 17 | - vim-enhanced 18 | - screen 19 | - tmux 20 | - curl 21 | - wget 22 | - lynx 23 | - links 24 | - sudo 25 | - libselinux-python 26 | - git 27 | - rsyslog 28 | - rsync 29 | - nmap 30 | - nc 31 | - strace 32 | - bind-utils 33 | - iotop 34 | - htop 35 | - name: update system (RHEL) 36 | when: ansible_os_family == "RedHat" 37 | command: yum upgrade -y 38 | - name: set selinux to permissive 39 | when: ansible_os_family == "RedHat" 40 | selinux: policy=targeted state=permissive 41 | - name: set timezone to UTC (RHEL) 42 | when: ansible_os_family == "RedHat" 43 | shell: "rm -f /etc/localtime && ln -s /usr/share/zoneinfo/UTC /etc/localtime" 44 | - name: install vmware tools (RHEL/vmware) 45 | yum: name=open-vm-tools state=latest 46 | when: ansible_os_family == "RedHat" and ansible_virtualization_type == "VMware" -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: cloudstack 4 | 5 | driver_config: 6 | cloudstack_api_url: http://cloudstack.fifthecho.com:8080/client/api 7 | cloudstack_api_key: ycEWIN17Pjazd9AN5AVdpE0ObrTWJhBuAXxBkJvhLgKz6Caq0Vq9v0vhpNXraOhb72Pk8d4kRwjbAwv_3fxIyg 8 | cloudstack_secret_key: Uv6i5BIJYFKLfBM6rQli8oTlnHxP3G8kRv3kK1vDuOoaCtXsot0anPjYEpi2klvaaWaSuKZ9eqfm0gYDVGya1Q 9 | cloudstack_serviceoffering_id: d04b4fb7-e0c6-4acc-85da-56437b8b873a 10 | cloudstack_zone_id: b7ee7151-b539-4c82-85d9-841c8c2b405d 11 | cloudstack_security_group_id: 77876e01-44c8-11e4-ad1f-52540080ad25 12 | cloudstack_ssh_keypair_name: jmoody_fifthecho 13 | 14 | provisioner: 15 | name: ansible_playbook 16 | hosts: all 17 | playbook: Template.yml 18 | require_ansible_repo: true 19 | roles_path: roles 20 | 21 | platforms: 22 | - name: Centos-7 23 | driver: 24 | cloudstack_template_id: fdf69820-523b-4386-9930-f3765525dc9b 25 | - name: Centos-6 26 | driver: 27 | cloudstack_template_id: 7fba1bb5-d653-4674-a744-f6a456ad89a2 28 | - name: Centos-5 29 | driver: 30 | cloudstack_template_id: d17721e7-91f6-4296-8029-257fd8158d13 31 | 32 | - name: Ubuntu-14 33 | driver: 34 | cloudstack_template_id: c265f1ee-1802-4877-9809-e013ba8f057e 35 | - name: Ubuntu-12 36 | driver: 37 | cloudstack_template_id: 9ce0707c-915a-4956-a610-d25cb84d02c0 38 | - name: Ubuntu-10 39 | driver: 40 | cloudstack_template_id: bfb22313-cef0-492c-a368-09d3e2a652eb 41 | 42 | - name: Debian-7 43 | driver: 44 | cloudstack_template_id: 30aee694-e115-4e94-8553-7e20ff730853 45 | - name: Debian-6 46 | driver: 47 | cloudstack_template_id: 1fdf61bc-c9fe-4c14-8532-e5013c2a342d 48 | 49 | 50 | suites: 51 | - name: lab -------------------------------------------------------------------------------- /Template-Cloud-Firstboot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add cloud-firstboot script (RHEL) 3 | when: ansible_os_family == "RedHat" 4 | template: src=templates/RHEL/firstboot-rhel.sh.j2 dest=/usr/share/cloudstack/cloudstack-firstboot mode=0755 5 | 6 | - name: add cloud-firstboot script (Debian) 7 | when: ansible_os_family == "Debian" 8 | template: src=templates/Debian/firstboot-debian.sh.j2 dest=/usr/share/cloudstack/cloudstack-firstboot mode=0755 9 | 10 | - name: add cloud-firstboot script (FreeBSD) 11 | when: ansible_os_family == "FreeBSD" 12 | template: src=templates/FreeBSD/firstboot-freebsd.j2 dest=/usr/share/cloudstack/cloudstack_firstboot mode=0755 13 | 14 | - name: setup cloudstack-firstboot (init) 15 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 16 | file: state=link force=yes src=/usr/share/cloudstack/cloudstack-firstboot dest=/etc/init.d/cloudstack-firstboot mode=0755 17 | 18 | - name: setup cloudstack-firstboot (upstart) 19 | when: upstart.stat.exists == true and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 20 | template: src=templates/upstart/firstboot.upstart.j2 dest=/etc/init/cloudstack-firstboot.conf mode=0644 21 | 22 | - name: setup cloudstack-firstboot (systemd) 23 | when: upstart.stat.exists == false and systemd.stat.exists == true and ansible_os_family != "FreeBSD" 24 | template: src=templates/systemd/firstboot.systemd.j2 dest=/usr/lib/systemd/system/cloudstack-firstboot.service mode=0644 25 | 26 | - name: setup cloudstack-set-guest-sshkey (FreeBSD) 27 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family == "FreeBSD" 28 | template: src=templates/FreeBSD/firstboot-rc.j2 dest=/usr/local/etc/rc.d/cloudstack_firstboot mode=0755 29 | 30 | - name: clear init legacy 31 | when: ansible_os_family == "RedHat" 32 | shell: chkconfig --del cloudstack-firstboot 33 | ignore_errors: true -------------------------------------------------------------------------------- /Template-Cloud-Userdata.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add cloud-run-userdata script (RHEL) 3 | when: ansible_os_family == "RedHat" 4 | template: src=templates/RHEL/cloud-run-userdata-rhel.j2 dest=/usr/share/cloudstack/cloudstack-run-userdata mode=0755 5 | 6 | - name: add cloud-run-userdata script (Debian) 7 | when: ansible_os_family == "Debian" 8 | template: src=templates/Debian/cloud-run-userdata-debian.j2 dest=/usr/share/cloudstack/cloudstack-run-userdata mode=0755 9 | 10 | - name: add cloud-run-userdata script (FreeBSD) 11 | when: ansible_os_family == "FreeBSD" 12 | template: src=templates/FreeBSD/cloud-run-userdata-freebsd.j2 dest=/usr/share/cloudstack/cloudstack_run_userdata mode=0755 13 | 14 | - name: setup cloudstack-run-userdata (init) 15 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 16 | file: state=link src=/usr/share/cloudstack/cloudstack-run-userdata dest=/etc/init.d/cloudstack-run-userdata mode=0755 force=yes 17 | 18 | - name: setup cloudstack-run-userdata (upstart) 19 | when: upstart.stat.exists == true and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 20 | template: src=templates/upstart/run-userdata.upstart.j2 dest=/etc/init/cloudstack-run-userdata.conf mode=0644 21 | 22 | - name: setup cloudstack-run-userdata (systemd) 23 | when: upstart.stat.exists == false and systemd.stat.exists == true and ansible_os_family != "FreeBSD" 24 | template: src=templates/systemd/run-userdata.systemd.j2 dest=/usr/lib/systemd/system/cloudstack-run-userdata.service mode=0644 25 | 26 | - name: setup cloudstack-run-userdata (FreeBSD) 27 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family == "FreeBSD" 28 | template: src=templates/FreeBSD/cloud-userdata-rc.j2 dest=/usr/local/etc/rc.d/cloudstack_run_userdata mode=0755 29 | 30 | - name: clear init legacy 31 | when: ansible_os_family == "RedHat" 32 | shell: chkconfig --del cloudstack-run-userdata 33 | ignore_errors: true 34 | -------------------------------------------------------------------------------- /templates/FreeBSD/firstboot-freebsd.j2: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | # 3 | # Flush all things not needed for a new VM and create default network environment 4 | # 5 | 6 | . /usr/share/cloudstack/cloudstack-common-functions 7 | 8 | echo "Initializing Virtual Machine..." 9 | logger -t "Setup" "Initializing Virtual Machine..." 10 | find_lease 11 | 12 | cat rc.conf | sed '/^hostname/d' > /etc/rc.conf 13 | HOST_NAME=`grep host-name $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | tr -d '"' | uniq` 14 | echo "Setting hostname to $HOST_NAME" 15 | logger -t "Setup" "Setting hostname to $HOST_NAME" 16 | echo "hostname=\"$HOST_NAME\"" >> /etc/rc.conf 17 | /bin/hostname $HOST_NAME 18 | 19 | echo "# $FreeBSD: releng/10.1/etc/hosts 109997 2003-01-28 21:29:23Z dbaker $" > /etc/hosts 20 | echo "#" >> /etc/hosts 21 | echo "# Host Database" >> /etc/hosts 22 | echo "#" >> /etc/hosts 23 | echo "# This file should contain the addresses and aliases for local hosts that" >> /etc/hosts 24 | echo "# share this file. Replace 'my.domain' below with the domainname of your" >> /etc/hosts 25 | echo "# machine." >> /etc/hosts 26 | echo "#" >> /etc/hosts 27 | echo "# In the presence of the domain name service or NIS, this file may" >> /etc/hosts 28 | echo "# not be consulted at all; see /etc/nsswitch.conf for the resolution order." >> /etc/hosts 29 | echo "#" >> /etc/hosts 30 | echo "#" >> /etc/hosts 31 | echo "::1 localhost localhost.my.domain" >> /etc/hosts 32 | echo "127.0.0.1 localhost localhost.my.domain" >> /etc/hosts 33 | 34 | IP=`grep fixed-address $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | uniq` 35 | echo "Setting up /etc/hosts for IP address $IP" 36 | logger -t "Setup" "Setting up /etc/hosts for IP address $IP" 37 | echo "$IP $HOST_NAME" >> /etc/hosts 38 | 39 | cat rc.conf | sed '/^cloud_firstboot/d' > /etc/rc.conf 40 | cat rc.conf | sed '/^linux/d' > /etc/rc.conf 41 | echo "linux_enable=\"YES\"" >> /etc/rc.conf 42 | if [ $(kldstat | grep linux | wc -l) -eq 0 ]; then 43 | kldload linux 44 | fi -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | centos5-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.23 ansible_ssh_port=22 2 | centos6-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.225 3 | centos7-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.138 4 | debian6-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.226 5 | debian7-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.246 6 | debian8-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.89 7 | ubuntu10-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.45 8 | ubuntu12-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.60 9 | ubuntu14-kvm ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.75 10 | freebsd10-kvm ansible_python_interpreter=/usr/local/bin/python ansible_connection=paramiko ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.139 11 | 12 | centos5-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.81 13 | centos6-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.199 14 | centos7-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.79 15 | debian6-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.4 16 | debian7-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.147 17 | debian8-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.51 18 | ubuntu10-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.131 19 | ubuntu12-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.175 20 | ubuntu14-xen ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.77 21 | freebsd10-xen ansible_python_interpreter=/usr/local/bin/python ansible_connection=paramiko ansible_ssh_user=root ansible_ssh_pass=cloudstack ansible_ssh_host=10.20.1.83 22 | -------------------------------------------------------------------------------- /Template-Packages-Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install backports (Debian 6) 3 | when: ansible_distribution == "Debian" and ansible_distribution_major_version|int == 6 4 | apt_repository: repo='deb http://http.debian.net/debian-backports squeeze-backports main' state=present 5 | - name: install backports (Debian 7) 6 | when: ansible_distribution == "Debian" and ansible_distribution_major_version|int == 7 7 | apt_repository: repo='deb http://http.debian.net/debian wheezy-backports main' state=present 8 | - name: install backports (Debian 8) 9 | when: ansible_distribution == "Debian" and ansible_distribution_major_version|int == 8 10 | apt_repository: repo='deb http://http.debian.net/debian jessie-backports main' state=present 11 | - name: install git ppa (Ubuntu 10.04) 12 | when: ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int == 10 13 | apt_repository: repo='ppa:git-core/ppa' state=present 14 | - name: install "core" packages (Debian) 15 | when: ansible_os_family == "Debian" 16 | apt: name={{ item }} state=latest update_cache=yes 17 | with_items: 18 | - vim 19 | - screen 20 | - tmux 21 | - curl 22 | - wget 23 | - lynx 24 | - links 25 | - sudo 26 | - git 27 | - rsyslog 28 | - rsync 29 | - netcat 30 | - nmap 31 | - strace 32 | - dnsutils 33 | - iotop 34 | - htop 35 | - name: install latest hwe for Ubuntu 12.04 36 | apt: name={{ item }} state=latest update_cache=yes 37 | when: ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int == 12 38 | with_items: 39 | - linux-generic-lts-trusty 40 | - linux-image-generic-lts-trusty 41 | - name: update system (Debian) 42 | when: ansible_os_family == "Debian" 43 | apt: upgrade=dist update_cache=yes 44 | - name: set timezone to UTC (Debian) 45 | when: ansible_os_family == "Debian" 46 | shell: "echo 'Etc/UTC' > /etc/timezone && dpkg-reconfigure -f noninteractive tzdata" 47 | - name: cleanup old packages (Debian) 48 | when: ansible_os_family == "Debian" 49 | shell: "apt-get autoremove -y" -------------------------------------------------------------------------------- /templates/SLES/cloud-set-guest-sshkey-sles.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Init file for SSH Public Keys Download Client 4 | # 5 | # chkconfig: 345 98 02 6 | # description: SSH Public Keys Download Client 7 | 8 | ### BEGIN INIT INFO 9 | # Provides: cloud-set-guest-sshkey 10 | # Required-Start: $network $syslog $local_fs 11 | # Required-Stop: $network $syslog $local_fs 12 | # Default-Start: 3 5 13 | # Default-Stop: 0 1 2 6 14 | # Short-Description: SSH Public Keys Download Client 15 | # Description: CloudStack SSH Public Keys Download Client 16 | ### END INIT INFO 17 | 18 | # Modify this line to specify the user (default is root) 19 | user=root 20 | 21 | # Add your DHCP lease folders here 22 | DHCP_FOLDERS="/var/lib/dhcpcd/*" 23 | 24 | keys_received=0 25 | file_count=0 26 | 27 | for DHCP_FILE in $DHCP_FOLDERS; do 28 | if [ -f $DHCP_FILE ]; then 29 | file_count=$((file_count+1)) 30 | source $DHCP_FILE 31 | SSHKEY_SERVER_IP=$DHCPSIADDR 32 | 33 | if [ -n $SSHKEY_SERVER_IP ]; then 34 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 35 | 36 | publickey=$(wget -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 37 | 38 | if [ $? -eq 0 ]; then 39 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 40 | keys_received=1 41 | break 42 | fi 43 | else 44 | logger -t "cloud" "Could not find ssh key server IP in $DHCP_FILE" 45 | fi 46 | fi 47 | done 48 | 49 | # did we find the keys anywhere? 50 | if [ "$keys_received" == "0" ]; then 51 | logger -t "cloud" "Failed to get ssh keys from any server" 52 | exit 1 53 | fi 54 | 55 | # set ssh public key 56 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 57 | sshdir=$homedir/.ssh 58 | authorized=$sshdir/authorized_keys 59 | 60 | if [ ! -e $sshdir ]; then 61 | mkdir $sshdir 62 | fi 63 | 64 | if [ ! -e $authorized ]; then 65 | touch $authorized 66 | fi 67 | 68 | #cat $authorized|grep -v "$publickey" > $authorized 69 | #echo "$publickey" >> $authorized 70 | #To support user copied ssh keys 71 | if [ `grep -c "$publickey" $authorized` == 0 ]; then 72 | echo "$publickey" >> $authorized 73 | fi 74 | 75 | exit 0 76 | -------------------------------------------------------------------------------- /templates/RHEL/firstboot-rhel.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Flush all things not needed for a new VM and create default network environment 4 | # 5 | # chkconfig: 235 49 02 6 | # description: Prepare new VM 7 | ### BEGIN INIT INFO 8 | # Provides: firstboot-cloudstack 9 | # Required-Start: $network $local_fs $remote_fs $syslog $all 10 | # Required-Stop: $network $local_fs $remote_fs $syslog $all 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Prepare new VM 14 | # Description: Prepare new VM by flushing old information and preparing network environment 15 | ### END INIT INFO 16 | 17 | . /usr/share/cloudstack/cloudstack-common-functions 18 | 19 | echo "Initializing Virtual Machine..." 20 | logger -t "Setup" "Initializing Virtual Machine..." 21 | find_lease 22 | 23 | HOST_NAME=`grep host-name $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | tr -d '"' | uniq` 24 | echo "Setting hostname to $HOST_NAME" 25 | logger -t "Setup" "Setting hostname to $HOST_NAME" 26 | echo $HOST_NAME > /etc/hostname 27 | /bin/hostname $HOST_NAME 28 | 29 | echo "# Do not remove the following line, or various programs" > /etc/hosts 30 | echo "# that require network functionality will fail." >> /etc/hosts 31 | echo "127.0.0.1 localhost.localdomain localhost" >> /etc/hosts 32 | echo "# The following lines are desirable for IPv6 capable hosts" >> /etc/hosts 33 | echo "::1 ip6-localhost ip6-loopback" >> /etc/hosts 34 | echo "fe00::0 ip6-localnet" >> /etc/hosts 35 | echo "ff00::0 ip6-mcastprefix" >> /etc/hosts 36 | echo "ff02::1 ip6-allnodes" >> /etc/hosts 37 | echo "ff02::2 ip6-allrouters" >> /etc/hosts 38 | echo "::1 localhost6.localdomain6 localhost6" >> /etc/hosts 39 | IP=`grep fixed-address $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | uniq` 40 | echo "Setting up /etc/hosts for IP address $IP" 41 | logger -t "Setup" "Setting up /etc/hosts for IP address $IP" 42 | echo "$IP $HOST_NAME" >> /etc/hosts 43 | 44 | /usr/bin/yum clean all 45 | 46 | chkconfig cloudstack-firstboot off 47 | 48 | if [ -f /usr/bin/systemd-run ] 49 | then 50 | systemctl disable cloudstack-firstboot 51 | fi 52 | -------------------------------------------------------------------------------- /templates/Generic/cloud-set-guest-sshkey: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for SSH Public Keys Download Client 4 | # 5 | # chkconfig: 2345 98 02 6 | # description: SSH Public Keys Download Client 7 | ### BEGIN INIT INFO 8 | # Provides: cloud-set-guest-sshkey 9 | # Required-Start: $sshd $network 10 | # Required-Stop: $sshd $network 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Sets root ssh key 14 | # Description: Sets the ssh key for the root user based upon keys stored by the CloudStack RouterVM 15 | ### END INIT INFO 16 | 17 | 18 | # Modify this line to specify the user (default is root) 19 | user=root 20 | sleep 10 21 | 22 | 23 | # Add your DHCP lease folders here 24 | DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* /var/lib/NetworkManager/*" 25 | keys_received=0 26 | file_count=0 27 | 28 | for DHCP_FILE in $DHCP_FOLDERS 29 | do 30 | if [ -f $DHCP_FILE ] 31 | then 32 | file_count=$((file_count+1)) 33 | SSHKEY_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 34 | 35 | if [ -n $SSHKEY_SERVER_IP ] 36 | then 37 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 38 | 39 | publickey=$(wget -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 40 | 41 | if [ $? -eq 0 ] 42 | then 43 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 44 | keys_received=1 45 | break 46 | fi 47 | else 48 | logger -t "cloud" "Could not find ssh key server IP in $DHCP_FILE" 49 | fi 50 | fi 51 | done 52 | 53 | # did we find the keys anywhere? 54 | if [ "$keys_received" == "0" ] 55 | then 56 | logger -t "cloud" "Failed to get ssh keys from any server" 57 | exit 1 58 | fi 59 | 60 | 61 | 62 | # set ssh public key 63 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 64 | sshdir=$homedir/.ssh 65 | authorized=$sshdir/authorized_keys 66 | 67 | 68 | if [ ! -e $sshdir ] 69 | then 70 | mkdir $sshdir 71 | fi 72 | 73 | if [ ! -e $authorized ] 74 | then 75 | touch $authorized 76 | fi 77 | 78 | cat $authorized|grep -v "$publickey" > $authorized 79 | echo "$publickey" >> $authorized 80 | 81 | 82 | exit 0 83 | -------------------------------------------------------------------------------- /Template-Cloud-SSH-Key.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add cloud-set-guest-sshkey script (RHEL) 3 | when: ansible_os_family == "RedHat" 4 | template: src=templates/RHEL/cloud-set-guest-sshkey-rhel.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-sshkey mode=0755 5 | 6 | - name: add cloud-set-guest-sshkey script (Debian) 7 | when: ansible_distribution == "Debian" 8 | template: src=templates/Debian/cloud-set-guest-sshkey-debian.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-sshkey mode=0755 9 | 10 | - name: add cloud-set-guest-sshkey script (Ubuntu) 11 | when: ansible_distribution == "Ubuntu" 12 | template: src=templates/Ubuntu/cloud-set-guest-sshkey-ubuntu.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-sshkey mode=0755 13 | 14 | - name: add cloud-set-guest-sshkey script (FreeBSD) 15 | when: ansible_os_family == "FreeBSD" 16 | template: src=templates/FreeBSD/cloud-set-guest-sshkey-freebsd.j2 dest=/usr/share/cloudstack/cloudstack_set_guest_sshkey mode=0755 17 | 18 | - name: setup cloudstack-set-guest-sshkey (init) 19 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 20 | file: state=link src=/usr/share/cloudstack/cloudstack-set-guest-sshkey dest=/etc/init.d/cloudstack-set-guest-sshkey mode=0755 force=yes 21 | 22 | - name: setup cloudstack-set-guest-sshkey (upstart) 23 | when: upstart.stat.exists == true and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 24 | template: src=templates/upstart/set-guest-sshkey.upstart.j2 dest=/etc/init/cloudstack-set-guest-sshkey.conf mode=0644 25 | 26 | - name: setup cloudstack-set-guest-sshkey (systemd) 27 | when: upstart.stat.exists == false and systemd.stat.exists == true and ansible_os_family != "FreeBSD" 28 | template: src=templates/systemd/set-guest-sshkey.systemd.j2 dest=/usr/lib/systemd/system/cloudstack-set-guest-sshkey.service mode=0644 29 | 30 | - name: setup cloudstack-set-guest-sshkey (FreeBSD) 31 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family == "FreeBSD" 32 | template: src=templates/FreeBSD/cloud-sshkey-rc.j2 dest=/usr/local/etc/rc.d/cloudstack_set_guest_sshkey mode=0755 33 | 34 | - name: clear init legacy 35 | when: ansible_os_family == "RedHat" 36 | shell: chkconfig --del cloudstack-set-guest-sshkey 37 | ignore_errors: true -------------------------------------------------------------------------------- /Template-Cloud-Password.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: add cloud-set-guest-password script (RHEL) 3 | when: ansible_os_family == "RedHat" 4 | template: src=templates/RHEL/cloud-set-guest-password-rhel.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-password mode=0755 5 | 6 | - name: add cloud-set-guest-password script (Debian) 7 | when: ansible_distribution == "Debian" 8 | template: src=templates/Debian/cloud-set-guest-password-debian.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-password mode=0755 9 | 10 | - name: add cloud-set-guest-password script (Ubuntu) 11 | when: ansible_distribution == "Ubuntu" 12 | template: src=templates/Ubuntu/cloud-set-guest-password-ubuntu.j2 dest=/usr/share/cloudstack/cloudstack-set-guest-password mode=0755 13 | 14 | - name: add cloud-set-guest-password script (FreeBSD) 15 | when: ansible_os_family == "FreeBSD" 16 | template: src=templates/FreeBSD/cloud-set-guest-password-freebsd.j2 dest=/usr/share/cloudstack/cloudstack_set_guest_password mode=0755 17 | 18 | - name: setup cloudstack-set-guest-password (init) 19 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 20 | file: state=link src=/usr/share/cloudstack/cloudstack-set-guest-password dest=/etc/init.d/cloudstack-set-guest-password mode=0755 force=yes 21 | 22 | - name: setup cloudstack-set-guest-password (upstart) 23 | when: upstart.stat.exists == true and systemd.stat.exists == false and ansible_os_family != "FreeBSD" 24 | template: src=templates/upstart/set-guest-password.upstart.j2 dest=/etc/init/cloudstack-set-guest-password.conf mode=0644 25 | 26 | - name: setup cloudstack-set-guest-password (systemd) 27 | when: upstart.stat.exists == false and systemd.stat.exists == true and ansible_os_family != "FreeBSD" 28 | template: src=templates/systemd/set-guest-password.systemd.j2 dest=/usr/lib/systemd/system/cloudstack-set-guest-password.service mode=0644 29 | 30 | - name: setup cloudstack-set-guest-password (FreeBSD) 31 | when: upstart.stat.exists == false and systemd.stat.exists == false and ansible_os_family == "FreeBSD" 32 | template: src=templates/FreeBSD/cloud-password-rc.j2 dest=/usr/local/etc/rc.d/cloudstack_set_guest_password mode=0755 33 | 34 | - name: clear init legacy 35 | when: ansible_os_family == "RedHat" 36 | shell: chkconfig --del cloudstack-set-guest-password 37 | ignore_errors: true -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-run-userdata-freebsd.j2: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | 3 | # Modify this line to specify the user (default is root) 4 | user=root 5 | 6 | . /usr/share/cloudstack/cloudstack-common-functions 7 | sleep $[ 1 + $[ RANDOM % 10 ]] 8 | find_lease 9 | 10 | HOSTNAME=`grep host-name $LEASE_FILE | uniq | awk '{print $NF}' | tr -d '\;' | tr -d '"' | uniq` 11 | CLOUD_DIR=/var/lib/cloud/instances/$HOSTNAME 12 | USER_DATA=/var/lib/cloud/instances/$HOSTNAME/user-data 13 | LOCK=/var/lib/cloud/user-data.ran 14 | user_data_received=0 15 | file_count=0 16 | 17 | if [ -f $LOCK ] 18 | then 19 | logger -t "cloud" "User-Data appears to be executed once, skipping" 20 | exit 0 21 | fi 22 | 23 | if [ ! -d $CLOUD_DIR ] 24 | then 25 | mkdir -p $CLOUD_DIR 26 | fi 27 | 28 | 29 | USER_DATA_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 30 | if [ -n $USER_DATA_SERVER_IP ] 31 | then 32 | logger -t "cloud" "Sending request to USER-DATA server at $USER_DATA_SERVER_IP" 33 | wget -t 3 -T 20 -O $USER_DATA http://$USER_DATA_SERVER_IP/latest/user-data 2>/dev/null 34 | if [ $? -eq 0 ] 35 | then 36 | logger -t "cloud" "Got user-data from server at $USER_DATA_SERVER_IP" 37 | if [ -s $USER_DATA ]; then 38 | chmod 600 $USER_DATA 39 | user_data_received=1 40 | else 41 | logger -t "cloud" "User-data is empty" 42 | fi 43 | fi 44 | else 45 | logger -t "cloud" "Could not find user-data server IP in $LEASE_FILE" 46 | fi 47 | 48 | # did we get the user-data? 49 | if [ "$user_data_received" == "0" ] 50 | then 51 | logger -t "cloud" "Failed to get user-data from any server" 52 | exit 1 53 | fi 54 | 55 | # test/execute user-data 56 | if [ "$user_data_received" == "1" ] 57 | then 58 | line1=`head -1 $USER_DATA` 59 | echo $line1 | grep -q ^#! 60 | if [ $? -eq 0 ]; then 61 | if [ -f $LOCK ] 62 | then 63 | logger -t "cloud" "User-Data appears to be executed once, skipping" 64 | exit 0 65 | else 66 | grep -r $'\r' $USER_DATA 67 | if [ $? -ne 0 ]; then 68 | chmod 700 $USER_DATA 69 | $USER_DATA 70 | else 71 | sed -i -e 's/\r//g' $USER_DATA 72 | chmod 700 $USER_DATA 73 | $USER_DATA 74 | fi 75 | 76 | chmod 600 $USER_DATA 77 | echo 'do not delete' > $LOCK 78 | logger -t "cloud" "user-data executed" 79 | fi 80 | else 81 | logger -t "cloud" "user-data is not a executable script" 82 | fi 83 | fi 84 | exit 0 85 | -------------------------------------------------------------------------------- /templates/Generic/cloud-set-rhn-systemid: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for RHN SystemID Client 4 | # 5 | # chkconfig: 2345 98 02 6 | # description: RHN SystemID Client 7 | ### BEGIN INIT INFO 8 | # Provides: cloud-set-rhn-systemid 9 | # Required-Start: $sshd $network 10 | # Required-Stop: $sshd $network 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Sets rhn systemid 14 | # Description: Sets the rhn systemid in cloud.datapipe.com 15 | ### END INIT INFO 16 | 17 | 18 | # Add your DHCP lease folders here 19 | DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* /var/lib/NetworkManager/*" 20 | SYSTEM_ID_FILE="/etc/sysconfig/rhn/systemid" 21 | CCP_URL="https://cloud.datapipe.com/api/instance/license" 22 | data_received=0 23 | DIST=$(lsb_release -i | sed 's/\t//g' |awk -F':' '{print $2}') 24 | RELEASE=$(lsb_release -r | sed 's/\t//g' |awk -F':' '{print $2}') 25 | 26 | # Check for RHEL7 -- it uses a different registrsation method and does not keep info in a file. 27 | if [[ "$DIST" == RedHat* ]] && [[ "$RELEASE" == 7.* ]]; then 28 | system_id=$(subscription-manager identity |grep 'system identity:' |awk '{print $NF}') 29 | elif [ -f $SYSTEM_ID_FILE ]; then 30 | system_id=$(grep -A 1 'system_id' /etc/sysconfig/rhn/systemid | sed -n '/string/{s/.*//;s/<\/string.*//;p;}' | sed 's/ID-//') 31 | else 32 | logger -t "cloud" "Could not find system id file: $SYSTEM_ID_FILE" 33 | exit 1 34 | fi 35 | 36 | for DHCP_FILE in $DHCP_FOLDERS 37 | do 38 | if [ -f $DHCP_FILE ] 39 | then 40 | file_count=$((file_count+1)) 41 | DHCP_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 42 | 43 | if [ -n $DHCP_SERVER_IP ] 44 | then 45 | logger -t "cloud" "Sending request to dhcp server at $DHCP_SERVER_IP" 46 | 47 | instance_id=$(wget -t 3 -T 20 -O - http://$DHCP_SERVER_IP/latest/instance-id 2>/dev/null) 48 | region_name=$(wget -t 3 -T 20 -O - http://$DHCP_SERVER_IP/latest/availability-zone 2>/dev/null) 49 | 50 | if [ $? -eq 0 ] 51 | then 52 | logger -t "cloud" "Got response from server at $DHCP_SERVER_IP" 53 | data_received=1 54 | break 55 | fi 56 | else 57 | logger -t "cloud" "Could not find dhcp server IP in $DHCP_FILE" 58 | fi 59 | fi 60 | done 61 | 62 | # did we find the keys anywhere? 63 | if [ "$data_received" == "0" ] 64 | then 65 | logger -t "cloud" "Failed to get metadata from any server" 66 | exit 1 67 | fi 68 | response=$(curl -m 60 -d "instance_id=$instance_id®ion_name=$region_name&license_key=$system_id&license_name=RHEL" $CCP_URL) 69 | ret_val=$? 70 | logger -t "cloud" "Got response from $CCP_URL: $response" 71 | exit $ret_val 72 | 73 | 74 | -------------------------------------------------------------------------------- /templates/Generic/cloud-common-functions.j2: -------------------------------------------------------------------------------- 1 | #!env bash 2 | function find_lease() { 3 | 4 | # Determine primary network adapter name 5 | if [ $(uname) == "Linux" ]; then 6 | NIC=`ip link | grep state\ UP | grep -v LOOPBACK | awk -F':' '{print $2}' | tr -d ' '` 7 | elif [ $(uname) == "FreeBSD" ]; then 8 | NIC=`ifconfig | grep UP | grep -v LOOPBACK | awk -F':' '{print $1}' | tr -d ' '` 9 | fi 10 | 11 | # Add your DHCP lease folders here 12 | if [ -f /etc/debian_version ]; then 13 | # Ubuntu / Debian 14 | DHCP_FOLDERS="/var/lib/dhclient/ /var/lib/dhcp3/ /var/lib/dhcp/" 15 | elif [ -f /etc/redhat-release ]; then 16 | # Redhat / CentOS / Scientific Linux 17 | DHCP_FOLDERS="/var/lib/dhclient/ /var/lib/dhcp3/" 18 | elif [ -f /etc/freebsd-update.conf ]; then 19 | # FreeBSD 20 | DHCP_FOLDERS="/var/db/" 21 | else 22 | # Others 23 | DHCP_FOLDERS="/var/lib/dhclient/ /var/lib/dhcp3/" 24 | fi 25 | 26 | for TEST_DIRECTORY in $DHCP_FOLDERS; do 27 | if [ -d $TEST_DIRECTORY ]; then 28 | LEASE_DIRECTORY=$TEST_DIRECTORY 29 | fi 30 | done 31 | 32 | DHCLIENT=$(which dhclient) 33 | RESTART_DHCLIENT=true 34 | 35 | RUNNING_NETWORKMANAGER=$(ps aux | grep -v grep | grep sbin\/NetworkManager | wc -l) 36 | 37 | if [[ -z $RUNNING_NETWORKMANAGER || $RUNNING_NETWORKMANAGER -eq 0 ]]; then 38 | if [ -e $LEASE_DIRECTORY/*-*$NIC* ] || [ -e $LEASE_DIRECTORY/*.$NIC* ]; then 39 | LEASE_FILE=$(ls $LEASE_DIRECTORY*$NIC*) 40 | logger -t "cloud" "DHCP file ($LEASE_FILE) exists. No need to restart dhclient." 41 | RESTART_DHCLIENT=false 42 | fi 43 | 44 | if [ $RESTART_DHCLIENT = false ]; then 45 | LEASE_SIZE=$(wc -l $LEASE_FILE | awk {'print $1'}) 46 | if [ $LEASE_SIZE -eq 0 ]; then 47 | RESTART_DHCLIENT=true 48 | fi 49 | fi 50 | 51 | if [ $RESTART_DHCLIENT = true ]; then 52 | logger -t "cloud" "DHCP file does not exist. Restarting dhclient." 53 | DHCLIENT_PID=$(ps ax | grep dhclient | grep -v grep | uniq | awk {'print $1'}) 54 | if [ -n $DHCLIENT_PID ]; then 55 | for CLIENTPID in $DHCLIENT_PID; do 56 | kill $CLIENTPID 57 | rm -f /var/run/dhc* 58 | done 59 | fi 60 | $DHCLIENT -lf $LEASE_DIRECTORY/dhclient-$NIC.leases -pf /var/run/dhclient-$NIC.pid $NIC 61 | sleep 5 62 | find_lease 63 | fi 64 | fi 65 | 66 | if [[ -n $RUNNING_NETWORKMANAGER && $RUNNING_NETWORKMANAGER -ge 1 ]] ; then 67 | LEASE_FILE=$( ps -eo args | grep -v grep | grep dhclient | sed -e 's/\s\+/\n/g' | grep lease | uniq) 68 | 69 | fi 70 | 71 | # echo "Using DHCP lease from $LEASE_FILE" 72 | logger -t "cloud" "Using DHCP lease from $LEASE_FILE" 73 | export LEASE_FILE 74 | } 75 | -------------------------------------------------------------------------------- /templates/Ubuntu/cloud-set-guest-sshkey-ubuntu.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for SSH Public Keys Download Client 4 | # 5 | ### BEGIN INIT INFO 6 | # Provides: cloud-set-guest-sshkey 7 | # Required-Start: $local_fs $syslog $network 8 | # Required-Stop: $local_fs $syslog $network 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # Short-Description: SSH Public Keys Download Client 12 | ### END INIT INFO 13 | 14 | set -e 15 | 16 | . /lib/lsb/init-functions 17 | 18 | # Modify this line to specify the user (default is root) 19 | user=root 20 | 21 | . /usr/share/cloudstack/cloudstack-common-functions 22 | 23 | function cloud_set_guest_sshkey() { 24 | keys_received=0 25 | file_count=0 26 | sleep $[ 1 + $[ RANDOM % 10 ]] 27 | find_lease 28 | 29 | SSHKEY_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 30 | 31 | if [ -n $SSHKEY_SERVER_IP ]; then 32 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 33 | 34 | publickey=$(wget -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 35 | 36 | if [ $? -eq 0 ]; then 37 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 38 | keys_received=1 39 | fi 40 | else 41 | logger -t "cloud" "Could not find ssh key server IP in $LEASE_FILE" 42 | fi 43 | 44 | # did we find the keys anywhere? 45 | if [ "$keys_received" == "0" ]; then 46 | logger -t "cloud" "Failed to get ssh keys from any server" 47 | exit 1 48 | fi 49 | 50 | # set ssh public key 51 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 52 | sshdir=$homedir/.ssh 53 | authorized=$sshdir/authorized_keys 54 | 55 | 56 | if [ ! -e $sshdir ]; then 57 | mkdir $sshdir 58 | fi 59 | 60 | if [ ! -e $authorized ]; then 61 | touch $authorized 62 | fi 63 | 64 | #cat $authorized|grep -v "$publickey" > $authorized 65 | #echo "$publickey" >> $authorized 66 | #To support user copied ssh keys 67 | if [ `grep -c "$publickey" $authorized` == 0 ]; then 68 | echo "$publickey" >> $authorized 69 | fi 70 | } 71 | 72 | case "$1" in 73 | start) 74 | log_action_msg "Starting cloud" "cloud-set-guest-sshkey" 75 | sleep 10 76 | cloud_set_guest_sshkey 77 | if [ $? -eq 0 ]; then 78 | log_end_msg 0 79 | else 80 | log_end_msg 1 81 | fi 82 | ;; 83 | stop) 84 | log_action_msg "Stopping cloud" "cloud-set-guest-sshkey" 85 | log_end_msg 0 86 | ;; 87 | *) 88 | log_action_msg "Usage: /etc/init.d/cloud-set-guest-sshkey {start}" 89 | exit 1 90 | ;; 91 | esac 92 | 93 | exit 0 94 | 95 | -------------------------------------------------------------------------------- /templates/RHEL/cloud-set-guest-sshkey-rhel.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # cloud-set-guest-sshkey SSH Public Keys Download Client 4 | # 5 | # chkconfig: 2345 50 02 6 | # description: SSH Public Keys Download Client 7 | # 8 | # Modify this line to specify the user (default is root) 9 | user=root 10 | 11 | ### BEGIN INIT INFO 12 | # Provides: cloud-set-guest-sshkey 13 | # Required-Start: $local_fs $network $sshd 14 | # Required-Stop: $local_fs $syslog 15 | # Should-Start: $syslog 16 | # Should-Stop: $network $syslog 17 | # Default-Start: 2 3 4 5 18 | # Default-Stop: 0 1 6 19 | # Short-Description: 20 | # Description: SSH Public Keys Download Client 21 | ### END INIT INFO 22 | 23 | # Source function library. 24 | . /etc/rc.d/init.d/functions 25 | 26 | . /usr/share/cloudstack/cloudstack-common-functions 27 | 28 | 29 | function cloud_set_guest_sshkey() { 30 | keys_received=0 31 | file_count=0 32 | sleep $[ 1 + $[ RANDOM % 10 ]] 33 | find_lease 34 | 35 | SSHKEY_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 36 | 37 | if [ -n $SSHKEY_SERVER_IP ]; then 38 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 39 | 40 | publickey=$(wget -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 41 | 42 | if [ $? -eq 0 ]; then 43 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 44 | keys_received=1 45 | fi 46 | else 47 | logger -t "cloud" "Could not find ssh key server IP in $LEASE_FILE" 48 | fi 49 | 50 | 51 | # did we find the keys anywhere? 52 | if [ "$keys_received" == "0" ]; then 53 | logger -t "cloud" "Failed to get ssh keys from any server" 54 | exit 1 55 | fi 56 | 57 | # set ssh public key 58 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 59 | sshdir=$homedir/.ssh 60 | authorized=$sshdir/authorized_keys 61 | 62 | if [ ! -e $sshdir ]; then 63 | mkdir $sshdir 64 | fi 65 | 66 | if [ ! -e $authorized ]; then 67 | touch $authorized 68 | fi 69 | 70 | if [ `grep -c "$publickey" $authorized` == 0 ]; then 71 | echo "$publickey" >> $authorized 72 | /sbin/restorecon -R $homedir/.ssh 73 | fi 74 | } 75 | 76 | # See how we were called. 77 | case "$1" in 78 | start) 79 | action $"Starting cloud-set-guest-sshkey: " /bin/true 80 | cloud_set_guest_sshkey 81 | RETVAL=$? 82 | ;; 83 | stop) 84 | action $"Shutting down cloud-set-guest-sshkey: " /bin/true 85 | RETVAL=$? 86 | ;; 87 | restart) 88 | $0 stop 89 | $0 start 90 | ;; 91 | *) 92 | echo $"Usage: cloud-set-guest-sshey {start}" 93 | RETVAL=2 94 | ;; 95 | esac 96 | 97 | exit $RETVAL 98 | -------------------------------------------------------------------------------- /templates/Debian/cloud-set-guest-sshkey-debian.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for SSH Public Keys Download Client 4 | # 5 | ### BEGIN INIT INFO 6 | # Provides: cloud-set-guest-sshkey 7 | # Required-Start: $local_fs $syslog $network 8 | # Required-Stop: $local_fs $syslog $network 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # X-Start-Before: $sshd 12 | # Short-Description: SSH Public Keys Download Client 13 | ### END INIT INFO 14 | 15 | set -e 16 | 17 | . /lib/lsb/init-functions 18 | 19 | # Modify this line to specify the user (default is root) 20 | user=root 21 | 22 | . /usr/share/cloudstack/cloudstack-common-functions 23 | 24 | function cloud_set_guest_sshkey() { 25 | keys_received=0 26 | file_count=0 27 | sleep $[ 1 + $[ RANDOM % 10 ]] 28 | find_lease 29 | 30 | SSHKEY_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 31 | 32 | if [ -n $SSHKEY_SERVER_IP ]; then 33 | logger -t "cloud" "Sending request to ssh key server at $SSHKEY_SERVER_IP" 34 | 35 | publickey=$(wget -t 3 -T 20 -O - http://$SSHKEY_SERVER_IP/latest/public-keys 2>/dev/null) 36 | 37 | if [ $? -eq 0 ]; then 38 | logger -t "cloud" "Got response from server at $SSHKEY_SERVER_IP" 39 | keys_received=1 40 | fi 41 | else 42 | logger -t "cloud" "Could not find ssh key server IP in $LEASE_FILE" 43 | fi 44 | 45 | # did we find the keys anywhere? 46 | if [ "$keys_received" == "0" ]; then 47 | logger -t "cloud" "Failed to get ssh keys from any server" 48 | exit 1 49 | fi 50 | 51 | # set ssh public key 52 | homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}') 53 | sshdir=$homedir/.ssh 54 | authorized=$sshdir/authorized_keys 55 | 56 | 57 | if [ ! -e $sshdir ]; then 58 | mkdir $sshdir 59 | fi 60 | 61 | if [ ! -e $authorized ]; then 62 | touch $authorized 63 | fi 64 | 65 | #cat $authorized|grep -v "$publickey" > $authorized 66 | #echo "$publickey" >> $authorized 67 | #To support user copied ssh keys 68 | if [ `grep -c "$publickey" $authorized` == 0 ]; then 69 | echo "$publickey" >> $authorized 70 | fi 71 | } 72 | 73 | case "$1" in 74 | start) 75 | log_action_msg "Starting cloud" "cloud-set-guest-sshkey" 76 | sleep 10 77 | cloud_set_guest_sshkey 78 | if [ $? -eq 0 ]; then 79 | log_end_msg 0 80 | else 81 | log_end_msg 1 82 | fi 83 | ;; 84 | stop) 85 | log_action_msg "Stopping cloud" "cloud-set-guest-sshkey" 86 | log_end_msg 0 87 | ;; 88 | *) 89 | log_action_msg "Usage: /etc/init.d/cloud-set-guest-sshkey {start}" 90 | exit 1 91 | ;; 92 | esac 93 | 94 | exit 0 95 | 96 | -------------------------------------------------------------------------------- /templates/FreeBSD/cloud-set-guest-password-freebsd.j2: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | # FreeBSD 3 | # Modify this line to specify the user (default is root) 4 | user=root 5 | 6 | # Add your DHCP lease folders here 7 | WGET=/usr/local/bin/wget 8 | password_received=0 9 | file_count=0 10 | error_count=0 11 | 12 | . /usr/share/cloudstack/cloudstack-common-functions 13 | find_lease 14 | 15 | PASSWORD_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 16 | 17 | if [ -n $PASSWORD_SERVER_IP ] 18 | then 19 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $LEASE_FILE" 20 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 21 | password=$($WGET -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 22 | password=$(echo $password | tr -d '\r') 23 | 24 | if [ $? -eq 0 ] 25 | then 26 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 27 | 28 | case $password in 29 | 30 | "") logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 31 | # continue 32 | ;; 33 | 34 | "bad_request") logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 35 | error_count=$((error_count+1)) 36 | #continue 37 | ;; 38 | 39 | "saved_password") logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 40 | #continue 41 | ;; 42 | 43 | *) logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 44 | password_received=1 45 | break 46 | ;; 47 | 48 | esac 49 | else 50 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 51 | error_count=$((error_count+1)) 52 | fi 53 | else 54 | logger -t "cloud" "Could not find password server IP in $LEASE_FILE" 55 | error_count=$((error_count+1)) 56 | fi 57 | 58 | 59 | 60 | if [ "$password_received" == "0" ] 61 | then 62 | if [ "$error_count" == "$file_count" ] 63 | then 64 | logger -t "cloud" "Failed to get password from any server" 65 | exit 1 66 | else 67 | logger -t "cloud" "Did not need to change password." 68 | exit 0 69 | fi 70 | fi 71 | 72 | logger -t "cloud" "Changing password ..." 73 | echo $password | pw mod user $user -h 0 74 | 75 | if [ $? -gt 0 ] 76 | then 77 | logger -t "cloud" "Failed to change password for user $user" 78 | exit 1 79 | else 80 | logger -t "cloud" "Successfully changed password for user $user" 81 | fi 82 | 83 | logger -t "cloud" "Sending acknowledgment to password server at $PASSWORD_SERVER_IP" 84 | $WGET -t 3 -T 20 -O - --header "DomU_Request: saved_password" $PASSWORD_SERVER_IP:8080 85 | exit 0 86 | -------------------------------------------------------------------------------- /templates/Debian/firstboot-debian.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Flush all things not needed for a new VM and create default network environment 4 | # 5 | # chkconfig: 235 90 02 6 | # description: Prepare new VM 7 | ### BEGIN INIT INFO 8 | # Provides: firstboot-cloudstack 9 | # Required-Start: $network $local_fs $remote_fs $syslog $all 10 | # Required-Stop: $network $local_fs $remote_fs $syslog $all 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # X-Start-Before: $sshd 14 | # Short-Description: Prepare new VM 15 | # Description: Prepare new VM by flushing old information and preparing network environment 16 | ### END INIT INFO 17 | . /lib/lsb/init-functions 18 | 19 | . /usr/share/cloudstack/cloudstack-common-functions 20 | 21 | start_daemon () { 22 | echo "Initializing Virtual Machine..." 23 | logger -t "Setup" "Initializing Virtual Machine..." 24 | find_lease 25 | 26 | HOST_NAME=`grep host-name $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | tr -d '"' | uniq` 27 | echo $HOST_NAME > /etc/hostname 28 | echo "Setting hostname to $HOST_NAME" 29 | logger -t "Setup" "Setting hostname to $HOST_NAME" 30 | /bin/hostname $HOST_NAME 31 | 32 | echo "# Do not remove the following line, or various programs" > /etc/hosts 33 | echo "# that require network functionality will fail." >> /etc/hosts 34 | echo "127.0.0.1 localhost.localdomain localhost" >> /etc/hosts 35 | echo "# The following lines are desirable for IPv6 capable hosts" >> /etc/hosts 36 | echo "::1 ip6-localhost ip6-loopback" >> /etc/hosts 37 | echo "fe00::0 ip6-localnet" >> /etc/hosts 38 | echo "ff00::0 ip6-mcastprefix" >> /etc/hosts 39 | echo "ff02::1 ip6-allnodes" >> /etc/hosts 40 | echo "ff02::2 ip6-allrouters" >> /etc/hosts 41 | echo "::1 localhost6.localdomain6 localhost6" >> /etc/hosts 42 | IP=`grep fixed-address $LEASE_FILE | awk '{print $NF}' | tr -d '\;' | uniq` 43 | echo "$IP $HOST_NAME" >> /etc/hosts 44 | echo "Setting up /etc/hosts for IP address $IP" 45 | logger -t "Setup" "Setting up /etc/hosts for IP address $IP" 46 | 47 | test -f /etc/ssh/ssh_host_dsa_key || dpkg-reconfigure openssh-server 48 | 49 | /usr/sbin/update-rc.d cloudstack-firstboot disable 50 | /usr/sbin/update-rc.d cloudstack-firstboot remove 51 | if [ -f /lib/init/upstart-job ] 52 | then 53 | echo manual > /etc/init/cloudstack-firstboot.override 54 | fi 55 | 56 | } 57 | 58 | case "$1" in 59 | start) 60 | log_daemon_msg "Starting $NAME daemon" "$NAME" 61 | start_daemon 62 | log_end_msg 0 63 | ;; 64 | stop) 65 | log_daemon_msg "Stopping $NAME daemon" "$NAME" 66 | log_end_msg 0 67 | ;; 68 | restart) 69 | log_daemon_msg "Restarting $NAME daemon" "$NAME" 70 | log_end_msg 0 71 | ;; 72 | *) 73 | echo "Usage: /etc/init.d/$NAME {start|stop|restart}" 74 | exit 2 75 | ;; 76 | esac 77 | -------------------------------------------------------------------------------- /templates/RHEL/cloud-run-userdata-rhel.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for User-Data download and execution 4 | # 5 | # chkconfig: 345 99 02 6 | # description: User-Data Download Client 7 | ### BEGIN INIT INFO 8 | # Provides: cloud-userdata 9 | # Required-Start: $network $local_fs $remote_fs $syslog $all 10 | # Required-Stop: $network $local_fs $remote_fs $syslog $all 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Download and run Cloud userdata 14 | # Description: Downloads and executes any userdata specified when initializing the virtual machine. 15 | ### END INIT INFO 16 | 17 | # Modify this line to specify the user (default is root) 18 | user=root 19 | 20 | . /usr/share/cloudstack/cloudstack-common-functions 21 | sleep $[ 1 + $[ RANDOM % 10 ]] 22 | find_lease 23 | 24 | HOSTNAME=`grep host-name $LEASE_FILE | uniq | awk '{print $NF}' | tr -d '\;' | tr -d '"' | uniq` 25 | CLOUD_DIR=/var/lib/cloud/instances/$HOSTNAME 26 | USER_DATA=/var/lib/cloud/instances/$HOSTNAME/user-data 27 | LOCK=/var/lib/cloud/user-data.ran 28 | user_data_received=0 29 | file_count=0 30 | 31 | if [ -f $LOCK ] 32 | then 33 | logger -t "cloud" "User-Data appears to be executed once, skipping" 34 | exit 0 35 | fi 36 | 37 | if [ ! -d $CLOUD_DIR ] 38 | then 39 | mkdir -p $CLOUD_DIR 40 | fi 41 | 42 | 43 | USER_DATA_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 44 | if [ -n $USER_DATA_SERVER_IP ] 45 | then 46 | logger -t "cloud" "Sending request to USER-DATA server at $USER_DATA_SERVER_IP" 47 | wget -t 3 -T 20 -O $USER_DATA http://$USER_DATA_SERVER_IP/latest/user-data 2>/dev/null 48 | if [ $? -eq 0 ] 49 | then 50 | logger -t "cloud" "Got user-data from server at $USER_DATA_SERVER_IP" 51 | if [ -s $USER_DATA ]; then 52 | chmod 600 $USER_DATA 53 | user_data_received=1 54 | else 55 | logger -t "cloud" "User-data is empty" 56 | fi 57 | fi 58 | else 59 | logger -t "cloud" "Could not find user-data server IP in $LEASE_FILE" 60 | fi 61 | 62 | # did we get the user-data? 63 | if [ "$user_data_received" == "0" ] 64 | then 65 | logger -t "cloud" "Failed to get user-data from any server" 66 | exit 1 67 | fi 68 | 69 | # test/execute user-data 70 | if [ "$user_data_received" == "1" ] 71 | then 72 | line1=`head -1 $USER_DATA` 73 | echo $line1 | grep -q ^#! 74 | if [ $? -eq 0 ]; then 75 | if [ -f $LOCK ] 76 | then 77 | logger -t "cloud" "User-Data appears to be executed once, skipping" 78 | exit 0 79 | else 80 | grep -r $'\r' $USER_DATA 81 | if [ $? -ne 0 ]; then 82 | chmod 700 $USER_DATA 83 | $USER_DATA 84 | else 85 | sed -i -e 's/\r//g' $USER_DATA 86 | chmod 700 $USER_DATA 87 | $USER_DATA 88 | fi 89 | 90 | chmod 600 $USER_DATA 91 | echo 'do not delete' > $LOCK 92 | logger -t "cloud" "user-data executed" 93 | fi 94 | else 95 | logger -t "cloud" "user-data is not a executable script" 96 | fi 97 | fi 98 | exit 0 99 | -------------------------------------------------------------------------------- /templates/Generic/cloud-set-guest-password: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for Password Download Client 4 | # 5 | # chkconfig: 2345 98 02 6 | # description: Password Download Client 7 | ### BEGIN INIT INFO 8 | # Provides: cloud-set-guest-password 9 | # Required-Start: $sshd $network 10 | # Required-Stop: $sshd $network 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 0 1 6 13 | # Short-Description: Sets root password 14 | # Description: Sets the password for the root user based upon passwords stored by the CloudStack RouterVM 15 | ### END INIT INFO 16 | 17 | # Modify this line to specify the user (default is root) 18 | user=root 19 | 20 | sleep 10 21 | # Add your DHCP lease folders here 22 | DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* /var/lib/NetworkManager/*" 23 | password_received=0 24 | file_count=0 25 | error_count=0 26 | 27 | for DHCP_FILE in $DHCP_FOLDERS 28 | do 29 | if [ -f $DHCP_FILE ] 30 | then 31 | file_count=$((file_count+1)) 32 | PASSWORD_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 33 | 34 | if [ -n $PASSWORD_SERVER_IP ] 35 | then 36 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $DHCP_FILE" 37 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 38 | password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 39 | password=$(echo $password | tr -d '\r') 40 | 41 | if [ $? -eq 0 ] 42 | then 43 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 44 | 45 | case $password in 46 | 47 | "") logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 48 | continue 49 | ;; 50 | 51 | "bad_request") logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 52 | error_count=$((error_count+1)) 53 | continue 54 | ;; 55 | 56 | "saved_password") logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 57 | continue 58 | ;; 59 | 60 | *) logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 61 | password_received=1 62 | break 63 | ;; 64 | 65 | esac 66 | else 67 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 68 | error_count=$((error_count+1)) 69 | fi 70 | else 71 | logger -t "cloud" "Could not find password server IP in $DHCP_FILE" 72 | error_count=$((error_count+1)) 73 | fi 74 | fi 75 | done 76 | 77 | if [ "$password_received" == "0" ] 78 | then 79 | if [ "$error_count" == "$file_count" ] 80 | then 81 | logger -t "cloud" "Failed to get password from any server" 82 | exit 1 83 | else 84 | logger -t "cloud" "Did not need to change password." 85 | exit 0 86 | fi 87 | fi 88 | 89 | logger -t "cloud" "Changing password ..." 90 | #echo $password | passwd --stdin $user 91 | passwd $user </dev/null 49 | if [ $? -eq 0 ] 50 | then 51 | logger -t "cloud" "Got user-data from server at $USER_DATA_SERVER_IP" 52 | if [ -s $USER_DATA ]; then 53 | chmod 600 $USER_DATA 54 | user_data_received=1 55 | else 56 | logger -t "cloud" "User-data is empty" 57 | fi 58 | fi 59 | else 60 | logger -t "cloud" "Could not find user-data server IP in $LEASE_FILE" 61 | fi 62 | 63 | # did we get the user-data? 64 | if [ "$user_data_received" == "0" ] 65 | then 66 | logger -t "cloud" "Failed to get user-data from any server" 67 | exit 1 68 | fi 69 | 70 | # test/execute user-data 71 | if [ "$user_data_received" == "1" ] 72 | then 73 | line1=`head -1 $USER_DATA` 74 | echo $line1 | grep -q ^#! 75 | if [ $? -eq 0 ]; then 76 | if [ -f $LOCK ] 77 | then 78 | logger -t "cloud" "User-Data appears to be executed once, skipping" 79 | exit 0 80 | else 81 | grep -r $'\r' $USER_DATA 82 | if [ $? -ne 0 ]; then 83 | chmod 700 $USER_DATA 84 | $USER_DATA 85 | else 86 | sed -i -e 's/\r//g' $USER_DATA 87 | chmod 700 $USER_DATA 88 | $USER_DATA 89 | fi 90 | 91 | chmod 600 $USER_DATA 92 | echo 'do not delete' > $LOCK 93 | logger -t "cloud" "user-data executed" 94 | fi 95 | else 96 | logger -t "cloud" "user-data is not a executable script" 97 | fi 98 | fi 99 | } 100 | 101 | case "$1" in 102 | start) 103 | log_action_msg "Starting cloud" "cloud-run-userdata" 104 | sleep 10 105 | cloud_run_userdata 106 | if [ $? -eq 0 ]; then 107 | log_end_msg 0 108 | else 109 | log_end_msg 1 110 | fi 111 | ;; 112 | stop) 113 | log_action_msg "Stopping cloud" "cloud-run-userdata" 114 | log_end_msg 0 115 | ;; 116 | *) 117 | log_action_msg "Usage: /etc/init.d/cloud-run-userdata {start}" 118 | exit 1 119 | ;; 120 | esac 121 | exit 0 122 | -------------------------------------------------------------------------------- /Template.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | tasks: 4 | - name: setup packages for RHEL 5 | include: Template-Packages-RHEL.yml 6 | - name: setup packages for Debian/Ubuntu 7 | include: Template-Packages-Debian.yml 8 | - name: setup packages for SUSE 9 | include: Template-Packages-SUSE.yml 10 | - name: setup packages for FreeBSD 11 | include: Template-Packages-FreeBSD.yml 12 | 13 | - name: disable sysklogd (if present) 14 | service: name=syslog enabled=no 15 | ignore_errors: true 16 | - name: enable rsyslog (if not) 17 | when: ansible_os_family != "FreeBSD" 18 | service: name=rsyslog enabled=yes 19 | ignore_errors: true 20 | - name: enable rsyslog (if not) 21 | when: ansible_os_family == "FreeBSD" 22 | service: name=rsyslogd enabled=yes 23 | ignore_errors: true 24 | 25 | - name: remove cloud user 26 | user: name=cloud state=absent 27 | - name: set root password to "cloudstack" (in case init scripts fail) 28 | user: name=root update_password=always password=$6$hIuIfYHMi8Vd$QCoX.nOo551xKqhIPjdc/aUhtSTpKf3kR0q5MjXrwOgP5Iu9G.MVojQZfvdK2hPqimnY16htsgLktuYhUehNQ0 29 | 30 | - name: add CloudStack login splash (Ubuntu) 31 | template: src=templates/Generic/motd.j2 dest=/etc/motd.tail 32 | when: ansible_distribution == "Ubuntu" 33 | - name: add CloudStack login spash (Others) 34 | template: src=templates/Generic/motd.j2 dest=/etc/motd 35 | when: ansible_distribution != "Ubuntu" 36 | - name: create ssh directory 37 | file: state=directory mode=0700 path=/root/.ssh 38 | 39 | - name: create directory to store cloudstack client scripts 40 | file: state=directory mode=0755 path=/usr/share/cloudstack 41 | 42 | - name: register init system variables 43 | include: Template-Test-Init-System.yml 44 | 45 | - name: setup common functions for init scripts 46 | include: Template-Cloud-Functions.yml 47 | 48 | - name: setup cloudstack-set-guest-password 49 | include: Template-Cloud-Password.yml 50 | - name: setup cloudstack-set-guest-sshkey 51 | include: Template-Cloud-SSH-Key.yml 52 | - name: setup cloudstack-run-userdata 53 | include: Template-Cloud-Userdata.yml 54 | - name: setup cloudstack-firstboot 55 | include: Template-Cloud-Firstboot.yml 56 | 57 | - name: register upstart services 58 | when: upstart.stat.exists == true and systemd.stat.exists == false 59 | shell: initctl reload-configuration 60 | - name: register systemd services 61 | when: upstart.stat.exists == false and systemd.stat.exists == true 62 | shell: systemctl daemon-reload 63 | 64 | - name: enable cloudstack-password service 65 | service: name=cloudstack-set-guest-password enabled=yes 66 | - name: enable cloudstack-sshkey service 67 | service: name=cloudstack-set-guest-sshkey enabled=yes 68 | - name: enable cloudstack-userdata service 69 | service: name=cloudstack-run-userdata enabled=yes 70 | - name: enable firstboot-cloudstack service 71 | service: name=cloudstack-firstboot enabled=yes 72 | 73 | - name: setup networking 74 | include: Template-Networking.yml 75 | 76 | - name: remove upstart overrides (if present) 77 | file: path=/etc/init/firstboot-cloudstack.override state=absent 78 | - name: remove userdata lock (if present) 79 | file: path=/var/lib/cloud/user-data.ran state=absent 80 | - name: remove userdata history 81 | shell: rm -Rf /var/lib/cloud/instances/* 82 | - name: remove dhcp history 83 | shell: rm -f /var/lib/dhc*/dhcl*leas* 84 | - name: cleanup logs 85 | include: Template-Clean-Logs.yml 86 | - name: remove shell history 87 | shell: rm -f /root/.*history* 88 | - name: remove authorized keys 89 | file: path=/root/.ssh/authorized_keys state=absent 90 | - name: remove ssh keys 91 | shell: rm -f /etc/ssh/*host*key* -------------------------------------------------------------------------------- /templates/Debian/cloud-set-guest-password-debian.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for Password Download Client 4 | # 5 | ### BEGIN INIT INFO 6 | # Provides: cloud-set-guest-password 7 | # Required-Start: $local_fs $syslog $network 8 | # Required-Stop: $local_fs $syslog $network 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # X-Start-Before: $sshd 12 | # Short-Description: Init file for Password Download Client 13 | ### END INIT INFO 14 | 15 | set -e 16 | 17 | . /lib/lsb/init-functions 18 | 19 | # Modify this line to specify the user (default is root) 20 | user=root 21 | 22 | . /usr/share/cloudstack/cloudstack-common-functions 23 | 24 | function cloud_set_guest_password() { 25 | sleep $[ 1 + $[ RANDOM % 10 ]] 26 | find_lease 27 | password_received=0 28 | file_count=0 29 | error_count=0 30 | 31 | file_count=$((file_count+1)) 32 | PASSWORD_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 33 | 34 | if [ -n "$PASSWORD_SERVER_IP" ]; then 35 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $LEASE_FILE" 36 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 37 | password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 38 | password=$(echo $password | tr -d '\r') 39 | 40 | if [ $? -eq 0 ]; then 41 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 42 | 43 | case $password in 44 | "") 45 | logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 46 | ;; 47 | "bad_request") 48 | logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 49 | error_count=$((error_count+1)) 50 | ;; 51 | "saved_password") 52 | logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 53 | ;; 54 | *) 55 | logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 56 | password_received=1 57 | ;; 58 | esac 59 | else 60 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 61 | error_count=$((error_count+1)) 62 | fi 63 | else 64 | logger -t "cloud" "Could not find password server IP in $LEASE_FILE" 65 | error_count=$((error_count+1)) 66 | fi 67 | 68 | 69 | if [ "$password_received" == "0" ]; then 70 | if [ "$error_count" == "$file_count" ]; then 71 | logger -t "cloud" "Failed to get password from any server" 72 | exit 1 73 | else 74 | logger -t "cloud" "Did not need to change password." 75 | exit 0 76 | fi 77 | fi 78 | 79 | logger -t "cloud" "Changing password ..." 80 | 81 | if [ -x /usr/sbin/chpasswd ]; then 82 | echo "${user}:${password}" | chpasswd 83 | else 84 | echo $password | passwd --stdin $user 85 | if [ $? -gt 0 ]; then 86 | logger -t "cloud" "Failed to change password for user $user" 87 | exit 1 88 | else 89 | logger -t "cloud" "Successfully changed password for user $user" 90 | fi 91 | fi 92 | 93 | logger -t "cloud" "Sending acknowledgment to password server at $PASSWORD_SERVER_IP" 94 | wget -t 3 -T 20 -O - --header "DomU_Request: saved_password" $PASSWORD_SERVER_IP:8080 95 | } 96 | 97 | case "$1" in 98 | start) 99 | log_action_msg "Starting cloud" "cloud-set-guest-password" 100 | sleep 10 101 | cloud_set_guest_password 102 | if [ $? -eq 0 ]; then 103 | log_end_msg 0 104 | else 105 | log_end_msg 1 106 | fi 107 | ;; 108 | stop) 109 | log_action_msg "Stopping cloud" "cloud-set-guest-password" 110 | log_end_msg 0 111 | ;; 112 | *) 113 | log_action_msg "Usage: /etc/init.d/cloud-set-guest-password {start}" 114 | exit 1 115 | ;; 116 | esac 117 | 118 | exit 0 119 | 120 | -------------------------------------------------------------------------------- /templates/Ubuntu/cloud-set-guest-password-ubuntu.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Init file for Password Download Client 4 | # 5 | ### BEGIN INIT INFO 6 | # Provides: cloud-set-guest-password 7 | # Required-Start: $local_fs $syslog $network 8 | # Required-Stop: $local_fs $syslog $network 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # Short-Description: Init file for Password Download Client 12 | ### END INIT INFO 13 | 14 | set -e 15 | 16 | . /lib/lsb/init-functions 17 | 18 | # Modify this line to specify the user (default is root) 19 | user=root 20 | 21 | . /usr/share/cloudstack/cloudstack-common-functions 22 | 23 | function cloud_set_guest_password() { 24 | sleep $[ 1 + $[ RANDOM % 10 ]] 25 | find_lease 26 | password_received=0 27 | file_count=0 28 | error_count=0 29 | 30 | file_count=$((file_count+1)) 31 | PASSWORD_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 32 | 33 | if [ -n "$PASSWORD_SERVER_IP" ]; then 34 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $LEASE_FILE" 35 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 36 | password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 37 | password=$(echo $password | tr -d '\r') 38 | 39 | if [ $? -eq 0 ]; then 40 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 41 | 42 | case $password in 43 | "") 44 | logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 45 | ;; 46 | "bad_request") 47 | logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 48 | error_count=$((error_count+1)) 49 | ;; 50 | "saved_password") 51 | logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 52 | ;; 53 | *) 54 | logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 55 | password_received=1 56 | ;; 57 | esac 58 | else 59 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 60 | error_count=$((error_count+1)) 61 | fi 62 | else 63 | logger -t "cloud" "Could not find password server IP in $LEASE_FILE" 64 | error_count=$((error_count+1)) 65 | fi 66 | 67 | if [ "$password_received" == "0" ]; then 68 | if [ "$error_count" == "$file_count" ]; then 69 | logger -t "cloud" "Failed to get password from any server" 70 | exit 1 71 | else 72 | logger -t "cloud" "Did not need to change password." 73 | exit 0 74 | fi 75 | fi 76 | 77 | logger -t "cloud" "Changing password ..." 78 | 79 | if [ -x /usr/sbin/chpasswd ]; then 80 | echo "${user}:${password}" | chpasswd 81 | else 82 | echo $password | passwd --stdin $user 83 | if [ $? -gt 0 ]; then 84 | logger -t "cloud" "Failed to change password for user $user" 85 | exit 1 86 | else 87 | logger -t "cloud" "Successfully changed password for user $user" 88 | fi 89 | fi 90 | 91 | logger -t "cloud" "Sending acknowledgment to password server at $PASSWORD_SERVER_IP" 92 | wget -t 3 -T 20 -O - --header "DomU_Request: saved_password" $PASSWORD_SERVER_IP:8080 93 | } 94 | 95 | case "$1" in 96 | start) 97 | log_action_msg "Starting cloud" "cloud-set-guest-password" 98 | sleep 10 99 | cloud_set_guest_password 100 | if [ $? -eq 0 ]; then 101 | log_end_msg 0 102 | else 103 | log_end_msg 1 104 | fi 105 | ;; 106 | stop) 107 | log_action_msg "Stopping cloud" "cloud-set-guest-password" 108 | log_end_msg 0 109 | ;; 110 | *) 111 | log_action_msg "Usage: /etc/init.d/cloud-set-guest-password {start}" 112 | exit 1 113 | ;; 114 | esac 115 | 116 | exit 0 117 | 118 | -------------------------------------------------------------------------------- /templates/RHEL/cloud-set-guest-password-rhel.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # cloud-set-guest-password Init file for Password Download Client 4 | # 5 | # chkconfig: 2345 50 02 6 | # description: Init file for Password Download Client 7 | 8 | ### BEGIN INIT INFO 9 | # Provides: cloud-set-guest-password 10 | # Required-Start: $local_fs $network 11 | # Required-Stop: $local_fs $syslog 12 | # Should-Start: $syslog 13 | # Should-Stop: $network $syslog 14 | # Default-Start: 2 3 4 5 15 | # Default-Stop: 0 1 6 16 | # Short-Description: Init file for Password Download Client 17 | # Description: Init file for Password Download Client 18 | ### END INIT INFO 19 | 20 | # Source function library. 21 | . /etc/rc.d/init.d/functions 22 | 23 | # Modify this line to specify the user (default is root) 24 | user=root 25 | 26 | . /usr/share/cloudstack/cloudstack-common-functions 27 | 28 | function cloud_set_guest_password() { 29 | sleep $[ 1 + $[ RANDOM % 10 ]] 30 | find_lease 31 | password_received=0 32 | file_count=0 33 | error_count=0 34 | if [ -f $LEASE_FILE ]; then 35 | file_count=$((file_count+1)) 36 | PASSWORD_SERVER_IP=$(grep dhcp-server-identifier $LEASE_FILE | uniq | tail -1 | awk '{print $NF}' | tr -d '\;') 37 | 38 | if [ -n $PASSWORD_SERVER_IP ]; then 39 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $LEASE_FILE" 40 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 41 | password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 42 | password=$(echo $password | tr -d '\r') 43 | 44 | if [ $? -eq 0 ]; then 45 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 46 | 47 | case $password in 48 | 49 | "") logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 50 | ;; 51 | 52 | "bad_request") logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 53 | error_count=$((error_count+1)) 54 | ;; 55 | 56 | "saved_password") logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 57 | ;; 58 | 59 | *) logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 60 | password_received=1 61 | ;; 62 | 63 | esac 64 | else 65 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 66 | error_count=$((error_count+1)) 67 | fi 68 | else 69 | logger -t "cloud" "Could not find password server IP in $LEASE_FILE" 70 | error_count=$((error_count+1)) 71 | fi 72 | fi 73 | 74 | if [ "$password_received" == "0" ]; then 75 | if [ "$error_count" == "$file_count" ]; then 76 | logger -t "cloud" "Failed to get password from any server" 77 | exit 1 78 | else 79 | logger -t "cloud" "Did not need to change password." 80 | exit 0 81 | fi 82 | fi 83 | 84 | logger -t "cloud" "Changing password ..." 85 | echo $password | passwd --stdin $user 86 | 87 | if [ $? -gt 0 ]; then 88 | logger -t "cloud" "Failed to change password for user $user" 89 | fi 90 | 91 | logger -t "cloud" "Successfully changed password for user $user" 92 | logger -t "cloud" "Sending acknowledgment to password server at $PASSWORD_SERVER_IP" 93 | wget -t 3 -T 20 -O - --header "DomU_Request: saved_password" $PASSWORD_SERVER_IP:8080 94 | } 95 | 96 | # See how we were called. 97 | case "$1" in 98 | start) 99 | action $"Starting cloud-set-guest-password: " /bin/true 100 | cloud_set_guest_password 101 | RETVAL=$? 102 | ;; 103 | stop) 104 | action $"Shutting down cloud-set-guest-password: " /bin/true 105 | RETVAL=$? 106 | ;; 107 | restart) 108 | $0 stop 109 | $0 start 110 | ;; 111 | *) 112 | echo $"Usage: cloud-set-guest-sshey {start}" 113 | RETVAL=2 114 | ;; 115 | esac 116 | 117 | exit $RETVAL 118 | -------------------------------------------------------------------------------- /templates/Generic/cloud-get-userdata: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | sleep 5 3 | # 4 | # Init file for User-Data download and execution 5 | # 6 | # chkconfig: 345 99 02 7 | # description: User-Data Download Client 8 | # Modify this line to specify the user (default is root) 9 | user=root 10 | 11 | # Add your DHCP lease folders here 12 | if [ -f /etc/debian_version ]; then 13 | # Ubuntu 14 | DHCP_FOLDERS="/var/lib/dhcpcd/dhcpcd-eth0.*" 15 | elif [ -f /etc/redhat-release ]; then 16 | # Redhat / CentOS / Scientific Linux 17 | #DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/*" 18 | DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/* /var/lib/dhcp/* /var/lib/NetworkManager/*" 19 | else 20 | # Others 21 | DHCP_FOLDERS="/var/lib/dhclient/* /var/lib/dhcp3/*" 22 | fi 23 | 24 | # RHEL/CENTOS 7 use NetworkManager 25 | # Don't know how to verify NetworkManager is being used via output of "systemctl status NetworkManager" 26 | # So for now simply assuming it is being used. 27 | DIST=$(lsb_release -i | sed 's/\t//g' |awk -F':' '{print $2}') 28 | RELEASE=$(lsb_release -r | sed 's/\t//g' |awk -F':' '{print $2}') 29 | if [[ "$DIST" == RedHat*||CentOS* ]] && [[ "$RELEASE" == 7.* ]]; then 30 | HOSTNAME=$(tac /var/lib/NetworkManager/dhclient*eth0.lease | grep -m1 host-name | awk '{print $NF}' | tr -d '\;' | tr -d '"' | tail -1) 31 | else 32 | HOSTNAME=$(tac /var/lib/dhc*/dhclient?eth0.leases | grep -m1 host-name | awk '{print $NF}' | tr -d '\;' | tr -d '"' | tail -1) 33 | fi 34 | 35 | CLOUD_DIR=/var/lib/cloud/instances/$HOSTNAME 36 | USER_DATA=/var/lib/cloud/instances/$HOSTNAME/user-data 37 | LOCK=/var/lib/cloud/user-data.ran 38 | user_data_received=0 39 | file_count=0 40 | 41 | if [ -f "${LOCK}" ] 42 | then 43 | logger -t "cloud" "User-Data appears to be executed once, skipping" 44 | exit 0 45 | fi 46 | 47 | if [ ! -d "${CLOUD_DIR}" ] 48 | then 49 | mkdir -p "${CLOUD_DIR}" 50 | fi 51 | 52 | for DHCP_FILE in ${DHCP_FOLDERS} 53 | do 54 | if [ -f "${DHCP_FILE}" ] 55 | then 56 | file_count=$((file_count+1)) 57 | if [ -f /etc/debian_version ]; then 58 | # Ubuntu 59 | #USER_DATA_SERVER_IP=$(grep DHCPSID $DHCP_FILE | tail -1 | egrep -o '([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})' ) 60 | USER_DATA_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 61 | elif [ -f /etc/redhat-release ]; then 62 | # Redhat / CentOS / Scientific Linux 63 | USER_DATA_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 64 | else 65 | # Others 66 | USER_DATA_SERVER_IP=$(grep dhcp-server-identifier $DHCP_FILE | tail -1 | awk '{print $NF}' | tr -d '\;') 67 | fi 68 | 69 | if [ -n "${USER_DATA_SERVER_IP}" ] 70 | then 71 | logger -t "cloud" "Sending request to USER-DATA server at ${USER_DATA_SERVER_IP}" 72 | wget -t 3 -T 20 -O "${USER_DATA}" http://"${USER_DATA_SERVER_IP}"/latest/user-data 2>/dev/null 73 | if [ $? -eq 0 ] 74 | then 75 | logger -t "cloud" "Got user-data from server at ${USER_DATA_SERVER_IP}" 76 | if [ -s "${USER_DATA}" ]; then 77 | chmod 600 "${USER_DATA}" 78 | user_data_received=1 79 | else 80 | logger -t "cloud" "User-data is empty" 81 | fi 82 | break 83 | fi 84 | else 85 | logger -t "cloud" "Could not find user-data server IP in ${DHCP_FILE}" 86 | fi 87 | fi 88 | done 89 | # did we get the user-data? 90 | if [ "${user_data_received}" == "0" ] 91 | then 92 | logger -t "cloud" "Failed to get user-data from any server" 93 | exit 1 94 | fi 95 | 96 | # test/execute user-data 97 | if [ "${user_data_received}" == "1" ] 98 | then 99 | line1=$(head -1 "${USER_DATA}") 100 | echo "${line1}" | grep -q ^#! 101 | if [ $? -eq 0 ]; then 102 | if [ -f "${LOCK}" ] 103 | then 104 | logger -t "cloud" "User-Data appears to be executed once, skipping" 105 | exit 0 106 | else 107 | grep -r $'\r' "${USER_DATA}" 108 | if [ $? -ne 0 ]; then 109 | chmod 700 "${USER_DATA}" 110 | "${USER_DATA}" 111 | else 112 | sed -i -e 's/\r//g' "${USER_DATA}" 113 | chmod 700 "${USER_DATA}" 114 | "${USER_DATA}" 115 | fi 116 | 117 | chmod 600 "${USER_DATA}" 118 | echo 'do not delete' > "${LOCK}" 119 | logger -t "cloud" "user-data executed" 120 | fi 121 | else 122 | logger -t "cloud" "user-data is not a executable script" 123 | fi 124 | fi 125 | exit 0 126 | -------------------------------------------------------------------------------- /templates/SLES/cloud-set-guest-password-sles.j2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (c) 2013 Apache CloudStack 3 | # 4 | # Author: Apache CloudStack 5 | # 6 | # /etc/init.d/cloud-set-guest-password 7 | # 8 | # Init file for Password Download Client 9 | # 10 | ### BEGIN INIT INFO 11 | # Provides: cloud-set-guest-password 12 | # Required-Start: $network $local_fs $syslog 13 | # Required-Stop: $network $local_fs $syslog 14 | # Default-Start: 3 5 15 | # Default-Stop: 0 1 2 6 16 | # Short-Description: Password Download Client 17 | # Description: CloudStack Password Download Client 18 | ### END INIT INFO 19 | 20 | . /etc/rc.status 21 | 22 | # First reset status of this service 23 | rc_reset 24 | 25 | # Modify this line to specify the user (default is root) 26 | user=root 27 | 28 | # Add your DHCP lease folders here 29 | DHCP_FOLDERS="/var/lib/dhcpcd/*" 30 | password_received=0 31 | file_count=0 32 | error_count=0 33 | 34 | case "$1" in 35 | start) 36 | echo -n "Starting cloud-guest-set-password" 37 | for DHCP_FILE in $DHCP_FOLDERS; do 38 | if [ -f $DHCP_FILE ]; then 39 | file_count=$((file_count+1)) 40 | . /$DHCP_FILE 41 | 42 | PASSWORD_SERVER_IP=$DHCPSIADDR 43 | 44 | if [ -n $PASSWORD_SERVER_IP ]; then 45 | logger -t "cloud" "Found password server IP $PASSWORD_SERVER_IP in $DHCP_FILE" 46 | logger -t "cloud" "Sending request to password server at $PASSWORD_SERVER_IP" 47 | password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" $PASSWORD_SERVER_IP:8080) 48 | password=$(echo $password | tr -d '\r') 49 | 50 | if [ $? -eq 0 ]; then 51 | logger -t "cloud" "Got response from server at $PASSWORD_SERVER_IP" 52 | 53 | case $password in 54 | 55 | "") logger -t "cloud" "Password server at $PASSWORD_SERVER_IP did not have any password for the VM" 56 | continue 57 | ;; 58 | 59 | "bad_request") logger -t "cloud" "VM sent an invalid request to password server at $PASSWORD_SERVER_IP" 60 | error_count=$((error_count+1)) 61 | continue 62 | ;; 63 | 64 | "saved_password") logger -t "cloud" "VM has already saved a password from the password server at $PASSWORD_SERVER_IP" 65 | continue 66 | ;; 67 | 68 | *) logger -t "cloud" "VM got a valid password from server at $PASSWORD_SERVER_IP" 69 | password_received=1 70 | break 71 | ;; 72 | 73 | esac 74 | else 75 | logger -t "cloud" "Failed to send request to password server at $PASSWORD_SERVER_IP" 76 | error_count=$((error_count+1)) 77 | fi 78 | else 79 | logger -t "cloud" "Could not find password server IP in $DHCP_FILE" 80 | error_count=$((error_count+1)) 81 | fi 82 | fi 83 | done 84 | 85 | if [ "$password_received" == "0" ]; then 86 | if [ "$error_count" == "$file_count" ]; then 87 | logger -t "cloud" "Failed to get password from any server" 88 | exit 1 89 | else 90 | logger -t "cloud" "Did not need to change password." 91 | exit 0 92 | fi 93 | fi 94 | 95 | logger -t "cloud" "Changing password ..." 96 | echo $password | passwd --stdin $user 97 | 98 | if [ $? -gt 0 ]; then 99 | usermod -p `mkpasswd -m SHA-512 $password` $user 100 | 101 | if [ $? -gt 0 ]; then 102 | logger -t "cloud" "Failed to change password for user $user" 103 | exit 1 104 | else 105 | logger -t "cloud" "Successfully changed password for user $user" 106 | fi 107 | fi 108 | 109 | logger -t "cloud" "Sending acknowledgment to password server at $PASSWORD_SERVER_IP" 110 | wget -t 3 -T 20 -O - --header "DomU_Request: saved_password" $PASSWORD_SERVER_IP:8080 111 | # Remember status and be verbose 112 | rc_status -v 113 | ;; 114 | stop) 115 | echo -n "Shutting down cloud-set-guest-password" 116 | rc_status -v 117 | ;; 118 | esac 119 | 120 | rc_exit 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | --------------------------------------------------------------------------------