.. Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information#
   regarding copyright ownership.  The ASF licenses this file
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
   with the License.  You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.


Cloud-init integration
-------------------------

Cloudstack and cloud-init integration provide Instances with advanced management features such as:

*  Password management
*  SSH keys management
*  Partition management
*  User-data input
*  `Other modules <https://cloudinit.readthedocs.io/en/latest/topics/modules.html>`_  



Examples for relevant features are listed for different distributions.

~~~~~~~~~~~~~~~~~~~~~~

Linux with Cloud-init
----------------------

These features can be implemented in `“Linux Template creation process” <_create_linux.html#creating-a-linux-template>`_. where they are executed just before the **Template cleanup** step.

#. **Install and configure cloud-init**

   Install cloud-init and mentioned auxiliary packages.

   ~  CentOS
   
    .. code:: bash

	 yum install -y cloud-init wget
   
   ~  Ubuntu
   
    .. code:: bash

     apt-get install -y cloud-init wget
	 
   Configure cloud-init to detect Cloudstack data source during runtime.
	
   Cloud-init data sources can be specified in /etc/cloud/cloud.cfg.d/ directory. Add the following config in /etc/cloud/cloud.cfg.d/99_cloudstack.cfg.
   
    .. code:: bash

     datasource_list: [ ConfigDrive, CloudStack, None ]
     datasource:
       CloudStack: {}
       None: {}

   .. note::
      For the vm instances running on VMware or XenServer/XCP-ng hypervisors, if there are multiple cloud-init data sources, it is a known issue that ds-identify is not able to detect if "CloudStack" DataSource is enabled. To fix the problem, please run the following command to enable cloud-init without any aid from ds-identify.

        .. code:: bash

          echo "policy: enabled" >  /etc/cloud/ds-identify.cfg
	   
#. **Password management**

   Cloudstack integration with cloud-init `set-passwords module <https://cloudinit.readthedocs.io/en/latest/topics/modules.html?highlight=ssh_pwauth#set-passwords>`_ will enable the platform to set a password for each Instance created from the Main Template. Additionally it will allow to reset the user password through the GUI.
   
   - **Enable set_passwords module on every boot**
   
     By default the set-passwords module runs only on first boot of the Instance, change that to run on every boot.
   
     .. code:: bash
   
      sudo sed -i s/" - set[_|-]passwords"/" - [set_passwords, always]"/g /etc/cloud/cloud.cfg
	
   - **Specify the managed user**
   
     Cloudstack will create the user, set a password and reset it when requested. To do that set the following configuration in /etc/cloud/cloud.cfg.d/80_user.cfg
		
     .. code:: bash

      system_info:
        default_user:
          name: cloud-user	               
          lock_passwd: false	          # disable user password login - true/false
          sudo: [\"ALL=(ALL) ALL\"] 	  # User permissions
      disable_root: 0	                  # root remote login is 0 - enabled, 1 - disabled
      ssh_pwauth: 1	                      # password login is 0 - disabled, 1- enabled

#. **SSH keys management**

   Cloud-init `ssh module <https://cloudinit.readthedocs.io/en/latest/topics/modules.html#ssh>`_ can automatically install new SSH keys when set or reset from Cloudstack GUI.
   By default the module runs once during Instance creation and will fetch Cloudstack keys without any additional configuration.
   To enable Cloudstack reset SSH keys feature configure cloud-init ssh module to run on every boot.
   
   .. code:: bash
   
    sudo sed -i s/" - ssh$"/" - [ssh, always]"/g /etc/cloud/cloud.cfg
    
=======
	
   .. warning::
    
    If the cloud-init ssh module is set to run every boot, it will regenerate the certificate fingerprint of the host. This will cause a warning to anyone that logs in the system and also bring trouble to anyone trying to automate ssh access.
	
   Disable cloud-init regenerating host certificates on boot. If Template certificates are deleted they will be regenerated by the OS on instnace first boot.
	
    .. code:: bash
	
     echo "ssh_deletekeys: false" > /etc/cloud/cloud.cfg.d/49_hostkeys.cfg

   Note that if this instance is moved or snapshotted, it will be vulnerable to man-in-the-middle attacks if the behavior is not re-enabled first.
	 
#. **Partition management**
	
   Cloud-init can detect and resize one or more existing partitions automatically after reboot. This guide will cover root partition and volume.
   First install the `Growpart module <https://cloudinit.readthedocs.io/en/latest/topics/modules.html#growpart>`_ as it is not shipped with cloud-init.
   
   ~ Centos 
	
    .. code:: bash
	  
     yum install cloud-utils-growpart -y
	
   ~ Ubuntu 
	
    .. code:: bash
	  
     apt-get install cloud-initramfs-growroot -y
	  
   - **Detect and extend MBR partitions**
      
     Locate the root partition.
	 
     .. note::
	 
      Root partition can differ per OS type, version and partition setup.
	  
     .. code:: bash
	 
      [root@localhost ~]# lvs 
      LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert 
      root centos -wi-ao---- <17.00g 
      swap centos -wi-ao----   2.00g 
      [root@localhost ~]# vgs 
      VG     #PV #LV #SN Attr   VSize   VFree 
      centos   1   2   0 wz--n- <19.00g    0 
      [root@localhost ~]# pvs 
      PV         VG     Fmt  Attr PSize   PFree 
      /dev/xvda2 centos lvm2 a--  <19.00g    0 
  
     On the current setup root is on /dev/xvda2 partition. Define the configuration below in /etc/cloud/cloud.cfg.d/50_growpartion.cfg
	  
     .. code:: bash
	
      growpart:
        mode: auto
        devices:
          - \"/dev/xvda2\"
        ignore_growroot_disabled: false
	  
     Now on every boot growpart will check and extend /dev/xvda2 if there is change in size.
	   
   - **Extend Physical volume, Volume group and root lvm**
   
     After partition is extended the upper layers should also be resized. This can be automated with cloud-init `runcmd module <https://cloudinit.readthedocs.io/en/latest/topics/modules.html?highlight=runcmd#runcmd>`_ . Set the configuration below in /etc/cloud/cloud.cfg.d/51_extend_volume.cfg.
	
     ~ CentOS
	 	 
      Centos 7 root volume is /dev/centos/root if no changes are done during installation. Change the value accordingly if setup is different.
	   
      .. code:: bash
	  
       runcmd:
         - [ cloud-init-per, always, grow_VG, pvresize, /dev/xvda2 ]
         - [ cloud-init-per, always, grow_LV, lvresize, -l, '+100%FREE', /dev/centos/root ]
         - [ cloud-init-per, always, grow_FS, xfs_growfs, /dev/centos/root ]
	  
     ~ Ubuntu
	 
      Ubuntu 20 root volume is /dev/ubuntu-vg/ubuntu-lv if no changes are done during installation. Change the value accordingly if setup is different.
	   
      .. code:: bash
	  
       runcmd:
         - [ cloud-init-per, always, grow_VG, pvresize, /dev/xvda3 ]
         - [ cloud-init-per, always, grow_LV, lvresize, -l, '+100%FREE', /dev/ubuntu-vg/ubuntu-lv ]
         - [ cloud-init-per, always, grow_FS, xfs_growfs, /dev/ubuntu-vg/ubuntu-lv ]
	
     .. warning::
	  
      The example code above is based on XFS parition type. If ext4 partitioning is utilized replace **xfs_growfs** with **resize2fs** in the last code line.
      It is possible to also use cloud-init `resize2fs module <https://cloudinit.readthedocs.io/en/latest/topics/modules.html#resizefs>`_ .
	
   - **Enable autoresize on every boot**
	
     By default cloud-init **runcmd** module executes defined commands on first boot only.
     Commands will run on every boot only if both **runcmd** and **user-scripts** modules are configured to run on every boot.
	 
     .. code:: bash

      sudo sed -i s/" - runcmd"/" - [runcmd, always]"/g /etc/cloud/cloud.cfg
      sudo sed -i s/" - scripts-user"/" - [scripts-user, always]"/g /etc/cloud/cloud.cfg

#. **User-data**

   Cloud-init can parse and execute user-data form Cloud-stack during Instance creation. This feature works as is without additional configuration.
	 
#. **Cleanup**

   Once desired cloud-init features are implemented, clean cloud-init tracker files.
   
     .. code:: bash
	 
	  cloud-init clean
	  
   Or do it manually.

     .. code:: bash
	 
	  rm -rf /var/lib/cloud/*
	  
   If **Password management** feature is used clean /etc/sudoers from any cloud-init user setups.
	 
     .. code:: bash
	 
	  rm -rf /etc/sudoers.d/*
	  
#. **Finalize Template**

   Proceed with `“Linux Template creation process” <_create_linux.html>`_ continuing with **Template cleanup** step.