Automate Infrastructure Lifecycle Management On PCA Using Ansible
Automate Infrastructure Lifecycle Management On PCA Using Ansible
Automate Infrastructure Lifecycle Management On PCA Using Ansible
Introduction 1
Prerequisites 2
Architecture 3
Playbook Execution 7
Create a VM 8
Delete a VM 11
Start a VM 14
start 14
Stop a VM 16
stop 16
Authentication 19
Conclusion 28
Resources 28
Introduction
Oracle Private Cloud Appliance is an Engineered System designed for rapid and turn-key deployment
of private cloud at an industry-leading price point. The agile and intelligent infrastructure allows for
scaling compute capacity on demand, zero downtime upgrades and supports your choice of external
storage. Whether running Linux, Microsoft Windows or Oracle Solaris applications, Oracle Private
Cloud Appliance supports a wide range of mixed workloads in medium-to-large sized data centers.
High-performance, low-latency Oracle Fabric Interconnect and Oracle SDN allow automated
configuration of the server and storage networks. The embedded controller software automates the
installation, configuration, and management of all infrastructure components.
Automation is a key requirement for achieving cloud-like agility. Ansible is an IT automation engine that
automates cloud provisioning, configuration management, application deployment and orchestration.
Ansible uses no agents and can be used to automate repetitive IT tasks in multi-node deployments. A
machine that has Ansible installed (‘Control Machine’) pushes code blocks (‘Ansible modules’) to the
remote machines (‘Managed nodes’) and executes them over SSH. This paper describes the process
to use the custom Ansible module ‘ovmm_vm.py’ to automate creation, deletion, halting and starting a
Virtual Machine in Oracle PCA.
The module interfaces with the REST APIs for Oracle VM and hence, can be even used in an Oracle
VM environment outside of a PCA.
/usr/lib/python2.7/site-packages/pca/plugins/ovmm_vm.py
/usr/lib/python2.7/site-packages/pca/plugins/ovmm_vm.pyc
/usr/lib/python2.7/site-packages/pca/plugins/ovmm_vm.pyo
/usr/share/doc/pca_ansible_examples-1.0
/usr/share/doc/pca_ansible_examples-1.0/COPYING
/usr/share/doc/pca_ansible_examples-1.0/Copyright
/usr/share/pca_ansible_examples/examples
/usr/share/pca_ansible_examples/examples/deletevm.yml
/usr/share/pca_ansible_examples/examples/play.yml
/usr/share/pca_ansible_examples/examples/startvm.yml
/usr/share/pca_ansible_examples/examples/stopvm.yml
Ansible checks for the custom module in the /library subdirectory of the directory where your playbook is
stored. Thus, in the above directory structure, you can place the ovmm_vm.py file in directory
/usr/share/pca_ansible_examples/examples/library/
Note: For the purpose of simplifying the directory paths in this paper, we will place the playbooks in the
Ansible directory ( /etc/ansible) and the module in the library subdirectory of the Ansible directory (here
etc/ansible/library) on Control Machine.
Control Machine
/etc/ansible
Play.yml , deletevm.yml, startvm.yml, stopvm.yml
Library
ovmm_vm.py
The automation jobs are described in YAML language. Playbooks, written in YAML, are used to manage
configurations and deployment to remote systems.
Playbooks contain plays which map remote hosts to tasks. A task is nothing more than a call to a Module. Modules
are task plugins that do the actual work on a remote host.
Figure 1 shows a sample playbook that has only one play to be executed on remote host ‘bastion’ as remote user
root. The task is to make sure httpd service is started on bastion host. This task calls the ‘service’ module and
declares the desired state as ‘started’ for service httpd.
Handlers are special tasks that are carried out if the preceding task was successful i.e. it made a change in state of
the remote host. Thus, in this case the handler “restart httpd” would only be called if httpd service had to be started
on bastion host by the task ‘make sure httpd is statrted’. In other words, if httpd was already running on bastion (i.e
task ‘make sure httpd is running’ didn’t make any change to the remote host bastion), the handler would not have
been executed.
Architecture
Figure 2 shows an Ansible Control Machine components and also the architecture of Oracle VM Manager located
on the Management node of PCA. Ansible manages the PCA by connecting to the REST APIs for Oracle VM
Manager (accessible by HTTPS over port 7002 as shown in figure). The detailed architecture for Oracle VM can be
found here.
Control Machine: An Oracle Linux 7 system external to the PCA on which Ansible is installed serves as the
Control Machine. Ansible package is available via the ol7_developer_EPEL Channel.
Managed Nodes: The remote systems that Ansible manages remotely. In our case, the managed nodes would
be the PCA management nodes. The location of managed nodes (Host names or IP address) is defined in
Inventory File. The default inventory file is etc/ansible/hosts on the control machine.
Note: The ovm_user and ovm_pass are required for basic HTTP Authentication. They are not required if you
set up SSL Certificate verification for Oracle VM as discussed in Appendix I. In this case, (required=False)
needs to be set for both ovm_user and ovm_pass in order to not supply
The ‘ovmm_vm’ module can be used for automating the following operations on a PCA.
» Creating a Virtual Machine
» Deleting a Virtual Machine
» Starting a Virtual Machine
» Stopping a Virtual Machine
Argument ‘state’ can take 4 values: Present, absent, start, stop. Each value represents the desired final state of
the VM. The value of argument ‘state’ determines the desired action.
» State=present means that the specified VM should exist on the PCA after execution of the module.
Thus, if it is already present, Ansible returns the ID of the existing VM without making any change to the
remote system. If the specified VM doesn’t exist, it is created with the specified configuration
» State=absent means the VM will be deleted if it exists on the PCA. This deletes the VM disk mapping,
VM disk and VNICs along with the Virtual Machine.
» State=start would start the specified VM, would do nothing if the VM doesn’t exist or is already running
The custom module and the Ansible playbook that uses the module need to be placed on the Ansible control
machine. For custom modules, Ansible will look in the library directory relative to the playbook, for
example: playbooks/library/your-module.
Figure 4 shows the relative location of playbook play.yml and Ansible module ovmm_vm.py on the Control
Machine.
Figure 4. Playbooks are located at /etc/ansible and custom modules are in /etc/ansible/library
Each of the tasks described in module ovmm_vm.py can be carried out by either making a call to the module from
Ansible command line (Ad-hoc command) or using Ansible Playbook. Both methods are discussed in the
following sections.
Figure 5 shows the Oracle VM Manager GUI for PCA. We have 2 VMs on Server Pool SP1, named ‘ST_vm1’ in
Stopped state and ‘testvm’ in the Running state. Let’s automate the lifecycle management tasks that can be
performed using the custom Ansible module ovmm_vm.py
Playbook Execution
Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you
want your remote systems to enforce, or a set of steps in a general IT process. Playbooks are written in YAML
format. The syntax for running a playbook is:
Note: Ansible uses the default inventory file located at /etc/ansible/hosts if flag –i is not specified while executing the
playbook.
Examples of executing the module ovmm_vm.py using playbook are shown in the following section.
Figure 6. Playbook play.yml showing the task ‘Create a VM’ on remote host ovm
Case 1:
Specified VM doesn’t exist on PCA, Desired State: present
In this case, as the specified VM doesn’t exist on PCA, we expect the module to create it on the specified server
pool and repository on PCA and display a changed=True message. Figure 7 shows this execution on the VM
‘ST_vm33’ and Ansible returns a message saying “VM created” and “changed=True”.
The fact that the VM ‘ST_vm33’ is created on the remote host can be seen in Figure .
In this case, as the specified VM exists on PCA, we expect the module to not make any changes on PCA and
display a changed=False message. Figure 9 shows the playbook play.yml used for this case. Figure 10 shows this
execution on the VM ‘ST_vm1’ and Ansible returns a message saying “VM exists” and “changed=False”.
Figure 9. Playbook play.yml with state=present when the VM already exists on the remote host
If the specified VM already exists on PCA, Ansible makes no change to the remote system and returns the ID of the
already existing VM with same name. In this case, the specified VM ‘ST_vm1’ exists and has ID
‘0004fb0000060000c16ea2401e5b80f4’
Figure 10. Execution of Playbook play.yml with state=present when the VM already exists on the remote host
Figure 11. Playbook deletevm.yml showing the task ‘Delete a VM’ on remote host ovm
Note: The module ovmm_vm.py carried out the deletion of a VM by calling the deleteVM function (defined in
ovmm_vm.py). This function deletes the VM disk mapping, virtual disk and the Virtual machine from the PCA as
shown in Figure 13.
Case 1:
Specified VM is running on PCA, Desired State: absent
In this case, the VM ‘testvm’ exists and is running on the PCA, so Ansible should kill it and then delete it on the
remote system and show a changed=True message to show that VM is deleted.
Figure 11 shows the playbook deletevm.yml used for this case. The VM “testvm” is present on the remote host
“ovm” and should be deleted after execution of this playbook. The state=absent
When this playbook is executed, we expect Ansible to change the state of remote host ‘ovm’ by deleting the
specified VM ‘testvm’.
Figure 12 shows the result of execution of this playbook. The output of the execution clearly shows that task ‘Delete
a Virtual Machine’ changed the state of remote host ovm. The test output shows “changed=True” and has a
message “VM deleted”.
The fact that the VM ‘testvm’ has actually been deleted can be verified by looking at the Oracle VM Manager GUI as
shown in Figure 13.
Figure 13. The VM ‘testvm’ is deleted as seen in the Oracle VM Manager GUI
In this case, the VM ‘myvm’ doesn’t exist on the PCA, so Ansible should not make any change to the remote system
and should exit gracefully.
Figure 14 shows the playbook deletevm.yml used for this case. This playbook contains one play called “test my
module” to be executed on the remote host ovm (specified in the /etc/ansible/hosts file). The playbook has 2 tasks –
Delete a VM and dump test output.
Figure 14. Playbook play.yml showing two tasks to be executed on remote host ‘ovm’
When this playbook is executed, we expect Ansible to not make any change on the remote system ‘ovm’ as the
specified VM ‘myvm’ doesn’t exist. In other words, the remote host ‘ovm’ is already in the desired state.
Figure 15 shows the result of execution of this playbook. The output of the execution clearly shows that nothing was
changed on the remote host and our module returns a message “VM doesn’t exist”
Figure 15. Execution of Playbook play.yml when the remote host is already in desired state
Figure 16. Playbook startvm.yml showing the task ‘Start a VM’ on remote host ovm
Case:
Specified VM exists on PCA and is in stopped condition, Desired State: start
In this case, as the specified VM is stopped, we expect the module to start it on the PCA and display a
changed=True message. Figure 17 shows this execution on the VM ‘ST_vm33’ and Ansible returns a message
saying “VM started” and “changed=True”.
The fact that the VM ‘ST_vm33’ has actually been started can be verified by looking at the Oracle VM Manager GUI
as shown in Figure 18.
Figure 18. The VM ‘ST_vm33’ can be seen running in the Oracle VM Manager GUI
The playbook used for this task ‘stopvm.yml’ is shown in Figure 19.
Figure 19. Playbook stopvm.yml showing task “Stop a VM’ to be executed on host ovm
Case:
Specified VM exists on PCA and is in stopped condition, Desired State: stop
In this case, as the specified VM is already stopped, we expect the module to not change anything on the PCA. This
property of Ansible is referred to as Idempotency. Figure 20 shows this execution on the VM ‘ST_vm1’ and Ansible
returns a message saying “VM is already stopped” as expected.
In this case, if the VM ‘ST_vm1’ was in the Running state prior to execution of the playbook, Ansible would have
stopped the VM and displayed “changed: True and VM stopped” message.
Idempotency
The custom module ‘ovmm_vm.py’ is Idempotent i.e. running the module multiple times has no side effects. In other
words, an operation is idempotent if the result of performing it once is exactly the same as the result of performing it
repeatedly without any intervening actions.
To illustrate this concept, we can use the same playbook as shown in Figure 10. The playbook specifies that the VM
‘testvm’ should be absent from the target host ovm. Running the playbook once, deleted the specified VM from the
target host. This means that the VM ‘testvm’ doesn’t exist anymore and running this playbook now should not make
any change to the remote host ‘ovm’.
Figure 21 shows that when we run the playbook play.yml again, the task “Delete a Virtual Machine” doesn’t change
anything on the remote host. We can also see from the test output that Ansible returns “changed=False” and the
message says “VM doesn’t exist” as expected.
This playbook can now be run any number of times without making any change to the remote host. This is an
important property of Ansible, which allows the user to only specify the desired state of the remote host without
having to worry about the current state.
Requests: HTTP library for python. Installed using $ yum install python-requests
urllib3: HTTP client of python used by Requests to keep sessions alive and HTTP connection pooling. Installed
using $ yum install python-urllib3
We import the Requests Python library to take care of our HTTP request processing using REST. The auth function
returns a REST session by passing the username and password credentials for Oracle VM for basic authentication.
It is possible to have certificate based SSL Authentication as described in the next section ‘Authentication’.
Authentication
HTTP Basic Authentication: Basic authentication is the simplest means of authenticating REST calls to OVM
ws-api using REST; simply provide the user name and password used to log into the Oracle VM Manager
(admin by default). This is simple solution, but weak security since it will send clear text password when you
make a REST call.
SSL Certificate Authentication: It is possible to use a signed SSL certificate to authenticate against Oracle
VM Manager via the REST API. To do this, you must have the certificate and key stored in a single PEM file
available to your application. The Requests library allows you to send a certificate with each request, or to set it
to be used for every request within a session:
session.cert='/path/to/mycertificate.pem
As long as the certificate is valid and can be authenticated by Oracle VM Manager, the session is automatically
logged in using your certificate.
Note: In the above figure, you can see that Certificate based authentication has been enabled to set up a HTTPS
requests to the REST API. Thus, you don’t need the ovm_user and ovm_pass parameters to authenticate and
hence, the line session.auth = (ovm_user, ovm_pass) has been commented.
By default, Oracle VM Manager generates and signs an SSL certificate that is valid for ten years from the date of
installation. You can use the genssl command to generate a new SSL certificate that is signed by the Oracle VM
Manager internal CA.
Here’s how you can generate a new SSL key for the VIP of PCA:
Log onto the Master Management node of PCA as oracle user and navigate to the directory where
ovmkeytool.sh is located.
Note that the command prompts you to provide the values for various steps through the procedure as the new
SSL certificate is generated. Notably, you must enter a valid fully qualified domain name for the server. This
value is used for the hostname in the SSL certificate and must match the hostname that is used to access the
Oracle VM Manager web-based user interface.
Restart the ovca service and wait for 3-5 minutes to make sure everything is running
Use the check command to verify the current CA and SSL configuration. If any issues exist with the
configuration, the command displays information to help you resolve them.
The following is an example of the check command:
Figure 25. Running ovmkeytool.sh to check whether OVM CA and SSL configuration are correct
We can see that the Oracle VM Manager Certificate Authority and SSL configuration have been correctly configured.
Now, this certificate can be used for SSL verification of the REST session.
The process below is the same for Oracle VM 3.3 and 3.4.
First create a key and certificate locally using the OpenSSL tool available on the Oracle VM management server.
The mykey.pem file shown in the example below is an important file that is used in a later step to create the
certificate you will use in your code; it must not have a passphrase. The first two lines below create this important
file. It takes two steps because specifying -des3 (des3 is higher security) on the first line requires at least a four
character passphrase; give it any passphrase that comes to mind because the second line below removes the
passphrase.
This step adds the certification key created in Step 1 to the Oracle VM Manager permanently. It also gets a key that
is returned from Oracle VM Manager and writes it to one of our temporary files.
import json
import requests
from requests.packages.urllib3 import disable_warnings
from requests.packages.urllib3.exceptions import InsecureRequestWarning
s=requests.Session()
s.verify=False
s.auth=('admin','Welcome1')
s.headers.update({'Accept': 'application/json', 'Content-Type': 'application/json'})
disable_warnings()
cert=open('mycert.pem').read()
body={'certificate': cert}
r=s.post('https://<mymanager.fqdn>:7002/ovm/core/wsapi/rest/Utilities/Certificate?sign=True',
data=json.dumps(body))
Once you have created a certificate, you can use the REST API to sign it (python, using requests module ).
The main function takes arguments from the user (provided as YAML playbook). Above figure shows that the
baseUri in our examples is https://<ovm_manager_host>:7002/ovm/core/wsapi/rest.
Note: Once SSL verification has been set up as shown in the previous steps, we no longer need to supply clear text
ovm_user and ovm_password. In this case, we can make (required=False) for ovm_user and ovm_pass
parameters. In that case, you don’t need to supply these as arguments in the playbook.
If the VM with the name specified by the user doesn’t exist on the target host, the createVM function is called. It
takes the restsession, modeule and the baseUri described above as arguments.
First, the ID for repository and server pool on the PCA where the VM needs to be created, is obtained by calling the
get_id_from_name function. The VM Data provided by the user as input YAML file is then passed as JSON input to
the POST request to uri https://<ovm_manager_host>:7002/ovm/core/wsapi/rest/Vm
Figure 28. ‘get_id_from_name’ function (above) and ‘CreateVM’ function of the ovmm_vm.py module
The vm_id variable is obtained by calling the wait_for_job function, which returns the ID of the job once it is
successfully completed or an error if the job run failed.
The user specifies the details for Virtual Disks to be attached to the newly created VM in the form of a
parameter ‘disks’ via the playbook.
The data type for ‘disks’ is list and Ansible expects the input to be in the form of a list of lists as shown in
playbook in Figure 6.
The function then loops over the list, creating each virtual disk of required name, size and on the specified
repository. This is done by sending a POST request to uri3 as shown in Figure above.
o The request path contains the repository ID of the repo where the Virtual Disk needs to be created.
o The request body contains the ‘name’ and ‘size’ as required inputs
o The parameter ‘sparse’ should be passed as a query parameter. Set it to True to create a Sparse
disk image.
After creating each disk, Oracle VM also needs to create a VM Disk Mapping to represent the association of
Virtual Disk and VM. Thus, for each virtual disk, a Disk Mapping is created by sending a POST request to uri4
as shown in above figure.
o The request path contains the VM ID of the VM to which the Virtual NICs needs to be associated.
o The request body contains the ‘virtualDiskId’ and ‘diskTarget’ as required inputs. VirtualDiskId is
obtained after the Oracle VM finishes creating a disk in last step. diskTarget maps the slot on the VM
to which the VirtualDisk should be attached.
The user specifies the names of the networks on which the VirtualNics for the VM need to be created as a
parameter ‘networks’ in the playbook. The data type for ‘networks’ is list and Ansible expects the input to be in
If you need 2 VNICs on the same network, specify the network name twice as shown in Figure 6.
The function then loops over the list, creating virtual NICs on each specified network by sending a POST
request to uri2 as shown in Figure above.
o The request path contains the VM ID to which the VNIC needs to be associated.
The module exits with a message “VM created” if the execution was successful and returns an error otherwise.
The module ‘ovmm_vm.py’ can be used to rapidly deploy a minimal server Virtual Machine on PCA. Ansible
Playbooks for deploying Oracle Databases and applications can be used in conjunction with this module to rapidly
deploy a VM with specified software in minutes on a PCA.
Resources
Oracle VM REST API guide
Ansible documentation
Sample code is provided for educational purposes or to assist your development or administration efforts. Your use rights
and restrictions for each sample code item are described in the applicable license agreement. Except as may be expressly
stated in the applicable license agreement or product documentation, sample code is provided "as is" and is not supported
by Oracle.
CONNECT W ITH US
blogs.oracle.com/oracle
Copyright © 2018, Oracle and/or its affiliates. All rights reserved. This document is provided for information purposes only, and the
contents hereof are subject to change without notice. This document is not warranted to be error-free, nor subject to any other
facebook.com/oracle warranties or conditions, whether expressed orally or implied in law, including implied warranties and conditions of merchantability or
fitness for a particular purpose. We specifically disclaim any liability with respect to this document, and no contractual obligations are
formed either directly or indirectly by this document. This document may not be reproduced or transmitted in any form or by any means,
twitter.com/oracle
electronic or mechanical, for any purpose, without our prior written permission.
oracle.com Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.
Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and
are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are
trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group. 0918