Skip to content

Getting Started With The OpenStack NET SDK

Don Schenck edited this page Aug 22, 2013 · 8 revisions

Getting Started with the OpenStack .NET SDK

About this document

This document will describe the steps required (including sample code) to allow a .NET developer to use the OpenStack .NET Software Development Kit (SDK). It assumes no prior knowledge of OpenStack and a very basic understanding of Cloud Computing in general.

Hint: Check on this document on a regular basis, as it will continue to grow.

This document has the following sections:

  • Section 1. Installing The SDK
  • Section 2. Getting A Server Up And Running
  • Section 3. Creating And Using A Server Image
  • Section 4. Storing Files In The Cloud
  • Section 5. Creating A Content Delivery Network (CDN)
  • Section 6: Creating A Network Of Servers
  • Section 7: Implementing AutoScale
  • Appendix A: Useful Techniques

Section 1: Installing The SDK

The OpenStack .NET SDK is installed by using the NuGet Package Manager, which is included with Visual Studio. You can install the SDK from the menu or from the Command window.

To use the Command windows, follow the menu path "Tools --> Library Package Manager --> Package Manager Console". After the Package Manager Console opens, type "Install-Package openstack.net" and press Enter to add openstack.net and its dependencies to your solution.

To use the graphical interface, follow the menu path "Tools --> Library Package Manager --> Manage NuGet Packages for Solution...", then search for "openstack.net" in the Online packages. Click the Install button and openstack.net and its dependencies will be added to your solution.

Sample Code

Sample code can be installed as well using the NuGet Package Manager. Search for OpenStackSampleCode and follow the installation method used for the SDK.

Section 2: Getting A Server Up And Running

There are several parts to OpenStack computing. They include:

  • Provider and Identity
  • Servers
  • Cloud Files
  • Block Storage
  • Images
  • DNS Records
  • Load Balancers
  • Content Delivery Network (or CDN)
  • Databases
  • Backup
  • Monitoring
  • AutoScale

Some of the parts of OpenStack have names:

  • Identity = "Keystone"
  • Servers, or Compute = "Nova"
  • Cloud Files, or Object storage = "Swift"
  • Block Storage = "Cinder"
  • Images = "Glance"
  • Networking, including DNS = "Neutron"
  • Dashboard, or Monitoring = "Horizon"

Two get a server up and running, we need to deal Keystone and Nova.

Keystone: Provider and Identity

The Provider is where you have your account. Examples include Rackspace, VMWare, Azure, etc. Obviously, you cannot use your Rackspace account to create (or "spin up") a server at Azure. By authenticating against your account at your provider you obtain your Identity, which allows you to work with your cloud objects. In other words, your Identity is who you are at the particular Provider.

Let’s take the example of Rackspace. In order to work with the cloud at Rackspace, you’ll need to visit their web site and establish your account. This includes things such as your name, email address, and a credit card number from which your monthly bill will be paid. Once this is done, you’ll have your user name and password, and you’ll also be issued an API Key.

The API Key, in combination with your user name, is used for authentication. Alternatively, you can use your user name and password, but there is a security risk; If someone learns your user name and password, they can log in to your account and change your password and effectively lock you out of your own account (meanwhile using your account). Using the API Key is safe, because you can log in to your account at any time and re-generate the API Key, making the previous API Key invalid.

When working with cloud objects, you can use your Identity in one of two ways:

  1. You can pass the Identity object along in every method call, or
  2. You can specify the Identity object when creating the Provider object, after which all calls using the Provider object will use the Identity object.

The following example (Example 1) demonstrates how to create an Identity object.

_cloudIdentity = new CloudIdentity(){Username = "username", APIKey = "700xxx74be13c93e3cedb702fc8b3ds245"};

Example 1

Once the Identity object is created, it is then used to create the Provider object. The Provider object allows you to perform cloud tasks such as spin up a server, upload a file, etc.

The following example (Example 2) uses the Identity object to demonstrate how to create a Provider object. Note that the Identity object is included when the Provider is instantiated. This allows us to make subsequent calls without needing to include the Identity every time.

_provider = new CloudServersProvider(_cloudIdentity);

Example 2

Now that we have a Provider object, we can use it to perform cloud tasks (which are covered in detail later in this document), such as spin up a server.

The following example (Example 2) demonstrates how to spin up a server. It's not important (yet) that you fully understand this example, only that the principle is clearly understood: The Provider is where you do most of the work.

NewServer newServer = _provider.CreateServer(serverName, imageId, flavorId);

Example 3

At this point, we have a new server. But what do the parameters "imageId" and "flavorId" mean? That's covered in the next section, "Servers".

Nova: Servers

Servers are where you run your web site, your web services, your computing. One of the basic features of cloud computing is the ability to spin up additional servers as demand rises, and scale back if demand diminishes.

OpenStack allows you to programmatically spin up a server. A software developer can write a very few lines of code to do in minutes what used to take a hardware technician and network administrator days to do.

Depending on your provider, you may have many operating systems and virtual machine configurations from which to choose. In addition, certain software may be available.

For example, it may be possible to spin up a Microsoft Windows 2012 Server with 15 GB of RAM and 620 GB of DASD running Microsoft SQL Server 2012.

The operating system, software, amount of RAM and size of DASD are specified by using an Image, with optional Flavor and DiskConfig attributes.

For example, an Image may be "Windows Server 2012 with SQL Server 2012 with 2GB of RAM and 40 GB of disk". A Flavor may be "15 GB of RAM and 620 GB". By specifying this combination when spinning up a server (i.e. calling the method "CreateServer", as in Example 2), the provider will create a virtual server meeting these criteria.

The DiskConfig parameter has two valid values, "AUTO" and "MANUAL". "AUTO" will allocate disk storage of the size specified in the Flavor, e.g. 160 GB.

A value of "MANUAL" for DiskConfig will allocate enough disk storage to boot the operating system (e.g. 5 GB), while the remaining amount is available for formatting.

There are combinations that are not valid (i.e. they are mutually exclusive or not available for reasons of system requirements or minimal performance). For example, you cannot create a virtual machine running CentOS 5.9 with Microsoft SQL Server. Likewise, you cannot create a Windows Server 2008 virtual machine with 512 MB of RAM (system requirements require at least 1 GB of RAM). When retrieving an Image, it will include the properties "MinDisk" and "MinRAM", which specify the minimun disk needed (in gigabytes) and minimum RAM needed (in megabytes) for the Image. You can use that information to decide which Flavors are available for an Image.

Because of this, while spinning up a server is, indeed, "one line of code", you will typically need to investigate the valid combinations of OS, RAM and DASD before that one line. For example, the Image Id may be a 32-character string that does not have meaning outside of the SDK; you would need to see the associated Image Name to understand the value of the Image.

The following code example, Example 4, will show you a list of Images, their ID, and some related information.

IEnumerable<ServerImage> listOfImages = _provider.ListImagesWithDetails();
String hline = new String('-', 70);
			
foreach (ServerImage anImage in listOfImages) {
	Console.WriteLine(hline);
	Console.WriteLine("Image: {0}", anImage.Name);
	Console.WriteLine("\tID:\t{0}", anImage.Id);
	Console.WriteLine("\tDisk:\t{0} GB", anImage.MinDisk.ToString());
	Console.WriteLine("\tRAM:\t{0} MB", anImage.MinRAM);
}

Example 4

See table 1 for some examples of Images.

Image Id Image Name
cafe82a1-f3f9-4dec-b445-2b958604a170 CentOS 6.2
d59749af-cd74-4f08-abe0-34f1e643390e CentOS 6.0
bb8c27f9-f3cf-4606-9a88-8a2123e02290 Gentoo 13.2
8958846f-679b-454e-9232-20d3792fc5d7 OpenSUSE 12.3
32b7d027-8a40-458b-9e73-bd719d660df6 Arch 2013.6
81877a6e-9e87-4b1f-93f3-b176e25f3c4a Debian 7 (Wheezy)
05313f52-c19b-4640-b5ed-c7b8e8d17775 Windows Server 2008 R2 SP1 (with updates) + SQL Server 2012 Standard SP1

Table 1

Likewise, you may want to know and use valid values for Flavors.

Flavors refer to the combination of RAM and Disk Space for the server.

See table 2 for some examples of Flavors:

Flavor Id Flavor Name Disk Size RAM
2 512MB Standard Instance 20 GB 512 MB
3 1GB Standard Instance 40 GB 1 GB
4 2GB Standard Instance 80 GB 2 GB
5 4GB Standard Instance 160 GB 4 GB
6 8GB Standard Instance 320 GB 8 GB
7 15GB Standard Instance 640 GB 15 GB
8 30GB Standard Instance 1.2 TB 30 GB

Table 2

Important

It is important to note that when you call the method "CreateServer", OpenStack will launch the server creation at the endpoint (i.e. where your server will be) and continue. While the method may be successful, it is not finished running. For example, it may take a few minutes for the server to be fully operational, while the virtual system is provisioned, the operating system is loaded and booted, and any additional software (as part of the Image, described later) is loaded.

You can wait for the server to become operational by using the method "WaitForActive", which is covered in the section "Advanced Topics".

Given that, the following code (Example 4) will create an object of type "Identity", an object of type "Provider", and then create a server.

using System;
using System.Collections.Generic;

using net.openstack.Core.Domain;
using net.openstack.Core.Providers;
using net.openstack.Providers.Rackspace;
using net.openstack.Providers.Rackspace.Objects;

namespace GettingStarted
{
	class Program
	{

		public static CloudIdentity			_cloudIdentity;
		public static CloudServersProvider 	_provider;

		public static void Main(string[] args)
		{
			
			try{
				
				Console.WriteLine("GettingStarted program execution has started...");
				
				// Create Identity
				Console.WriteLine(" Creating Identity...");
				_cloudIdentity = new CloudIdentity(){Username = "your_username", APIKey = "your_APIKey"};
				
				// Create Provider
				Console.WriteLine("	Creating Provider...");
				_provider = new CloudServersProvider(_cloudIdentity);
				
				// Spin up a new Server
				Console.WriteLine("	Creating Server...");

				Metadata metaData = new Metadata();	// Add some metadata just because we can
				metaData.Add("Description", "Example 4 - Getting Started");

				string serverName = "Example4";
				string imageId = "48df4181-040e-4821-8723-d9e4ba908d2f";
				string flavorId = "3";
				
				NewServer newServer = _provider.CreateServer(serverName, imageId, flavorId, "MANUAL", metaData);	

				Console.WriteLine("Your Administrator password is: {0}", newServer.AdminPassword);
				
				Console.Write("Press any key to continue . . . ");
				Console.ReadKey(true);
			}
			catch(Exception ex){
				Console.WriteLine(ex.Message);
				Console.Write("Press any key to dismiss error and quit program . . . ");
				Console.ReadKey(true);
			}
		}
				
	}
}

Example 5

We've seen how to create a server using an off-the-shelf configuration by specifying an Image and a Flavor. But what if we could create custom images for our own, very specific needs? We could, say, create a server, install some software, then use that as a basis for all servers in the future.

Well, we can. In the next section, Creating And Using A Server Image, we'll learn how to create an Image of a server and then use that Image to create a new server.

Section 3: Creating And Using A Server Image

One of the strengths of cloud computing includes the ability to add processing power by adding servers to the network. But quickly spinning up a server and then spending hours to configure it is antithetical to the idea of the cloud. A better way would be to configure one server (adding software, adjusting the server's configuration, etc), take a snapshot of it, and use that snapshot to create additional servers in the future.

That's what the Server Image does, and in this section you'll learn how to create and save your own images.

What might be included in an image?

After creating a server, you will typically install software. Examples might include a web service, a database server such as MySQL, etc. In addition to installing software, you may want to change system setting specific to your needs, including IIS pool sizes, database defaults, configuration files for your applications, etc.

Making these changes every time you spin up a new server can be a self-defeating time sink. It also opens the door to mistakes which may later be difficult to find.

Enter the Image.

The Image is quite simple: You create a server, make the configuration changes you want, then create an Image of that server. Later, you can use that saved Image to create more servers.

How to create and save an image

Creating an Image is easy; It is literally one line of code.

server.CreateSnapshot("imageNameGoesHere");

Example 6: Creating an Image of a server

You can also add metadata to the image, which is helpful when you have multiple images. For example, you may wish to add metadata that identifies a server as being related to a certain project or application. The code is straightforward; you specify a key and a value. You can add up to five metadata items to an Image.

image.AddMetadata("application", "StockTickerV3");

Example 7: Adding metadata to an Image

How to use an Image

Using an Image is something you've already done. In Section 2, we used a vendor-supplied ImageId in our method "CreateServer" to specify how to create our virtual server. To use your own Image, simply use the ImageId associated with i; it's that easy.

For example, going back to the code in Example 5, you simply supply the ImageId of your image when creating the server.

Section 4: Storing Files In The Cloud

Files can, of course, be stored on a server. Typically, developers will use an FTP Server and client to upload and download files from a server.

With OpenStack .NET and the cloud, you can store files independent of them being stored on a server. You don't upload to and download from a server; you deal with the cloud.

In addition, you can put files into a Content Delivery Network, or CDN, for mass distribution -- more about that in Section 5, Creating A Content Delivery Network (CDN). For now, let's explore the process of uploading a file to the cloud.

Cloud files are stored in Containers, a virtual collection that you name. For example, you may have a container named "MarketingVideos" into which you upload a file named "ChicagoCampaign_Q22015.mp4".

The following example code demonstrates how to create a Container:

// Get a list of containers
// Notice: Cloud *Files* Provider instead of the previous
// Cloud *Servers* Provider.
			
CloudFilesProvider cfp = new CloudFilesProvider(_cloudIdentity);
cfp.CreateContainer("MarketingVideos");

Example 8: Creating a cloud files container

The following example code demonstrates how to upload a file into the Container created in Example 8:

cfp.CreateObjectFromFile("MarketingVideos", @"C:\ToBeUploaded\ChicagoCampaign_Q22015.mp4","ChicagoCampaignVideo");

Example 9: Uploading a video file to a cloud file Container

Notice that you can rename the file while you are uploading it.

After creating a container and uploading a file, the file is available for private use.

But what if you wish to make the file available publicly, to those outside of your network? To do that, you'll need to create a Content Delivery Network.

Section 5: Creating A Content Delivery Network (CDN)

A Content Delivery Network, or CDN, is one of the more powerful features of cloud computing. A CDN allows a file to be uploaded and made publicly available. From that point, the file is replicated across the cloud by the provider. You have links with which to share access to the file, with the location of the file being spread across the provider's network, which helps with performance. Popular online services such as YouTube, Instagram, or Flickr use CDNs to increase their speed of delivery, as file access is directed to the nearest location instead of a central storage location.

The following code allows you to enable the CDN feature for a container. Note that the ttl (Time To Live) value of 259200 is 72 hours; this determines how long the CDN will wait before looking for new versions of files.

cfp.EnableCDNOnContainer("MarketingVideos", 259200);

Example 10:Enabling a CDN

Once a file container has been CDN-enabled, you then have links with which to share the files. You can use the container links and append the object names to share files. The following example demonstrates how to access the URI properties for a container.

// Get a list of containers
CloudFilesProvider cfp = new CloudFilesProvider(_cloudIdentity);
			
IEnumerable<ContainerCDN> listOfContainers = cfp.ListCDNContainers();
Console.WriteLine("--------- CDN Containers ------------");
			
foreach (ContainerCDN ctnr in listOfContainers) {
				
	if (ctnr.CDNEnabled) {

		Console.WriteLine("Container Name: {0}",ctnr.Name);
		Console.WriteLine("\tiOS Streaming URI: {0}", ctnr.CDNIosUri);
		Console.WriteLine("\tHTTPS URI: {0}", ctnr.CDNSslUri);
		Console.WriteLine("\tStreaming URI: {0}", ctnr.CDNStreamingUri);
		Console.WriteLine("\tHTTP URI: {0}", ctnr.CDNUri);
					
		IEnumerable<ContainerObject> listOfCO = cfp.ListObjects(ctnr.Name);
					
		foreach (ContainerObject co in listOfCO) {
						
			Console.WriteLine("Object details...");
			Console.WriteLine("--> {0} ({1})",co.Name,co.ContentType);
			Console.WriteLine("Link, URI --> {0}/{1}", ctnr.CDNUri, co.Name);
		}

	}
}

Example 11: Viewing CDN Containers and their contents

Section 6: Creating A Network Of Servers

You can create a network of servers.

First, you create the network.

Then, you create servers and place them into one or more networks.

Section 7: Implementing AutoScale

(not yet implemented)

Appendix A: Useful Techniques

##Waiting for a server to become active When you create a server, it may take a few minutes for it to become active. The image must be installed, the server booted and configured, and all the network connections made active -- just a few of the things going on under the covers.

The OpenStack SDK exposes a method that allows you to wait for a server, getting updates on its progress that you can then report to any user interface. The following code, Example 12, demonstrates this.

private static NewServer SpinUpAServer(string serverName, string imageGUID, string flavorID)
	{
		Console.WriteLine("	About to Spin Up a new Server...");
		
  		Metadata metaData = new Metadata(); // Max 5 metadata items
		metaData.Add("Nickname","ThisIsANickname");
		
		NewServer newServer = _provider.CreateServer(serverName, imageGUID, flavorID, "MANUAL", metaData);
		Console.WriteLine("	While you're waiting, make note of your Administrator password: {0}", newServer.AdminPassword);
		
		newServer.WaitForActive(30, 25000, WriteStatus);

		return newServer;
	}

private static void WriteStatus(int pct){
	Console.WriteLine("{0}%",pct);
	}

Example 12: Waiting for a server to become active

### END ###