Bootstraping Juju on top of an OpenStack private cloud


Juju uses the concept of an environment. An environment is a particular type of infrastructure used to deploy software (described via Juju Charms). Juju supports different types of environments: deploying on top of Joyent, OpenStack, Amazon EC2, HP Public Cloud, Windows Azure, directly on top of hardware (what is called bare metal and MAAS) or even directly on the local host, as described in Using the Local Provider (essentially LXC and I guess that Docker in a near future).

For this exercise, let’s assume we want to deploy software using Juju on top of a private Cloud running OpenStack. Therefore, before proceeding, make sure a proper OpenStack deployment is available and functioning properly. That means that Keystone, Nova, Neutron and all necessary components are up, healthy and reachable. If you want to deploy OpenStack on a single machine for testing and experimentation purposes, you can try using DevStack or Packstack.

From this OpenStack deployment, a demo tenant will be used to bootstrap Juju. By default, DevStack and Packstack automatically provision this demo tenant:

$ source keystone-admin
$ keystone tenant-get demo
| Property    |   Value                          |
| description |                                  |
| enabled     | True                             |
| id          | eb3a05f2ed46424584586a12bad5d2f5 |
| name        | demo                             |

Installing Juju

Follow instructions from the official Juju documentation. I chose to run Juju on Ubuntu, but you can choose the one you prefer the most. Therefore, in my case:

$ sudo add-apt-repository ppa:juju/stable
$ sudo apt-get update && sudo apt-get install juju-core

Configuring the Juju environment

Before being able to deploy software on top of an environment, the environment itself has to be bootstrapped (from the point of view of Juju, of course). For OpenStack environments, the bootstrap process spawns an OpenStack instance (Nova virtual machine), the control instance, that keeps state and server software used by Juju’s workflows and proper operation.

But first, one has to configure an environment that describes this OpenStack environment.

$ juju help init
usage: juju init [options]
purpose: generate boilerplate configuration for juju environments

-f  (= false)
    force overwriting environments.yaml file even if it exists (ignored if --show flag specified)
--show  (= false)
    print the generated configuration data to stdout instead of writing it to a file

aliases: generate-config

$ juju init

This creates a skeleton file named $HOME/.juju/environments.yaml that describes the environments to be available for Juju to deploy software onto. For this particular exercise, the skeleton is not interesting, as it describes public cloud environments (like HP Public Cloud or Amazon EC2). OpenStack private clouds are a little bit different from public clouds.

So, let’s create our own $HOME/.juju/environments.yaml that describes our private OpenStack cloud environment:

$ cat .juju/environments.yaml
default: ost

    type: openstack
    # For this exercise, the use of floating IPs is not needed
    use-floating-ip: false
    # Do not use the default security group. Juju's bootstrap process creates
    # necessary security groups to allow the control instance to access the
    # network
    use-default-secgroup: false
    # The name or ID of the OpenStack network (e.g. Neutron network) to which
    # the control instance will attach to
    network: private
    # The Keystone URL
    region: RegionOne
    # How to authenticate to OpenStack. In this case, with user 'demo' from the
    # 'demo' tenant using password 'password'
    auth-mode: userpass
    tenant-name: demo
    username: demo
    password: thepassword

Configuring OpenStack Glance

Juju’s control instance is just a virtual machine running a particular release of Ubuntu Server Cloud. In order to spawn this virtual machine, Juju will ask Nova to create a new instance. Each Nova instance requires an image to boot from (e.g. Ubuntu Server Cloud 14.04 LTS) which is, in turn, stored and provided by Glance (the OpenStack component in charge of keeping the catalog of available images for booting virtual machines).

First step is downloading a proper Ubuntu Server Cloud image suitable for OpenStack, and configuring it in Glance:

$ wget

$ glance image-create --name ubuntu-14.04-server-cloudimg-amd64-disk1 --disk-format qcow2 --container-format bare --owner demo --is-public True --file ubuntu-14.04-server-cloudimg-amd64-disk1.img
| Property         | Value                                    |
| checksum         | b65cbc63bfa4abb6144dddf43caa6b5e         |
| container_format | bare                                     |
| created_at       | 2014-04-28T14:47:01                      |
| deleted          | False                                    |
| deleted_at       | None                                     |
| disk_format      | qcow2                                    |
| id               | b2731f9e-6971-4c91-bea3-39aa0e23e15b     |
| is_public        | True                                     |
| min_disk         | 0                                        |
| min_ram          | 0                                        |
| name             | ubuntu-14.04-server-cloudimg-amd64-disk1 |
| owner            | demo                                     |
| protected        | False                                    |
| size             | 252707328                                |
| status           | active                                   |
| updated_at       | 2014-04-28T14:47:03                      |
| virtual_size     | None                                     |

Next steps is to create proper metadata to describe this image. For more information about Juju metadata and the tools used to manage it, please read .

$ juju metadata generate-image -a amd64 -i b2731f9e-6971-4c91-bea3-39aa0e23e15b -r RegionOne -s trusty -d /opt/stack -u -e ost

image metadata files have been written to:
For Juju to use this metadata, the files need to be put into the
image metadata search path. There are 2 options:

1. Use the --metadata-source parameter when bootstrapping:
   juju bootstrap --metadata-source /opt/stack

2. Use image-metadata-url in $JUJU_HOME/environments.yaml
   Configure a http server to serve the contents of /opt/stack
   and set the value of image-metadata-url accordingly.


Regarding the command-line flags used:

  • -i b2731f9e-6971-4c91-bea3-39aa0e23e15b: specifies the ID of the Glance image that we just created before.
  • -u specifies the Keystone URL, and should match the value from the auth-url field of our environment as specified in $HOME/.juju/environments.yaml.
  • -e ost: identifies the Juju environment described in $HOME/.juju/environments.yaml file.
  • -s trusty: specifies the image series (the Ubuntu release name).
  • -a amd64: specifies the CPU architecture.
  • -d /opt/stack: specifies the base directory where the metadata will be written to. For images, the path will be /opt/stack/images/streams/v1..

Let’s take a look at the metadata that was just generated:

$ find /opt/stack/images/streams/v1/

$ cat /opt/stack/images/streams/v1/index.json
    "index": {
        "": {
            "updated": "Mon, 28 Apr 2014 16:49:57 +0200",
            "format": "products:1.0",
            "datatype": "image-ids",
            "cloudname": "custom",
            "clouds": [
                    "region": "RegionOne",
                    "endpoint": ""
            "path": "streams/v1/",
            "products": [
    "updated": "Mon, 28 Apr 2014 16:49:57 +0200",
    "format": "index:1.0"

$ cat images/streams/v1/\:released\:iagemetadata.json
    "products": {
        "": {
            "version": "14.04",
            "arch": "amd64",
            "versions": {
                "20142804": {
                    "items": {
                        "b2731f9e-6971-4c91-bea3-39aa0e23e15b": {
                            "id": "b2731f9e-6971-4c91-bea3-39aa0e23e15b",
                            "region": "RegionOne",
                            "endpoint": ""
    "updated": "Mon, 28 Apr 2014 16:49:57 +0200",
    "format": "products:1.0",
    "content_id": ""

Next step is populating the metadata that describes the tools used by Juju to do its magic:

$ juju metadata generate-tools -d /opt/stack
Finding tools in /opt/stack

$ find /opt/stack/tools

Bootstrapping Juju

Provided that everything has gone well, it should be possible to initiate the bootstrapping of Juju, using the metadata that we just generated locally:

$ juju bootstrap --metadata-source /opt/stack --upload-tools -v
Bootstrapping Juju machine agent
Starting Juju machine agent (jujud-machine-0)
stack@ubuntu-ost-controller1:~ (keystone-demo)$ juju status
environment: ost
agent-state: started
instance-id: 0eaf9226-7adc-4e68-a296-f99a63e504a2
series: trusty
hardware: arch=amd64 cpu-cores=2 mem=1024M
services: {}

At this point, the environment has been bootstrapped. This means there will be a Nova instance running named juju-ost-machine-0 that contains the necessary state and server software required by Juju:

$ nova list
| ID                                   | Name               | Status | Task State | Power State | Networks          |
| 0bbb30f6-d9ed-450e-8405-7f7b21b49d21 | cirros1            | ACTIVE | -          | Running     | private=  |
| 0eaf9226-7adc-4e68-a296-f99a63e504a2 | juju-ost-machine-0 | ACTIVE | -          | Running     | private= |

In order to SSH into this Juju controller, one can use the ssh subcommand to juju:

$ juju ssh 0
Welcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64)

* Documentation:

System information as of Mon Apr 28 15:35:29 UTC 2014

System load: 0.03 Processes: 81
Usage of /: 47.1% of 2.13GB Users logged in: 0
Memory usage: 11% IP address for eth0:
Swap usage: 0%

Graph this data and manage this system at:

Get cloud support with Ubuntu Advantage Cloud Guest:

Last login: Mon Apr 28 15:35:29 2014 from

2 thoughts on “Bootstraping Juju on top of an OpenStack private cloud

  1. Excellent article.
    But I have a question here.
    1.) Isn’t it possible to deploy juju server separately, openstack controller separately and still deploy software on openstack cloud using JuJu server?
    If it is possible then what should be configuration.
    To be specific, what we do here is first deploy openstack and setup openstack cloud environment. Then we deploy juju server on top of openstack and make the openstack cloud environment also a juju accessible environment. Then we deploy software on top of that.

    My requirement is to install JuJu server and openstack separately.


  2. Pingback: juju openstack juju-bootstrap not working properly - ubuntutextbook

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s