skip to navigation
skip to content

opdemand 0.9

Command-line Client for OpDemand

Downloads ↓

Latest Version: 0.9.3

The opdemand-cli project contains the command-line client interface to the OpDemand system. These python modules use OpDemand's REST API.

Open Source

The opdemand-cli project has been made open source by OpDemand.

OpDemand CLI Documentation

Before you begin

  • You will need an active OpDemand account. Create one at http://www.opdemand.com
  • Instructions assume OSX or Linux (Windows has not been tested, but should work)

Installation

Installation uses standard distutils convention.

sudo pip install opdemand

Logging In

Issue an opdemand login, which will prompt you for a username and password.

user@box:~$ opdemand login
username: myuser
password:
2011-06-07 08:44:12,052 - INFO - => POST https://c2.opdemand.com/api/system/session
2011-06-07 08:44:13,095 - INFO - <= 201 Created, reading 4082 bytes of application/json
{
    # JSON Representation of the login session
}
2011-06-07 08:44:13,169 - INFO - (login) success in 3.283798s

Submit your AWS credentials

Edit the template provided in json/aws_credentials.json and supply the correct:

  • Email
  • Access Key
  • Secret Key

Issue an opdemand credential create and read the credential body from standard input.

user@box:~$ opdemand credential create - < json/aws_credentials.json
2011-06-07 08:59:07,811 - INFO - reading object from stdin, ctrl-c to break...
2011-06-07 08:59:07,826 - INFO - => POST https://c2.opdemand.com/api/account/myuser/credential
2011-06-07 08:59:10,278 - INFO - <= 201 Created, reading 23623 bytes of application/json
{
        # JSON Representation of credentials and their associated "clouds"
}
2011-06-07 08:59:10,527 - INFO - (credential/create) success in 2.716193s

Note: "-" parameter specifies reading from stdin

List Platform Templates

You now have access to the OpDemand Template Library. Issue an opdemand template list to view available templates.

user@box:~$ opdemand template list
2011-06-07 09:21:21,374 - INFO - => GET https://c2.opdemand.com/api/lib/system/core
2011-06-07 09:21:21,879 - INFO - <= 200 OK, reading 1822 bytes of application/json
[     # JSON list of templates
  {
      # First template
  },
  {
      # Second template
  }
]
2011-06-07 09:21:21,881 - INFO - (template/list) success in 0.524872s

Find the _id value of the template you want to deploy, and copy it to your clipboard.

Create a new Platform

Select the desired template and issue a opdemand template load of the template _id, which will create a fresh platform.

user@box:~$ opdemand template load --_id=6c86dfc5ddfe464199021b8dcaf521a2
2011-06-07 09:42:36,711 - INFO - => POST https://c2.opdemand.com/api/lib/system/core/template/6c86dfc5ddfe464199021b8dcaf521a2/load
2011-06-07 09:42:38,606 - INFO - <= 201 Created, reading 14850 bytes of application/json
{
    # Much longer JSON representation of the template

}
2011-06-07 09:42:38,757 - INFO - (template/load) success in 2.061932s

List Platforms

Issue an opdemand platform list to see the available platforms in your account.

user@box:~$ opdemand platform list
2011-06-07 09:46:48,327 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform
2011-06-07 09:46:48,884 - INFO - <= 200 OK, reading 566 bytes of application/json
[
  {
      # Your new platform
  }
]
2011-06-07 09:46:48,885 - INFO - (platform/list) success in 0.572228s

Copy the _id of this platform to your clipboard.

Read the platform

List operations only show summary representations of items in a collection. To view the full representation of a platform (one that includes its nested components) you must issue a opdemand platform read and provide the _id:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:16:06,050 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:16:06,984 - INFO - <= 200 OK, reading 14850 bytes of application/json
{
        # Full platform representation
}
2011-06-07 10:16:07,152 - INFO - (platform/read) success in 1.117754s

Working with JSON responses

The above platform is too long to read. Fortunately the OpDemand shell includes an integrated JSON prettifier that makes JSON output from any OpDemand command much easier to read.

Simply pipe any opdemand command to opdemand pretty:

user@box:~$ opdemand template read --_id=6c86dfc5ddfe464199021b8dcaf521a2 | opdemand pretty
2011-06-07 09:32:00,646 - INFO - => GET https://c2.opdemand.com/api/lib/system/core/template/6c86dfc5ddfe464199021b8dcaf521a2
2011-06-07 09:32:01,378 - INFO - <= 200 OK, reading 12022 bytes of application/json
2011-06-07 09:32:01,535 - INFO - (template/read) success in 0.904613s
tiers.0.name                                                        "Network Tier"
tiers.0.doctype                                                     "tier"
tiers.0._rev                                                        "1-5a37d211b276deee536cd72a016af8fa"
...rest of prettified JSON

All OpDemand commands read from standard input and write to standard output. This means raw JSON and prettified JSON can be piped to any other command that uses UNIX-style pipes. (e.g. grep).

Configure the platform

First read the platform and grep for the default config information:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep config
2011-06-07 10:26:29,828 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:26:30,486 - INFO - <= 200 OK, reading 14850 bytes of application/json
2011-06-07 10:26:30,635 - INFO - (platform/read) success in 0.821403s
config.access_network                                           "0.0.0.0/0"
config.image_id                                                 "ami-06ad526f"
config.doctype                                                  "config"
config._rev                                                     "1-38d720a0975e4d377ccbfd3cb7864185"
config.access_port                                              "22"
config.cloud_name                                               "us-east-1"
config.clone_.parent_id                                         "ceee3724a3674bc096a2a6d2dfde7209"
config.clone_.parent_impl.cls_                                  "c2.resolve.Config"
config.admin_network                                            "0.0.0.0/0"
config._id                                                      "ceee3724a3674bc096a2a6d2dfde7209"
config.impl.cls_                                                "c2.resolve.Config"
config.views.7bbeacb1082e4810bb1a6643d024496e.0.0               "7bbeacb1082e4810bb1a6643d024496e"
config.views.7bbeacb1082e4810bb1a6643d024496e.0.1               "config"
metadata.config_info.access_port                                "Port listening on the server"
metadata.config_info.access_network                             "Network mask for public users"
metadata.config_info.cloud_name                                 "Name of AWS region"
metadata.config_info.admin_network                              "Network mask for admin users"

Let's restrict all network access to one host -- 1.1.1.1/32. This will require changing the access_network and admin_network keys.

Since config is a nested document with its own _id and _rev, we must modify the config document directly. To do this, we follow the RESTful convention of reading the representation and piping it to an update operation:

user@box:~$ opdemand config read --_id=ceee3724a3674bc096a2a6d2dfde7209 | opdemand config update - --access_network=1.1.1.1/32 --admin_network=1.1.1.1/32
2011-06-07 10:35:39,643 - INFO - reading object from stdin, ctrl-c to break...
2011-06-07 10:35:39,661 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/config/ceee3724a3674bc096a2a6d2dfde7209
2011-06-07 10:35:40,573 - INFO - <= 200 OK, reading 692 bytes of application/json
2011-06-07 10:35:40,574 - INFO - (config/read) success in 0.931527s
2011-06-07 10:35:40,603 - INFO - => PUT https://c2.opdemand.com/api/env/myuser/master/config/ceee3724a3674bc096a2a6d2dfde7209
2011-06-07 10:35:41,316 - INFO - <= 200 OK, reading 694 bytes of application/json
{
  "_id": "ceee3724a3674bc096a2a6d2dfde7209",
  "_rev": "2-6a1cac4a1851fead776d4184e1218028",
  "access_network": "1.1.1.1/32",
  "access_port": "22",
  "admin_network": "1.1.1.1/32",
  "....": "...."
}
2011-06-07 10:35:41,317 - INFO - (config/update) success in 0.730138s

Re-read the platform configuration to confirm the parent document includes the updated, nested configuration:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep config
2011-06-07 10:37:11,131 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:37:11,825 - INFO - <= 200 OK, reading 14852 bytes of application/json
2011-06-07 10:37:11,977 - INFO - (platform/read) success in 0.862029s
config.access_network                                           "1.1.1.1/32"
config.image_id                                                 "ami-06ad526f"
config.doctype                                                  "config"
config._rev                                                     "2-6a1cac4a1851fead776d4184e1218028"
config.access_port                                              "22"
config.cloud_name                                               "us-east-1"
config.clone_.parent_id                                         "ceee3724a3674bc096a2a6d2dfde7209"
config.clone_.parent_impl.cls_                                  "c2.resolve.Config"
config.admin_network                                            "1.1.1.1/32"
config._id                                                      "ceee3724a3674bc096a2a6d2dfde7209"
config.impl.cls_                                                "c2.resolve.Config"
config.views.7bbeacb1082e4810bb1a6643d024496e.0.0               "7bbeacb1082e4810bb1a6643d024496e"
config.views.7bbeacb1082e4810bb1a6643d024496e.0.1               "config"
metadata.config_info.access_port                                "Port listening on the server"
metadata.config_info.access_network                             "Network mask for public users"
metadata.config_info.cloud_name                                 "Name of AWS region"
metadata.config_info.admin_network                              "Network mask for admin users"

Start the platform

With our AWS credentials in place, and our platform queued up we're ready to go. Issue a opdemand platform start and let the orchestration begin:

user@box:~$ opdemand platform start --_id=7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:42:52,849 - INFO - => POST https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e?action=start&async=true
2011-06-07 10:42:53,816 - INFO - <= 202 Accepted, reading 0 bytes of application/json
2011-06-07 10:42:53,816 - INFO - (platform/start) success in 0.981219s

To follow the platform's progress, read the full platform representation and grep for the status of all nested objects:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep status
2011-06-07 10:43:06,530 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:43:07,228 - INFO - <= 200 OK, reading 22227 bytes of application/json
2011-06-07 10:43:07,451 - INFO - (platform/read) success in 0.935643s
tiers.0.status_.value                                           "building"
tiers.0.keypair.status_.detail                                  "key pair created"
tiers.0.keypair.status_.value                                   "built"
tiers.0.sg.status_.detail                                       "rules authorized successfully"
tiers.0.sg.status_.value                                        "built"
tiers.1.status_.value                                           "building"
tiers.1.server.status_.detail                                   "waiting for running, currently pending"
tiers.1.server.status_.value                                    "building"
status_.detail                                                  "start operation triggered"
status_.value                                                   "starting"

We can see the platform-level status is starting. Re-issue this command a number of times to "poll" status. Grepping for state is also useful for demonstrating which components are currently transitioning. Once the platform is done, status should look as follows:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep status
2011-06-07 10:44:21,015 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:44:21,736 - INFO - <= 200 OK, reading 27129 bytes of application/json
2011-06-07 10:44:21,988 - INFO - (platform/read) success in 0.990599s
tiers.0.status_.detail                                          "started successfully"
tiers.0.status_.value                                           "running"
tiers.0.keypair.status_.detail                                  "key pair created"
tiers.0.keypair.status_.value                                   "running"
tiers.0.sg.status_.detail                                       "rules authorized successfully"
tiers.0.sg.status_.value                                        "running"
tiers.1.status_.detail                                          "started successfully"
tiers.1.status_.value                                           "running"
tiers.1.server.status_.detail                                   "listener ready at 22/tcp"
tiers.1.server.status_.value                                    "running"
status_.detail                                                  "start operation successful"
status_.value                                                   "running"

Note a parent-level status of "running" with the server listener ready on 22/tcp. Our platform is ready.

Using the platform

All platforms publish information about how they are used. Most platforms publish some combination of:

  • URLs
  • Hostname/Port combinations
  • Logins
  • Passwords

If we read the platform and grep for publish we can see this platform published a simple SSH url:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep publish
2011-06-07 10:51:30,694 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:51:31,764 - INFO - <= 200 OK, reading 27129 bytes of application/json
2011-06-07 10:51:32,038 - INFO - (platform/read) success in 1.367026s
tiers.1.server.publish.access_url                               "ssh://ubuntu@ec2-50-19-55-84.compute-1.amazonaws.com/"
metadata.publish_info.access_url                                "URL for accessing the platform"

A common pattern is for platforms to publish:

  • Admin URL
  • Admin Login
  • Admin Password
  • Access URL

Stopping the platform

Once the platform has stopped, its status will look something like this:

user@box:~$ opdemand platform read --_id=7bbeacb1082e4810bb1a6643d024496e | opdemand pretty | grep status
2011-06-07 10:57:51,345 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 10:57:52,128 - INFO - <= 200 OK, reading 27966 bytes of application/json
2011-06-07 10:57:52,424 - INFO - (platform/read) success in 1.093576s
tiers.0.status_.detail                                          "stopped successfully"
tiers.0.status_.value                                           "stopped"
tiers.0.keypair.status_.detail                                  "key pair created"
tiers.0.keypair.status_.value                                   "stopped"
tiers.0.sg.status_.detail                                       "rules authorized successfully"
tiers.0.sg.status_.value                                        "stopped"
tiers.1.status_.detail                                          "stopped successfully"
tiers.1.status_.value                                           "stopped"
tiers.1.server.status_.detail                                   "waiting for stopped, currently stopped"
tiers.1.server.status_.value                                    "stopped"
status_.detail                                                  "stop operation successful"
status_.value                                                   "stopped"

The platform still exists in the cloud, but it is no longer incurring expensive compute costs (it is, however incurring negligible storage costs). You're also no longer incurring OpDemand usage fees. At this point, your platform costs effectively nothing.

Platforms can be stopped and started without limit.

Destroy the platform

To actually destroy all of the cloud components included in your platform, you must issue a opdemand platform destroy and provide the _id of the target platform:

user@box:~$ opdemand platform destroy --_id=7bbeacb1082e4810bb1a6643d024496e
2011-06-07 11:04:10,667 - INFO - => POST https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e?action=destroy&async=true
2011-06-07 11:04:11,953 - INFO - <= 202 Accepted, reading 0 bytes of application/json
2011-06-07 11:04:11,953 - INFO - (platform/destroy) success in 1.300462s

Delete the platform

If you list the platforms you'll see that the destroyed platform still exists:

user@box:~$ opdemand platform list | opdemand pretty
2011-06-07 11:12:02,771 - INFO - => GET https://c2.opdemand.com/api/env/myuser/master/platform
2011-06-07 11:12:03,149 - INFO - <= 200 OK, reading 1577 bytes of application/json
2011-06-07 11:12:03,150 - INFO - (platform/list) success in 0.394324s
0.views.7bbeacb1082e4810bb1a6643d024496e.0.0    "7bbeacb1082e4810bb1a6643d024496e"
0.time_.disconnect.date_                        "1307466249.487580"
0.time_.stop.date_                              "1307465858.607597"
0.time_.start.date_                             "1307465019.767619"
0.time_.build.date_                             "1307465019.475195"
0.time_.destroy.date_                           "1307466249.487347"
0.time_.connect.date_                           "1307466240.220381"
0.status_.detail                                "destroy operation successful"
0.status_.value                                 "destroyed"
0.doctype                                       "platform"
0._rev                                          "7-38fe44c5a900894adf48f4a416c94338"
0.template.cls_                                 "lib.platform.vanilla.natty.UbuntuNattyPlatform"
0._id                                           "7bbeacb1082e4810bb1a6643d024496e"
0.state.running                                 false
0.state.transitioning                           false
0.state.built                                   false
0.impl.cls_                                     "lib.platform.vanilla.natty.UbuntuNattyPlatform"
0.interval_.destroy                             9.3936290740966797
0.interval_.stop                                33.600441932678223
0.interval_.build                               57.54404091835022
0.interval_.start                               57.836580991744995

From the interval you can see it took:

  • 58 seconds to start this platform
  • 33 seconds to stop it
  • 9 seconds to destroy it

You can always re-start a destroyed platform and have it rebuild the cloud components again. However to complete delete the platform and its nested documents, you must issue an opdemand platform delete:

user@box:~$ opdemand platform delete --_id=7bbeacb1082e4810bb1a6643d024496e
2011-06-07 11:15:45,235 - INFO - => DELETE https://c2.opdemand.com/api/env/myuser/master/platform/7bbeacb1082e4810bb1a6643d024496e
2011-06-07 11:15:46,474 - INFO - <= 204 No Content, reading 0 bytes of application/json
2011-06-07 11:15:46,474 - INFO - (platform/delete) success in 1.252582s

To confirm, we can see our platform list is now empty:

user@box:~$ opdemand platform list
2011-06-07 11:15:51,890 - INFO - => GET https://c2.opdemand.com/platform
2011-06-07 11:15:52,296 - INFO - <= 200 OK, reading 2 bytes of application/json
2011-06-07 11:15:52,297 - INFO - (platform/list) success in 0.423616s

Logging out

By issuing a opdemand info we can see the status of our session:

user@box:~/workspace/c2-shell$ opdemandinfo
2011-06-07 11:17:11,656 - INFO - => GET https://c2.opdemand.com/api/system/session/73c2e9b49d01c695fb6c74927b8eb0eee5cdc82c2064cd728a8033eb83ea5b95
2011-06-07 11:17:12,134 - INFO - <= 200 OK, reading 4082 bytes of application/json
{
  "expires_at": "Friday, 10 June 2011 08:44AM",
  "session_id": "73c2e9b49d01c695fb6c74927b8eb0eee5cdc82c2064cd728a8033eb83ea5b95",
  "username": "myuser"
}
2011-06-07 11:17:12,138 - INFO - (info) success in 0.497018s

Logging out is simply opdemand logout:

user@box:~$ opdemand logout
2011-06-07 11:17:44,903 - INFO - => DELETE https://c2.opdemand.com/api/system/session/73c2e9b49d01c695fb6c74927b8eb0eee5cdc82c2064cd728a8033eb83ea5b95
2011-06-07 11:17:45,330 - INFO - <= 204 No Content, reading 0 bytes of application/json
2011-06-07 11:17:45,330 - INFO - (logout) success in 0.443405s
user@box:~$ opdemand info
2011-06-07 11:17:49,025 - INFO - (info) success in 0.000376s
 
File Type Py Version Uploaded on Size # downloads
opdemand-0.9.tar.gz (md5) Source 2012-01-10 12KB 366