Skip to content
Rohit Yadav edited this page Aug 8, 2022 · 11 revisions

Link to old docs: https://cwiki.apache.org/confluence/display/CLOUDSTACK/CloudStack+cloudmonkey+CLI

Server profiles

CloudMonkey supports multiple (management) server profiles, using which one can use to make API requests to different CloudStack servers. If cloudmonkey starts for the first time, it will create a default server profile by the name [localcloud] and use the following default values which one can then override using the set command. The default cmk config file at ~/.cmk/config looks as follows:

prompt          = 🐱
asyncblock      = true
timeout         = 1800
output          = json
verifycert      = true
profile         = localcloud

[localcloud]
url       = http://localhost:8080/client/api
username  = admin
password  = password
domain    = /
apikey    = 
secretkey = 

To create a new server profile, one can use set profile <profile-name> and this will create a new server profile config section in ~/.cmk/config and use the above default values. You can set parameters of a server profile such as the url, username, password and it will set the passed values for the current server profile.

These are the various options you can configure in cmk using set:

Option Description Default
prompt The CLI prompt 🐱
asyncblock Whether to block and poll for async API job result, valid options: true and false true
timeout The API timeout in seconds 1800
output The API response output format, valid options: json, table, text, column, csv json
verifycert Whether to verify X509/TLS certificate if URL is https enabled true
profile The server profile name, set will switch to an existing profile or create a new profile with default if it does not exist localcloud
autocomplete To enable or disable auto-completion of an API's parameter values true
url* The CloudStack server API url http://localhost:8080/client/api
username* The user's username admin
password* The user's password password
domain* The user's domain /
apikey* The user's API key
secretkey* The user's secret key

Notes:

  • Options marked with * are settings server profile settings, other settings are core/global settings.
  • When both api/secret key and username/passwords are provided, the api/secret keys take precedence for API authentication over username/password.
  • An additional setting debug exists when can be turned on to enable console based debugging.

Shell and Interactive Usage

cmk implements readline compliant shell and most of the emacs/readline bindings are honoured. For example: Ctrl+r (reverse search), 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.

The command history can be accessed by using up/down arrow keys as well and it is saved at ~/.cmk/history.

Debugging

Debugging in log is disabled, but you can enable debugging on console by starting CloudMonkey with cmk -d or use set debug [true|false].

Argument passing

Arguments can be passed to an api command using the syntax <cmd> <verb> key1=value1 .... CloudMonkey's shell input parsing is similar to shlex and arguments are split by spaces. Arguments/values with space in them can be wrapped instead double/single quotes such as list api arg1="some value with spaces" arg2='example input'.

If values have spaces, one can put them under quotes, like:

> create project name="my unique name" displaytext="my lengthy description"

Some APIs accept array or maps as their arguments, in that case use arg0.key=value syntax. For example, while creating network offering:

> create networkoffering supportedservices=Dhcp,Dns serviceproviderlist[0].service=Dhcp serviceproviderlist[0].provider=VirtualRouter serviceproviderlist[1].service=Dns serviceproviderlist[1].provider=VirtualRouter

Content of a file can be passed using a special syntax of @/path/to/file passed to the API request. For example:

> upload customcertificate certificate=@/tmp/c.crt privatekey=@/tmp/c.key domainsuffix=some.domain.com

Text processing using pipes

Text processing is very easy, one can pipe the output to other terminal tools such as awk, sed, grep, jq etc. Examples:

$ cmk list users | jq -r '.user[].id'
$ cmk ...
> list accounts listall=true | grep 'id'
> list users | wc -l

Raw API execution

You may directly call the API on the shell or command-line to execute it, for example:

> listUsers
> uploadVolume url=xxx format=yyy name=zzz zoneid=aaa

Async Job execution

There are two kinds of APIs in CloudStack; blocking or synchronous, and non-blocking or asynchronous. By default, CloudMonkey will poll and wait for async APIs to finish and return a response. This behaviour can be changed by seting asyncblock to false:

> set asyncblock false

When asynblock is false, CloudMonkey will return a jobid which can be used to poll the result of the API using the query asyncjobresult API request. For example:

> query asyncjobresult jobid=<job-id>

Output

Irrespective of the configured output, the filter argument can be clubbed with an API request (generally with list/get APIs) to filter the API response based on the provided list of comma-separated response keys.

The JSON output is the default output. For example:

(mycloud) 🐱 > set output json
(mycloud) 🐱 > list users account=admin filter=
account,             accountid,           accounttype,         apikey,              created,             domain,              domainid,            email,               
firstname,           id,                  iscallerchilddomain, isdefault,           lastname,            roleid,              rolename,            roletype,            
secretkey,           state,               timezone,            username,            usersource, 
(mycloud) 🐱 > list users account=admin filter=account,id,domain,username,
{
  "count": 1,
  "user": [
    {
      "account": "admin",
      "domain": "ROOT",
      "id": "7966afa9-3cd4-11e9-bf33-f4d1082409e6",
      "username": "admin"
    }
  ]
}
(mycloud) 🐱 > set output table
(mycloud) 🐱 > list users account=admin filter=account,id,domain,username
user:
count = 1
+---------+--------+--------------------------------------+----------+
| ACCOUNT | DOMAIN |                  ID                  | USERNAME |
+---------+--------+--------------------------------------+----------+
| admin   | ROOT   | 7966afa9-3cd4-11e9-bf33-f4d1082409e6 | admin    |
+---------+--------+--------------------------------------+----------+
(mycloud) 🐱 > set output text
(mycloud) 🐱 > list users account=admin filter=account,id,domain,username
count = 1
user:
account = admin
id = 7966afa9-3cd4-11e9-bf33-f4d1082409e6
domain = ROOT
username = admin
(mycloud) 🐱 > set output column
(mycloud) 🐱 > list users account=admin filter=account,id,domain,username
ACCOUNT   DOMAIN   ID                                     USERNAME
admin     ROOT     7966afa9-3cd4-11e9-bf33-f4d1082409e6   admin
(mycloud) 🐱 > list users account=admin filter=account,id,domain,username
account,domain,id,username
admin,ROOT,7966afa9-3cd4-11e9-bf33-f4d1082409e6,admin

Shell Script Usage

The modern CloudMonkey is backwards compatible with legacy cloudmonkey and can be used as a drop-in replacement for shell script and automation related usage. The follow example illustrates how one can use cmk to automate their deployments, this one deploys a basic zone:

#!/bin/bash
 
cli=cmk
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!"