Developing OpenStack Services

Enable dev mode for a service:

In the defaults.yml, specify kolla_dev_repos_git as a git URL prefix, and for each service to enable dev mode in, create options NAME_dev_mode and NAME_source_version. For example, to enable blazar dev mode:

kolla_dev_repos_git: # git URL prefix
blazar_dev_mode: yes
blazar_source_version: chameleoncloud/train # git branch 

Then run ./cc-ansible --tags blazar reconfigure. The source will be places in /opt/stack/blazar, and mounted into the container. After updating the source, you can restart the docker container for the service, and the changes will be reloaded.

// example for neutron + neutron plugin
neutron_dev_mode: yes
neutron_source_version: chameleoncloud/train

  - name: networking-generic-switch
    source_version: "feature/dell_os10"
      - networking_generic_switch

Fake hypervisors

In order to create blazar hosts, and use nova servers, you must have hypervisors. You can list hypervisors with openstack hypervisor list.

To add fake hypervisors, in defaults.yml, remove the line nova_compute_virt_type: kvm, and add the following lines

enable_nova_fake: "yes"
num_nova_fake_per_node: 5 # Number of fake hypervisors to create

Then run ./cc-ansible --tags nova reconfigure.

You might also have to run cp /opt/chi-in-a-box/kolla/node_custom_config/nova/policy.json /etc/kolla/nova-compute-fake-5/ since the fake hypervisors require the policy.json file, but it is not in the correct volume.

Create a blazar host

Get the name of a hypervisor, and then run openstack reservation host create <NAME>

If that doesn't work, you may need to install blazar client and/or run blazar host-create <NAME>

Create a server on a fake hypervisor

First, you must have an image created. You can download the lightweight test image cirros from here and then run openstack image create test-image --file cirros-0.5.2-x86_64-disk.img --disk-format qcow2.

Check openstack image list to ensure the image was created.

Create a reservation for a host, as normal using blazar. Get the reservation ID.

Create the server: openstack --os-compute-api-version 2.37 server create --image test-image --flavor mini my_server --hint reservation=<RES_ID> --network none

Creating a network

For some services, it may be useful to create a network on your development instance. Here is an example network that can help with certain tasks.

# Create network
openstack network create \
    --provider-network-type flat \
    --provider-physical-network public \

# Create subnet
openstack subnet create \
    --network my-network \
    --allocation-pool start=,end= \
    --subnet-range \

After this is created, you can use the network ID when creating a Floating IP, for instance.

Running tests

Openstack testing frameworks do not show the output from LOG statements. To see this output, modify the root logger:

from flask.logging import default_handler
from oslo_log import log as logging
root = logging.getLogger()

Customizing Containers

CHI-in-a-box, kolla-ansible, and kolla allow for customization at many levels.


The containers and their dockerfiles are defined in the kolla repository, for example, certbot. These dockerfiles contain macros and support templating.

{% block letsencrypt_certbot_header %}{% endblock %}


The Build-time customization is done in the kolla-containers repository. We maintain a file, template-overrides.j2, with per-service overrides. In addition, the kolla-build.conf sets build-wide settings, including the git repos and branches to use for each service build.

We have an extra layer of templating in place, as we maintain multiple variants of this build config. Currently, we have the following variants.

OpenStack ReleaseOperating SystemArchitectureVariant


Ubuntu 20.04




Ubuntu 20.04







All Centos8 variants are deprecated, as are the arm64 builds for CHI@Edge.


Kolla-ansible defines run-time defaults, configuration, and tooling. Each service has a set of roles, corresponding to deployment phases. See Letsencrypt example.

They template configuration files from ansible key-value pairs into a configuration directory, usually /etc/kolla/service. The source for said configuration can be selectively overridden. merge_configs will combine ini-like config from the entries, while with_first_found will do as its name suggests.

    - "{{ role_path }}/templates/doni.conf.j2"
    - "{{ node_custom_config }}/global.conf"
    - "{{ node_custom_config }}/doni.conf"
    - "{{ node_custom_config }}/doni/{{ item.key }}.conf"
    - "{{ node_custom_config }}/doni/{{ inventory_hostname }}/doni.conf"

Finally, each time a container starts, it uses a config.json file to define what volumes to load, and what config files to copy from said volume into its runtime location. Example for Doni-worker.

Upstream documentation:


Finally, the chi-in-a-box repository sets the key-value pairs used by kolla-ansbile for configuration, as well as provides templated configuration files, using by the above merge_configs or with_first_found methods.

Configuration files are applied in the following order, with more specific replacing less specific.

  • defaults from kolla-ansible

  • node_custom_config/service.conf

  • node_custom_config/service/service.conf

  • node_custom_config/service/hostname/service.conf

See the kolla-ansible docs for more.

Last updated