h2. What is cloudmonkey?

_cloudmonkey_ is a command line interface (CLI) tool written in python that leverages Marvin that provides cloudstackAPI. cloudmonkey can be use both as an interactive shell and as a command line tool which simplifies CS configuration and management. It is unofficially distributed by community maintained distribution at the cheese shop [http://pypi.python.org/pypi/cloudmonkey/] as well as within the git repository in tools/cli/. It can be used with Apache CloudStack 4.0-incubating and above.

h2. Features

- Usable as a command line tool and interactive shell
- All commands are lowercase unlike API
- Precached APIs, doc strings and params
- Raw api execution support
- Auto-completion via double <tab>
- Reverse search using Ctrl+R
- Emacs compatible keybindings
- Pipeable output
- Unix shell execution
- Support to handle async jobs using user defined blocking or non-blocking way
- Tabular output
- Colored output

h2. Installation

h3. Requirements

cloudmonkey requires Python 2.5 or above and has following dependencies:

{code}
readline
clint
{code}

h4. Platform independent installation

For installing any Python package, _pip_ is recommended: [http://www.pip-installer.org/en/latest/installing.html]

{code}
$ pip install cloudmonkey
{code}

To upgrade:
{code}
$ pip install --upgrade cloudmonkey
{code}

Thought a clean upgrade is recommended:
{code}
$ pip uninstall cloudmonkey
$ pip install cloudmonkey
{code}

h4. RHEL/CentOS 6.x (internet access required for python eggs repository)

{code}
$ yum install python-setuptools
$ easy_install cloudmonkey
{code}

or if pip available (pip is recommended)
{code}
$ pip install cloudmonkey
{code}

h4. Ubuntu/Debian

{code}
$ apt-get install python-pip
$ pip install cloudmonkey
{code}

Or, if pip is not available
{code}
$ apt-get install python-setuptools
$ easy_install cloudmonkey
{code}

h4. Building from source code withing source code

{code}
$ git clone https://git-wip-us.apache.org/repos/asfgit clone https://git-wip-us.apache.org/repos/asf/incubator-cloudstack.git
$ mvn clean install -P developer
$ cd tools/cli # cloudmonkey-x.x.x.tar.gz will be built in dist
$ python setup.py build
$ python setup.py install
{code}

h2. Configuration

cloudmonkey gets configuration from \~/.cloudmonkey_config which is it's config file in user's home directory.

Further it logs in \~/.cloudmonkey_log and stores history in \~/.cloudmonkey_history. The log and history files can be custom paths and can be configured by setting appropriate file paths in \~/.cloudmonkey_config or by command:
{code}
$ cloudmonkey
> set history_file /usr/share/cloudmonkey_history
> set log_file /var/log/cloudmonkey
{code}

There are other parameters which can be customized:
| *Key* | *Purpose* | *Default* |
| host | IP or resolvable domain of management server | localhost |
| port | Api server port, 8080 is encouraged over 8096 | 8080 |
| protocol | Specifies http or https | http |
| path | Specifies the absolute path to the api on the specified host | /client/api |
| apikey | User api key | "" |
| secretkey | User secret key | "" |
| prompt | cloudmonkey prompt, default prompt has a UTF-8 char which can be an issue | 🐵  cloudmonkey> |
| asyncblock | Poll for async commands, making it false will cause cloudmonkey to return jobid | true |
| timeout | Timeout interval for polling async commands | 3600 |
| color | Enable coloured output, set to false to disable | true |
| tabularize | Enable tabular output, set to true to ensable | false |
| log_file | Log file | \~/.cloudmonkey_log |
| history_file | History file | \~/.cloudmonkey_history |

h2. Usage

h3. Getting started

First set your host, port, apikey and secretkey using set. Api and Secret keys can be created via CloudStack management server UI, Accounts->Users->Generate keys.

{code}
> set host 192.168.56.1
> set port 8080
> set apikey <put-your-api-key-for-your-user>
> set secretkey <put-your-secret-key-for-your-user>
> set prompt mycloudmonkey>
{code}

Make sure your management server is running, try out some commands:
{code}
> <tab><tab>
> list <tab><tab>
> list users <tab><tab>
{code}

h3. Getting help

Help for any command can be obtained using help <cmd> or ?<cmd> or <cmd> \--help or <cmd> \-h, examples:
{code}
> help list
> help list users
> ?list
> ?list users
> list users --help
> list users -h
{code}

A typical help doc for an api will list all available acceptable arguments and required arguments.

h3. Tabular output

You may enable tabular listing and even choose set of column fields, this allows you to create your own field using the filter param which takes in comma separated argument. If argument has a space, put them under double quotes. The create table will have the same sequence of field filters provided. If your present cli does not have this, pl. upgrade cloudmonkey: pip install --upgrade cloudmonkey
To enable tabular output:

{code}
> set tabularize true
{code}

Examples:
{code}
> list domains listall=true
> list domains listall=true filter=id,name,path
{code}

h3. Emacs style key handling

Ctrl+a (start of the line)
Ctrl+e (end of the line)
Ctlr+w (remove one word from back)
Ctrl+u (remove whole line) etc.

h3. Reverse Searching

Ctrl+R etc. If it does not work and also any issue with tab completion it's probably a readline issue on your env. If autocompletion using tabs does not work for you, pl. open an issue on jira, issues.a.o

h3. Comments within shell

Anything after # is treated as comment and is not processed on the shell.

h3. Debug log

By default cloudmonkey logs in ~/.cloudmonkey_log which can be changed using the set command:

{code}
> set log_file /var/log/cloud-cli.log
{code}

One can tail the log to keep track on what's happening:
{code}
> tail -f ~/.cloudmonkey_log
{code}

h3. Using as a command line tool

Use cloudmonkey as a command line tool, by passing args to cloudmonkey. Example:
{code}
$ cloudmonkey list users
$ cloudmonkey create domain name=mydomain
{code}

It can also take in list of commands from a file and interpret them, for example:
{code}
$ cat file-with-cmds
list users
list zones
$ cloudmonkey < file-with-cmds
{code}


The follow example illustrates how one can use cloudmonkey to automate their deployments, this one deploys a basic zone:
{code}
#!/bin/bash

cli=cloudmonkey
dns_ext=8.8.8.8
dns_int=10.147.28.6
gw=10.147.28.1
nmask=255.255.255.0
hpvr=XenServer
pod_start=10.147.28.225
pod_end=10.147.28.234
vlan_start=10.147.28.235
vlan_end=10.147.28.254

#Put space separated host ips in following
host_ips=10.147.28.60
host_user=root
host_passwd=password
sec_storage=nfs://10.147.28.7/export/home/rohit/secondary
prm_storage=nfs://10.147.28.7/export/home/rohit/primary

zone_id=`$cli create zone dns1=$dns_ext internaldns1=$dns_int name=MyZone networktype=Basic | grep ^id\ = | awk '{print $3}'`
echo "Created zone" $zone_id

phy_id=`$cli create physicalnetwork name=phy-network zoneid=$zone_id | grep ^id\ = | awk '{print $3}'`
echo "Created physical network" $phy_id
$cli add traffictype traffictype=Guest physicalnetworkid=$phy_id
echo "Added guest traffic"
$cli add traffictype traffictype=Management physicalnetworkid=$phy_id
echo "Added mgmt traffic"
$cli update physicalnetwork state=Enabled id=$phy_id
echo "Enabled physicalnetwork"

nsp_id=`$cli list networkserviceproviders name=VirtualRouter physicalnetworkid=$phy_id | grep ^id\ = | awk '{print $3}'`
vre_id=`$cli list virtualrouterelements nspid=$nsp_id | grep ^id\ = | awk '{print $3}'`
$cli api configureVirtualRouterElement enabled=true id=$vre_id
$cli update networkserviceprovider state=Enabled id=$nsp_id
echo "Enabled virtual router element and network service provider"

nsp_sg_id=`$cli list networkserviceproviders name=SecurityGroupProvider physicalnetworkid=$phy_id | grep ^id\ = | awk '{print $3}'`
$cli update networkserviceprovider state=Enabled id=$nsp_sg_id
echo "Enabled security group provider"

netoff_id=`$cli list networkofferings name=DefaultSharedNetworkOfferingWithSGService | grep ^id\ = | awk '{print $3}'`
net_id=`$cli create network zoneid=$zone_id name=guestNetworkForBasicZone displaytext=guestNetworkForBasicZone networkofferingid=$netoff_id | grep ^id\ = | awk '{print $3}'`
echo "Created network $net_id for zone" $zone_id

pod_id=`$cli create pod name=MyPod zoneid=$zone_id gateway=$gw netmask=$nmask startip=$pod_start endip=$pod_end | grep ^id\ = | awk '{print $3}'`
echo "Created pod"

$cli create vlaniprange podid=$pod_id networkid=$net_id gateway=$gw netmask=$nmask startip=$vlan_start endip=$vlan_end forvirtualnetwork=false
echo "Created IP ranges for instances"

cluster_id=`$cli add cluster zoneid=$zone_id hypervisor=$hpvr clustertype=CloudManaged podid=$pod_id clustername=MyCluster | grep ^id\ = | awk '{print $3}'`
echo "Created cluster" $cluster_id

#Put loop here if more than one
for host_ip in $host_ips;
do
$cli add host zoneid=$zone_id podid=$pod_id clusterid=$cluster_id hypervisor=$hpvr username=$host_user password=$host_passwd url=http://$host_ip;
echo "Added host" $host_ip;
done;

#$cli create storagepool zoneid=$zone_id podid=$pod_id clusterid=$cluster_id name=MyNFSPrimary url=$prm_storage
#echo "Added primary storage"

$cli add secondarystorage zoneid=$zone_id url=$sec_storage
echo "Added secondary storage"

$cli update zone allocationstate=Enabled id=$zone_id
echo "Basic zone deloyment completed!"

{code}

h3. Argument passing

Arguments can be passed to an api command using the syntax; <cmd> <verb> key1=value1 etc.
By default cloudmonkey's lexical parser parses like shlex and split by spaces.

If values have spaces, one can put them under quotes, like:
{code}
> create project name="my unique name" displaytext="my lengthy description"
{code}

Some api accept array or maps as their arguments, in that case use arg[0].key=value syntax. For example, while creating network offering:
{code}
> create networkoffering supportedservices=Dhcp,Dns serviceproviderlist[0].service=Dhcp serviceproviderlist[0].provider=VirtualRouter serviceproviderlist[1].service=Dns serviceproviderlist[1].provider=VirtualRouter
{code}

h3. Text processing using pipes

Text processing is very easy, one can pipe the data and call their favourite text processors, be it awk, sed or grep.
Examples:
{code}
> list accounts listall=true | grep ^id\ =
> list users | wc -l
> list routers | more
{code}

h3. Automation using shell

Automation can be done using shell or \! followed by shell commands. For example:
{code}
> shell ls -lahi
> shell whoami
> shell ssh root@<ip>
> !date
> !ping google.com
{code}

For example if one has to create 100 users, one can execute cloudmonkey with args in a loop:
{code}
> !for((i=0;i<100;i++)); do cloudmonkey create user username=user$i account=admin firstname=user$i lastname=user$i password=password$i email=user$i@domain.org; done;
{code}

h3. Raw API execution

Use the special command api to send a raw api. It does not do autocompletion and assumes the user knows what he's trying to do.
For example:
{code}
> api uploadVolume url=xxx format=yyy name=zzz zoneid=aaa
{code}

h3. Async Job execution

There are two kinds of apis in CloudStack, one are blocking or synchronous and other one is non-blocking or asynchronous. By default for async apis like deploying a vm ec. are polled by cloudmonkey, one can set cloudmonkey not to poll or wait till the api is finished using:

{code}
> set asyncblock false
{code}

This causes an async command in cloudmonkey to return a jobid which can be used to poll the completion of that command. This is particularly useful if one wants to starts a lot of VMs without having to wait for the commands to complete. The job can be polled using query async job command, like:
{code}
> query asyncjobresult jobid=<job-id>
{code}

h2. TODOs

0. Unicode support
1. Bash/zsh completion (example: [https://github.com/bobthecow/git-flow-completion/])
2. DocBook Documentation

h2. About

cloudmonkey was named after the beloved mascot of Apache CloudStack and is powered by Marvin.
Author: The Apache CloudStack Team <cloudstack-dev@incubator.apache.org>
Maintainer: Rohit Yadav <bhaisaab@apache.org>
