Cluster lifecycle management endpoints overview

The Lifecycle Manager (LCM) API provides tools for provisioning and configuring DataStax Enterprise (DSE) on existing hardware or virtual machines. This is a RESTful API that supports everything provided by the DSE OpsCenter LCM user interface and allows for greater control and automation by API users.

LCM implements a centralized approach to configuration management and installation. The OpsCenter server maintains what the state of the cluster should be and Jobs are what make it so. With the exception of a cluster import, LCM always pushes configuration to the nodes. It does not attempt to reconcile differences between configuration state on the nodes and what it thinks the state should be. Thus, any local hand-made changes to configs on the nodes are overwritten by the next configure job.

  • Repository: yum/apt repository information for access to DSE packages.

  • Machine credentials: SSH credentials and privilege escalation (sudo/su).

  • Configuration profile: configuration settings for DSE components (cassandra.yaml, dse.yaml, etc.)

  • Configuration file definitions: describes the structure, properties, and rendering options for configuration files.

  • Cluster: information about the DSE cluster. Contains datacenters.

  • Datacenter: information about DSE datacenters. Contains nodes.

  • Node: information about individual DSE nodes.

  • Jobs: information about the job system.

Common response properties

Most objects returned by API endpoints share a set of common properties, many of which are transient or read-only. These include:

Property Description of value

id

A UUID surrogate key for the object. Used in URLs to identify the object.

type

The object type.

created-on

A timestamp indicating when the object was created.

created-by

Who created the object.

Only 'system' is used for created-by and modified-by.

modified-on

A timestamp indicating the last time the object was changed.

modified-by

Who changed the object.

Field filtering has the following limitations:

  • timestamp fields are not currently supported (created-on, modified-on), although they can be used as an order field.

  • multiple filters are ANDed. OR is not supported.

  • only equality is supported, no ranges or inequalities.

  • IN and LIKE are not supported.

href

The full URL to the object.

related-resources

A map of resource name (i.e., "datacenters") to a full URL to the resource.

Example:

{
    "id": "ba908cb4-9116-4cf9-abe6-694ad75b70d3",
    "type": "machine-credential",
    "created-on": "2016-06-20T21:00:41.405Z",
    "created-by": "system",
    "modified-on": "2016-06-20T21:00:41.405Z",
    "modified-by": "system",
    "href": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3",
    "related-resources": {
        "datacenters": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/datacenters/",
        "nodes": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/nodes/",
        "clusters": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/clusters/"
    },

    // type-specific properties...
    "name": "my cluster creds",
    "use-ssh-keys": false,
    "login-user": "johndoe"
}

Paginated results

There are a number of API endpoints that return listings of objects. All of these return a paginated list of results, with each page limited to a certain configurable number of objects to avoid very large response sizes. All paginated results have the following properties:

Properties Description of value

results

The list of objects in the current page.

count

The total number of results (across all pages).

per-page

Limits the number of objects per page.

current

The current page number.

previous

The previous page number. Is null when on the first page.

next

The next page number. Is null when on the last page.

Example:

{
    "next": null,
    "previous": null,
    "last": 1,
    "count": 1,
    "per-page": 50,
    "current": 1,
    "results": [
        {
            "created-on": "2016-06-20T21:00:41.405Z",
            "type": "machine-credential",
            "related-resources": {
                "datacenters": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/datacenters/",
                "nodes": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/nodes/",
                "clusters": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3/clusters/"
            },
            "modified-on": "2016-06-20T21:00:41.405Z",
            "name": "my cluster creds",
            "login-user": "johndoe",
            "id": "ba908cb4-9116-4cf9-abe6-694ad75b70d3",
            "href": "http://localhost:8888/api/v2/lcm/machine_credentials/ba908cb4-9116-4cf9-abe6-694ad75b70d3"
        }
    ]
}

All endpoints with paginated results support the following query string parameters, in addition to supporting object-specific field filters for most fields.

Field filtering has the following limitations:

  • timestamp fields are not currently supported (created-on, modified-on), although they can be used as an order field.

  • multiple filters are ANDed. OR is not supported.

  • only equality is supported, no ranges or inequalities.

  • IN and LIKE are not supported.

Query string param Description of value

per-page

Changes the page-size limit (up to 300 max).

page

The page number to fetch. Not required for page 1.

order

An object field to order by. Only 1 order field is supported at this time.

direction

Sort direction: ASC or DESC for ascending (default) or descending.

<object field>

Filter results by field value. Multiple field filters are supported, and are ANDed together. Specify null field values by including just the field name with no parameter value or = character. There are some limitations.

Field filtering has the following limitations:

  • timestamp fields are not currently supported (created-on, modified-on), although they can be used as an order field.

  • multiple filters are ANDed. OR is not supported.

  • only equality is supported, no ranges or inequalities.

  • IN and LIKE are not supported.

Example:

curl http://localhost:8888/api/v2/lcm/machine_credentials/?login-user=johndoe&page=5&per-page=10&order=created-on&direction=DESC

Example: Cluster install

The following example demonstrates the API calls that are used to deploy a cluster using the Lifecycle Manager (LCM) API:

  1. Create a Repository.

  2. Create Machine credentials with appropriate settings for your cluster. You may need to create multiple if you have disparate credentials across your cluster.

  3. Create a Configuration profile with appropriate configuration settings where you wish to override the defaults. If you wish to vary your configs for each datacenter or even at the node-level, you need to create multiple.

  4. Create a Cluster model, including datacenters and nodes (see Datacenter and Node). Assign repository, machine credentials, and config profiles to the appropriate cluster model objects.

  5. Create a Node job.

  6. Watch the job (see Jobs) for COMPLETE status.

The complete script for the preceding steps is as follows:

#!/usr/bin/env python
# (C) DataStax, 2015.  All Rights Reserved
#
# Demonstrates installation of DataStax Community on existing empty servers
# using the LCM API
#
# Example Usage:
#   node-install-demo.py (target node ip one) (target node ip two) (...)

import sys
import os
import requests
import json
import threading

# CONFIGURABLE GLOBAL VARIABLES
server_ip = "127.0.0.1"
base_url = 'http://%s:8888/api/v2/lcm/' % server_ip
homedir = os.getenv("HOME")
# private_key_path = os.path.join(homedir, ".ssh/id_rsa")
# private_key = open(private_key_path).read()

# HELPER FUNCTIONS
def do_post(url, post_data):
    """Convenience function to simplify posting data to the LCM api."""
    print "Posting to:", url
    result = requests.post(base_url + url,
                           data=json.dumps(post_data),
                           headers={'Content-Type': 'application/json'})
    result_data = json.loads(result.text)
    print "Response is:", result.text
    return result_data

# CLUSTER SETUP
# Credentials to log-in to the {dse-short} nodes over SSH and obtain root privileges
#
# Log in over SSH as root authenticating with a password
# Run commands directly, without su or sudo
# machine_credential = do_post("machine_credentials/",
#                              {"name": "mc11",
#                               "login-user": "root",
#                               "login-password": "root",
#                               "become-mode": "direct"})

# Log in over SSH as vagrant, authenticating with an ssh-key
# Run commands through su when root privileges are necessary
# machine_credential = do_post("provisioning/machine_credentials/",
#                              {"name": "mc11",
#                               "login-user": "vagrant",
#                               "ssh-private-key": private_key,
#                               "become-mode": "su",
#                               "become-user": "root",
#                               "become-password": "password"})

# Log in over SSH as ubuntu, authenticating with a password
# Run commands through sudo when root privileges are necessary
machine_credential = do_post("machine_credentials/",
                             {"name": "mc11",
                              "login-user": "johndoe",
                              "login-password": "foobie",
                              "become-mode": "sudo",
                              "become-password": "foobie"})

# Describes many {dse-short} settings and LCM options to the LCM api.
# Other than the name and datastax-version, all attributes are optional
# and have sensible defaults.
cluster_profile = do_post(
    "config_profiles/",
    {"name": "cp1",
     "datastax-version": "4.8.1",
     "json": {'cassandra-yaml': {"start-native-transport": True},
              'logback-xml': {'file-appender-min-index': 2,
                              'loggers': [{'name': 'com.thinkaurelius.thrift',
                                           'level': 'ERROR'}]},
              'java-setup': {'major-version': "1.8.0"
                             # 'update-version': "77",
                             # 'build-version': '02'
                             },
              'package-proxy': {
                  'enabled': False
                  # 'protocol': 'http',
                  # 'host': 'proxy.lan',
                  # 'port': '3128'
                  # 'authentication-required': False,
                  # 'username': 'user',
                  # 'password': 'pw'
         }},
     "comment": "no comment"})

repository = do_post(
    "repositories/",
    {"name": "my-repo-credentials",
     "username": "johndoe",
     "password": "foobie"
     })

# Describes a cluster to the LCM api.
cluster = do_post("clusters/",
                  {"name": "cluster01",
                   "machine-credential-id": machine_credential["id"],
                   "repository-id": repository["id"],
                   "config-profile-id": cluster_profile["id"]})

# Describes a data-center to the LCM api.
# Machine-credentials, repository-credentials, and config-profiles can also be
# assigned to datacenters, or will be inherited from the cluster if unset.
datacenter = do_post("datacenters/",
                     {"name": "datacenter01",
                      "cluster-id": cluster["id"]})

# Describes a list of nodes to the LCM api using ip-addresses specified as
# command-line arguments to this script, ie:
# node-install-demo.py 10.0.1.10 10.0.1.11
ip_addresses = sys.argv[1:]
nodes = [do_post("nodes/",
                 {"name": ip,
                  "ssh-management-address": ip,
                  "datacenter-id": datacenter["id"]})
         for ip in ip_addresses]

# Request an install job to execute the installation and configuration of the
# cluster. Until this point, we've been describing future state. Now LCM will
# execute the changes necessary to achieve that state.
install_job = do_post("actions/install",
                      {"job-scope": "cluster",
                       "resource-id": cluster["id"]})

# Poll the LCM api for updates on the status of the job and progress events
displayed_events = {}

def check_job_status(job_id, displayed_events):
    # Fetch the most recent 200 job-events
    url = "job_events/?job-id=%s&per-page=200" % job_id
    result = requests.get(base_url + url)

    # Display events if we haven't seen them before
    search_results = json.loads(result.text)
    for search_result in search_results['results']:
        job_event_result = requests.get(search_result['href'])
        job_event = json.loads(job_event_result.text)
        if job_event['id'] not in displayed_events:
            displayed_events[job_event['id']] = True
            # Job events are extremely detailed, select some of the more
            # human-friendly fields for display
            print "Node %s: %s %s (%s): %s" % (job_event['node-id'],
                                               job_event['event-type'],
                                               job_event['event-subtype'],
                                               job_event['message'],
                                               job_event['event-resource'])
    # Check if the entire job has been completed
    job_url = "jobs/%s" % job_id
    job_response = requests.get(base_url + job_url)
    job_results = json.loads(job_response.text)

    # Poll every 5 seconds, displaying status until the job is complete
    if job_results['status'] == 'RUNNING':
        t = threading.Timer(5.0,
                            check_job_status,
                            [job_id, displayed_events])
        t.start()
    elif job_results['status'] == 'COMPLETE':
        print "Job completed successfully."

# Initiate status polling
t = threading.Timer(5.0,
                    check_job_status,
                    [install_job["id"], displayed_events])
t.start()

Was this helpful?

Give Feedback

How can we improve the documentation?

© Copyright IBM Corporation 2026 | Privacy policy | Terms of use |  Manage Privacy Choices

Apache, Apache Cassandra, Cassandra, Apache Tomcat, Tomcat, Apache Lucene, Apache Solr, Apache Hadoop, Hadoop, Apache Pulsar, Pulsar, Apache Spark, Spark, Apache TinkerPop, TinkerPop, Apache Kafka and Kafka are either registered trademarks or trademarks of the Apache Software Foundation or its subsidiaries in Canada, the United States and/or other countries. Kubernetes is the registered trademark of the Linux Foundation.

General Inquiries: Contact IBM