layout: page title: “OpenStack: Getting Started Guide” permalink: /guides/openstack/

  1. Introduction
  2. Get OpenStack
  3. Get jclouds
  4. Terminology
  5. Keystone v2-v3 authentication
  6. Nova: List Servers
  7. Swift: Use Containers
  8. Next Steps
  9. OpenStack Dependencies

Introduction

OpenStack is a global collaboration of developers and cloud computing technologists producing the ubiquitous open source cloud computing platform for public and private clouds. The project aims to deliver solutions for all types of clouds by being simple to implement, massively scalable, and feature rich. The technology consists of a series of interrelated projects delivering various components for a cloud infrastructure solution.

Get OpenStack

You can either install a private OpenStack cloud for yourself or use an existing OpenStack public cloud.

Private Clouds

If you don't have a private OpenStack cloud but still want to try it out, you can use DevStack to create your own mini-OpenStack cloud.

Public Clouds

Because the OpenStack API is also open, the jclouds APIs that talk to private OpenStack clouds work just as well with public OpenStack clouds. OpenStack is used by several large public clouds, both the HP Cloud (HP Cloud Getting Started Guide) and Rackspace Cloud (Rackspace Getting Started Guide) are based on it. If you don't want to sign up for a paid public cloud, you can use TryStack.

Get jclouds

  1. Ensure you are using the Java Development Kit (JDK) version 6 or later.
    • javac -version
  2. Ensure you are using Maven version 3 or later.
    • mvn -version
  3. Create a directory to try out jclouds.
    • mkdir jclouds
    • cd jclouds
  4. Make a local copy of the pom.xml file below in the jclouds directory.
    • mvn dependency:copy-dependencies "-DoutputDirectory=./lib"
  5. You should now have a directory with the following structure:
    • jclouds/
      • pom.xml
      • lib/
        • *.jar

Terminology

There are some differences in terminology between jclouds and OpenStack that should be made clear.

Keystone v2-v3 authentication

OpenStack Keystone (aka: OpenStack Identity Service) has major changes between v2 and v3 (detail. Identity API v2.0 and v3 History).

To login, provide:

  • On v2: tenant, user, password.
  • On v3: a project (new name for tenant), an authentication domain for this project, a user, an authentication domain for this user (the two domains can be different).

jclouds provides backward compatibility between Keystone v2 and v3, but you should keep the following in mind to fully understand authentication against your OpenStack platform (See also the recent OpenStack Keystone v3 Support blog post).

v2

This snippet: {% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “2”);

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v2.0”) .credentials(“myTenant:foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

or

{% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “2”); overrides.put(KeystoneProperties.TENANT_NAME, “myTenant”);

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v2.0”) .credentials(“foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

Will produce when authentication needed:

POST https://host:5000/v2.0/tokens HTTP/1.1
{
    "auth": {
        "passwordCredentials": {
            "username": "foo",
            "password": "bar"
        },
        "tenantName": "myTenant"
    }
}    

v3: Default (unscoped)

Keystone v3 requires at min a user authentication domain (generally the one you are using to login through UI console), so this snippet: {% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “3”);

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v3”) .credentials(“ldap:foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

Will produce when authentication needed:

POST https://host:5000/v3/auth/tokens HTTP/1.1
{
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "name": "foo",
                    "domain": {
                        "name": "ldap"
                    },
                    "password": "bar"
                }
            }
        },
        "scope": "unscoped"
    }
}

In this case, no project (previously tenant in OpenStack keystone v2) is provided.

v3: Project-scoped

A common usage of OpenStack keystone v3 is to provide the project scope, this snippet: {% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “3”); overrides.put(KeystoneProperties.SCOPE, “project:myTenant”);

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v3”) .credentials(“ldap:foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

Will produce when authentication needed:

POST https://host:5000/v3/auth/tokens HTTP/1.1
{
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "name": "foo",
                    "domain": {
                        "name": "ldap"
                    },
                    "password": "bar"
                }
            }
        },
        "scope": {
            "project": {
                "name": "myTenant",
                "domain": {
                    "name": "ldap"
                }
            }
        }
    }
}

If the project domain is different than the user domain (Use case when ‘default’ is used for projects and a third-part IAM like ldap is use for user authentication), use this snippet: {% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “3”); overrides.put(KeystoneProperties.SCOPE, “project:myTenant”); overrides.put(KeystoneProperties.PROJECT_DOMAIN_NAME, “default”); // Since jclouds > v2.1.0 (see PROJECT_DOMAIN_ID as complement)

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v3”) .credentials(“ldap:foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

Will produce when authentication needed:

POST https://host:5000/v3/auth/tokens HTTP/1.1
{
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "name": "foo",
                    "domain": {
                        "name": "ldap"
                    },
                    "password": "bar"
                }
            }
        },
        "scope": {
            "project": {
                "name": "myTenant",
                "domain": {
                    "name": "default"
                }
            }
        }
    }
}

v3: Domain-scoped

If your authentication is domain-scoped, this snippet: {% highlight java %} final Properties overrides = new Properties(); overrides.put(KeystoneProperties.KEYSTONE_VERSION, “3”); overrides.put(KeystoneProperties.SCOPE, “domain:default”);

ContextBuilder.newBuilder(“openstack-nova”) .endpoint(“https://host:5000/v3”) .credentials(“ldap:foo”, “bar”) .overrides(overrides) .buildApi(NovaApi.class); {% endhighlight %}

Will produce when authentication needed:

POST https://host:5000/v3/auth/tokens HTTP/1.1
{
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "name": "foo",
                    "domain": {
                        "name": "ldap"
                    },
                    "password": "bar"
                }
            }
        },
        "scope": {
            "domain": {
                "name": "default"
            }
        }
    }
}

Nova: List Servers

Introduction

OpenStack Compute (aka Nova) is an easy to use service that provides on-demand servers that you can use to to build dynamic websites, deliver mobile apps, or crunch big data.

The Source Code

  1. Create a Java source file called JCloudsNova.java in the jclouds directory above.
  2. You should now have a directory with the following structure:
    • jclouds/
      • JCloudsNova.java
      • pom.xml
      • lib/
        • *.jar
  3. Open JCloudsNova.java for editing, read the code below, and copy it in.

{% highlight java %} import com.google.common.collect.ImmutableSet; import com.google.common.io.Closeables; import com.google.inject.Module; import org.jclouds.ContextBuilder; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.domain.Server; import org.jclouds.openstack.nova.v2_0.features.ServerApi;

import java.io.Closeable; import java.io.IOException; import java.util.Set;

public class JCloudsNova implements Closeable { private final NovaApi novaApi; private final Set regions;

public static void main(String[] args) throws IOException {
    JCloudsNova jcloudsNova = new JCloudsNova();

    try {
        jcloudsNova.listServers();
        jcloudsNova.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        jcloudsNova.close();
    }
}

public JCloudsNova() {
    Iterable<Module> modules = ImmutableSet.<Module>of(new SLF4JLoggingModule());

    // Please refer to 'Keystone v2-v3 authentication' section for complete authentication use case
    String provider = "openstack-nova";
    String identity = "demo:demo"; // tenantName:userName
    String credential = "devstack";

    novaApi = ContextBuilder.newBuilder(provider)
            .endpoint("http://xxx.xxx.xxx.xxx:5000/v2.0/")
            .credentials(identity, credential)
            .modules(modules)
            .buildApi(NovaApi.class);
    regions = novaApi.getConfiguredRegions();
}

private void listServers() {
    for (String region : regions) {
        ServerApi serverApi = novaApi.getServerApi(region);

        System.out.println("Servers in " + region);

        for (Server server : serverApi.listInDetail().concat()) {
            System.out.println("  " + server);
        }
    }
}

public void close() throws IOException {
    Closeables.close(novaApi, true);
}

} {% endhighlight %}

In the constructor note that

  • String provider = "openstack-nova";
    • This ones pretty self explanatory, we're using the OpenStack Nova provider in jclouds
  • String identity = "demo:demo"; // tenantName:userName
    • Here we use the tenant name and user name with a colon between them instead of just a user name
  • String credential = "devstack";
    • The demo account uses ADMIN_PASSWORD too
  • .endpoint("http://xxx.xxx.xxx.xxx:5000/v2.0/")
    • This is the Keystone endpoint that jclouds needs to connect with to get more info (services and endpoints) from OpenStack
    • When a DevStack installation completes successfully, one of the last few lines will read something like “Keystone is serving at http://xxx.xxx.xxx.xxx:5000/v2.0/
    • Set the endpoint to this URL depending on the method used to get OpenStack above.

Compile and Run

$ javac -classpath ".:lib/*" JCloudsNova.java

$ java -classpath ".:lib/*" JCloudsNova

Servers in RegionOne
  Server{id=...}
  ...

# You'll see a lot of logging in the output

Swift: Use Containers

Introduction

OpenStack Object Storage (aka Swift) provides redundant, scalable object storage using clusters of standardized servers capable of storing petabytes of data.

The Source Code

  1. Create a Java source file called JCloudsSwift.java in the jclouds directory above.
  2. You should now have a directory with the following structure:
    • jclouds/
      • JCloudsSwift.java
      • pom.xml
      • lib/
        • *.jar
  3. Open JCloudsSwift.java for editing, read the code below, and copy it in.

{% highlight java %} import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.io.Closeables; import com.google.inject.Module; import org.jclouds.ContextBuilder; import org.jclouds.io.Payload; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.openstack.swift.v1.SwiftApi; import org.jclouds.openstack.swift.v1.domain.Container; import org.jclouds.openstack.swift.v1.features.ContainerApi; import org.jclouds.openstack.swift.v1.features.ObjectApi; import org.jclouds.openstack.swift.v1.options.CreateContainerOptions; import org.jclouds.openstack.swift.v1.options.PutOptions;

import java.io.Closeable; import java.io.IOException; import java.util.Set;

import static com.google.common.io.ByteSource.wrap; import static org.jclouds.io.Payloads.newByteSourcePayload;

public class JCloudsSwift implements Closeable { public static final String CONTAINER_NAME = “jclouds-example”; public static final String OBJECT_NAME = “jclouds-example.txt”;

private SwiftApi swiftApi;

public static void main(String[] args) throws IOException { JCloudsSwift jcloudsSwift = new JCloudsSwift();

  try {
     jcloudsSwift.createContainer();
     jcloudsSwift.uploadObjectFromString();
     jcloudsSwift.listContainers();
     jcloudsSwift.close();
  } catch (Exception e) {
     e.printStackTrace();
  } finally {
     jcloudsSwift.close();
  }

}

public JCloudsSwift() { Iterable modules = ImmutableSet.of( new SLF4JLoggingModule());

  // Please refer to 'Keystone v2-v3 authentication' section for complete authentication use case
  String provider = "openstack-swift";
  String identity = "demo:demo"; // tenantName:userName
  String credential = "devstack";

  swiftApi = ContextBuilder.newBuilder(provider)
        .endpoint("http://xxx.xxx.xxx.xxx:5000/v2.0/")
        .credentials(identity, credential)
        .modules(modules)
        .buildApi(SwiftApi.class);

}

private void createContainer() { System.out.println(“Create Container”);

  ContainerApi containerApi = swiftApi.getContainerApi("RegionOne");
  CreateContainerOptions options = CreateContainerOptions.Builder
        .metadata(ImmutableMap.of(
              "key1", "value1",
              "key2", "value2"));

  containerApi.create(CONTAINER_NAME, options);

  System.out.println("  " + CONTAINER_NAME);

}

private void uploadObjectFromString() { System.out.println(“Upload Object From String”);

  ObjectApi objectApi = swiftApi.getObjectApi("RegionOne", CONTAINER_NAME);
  Payload payload = newByteSourcePayload(wrap("Hello World".getBytes()));

  objectApi.put(OBJECT_NAME, payload, PutOptions.Builder.metadata(ImmutableMap.of("key1", "value1")));

  System.out.println("  " + OBJECT_NAME);

}

private void listContainers() { System.out.println(“List Containers”);

  ContainerApi containerApi = swiftApi.getContainerApi("RegionOne");
  Set<Container> containers = containerApi.list().toSet();

  for (Container container : containers) {
     System.out.println("  " + container);
  }

}

public void close() throws IOException { Closeables.close(swiftApi, true); } } {% endhighlight %}

Compile and Run

$ javac -classpath ".:lib/*" JCloudsSwift.java

$ java -classpath ".:lib/*" JCloudsSwift

Create Container
  jclouds-example
Upload Object From String
  jclouds-example.txt
List Containers
  Container{name=...}
  ...

# You'll see a lot of logging in the output

Next Steps

  • Try the List Servers example above with one of the public clouds. For the Rackspace Cloud the constructor becomes:

{% highlight java %} import org.jclouds.Constants; import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;

// snip

public JCloudsNova() { Iterable modules = ImmutableSet.of(new SLF4JLoggingModule());

Properties overrides = new Properties();
overrides.setProperty(KeystoneProperties.CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
overrides.setProperty(Constants.PROPERTY_API_VERSION, "2");

// Please refer to 'Keystone v2-v3 authentication' section for complete authentication use case
String provider = "openstack-nova";
String identity = "username";
String credential = "password";

novaApi = ContextBuilder.newBuilder(provider)
        .endpoint("https://identity.api.rackspacecloud.com/v2.0/")
        .credentials(identity, credential)
        .modules(modules)
        .overrides(overrides)
        .buildApi(NovaApi.class);
regions = novaApi.getConfiguredRegions();

} {% endhighlight %}

OpenStack Dependencies

This pom.xml file specifies all of the dependencies you'll need to work with OpenStack.

{% highlight xml %} 4.0.0 <jclouds.version>{{ site.latest_version }}</jclouds.version> org.apache.jclouds.examples openstack-examples 1.0 org.apache.jclouds.driver jclouds-slf4j ${jclouds.version} org.apache.jclouds.driver jclouds-sshj ${jclouds.version} org.apache.jclouds.api openstack-keystone ${jclouds.version} org.apache.jclouds.api openstack-nova ${jclouds.version} org.apache.jclouds.api openstack-swift ${jclouds.version} org.apache.jclouds.api openstack-cinder ${jclouds.version} org.apache.jclouds.api openstack-trove ${jclouds.version} org.apache.jclouds.labs openstack-glance ${jclouds.version} org.apache.jclouds.labs openstack-marconi ${jclouds.version} org.apache.jclouds.labs openstack-neutron ${jclouds.version} ch.qos.logback logback-classic 1.0.13 mysql mysql-connector-java 5.1.25 {% endhighlight %}