Provisioning Libvirt virtual machines with LinchPin
=================================================

LinchPin can be used to provision Libvirt VMs.  If you need to familiarize yourself with Libvirt, `read this`_. Now let's step through the process of creating a new workspace for provisioning Libvirt

.. _read this: https://libvirt.org/docs.html

.. include:: templates/fetch.rst

.. include:: templates/initialization.rst

Creating a Topology
-------------------

Now that we have a PinFile, its time to add the code for a Libvirt VM.  Edit your PinFile so it looks like the one below.

.. code:: yaml

    simple:
      topology:
        topology_name: simple
        resource_groups:
          - resource_group_name: libvirt_simple
            resource_group_type: libvirt
            resource_definitions:
              - name: simple_vm
                role: libvirt_node
                vcpus: 1 
                memory: 2048
                count: 1

There are a number of other fields available for these two roles.  Information about those fields as well as the other Libvirt roles can be found on the `Libvirt provider page`_.

A :term:`resource group` is a group of resources related to a single provider.  In this example we have a Libvirt resource group that defines two different types of Libvirt resources.  We could also define an AWS resource group below it that provisions a handful of EC2 nodes.  A single resource group can contain many :term:`resource definitions`. A resource definition details the requirements for a specific resource.  We could add another resource definition to this topology to create a network for our Libvirt VMs.  Multiple resources can be provisioned from a single resource definition by editing the :code:`count` field, but all non-unique properties of the resources will be identical.  So the amount of memory will remain the same but each node will have a unique name. The name will be {{ name }}_0, {{ name }}_1, etc. from 0 to count.

.. _Libvirt provider page: ../libvirt.rst

Customizing a Machine Image
```````````````````````````

:term:`virt-customize` or :term:`cloud-init` can be used to customize a machine image before provisioning.  This can be used to, for example, configure a login user before provisioning.

.. node:: A resource definition can use virt-customize or cloud-init for customization, but not both.

Below is an example of virt-customize and cloud-init

.. code:: yaml

    cloud_config:
      virt_type: cloud-init
      users:
        - name: test
          gecos: test
          groups: wheel
          sudo: ALL=(ALL) NOPASSWD:ALL
        - name: someuser
          gecos: someuser
          groups: wheel
          sudo: ALL=(ALL) NOPASSWD:ALL

.. code:: yaml

    cloud_config:
      virt_type: virt-customize
      root_password: "testrootpwd" # insecure plaintext password
      run_script: "/home/srallaba/workspace/lp_ws/virt_customize/test.sh"
      first_boot_commands: 
        - "echo \"this is created by the linchpin first_boot_commands\" >> first_boot_commands.txt"
      users:
        - name: test
          gecos: test
          groups: wheel
        - name: testuser2
          groups: wheel
          password: $1$ZA8hoL7w$eZexnQWoXTZajtfKGYy4f.  # encrypted password for "TestPWD"
        - name: someotheruser
          groups: wheel
          inject_ssh_keys: true  # by default linchpin generated libvirt key is injected.
        - name: srallaba
          groups: wheel
          inject_ssh_keys: true  # by default linchpin generated libvirt key is injected.
      packages:
        - gcc
        - openssh-server
      run_commands:
        - "echo \"hello world\""
        - "echo \"This is a file generated by run_commands parameters\" > /tmp/run_commands.txt"

Credentials
-----------

Finally, we need to add credentials to the resource group.

.. include:: ../credentials/libvirt.rst

.. include:: templates/layout.rst

.. include:: templates/up.rst

.. include:: templates/destroy.rst

.. include:: templates/journal.rst
