
h2. What is cloudmonkey?

{panel}
_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.
{panel}

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
- 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 python-pip
$ pip install cloudmonkey
{code}

Or, if pip is not available
{code}
$ apt get 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 | (development version only) Specifies http or https | http |
| path | (development version only) 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 |
| 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. 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 and rest you know :-)

h3. Comments within shell

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

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}

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>
