8 min read

OpenStack is a software that can help us build a system similar to popular cloud providers, such as AWS or GCP. OpenStack provides an API and a dashboard to manage the resources that it controls. Basic operations, such as creating and managing virtual machines, block storage, object storage, identity management, and so on, are supported out of the box.

This is an excerpt from Ansible 2 Cloud Automation Cookbook written by Aditya Patawari, Vikas Aggarwal. No matter the Cloud Platform you are using this book will help you orchestrate your cloud infrastructure. 

In the case of OpenStack, we control the underlying hardware and network, which comes with its own pros and cons. In this article we will leverage Ansible 2 to automate not so common networking tasks in OpenStack.

We can use custom network solutions. We can use economical equipment or high-end devices, depending upon the actual need. This can help us get the features that we want and may end up saving money.

Caution: Although OpenStack can be hosted on premises, several cloud providers provide OpenStack as a service. Sometimes these cloud providers may choose to turn off certain features or provide add-on features. Sometimes, even while configuring OpenStack on a self-hosted environment, we may choose to toggle certain features or configure a few things differently. Therefore, inconsistencies may occur. All the code examples in this article are tested on a self-hosted OpenStack released in August 2017, named Pike. The underlying operating system was CentOS 7.4.

Managing security groups

Security groups are the firewalls that can be used to allow or disallow the flow of traffic. They can be applied to virtual machines. Security groups and virtual machines have a many-to-many relationship. A single security group can be applied to multiple virtual machines and a single virtual machine can have multiple security groups.

How to do it…

  1. Let’s create a security group as follows:
- name: create a security group for web servers
    name: web-sg
    state: present
    description: security group for web servers

The name parameter has to be unique. The description parameter is optional, but we recommend using it to state the purpose of the security group. The preceding task will create a security group for us, but there are no rules attached to it. A firewall without any rules is of little use. So let’s go ahead and add a rule to allow access to port 80 as follows:

- name: allow port 80 for http
    security_group: web-sg
    protocol: tcp
    port_range_min: 80
    port_range_max: 80
  1. We also need SSH access to this server, so we should allow port 22 as well:
- name: allow port 80 for SSH
    security_group: web-sg
    protocol: tcp
    port_range_min: 22
    port_range_max: 22

How it works…

For this module, we need to specify the name of the security group. The rule that we are creating will be associated with this group. We have to supply the protocol and the port range information. If we just want to whitelist only one port, then that would be the upper and lower bound of the range. Lastly, we have to specify the allowed addresses in the form of CIDR. The address signifies that port 80 is open for everyone. This task will add an ingress type rule and allow traffic on port 80 to reach the instance. Similarly, we have to add a rule to allow traffic on port 22 as well.

Managing network resources

A network is a basic building block of the infrastructure. Most of the cloud providers will supply a sample or default network. While setting up a self-hosted OpenStack instance, a single network is typically created automatically. However, if the network is not created, or if we want to create another network for the purpose of isolation or compliance, we can do so using the os_network module.

How to do it…

  1. Let’s go ahead and create an isolated network and name it private, as follows:
- name: creating a private network
    state: present
    name: private
  1. In the preceding example, we created a logical network with no subnets. A network with no subnets is of little use, so the next step would be to create a subnet:
- name: creating a private subnet
    state: present
    network_name: private
    name: app
      - destination:
      - destination:

How it works…

The preceding task will create a subnet named app in the network called private. We have also supplied a CIDR for the subnet, We are using Google DNS for nameservers as an example here, but this information should be obtained from the IT department of the organization. Similarly, we have set up the example host routes, but this information should be obtained from the IT department as well.

After successful execution of this recipe, our network is ready to use.

User management

OpenStack provides an elaborate user management mechanism. If we are coming from a typical third-party cloud provider, such as AWS or GCP, then it can look overwhelming. The following list explains the building blocks of user management:

  • Domain: This is a collection of projects and users that define an administrative entity. Typically, they can represent a company or a customer account. For a self-hosted setup, this could be done on the basis of departments or environments. A user with administrative privileges on the domain can further create projects, groups, and users.
  • Group: A group is a collection of users owned by a domain. We can add and remove privileges from a group and our changes will be applied to all the users within the group.
  • Project: A project creates a virtual isolation for resources and objects. This can be done to separate departments and environments as well.
  • Role: This is a collection of privileges that can be applied to groups or users.
  • User: A user can be a person or a virtual entity, such as a program, that accesses OpenStack services.

For a complete documentation of the user management components, go through the OpenStack Identity document at https://docs.openstack.org/keystone/pike/admin/identity-concepts.html.

 How to do it…

Let’s go ahead and start creating some of these basic building blocks of user management. We should note that, most likely, a default version of these building blocks will already be present in most of the setups:

  1. We’ll start with a domain called demodomain, as follows:
- name: creating a demo domain
     name: demodomain
     description: Demo Domain
     state: present
     register: demo_domain
  1. After we get the domain, let’s create a role, as follows:
- name: creating a demo role
    state: present
    name: demorole
  1. Projects can be created, as follows:
- name: creating a demo project
    state: present
    name: demoproject
    description: Demo Project
    domain_id: "{{ demo_domain.id }}"
    enabled: True
  1. Once we have a role and a project, we can create a group, as follows:
- name: creating a demo group
    state: present
    name: demogroup
    description: "Demo Group"
    domain_id: "{{ demo_domain.id }}"
  1. Let’s create our first user:
- name: creating a demo user
    name: demouser
    password: secret-pass
    update_password: on_create
    email: [email protected]
    domain: "{{ demo_domain.id }}"
    state: present
  1. Now we have a user and a group. Let’s add the user to the group that we created before:
- name: adding user to the group 
    user: demouser
    group: demogroup
  1. We can also associate a user or a group with a role:
- name: adding role to the group
    group: demo2
    role: demorole
    domain: "{{ demo_domain.id }}"

How it works…

In step 1, the os_keystone_domain would take a name as a mandatory parameter. We also supplied a description for our convenience. We are going to use the details of this domain, so we saved it in a variable called demo_domain.

In step 2, the os_keystone_role would just take a name and create a role. Note that a role is not tied up with a domain.

In step 3, the os_project module would require a name. We have added the description for our convenience. The projects are tied to a domain, so we have used the demo_domain variable that we registered in a previous task.

In step 4, the groups are tied to domains as well. So, along with the name, we would specify the description and domain ID like we did before. At this point, the group is empty, and there are no users associated with this group.

In step 5, we supply name along with a password for the user. The update_password parameter is set to on_create, which means that the password won’t be modified for an existing user. This is great for the sake of idempotency. We also specify the email ID. This would be required for recovering the password and several other use cases. Lastly, we add the domain ID to create the user in the right domain.

In step 6, the os_user_group module will help us associate the demouser with the demogroup.

In step 7, the os_user_role will take a parameter for user or group and associate it with a role.

A lot of these divisions might not be required for every organization. We recommend going through the documentation and understanding the use case of each of them. Another point to note is that we might not even see the user management bits on a day-to-day basis. Depending on the setup and our responsibilities, we might only interact with modules that involve managing resources, such as virtual machines and storage.

We learned how to successfully to solve complex OpenStack networking tasks with Ansible 2. To learn more about managing other public cloud platforms like AWS and Azure refer to our book  Ansible 2 Cloud Automation Cookbook.

Read Next:

Getting Started with Ansible 2

System Architecture and Design of Ansible

An In-depth Look at Ansible Plugins


Please enter your comment!
Please enter your name here