Friday, May 22, 2020

vRA8 Blueprint: Linux with Python

Most of my posts, up to this point are referencing Python scripts.  In my original post, I reference the vRealize Automation 8 (vRA8) blueprint I use for my build environment.  I thought is might better to isolate the environment build in a separate write-up.  

If you're familiar with vRA, you know the basis of a VM deployment is a blueprint and probably a template.  You can do a lot within an automation deployment.  The one below is just a small example but gives me a workstation that any of my current scripts can be built and executed.   I'll explain each section further below.  If you have vRA8 deployed or using our SaaS vRA-Cloud, you can copy the YAML and use it to build a blueprint.


name: Flask-Jinja2
version: 1
formatVersion: 1
inputs:
  VmName:
    type: string
    description: Will also be the hostname of the FQDN.
    title: VM Name
  ImageSelect:
    type: string
    description: The operating system version to use.
    title: Operating System
    oneOf:
      - title: CentOS Linux 7
        const: CentOS7
      - title: CentOS Linux 8 (Core)
        const: CentOS8
      - title: Debian Linux 10 (Buster)
        const: debian10
      - title: Ubuntu 18.04.4 LTS
        const: Ubuntu18
      - title: Ubuntu 19.10
        const: Ubuntu19
  CPU:
    type: integer
    enum:
      - 4
      - 2
      - 1
    description: Requested vCPU Count
    default: 1
    title: Requested vCPU Count
    minimum: 1
    maximum: 4
  Mem:
    type: integer
    description: Requested Mem (GB)
    title: Requested Mem (GB)
    minimum: 1
    maximum: 8
    default: 2
    enum:
      - 8
      - 7
      - 6
      - 5
      - 4
      - 3
      - 2
      - 1
  username:
    type: string
    title: Username
    default: testUser
    description: Create a user during deployment
  password:
    type: string
    title: Password
    default: VMware1\!
    encrypted: true
    description: Password for the given username
resources:
  Cloud_vSphere_Machine_1:
    type: Cloud.vSphere.Machine
    properties:
      image: '${input.ImageSelect}'
      newName: '${input.VmName}'
      cpuCount: '${input.CPU}'
      totalMemoryMB: '${input.Mem*1024}'
      cloudConfig: |
        #cloudconfig
        hostname: ${input.VmName}
        fqdn: ${input.VmName}.thewhiteshouse.net
        repo_update: true
        repo_upgrade: all
        package_update: true
        package_upgrade: true
        ssh_pwauth: yes
        disable_root: false
        chpasswd:
          list: |
            ${input.username}:${input.password}
          expire: false
        users:
          - default
          - name: ${input.username}
            lock_passwd: false
            sudo: ['ALL=(ALL) NOPASSWD:ALL']
            groups: [wheel, sudo, admin]
            shell: '/bin/bash'
        packages:
         - python3
         - python3-pip
        runcmd:
         - echo "Defaults:${input.username}  !requiretty" >> /etc/sudoers.d/${input.username}
         - echo root:VMware1\!|sudo chpasswd
         - history -c
         - systemctl stop firewalld
         - systemctl disable firewalld
         - sudo pip3 install flask
         - sudo pip3 install jinja2
         - sudo pip3 install requests
         - sudo pip3 install ConfigParser
         - sudo ln -s /usr/bin/python3 /usr/bin/python


I'll breakdown each section of the YAML starting with "inputs".  Inputs give us the flexibility of variables within a blueprint.  I'm making use of six inputs: VmName, ImageSelect, CPU, Mem, username and password.  When the blueprint is deployed, the requestor will have the ability to specify each of these 6 varialbles.  

VmName:  It's obvious we are naming the VM.  What often get's overlooked during a deployment is the hostname.  To get inside the VM and assign the hostname, we have a couple of options.  I'll leave the bulk of that explanation outside of this post.  One can use the configuration specifications in vCenter to pass the VM name to the hostname.  We can also use Cloud-Init.  I'll write more about the naming process and cloud-init later in this blog.  

ImageSelect:  This input allows a user to select from a list of options.  The "title" is displayed to the user while "const" holds the name of the template vRA8 is configured to use.

CPU:  We are controlling the number of virtual CPU a user can request.  I'm showing a max of 4 and allowing users to select only 1, 2 or 4 vCPU.

Mem:  Just like CPU, we are controlling how much memory a user can request from 1GB to 8GB.

UserName and Password:  The requestor can have the username automatically created with a password assigned during the deployment

inputs:
  VmName:
    type: string
    description: Will also be the hostname of the FQDN.
    title: VM Name
  ImageSelect:
    type: string
    description: The operating system version to use.
    title: Operating System
    oneOf:
      - title: CentOS Linux 7
        const: CentOS7
      - title: CentOS Linux 8 (Core)
        const: CentOS8
      - title: Debian Linux 10 (Buster)
        const: debian10
      - title: Ubuntu 18.04.4 LTS
        const: Ubuntu18
      - title: Ubuntu 19.10
        const: Ubuntu19
  CPU:
    type: integer
    enum:
      - 4
      - 2
      - 1
    description: Requested vCPU Count
    default: 1
    title: Requested vCPU Count
    minimum: 1
    maximum: 4
  Mem:
    type: integer
    description: Requested Mem (GB)
    title: Requested Mem (GB)
    minimum: 1
    maximum: 8
    default: 2
    enum:
      - 8
      - 7
      - 6
      - 5
      - 4
      - 3
      - 2
      - 1
  username:
    type: string
    title: Username
    default: testUser
    description: Create a user during deployment
  password:
    type: string
    title: Password
    default: VMware1\!
    encrypted: true
    description: Password for the given username


In the next section, "Resources" we set the parameters for the virtual machine.   For the "type" I'm specifying "Cloud.vSphere.Machine" which tells vRA we are using a vSphere virtual machine.  After that, we declare the properties for the VM.  Under "Properties" we are going to use our inputs specified during the deployment.  For the properties section, we only have 5 categories in this blueprint:

image:  The selected OS image to deploy.  Prior to any work in vRA, I build a Linux VM with a minimal install, no GUI.  After the installation is complete, I install ssh, cloud-init, open-vm-tools and Perl.  I then shutdown and convert the VM to a template.  For the Linux distribution, if possible I usually download the network ISO for the VM build.  FYI - At the time of this writing, cloud-init and custom specs do not work together within a vRA blueprint.  If you are using custom specs in your blueprints, you will need to ensure Perl and VM Tools are installed on your image.

newName:  The newName variable is assigned the value we received from the requestor.  This will assign the name to VM.  We'll have another process in the cloudConfig section to get inside the VM to assign the hostname.  Follow the instructions on this blog: Create Custom Names with vrealize automation 8, to understand how to create an implement the necessary vRA8 action to make this newName assignment.

cpuCount:  The number of vCPU the requestor specified

totalMemoryMB:  The default unit is Megabytes.  The requestor is asking for Gigabytes of memory.  Here we take the requested amount and multiply by 1024 to convert to Megabytes.

cloudConfig:  There is a lot of things Cloud Init can do.  Essentially, we are setting the hostname and FQDN for the VM being requested.  We are performing an update to the distribution, configuring SSH, creating the specified user with the password the requestor entered.  The user will also be added to the sudoer list and assigned to the appropriate groups.  We are also setting the root password and clearing any history (previous commands).  The package section tells cloud init to retrieve Python2 and Python3 and install them.  Once those are installed, we install some Python3 modules via pip3 that are necessary for the scripts I've created.  Finally, a link is created so that python3 is executed when the command python is issued.  I disable the firewall on the VM.  You may choose to modify that depending on your needs.  

resources:
  Cloud_vSphere_Machine_1:
    type: Cloud.vSphere.Machine
    properties:
      image: '${input.ImageSelect}'
      newName: '${input.VmName}'
      cpuCount: '${input.CPU}'
      totalMemoryMB: '${input.Mem*1024}'
      cloudConfig: |
        #cloudconfig
        hostname: ${input.VmName}
        fqdn: ${input.VmName}.thewhiteshouse.net
        repo_update: true
        repo_upgrade: all
        package_update: true
        package_upgrade: true
        ssh_pwauth: yes
        disable_root: false
        chpasswd:
          list: |
            ${input.username}:${input.password}
          expire: false
        users:
          - default
          - name: ${input.username}
            lock_passwd: false
            sudo: ['ALL=(ALL) NOPASSWD:ALL']
            groups: [wheel, sudo, admin]
            shell: '/bin/bash'
        packages:
         - python3
         - python3-pip
        runcmd:
         - echo "Defaults:${input.username}  !requiretty" >> /etc/sudoers.d/${input.username}
         - echo root:VMware1\!|sudo chpasswd
         - history -c
         - systemctl stop firewalld
         - systemctl disable firewalld
         - sudo pip3 install flask
         - sudo pip3 install jinja2
         - sudo pip3 install requests
         - sudo pip3 install ConfigParser
         - sudo ln -s /usr/bin/python3 /usr/bin/python

Thanks for checking out this blog.

No comments:

Post a Comment