Leaseweb Cloud AWS EC2 support

As you might know, some of the products LeaseWeb include in its portfolio are Public and Private Cloud based on Apache CloudStack, which supports a full API. We, LeaseWeb, are very open about this, and we try to be as much involved and participative in the community and product development as possible. You might be familiar with this if you are a Private Cloud customer. In this article we target the current and former EC2 users, who probably have already tools built upon AWS CLI, by demonstrating how you can keep using them with LeaseWeb Private Cloud solutions.

Apache CloudStack has supported EC2 API for some time in the early days, but along the way, while EC2 API evolved, CloudStack’s support has somewhat stagnated. In fact, The AWS API component from CloudStack was recently detached from the main distribution as to simplify the maintenance of the code.

While this might sound like bad news, it’s not – at all. In the meantime, another project spun off, EC2Stack, and was embraced by Apache as well. This new stack supports the latest API (at the time of writing) and is much easier to maintain both in versatility as in codebase. The fact that it is written in Python opens up the audience for further contribution while at the same time allows for quick patching/upgrade without re-compiling.

So, at some point, I thought I could share with you how to quickly setup your AWS-compatible API so you can reuse your existing scripts. On to the details.

The AWS endpoint acts as an EC2 API provider, proxying requests to LeaseWeb API, which is an extension to the native CloudStack API. And since this API is available for Private Cloud customers, EC2Stack can be installed by the customer himself.

Following is an illustration of how this can be done. For the record, I’m using Ubuntu 14.04 as my desktop, and I’ll be setting up EC2stack against LeaseWeb’s Private Cloud in the Netherlands.

First step is to gather all information for EC2stack. Go to your LeaseWeb platform console, and obtain API keys for your user (sensitive information blurred):

apikeys-blurred

Note down the values for API Key and Secret Key (you should already know the concepts from AWS and/or LeaseWeb Private Cloud).

Now, install EC2Stack and configure it:

ntavares@mylaptop:~$ pip install ec2stack 
[…]
ntavares@mylaptop:~$ ec2stack-configure 
EC2Stack bind address [0.0.0.0]: 127.0.0.1 
EC2Stack bind port [5000]: 5000 
Cloudstack host [mgt.cs01.leaseweb.net]: csrp01nl.leaseweb.com 
Cloudstack port [443]: 443 
Cloudstack protocol [https]: https 
Cloudstack path [/client/api]: /client/api 
Cloudstack custom disk offering name []: dualcore
Cloudstack default zone name [Evoswitch]: CSRP01 
Do you wish to input instance type mappings? (Yes/No): Yes 
Insert the AWS EC2 instance type you wish to map: t1.micro 
Insert the name of the instance type you wish to map this to: Debian 7 amd64 5GB 
Do you wish to add more mappings? (Yes/No): No 
Do you wish to input resource type to resource id mappings for tag support? (Yes/No): No 
INFO  [alembic.migration] Context impl SQLiteImpl. 
INFO  [alembic.migration] Will assume non-transactional DDL. 

The value for the zone name will be different if your Private Cloud is not in the Netherlands POP. The rest of the values can be obtained from the platform console:

serviceoffering-blurred

template-blurred
You will probably have different (and more) mappings to do as you go, just re-run this command later on.

At this point, your EC2stack proxy should be able to talk to your Private Cloud, so we now need to instruct it to launch it to accept EC2 API calls for your user. For the time being, just run it on a separate shell:

ntavares@mylaptop:~$ ec2stack -d DEBUG 
 * Running on http://127.0.0.1:5000/ 
 * Restarting with reloader

And now register your user using the keys you collected from the first step:

ntavares@mylaptop:~$ ec2stack-register http://localhost:5000 H5xnjfJy82a7Q0TZA_8Sxs5U-MLVrGPZgBd1E-1HunrYOWBa0zTPAzfXlXGkr-p0FGY-9BDegAREvq0DGVEZoFjsT PYDwuKWXqdBCCGE8fO341F2-0tewm2mD01rqS1uSrG1n7DQ2ADrW42LVfLsW7SFfAy7OdJfpN51eBNrH1gBd1E 
Successfully Registered!

And that’s it, as far the API service is concerned. As you’d normally do with AWS CLI, you now need to “bind” the CLI to this new credentials:

ntavares@mylaptop:~$ aws configure 
AWS Access Key ID [****************yI2g]: H5xnjfJy82a7Q0TZA_8Sxs5U-MLVrGPZgBd1E-1HunrYOWBa0zTPAzfXlXGkr-p0FGY-9BDegAREvq0DGVEZoFjsT
AWS Secret Access Key [****************L4sw]: PYDwuKWXqdBCCGE8fO341F2-0tewm2mD01rqS1uSrG1n7DQ2ADrW42LVfLsW7SFfAy7OdJfpN51eBNrH1gBd1E  Default region name [CS113]: CSRP01 
Default output format

: text

And that’s it! You’re now ready to use AWS CLI as you’re used to:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 --output json ec2 describe-images | jq ' .Images[] | .Name ' 
"Ubuntu 12.04 i386 30GB" 
"Ubuntu 12.04 amd64 5GB" 
"Ubuntu 13.04 amd64 5GB" 
"CentOS 6 amd64 5GB" 
"Debian 6 amd64 5GB" 
"CentOS 7 amd64 20140822T1151" 
"Debian 7 64 10 20141001T1343" 
"Debian 6 i386 5GB" 
"Ubuntu 14.04 64bit with docker.io" 
"Ubuntu 12.04 amd64 30GB" 
"Debian 7 i386 5GB" 
"Ubuntu 14.04 amd64 20140822T1234" 
"Ubuntu 12.04 i386 5GB" 
"Ubuntu 13.04 i386 5GB" 
"CentOS 6 i386 5GB" 
"CentOS 6 amd64 20140822T1142" 
"Ubuntu 12.04 amd64 20140822T1247" 
"Debian 7 amd64 5GB"

Please note that I only used JSON output (and JQ to parse it) for summarising the results, as any other format wouldn’t fit on the page.

To create a VM with built-in SSH keys, you should create/setup your keypair in LeaseWeb Private Cloud, if you didn’t already. In the following example I’m generating a new one, but of course you could load your existing keys.

ssh-keypairs-blurred

You will want to copy paste the generated key (in Private Key) to a file and protect it. I saved mine in $HOME/.ssh/id_ntavares.csrp01.key .

ssh-keypairs2-blurred

This key will be used later to log into the created instances and extract the administrator password. Finally, instruct the AWS CLI to use this keypair when deploying your instances:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 run-instances \
 --instance-type dualcore \
 --image-id 7c123f01-9865-4312-a198-05e2db755e6a \
 --key-name ntavares-key 
INSTANCES	KVM	7c123f01-9865-4312-a198-05e2db755e6a	a0977df5-d25e-40cb-9f78-b3a551a9c571	dualcore	ntavares-key	2014-12-04T12:03:32+0100	10.42.1.129 
PLACEMENT	CSRP01 
STATE	16	running 

Note that the image-id is taken from the previous listing (the one I simplified with JQ).

Also note that although EC2stack is fairly new, and there are still some limitations to this EC2-CS bridge – see below for a mapping of supportedAPI calls. For instance, one that you can could run into at the time of writing this article (~2015) was the inability to deploy an instance if you’re using multiple Isolated networks (or multiple VPC). Amazon shares this concept as well, so a simple patch was necessary.

For this demo, we’re actually running in an environment with multiple isolated networks, so if you ran the above command, you’d get the following output:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 run-instances \
 --instance-type dualcore \
 --image-id 7c123f01-9865-4312-a198-05e2db755e6a \
 --key-name ntavares-key
A client error (InvalidRequest) occurred when calling the RunInstances operation: More than 1 default Isolated networks are found for account Acct[47504f6c-38bf-4198-8925-991a5f801a6b-rme]; please specify networkIds

In the meantime, LeaseWeb’s patch was merged, as many others, which both demonstrates the power of Open Source and the activity on this project.

Naturally, the basic maintenance tasks are there:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 describe-instances 
RESERVATIONS	None 
INSTANCES	KVM	7c123f01-9865-4312-a198-05e2db755e6a	a0977df5-d25e-40cb-9f78-b3a551a9c571	dualcore	ntavares-key	2014-12-04T12:03:32+0100	10.42.1.129	10.42.1.129 
PLACEMENT	CSRP01	default 
STATE	16	running

I’ve highlighted some information you’ll need now to login to the instance: the instance id, and IP address, respectively. You can login either with your ssh keypair:

[root@jump ~]# ssh -i $HOME/.ssh/id_ntavares.csrp01.key root@10.42.1.129 
Linux localhost 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 

[...] 
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent 
permitted by applicable law. 
root@a0977df5-d25e-40cb-9f78-b3a551a9c571:~#

If you need, you can also retrieve the password the same way you do with EC2:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 get-password-data --instance-id a0977df5-d25e-40cb-9f78-b3a551a9c571 
None dX5LPdKndjsZkUo19Z3/J3ag4TFNqjGh1OfRxtzyB+eRnRw7DLKRE62a6EgNAdfwfCnWrRa0oTE1umG91bWE6lJ5iBH1xWamw4vg4whfnT4EwB/tav6WNQWMPzr/yAbse7NZHzThhtXSsqXGZtwBNvp8ZgZILEcSy5ZMqtgLh8Q=

As it happens with EC2, password is returned encrypted, so you’ll need your key to display it:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 get-password-data --instance-id a0977df5-d25e-40cb-9f78-b3a551a9c571 | awk '{print $2}' > ~/tmp.1
ntavares@mylaptop:~$ openssl enc -base64 -in tmp.1 -out tmp.2 -d -A 
ntavares@mylaptop:~$ openssl rsautl -decrypt -in tmp.2 -text -inkey $HOME/.ssh/id_ntavares.csrp01.key 
ntavares@mylaptop:~$ cat tmp.3 ; echo 
hI5wueeur
ntavares@mylaptop:~$ rm -f tmp.{1,2,3} 
[root@jump ~]# sshpass -p hI5wueeur ssh root@10.42.1.129 
Linux localhost 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 

[...]
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent 
permitted by applicable law. 
Last login: Thu Dec  4 13:33:07 2014 from jump.rme.leasewebcloud.com 
root@a0977df5-d25e-40cb-9f78-b3a551a9c571:~#

The multiple isolated networks scenario

If you’re already running multiple isolated networks in your target platform (be either VPC-bound or not), you’ll need to pass argument –subnet-id to the run-instances command to specify which network to deploy the instance into; otherwise CloudStack will complain about not knowing in which network to deploy the instance. I believe this is due to the fact that Amazon doesn’t allow the use the Isolated Networking as freely as LeaseWeb – LeaseWeb delivers you the full flexibility at the platform console.

Since EC2stack does not support describe-network-acls (as of December 2014) in order to allow you to determine which Isolated networks you could use, the easiest way to determine them is to go to the platform console and copy & paste the Network ID of the network you’re interested in:

Then you could use –subnet-id:

ntavares@mylaptop:~$ aws --endpoint=http://127.0.0.1:5000 ec2 run-instances \
 --instance-type dualcore \
 --image-id 7c123f01-9865-4312-a198-05e2db755e6a \
 --key-name ntavares-key \
 --subnet-id 5069abd3-5cf9-4511-a5a3-2201fb7070f8
PLACEMENT	CSRP01 
STATE	16	running 

I hope I demonstrated a bit of what can be done in regards to compatible EC2 API. Other funtions are avaiable for more complex tasks although, as wrote earlier, EC2stack is quite new, for which you might need community assistance if you cannot develop the fix on your own. At LeaseWeb we are very interested to know your use cases, so feel free to drop us a note.

How to test Apache CloudStack 4.2 on your local machine

LeaseWeb released its Private Cloud powered by Apache CloudStack two months ago [1]. Apache CloudStack [2] is an open source software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds.

In this post, I will give a short introduction of Apache CloudStack and introduce an easy way to test Apache CloudStack 4.2 on our local machine using DevCloud.

Apache CloudStack manages the network, storage, and compute nodes that make up a cloud infrastructure. Apache CloudStack provides a first-class user interface (UI), a command line tool named CloudMonkey [3], and a full-featured RESTful API. Apache CloudStack currently supports the most popular hypervisors: VMware, KVM, XenServer and Xen Cloud Platform (XCP).

For now, the latest stable version of Apache CloudStack is 4.2.0. However, if you want to change and test your change in Apache CloudStack, or test the new features of CloudStack, you can check out the Apache CloudStack source code, build RPM/DEB packages, and install them on servers. However, Apache CloudStack also provides an easier way for testing.

DevCloud [4] is a virtual appliance shipped as an OVA image which runs on VirtualBox (an opensource type-2 or desktop hypervisor) and can be used for CloudStack’s development and testing. An NFS server is already configured in DevCloud, the System VM Template for Apache CloudStack 4.0/4.1 and a ttylinux virtual machine template are already installed on it. Moreover, Xen hypervisor and Xen Cloud Platform (XCP) are already installed in DevCloud, so virtual machines can be deployed in it.

Now we can test Apache Cloudstack on our local machines using DevCloud:

1. Preparation

(1)  Install VirtualBox

(2) Create a “host-only” network in VirtualBox if not exists. Set the IPv4 to 192.168.56.1

devcloud-11

(3) It is recommended that we install a Linux (such as CentOS, Ubuntu) virtual machine in VirtualBox as the working VM (WORK-VM) at first. There are two network adaptor attached to the VM (on is attached to NAT , another one is attached to the Host-Only Adaptor created in Step 2). Suppose it has a IP 192.168.56.2 .

Make sure the following programs have been installed: mysql-server, Python, Python-Dev (python-devel), mysql-connector-java, Java, tomcat6, python-paramiko, nfs-utils, Jsvc, maven, mysql-connector-python (pip install), requests (pip install)

(4) Get DevCloud2 [5] and import it to VirtualBox. Please do NOT select “re-initialize the MAC address of all network cards”. Make sure ‘Enable PAE/NX’ mode under VM settings -> System -> Processor Tab is checked. Change the network setting like Step 3. The network configuration should like this:
devcloud-12

2. Management server installation from CloudStack source codes

(5) Checkout Apache CloudStack source code from Apache Git repository in WORK-VM (see step 3).

git clone https://git-wip-us.apache.org/repos/asf/cloudstack.git testing
cd testing
git checkout 4.2    # or other branches or tags (like 4.2.0)

Revert commit 7f9463bb54f19e7676f8c6049d1ebc02330a730f which make DevCloud not working on Apache CloudStack 4.2 branch.

[root@weizhou-centos testing(4.2)]# git show 7f9463bb54f19e7676f8c6049d1ebc02330a730f
commit 7f9463bb54f19e7676f8c6049d1ebc02330a730f
Author: Anthony Xu <anthony.xu@citrix.com>;
Date:   Tue Dec 3 01:36:24 2013 -0800

    put shell scripts to a seperate directory in XS
    use same scripts for both XS and XCP
[root@weizhou-centos testing(4.2)]# git revert 7f9463bb54f19e7676f8c6049d1ebc02330a730f

(6) Compile Apache CloudStack source code, deploy database, and run the management server

mvn -P developer,systemvm clean install
mvn -P developer -pl developer,tools/devcloud –Ddeploydb
mvn -pl :cloud-client-ui jetty:run

Now we can see the Apache CloudStack UI on http://192.168.56.2:8080/client (username:admin, password:password)
devcloud-13
(7) Change some global configuration in Apache CloudStack, and restart management server. Or you can change by MySQL:

mysql -e &quot;update cloud.configuration set value='192.168.56.2' where name='host'&quot;;
# the value should be the ip of WORK-VM.
mysql -e &quot;update cloud.configuration set value='10' where name='cpu.overprovisioning.factor'&quot;;
mvn -pl :cloud-client-ui jetty:run

3. DevCloud deployment and testing

(8) Start DevCloud in VirtualBox. And run the following command in WORK-VM for testing Apache CloudStack 4.2 and newer.

mkdir /mnt/secondary
mount 192.168.56.10:/opt/storage/secondary /mnt/secondary
wget http://download.cloud.com/templates/4.2/systemvmtemplate-2013-07-12-master-xen.vhd.bz2 -O /root/systemvmtemplate-2013-07-12-master-xen.vhd.bz2
./client/target/generated-webapp/WEB-INF/classes/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -f /root/systemvmtemplate-2013-07-12-master-xen.vhd.bz2 -h xenserver -F

This is because the system VM (System Virtual Machines) [6] template changed between Apache CloudStack 4.1 and 4.2. So the old system VM template inside DevCloud is no longer valid when we test Apache CloudStack 4.2. These commands download the new system VM template and install it to Secondary Storage (NFS inside DevCloud).
After this, take a snapshot of DevCloud in VirtualBox, so that we do not need to update systemvm template any more. Each time when we want a clean DevCloud, we can restore the snapshot.
devcloud-14
(9) Using Marvin to deploy DevCloud. Open another session and run the following commands:

cd tools/marvin
python setup.py install	# run only the first time. Check python-devel package if fails
cd ../../
mvn -P developer -pl tools/devcloud -Ddeploysvr	# Basic Network

If you want to use other type of networks, you can replace the last command with one of the following commands.

python tools/marvin/marvin/deployDataCenter.py -i tools/devcloud/devcloud.cfg    # Basic Network, same to before
python tools/marvin/marvin/deployDataCenter.py -i tools/devcloud/devcloud-advanced.cfg     # Advanced Network
python tools/marvin/marvin/deployDataCenter.py -i tools/devcloud/devcloud-advancedsg.cfg  # Advanced with Security Groups

(10) After Step (9), a Zone/Pod/Cluster have been created, and DevCloud has been added as a host. After a few minutes, we can see that the system VMs are running on Apache CloudStack UI -> Infrastructure -> System VMs.
devcloud-15
(11) Now we can deploy a VM on Apache CloudStack UI -> Instances -> Add Instance -> Template -> select “tty Linux” -> select “tinyOffering” -> next . After a few minutes, the VM will be up.
devcloud-16
A virtual router (for default network) is also running.
devcloud-17

4. Limitation and future work

Now we have an testing environment with Apache CloudStack 4.2. We can test the functionalities in CloudStack like virtual machine operations, network, template, domain/account.

However, in this environment, we have only one host (devcloud) with local storage (this means the volumes of virtual machines are stored on the host, not shared storage, so virtual machines live migration is disabled). In the next post, I will introduce how to test with multiple devcloud hosts, and shared storage (like NFS).

Tips

(1) It is better for testing Apache CloudStack 4.2. The 4.3/master branch have not been tested.

(2) If you are new to CloudStack, you can get some concepts from Apache CloudStack Installation Guide [7] and Apache CloudStack Admin Guide [6]. Please note a new type of network (Advanced Network with Security Groups) was introduced in Apache CloudStack 4.2.0.

(3) You can use XCP command lines [8] to manage virtual machines inside DevCloud. For example:

root@devcloud:~# xe vm-list
uuid ( RO)           : 576aacc8-4c8e-e0b4-f035-79001b4a7284
     name-label ( RW): r-4-VM
    power-state ( RO): running

uuid ( RO)           : 1efad534-bcd5-c183-9bfa-5eaf4a4afe80
     name-label ( RW): i-2-3-VM
    power-state ( RO): running

uuid ( RO)           : c8c2f1a3-40d3-308f-70bf-687f7f49b9a5
     name-label ( RW): Control domain on host: devcloud
    power-state ( RO): running

uuid ( RO)           : 61721ac5-c139-de00-c167-9e2edda49471
     name-label ( RW): v-2-VM
    power-state ( RO): running

uuid ( RO)           : 464b1a57-1d82-eb33-b8da-93f029289389
     name-label ( RW): s-1-VM
    power-state ( RO): running

(4) You can find more details in log files:

1. vmops.log in testing directory (WORK-VM).
2. /var/log/xcp-xapi.log inside DevCloud.

(5) If you want to attach the git branch name to directory path, please follow the article: “Git tip: Show your branch name on the Linux prompt”

(6) If we change some source codes, but now willing to build all projects as it take a long time. We can build the specified projects using maven.

mvn –P developer –pl api,server		# if you want to re-build api and server projects
cp ./api/target/cloud-api-4.2.1-SNAPSHOT.jar ./client/target/cloud-client-ui-4.2.1-SNAPSHOT/WEB-INF/lib/cloud-api-4.2.1-SNAPSHOT.jar
cp ./server/target/cloud-server-4.2.1-SNAPSHOT.jar ./client/target/cloud-client-ui-4.2.1-SNAPSHOT/WEB-INF/lib/cloud-server-4.2.1-SNAPSHOT.jar

If you want to re-build systemvm.iso which is attached to system VMs when they start.

mvn -P developer,systemvm -pl patches/,services/console-proxy/,services/console-proxy/server/
cp ./services/console-proxy/server/dist/systemvm.iso ./client/target/cloud-client-ui-4.2.1-SNAPSHOT/WEB-INF/classes/vms/systemvm.iso
scp ./services/console-proxy/server/dist/systemvm.iso 192.168.56.10:/usr/share/xcp/packages/iso/systemvm.iso

References

[1] http://www.leaseweb.com/en/about-us/press/leaseweb-introduces-new-private-cloud-platform-powered-by-apache-cloudstack
[2] http://cloudstack.apache.org/
[3] https://pypi.python.org/pypi/cloudmonkey/
[4] https://cwiki.apache.org/confluence/display/CLOUDSTACK/DevCloud
[5] http://people.apache.org/~bhaisaab/cloudstack/devcloud/devcloud2.ova
[6] https://cloudstack.apache.org/docs/en-US/Apache_CloudStack/4.2.0/html/Admin_Guide/working-with-system-vm.html
[7] http://cloudstack.apache.org/docs/en-US/Apache_CloudStack/4.2.0/html/Installation_Guide/deployment-architecture-overview.html
[8] http://wiki.xen.org/wiki/XCP_Command_Line_Interface
[9] http://www.leaseweb.com/labs/2013/08/git-tip-show-your-branch-name-on-the-linux-prompt/