The CML Request for Comments

A generic way of managing AMQP servers



We define a standard language (Console Markup Language, or CML) and transport mechanism for the remote administration of AMQP servers. CML is a simple XML language for representing server-side entities, their properties, and possible actions. Further, CML defines semantics for actions to be taken on objects. CML is transported on top of AMQP using basic AMQP routing and queueing functionality. This document is not an official standard but is made available for public use to encourage interoparability between products.


A 'console' is a remote application that monitors, configures, and manages one or more servers. CML is designed to allow remote configuration, control and management of an AMQP server, including:

  • Server configuration.
  • Security configuration (authentication and access controls).
  • Monitoring of key entities (queues, etc.)
  • Collection of status information (performance, statistics)
  • Administrative actions (purge queue, disconnect connection, etc.)

We want the console to be able to have these features:

  • To be rapid, even when many people are operating (different parts of) an AMQP server. The speed of reaction of the console is an important part of its functionality.
  • To be portable to any desired user interface technology, including web, command-line, JMX, etc. Ideally, end-users should be able to make customised operator interfaces, scripts, etc. We want the console to be user-extensible.
  • To be generally compatible with conventional console abstractions, e.g. Java management beans.
  • To provide access to all "operable" internals of the server, i.e. to any object that may be tuned, configured, or managed.
  • To hide all aspects of the server that are not "operable", i.e. any object that should not be touched or seen. The operator must not be able to cause harm by misuse of the console.
  • To have no significant impact on server performance or stability even when heavily used. The console must be non-intrusive, and wholly safe.
  • Eventually, to be transactional, so that operations are completed fully, or not at all.
  • Lastly, to be self-describing, using data schemas that clients can refer to, adapting statically or dynamically as suitable.

General console architecture

Server and client Layers

The console is built using the AMQP protocol. That is, the server does not export any user interface, but rather an API on top of which arbitrary user interfaces can be built. The simplest architecture is this:

 AMQP Server              GUI or cmdline
.-----------.             .-----------.
|           |             |           |
|  Console  | <==AMQP==>  |  Console  |
|  Server   |             |  Client   |
|           |             |           |
`-----------'             `-----------'

Where the console client is responsible for the user interface - command line or GUI. A more sophisticated architecture uses a console standard such as JMX so that it is easy to write arbitrary operator applications:

 AMQP Server                 Proxy               GUI or cmdline
.-----------.             .-----------.           .----------.
|           |             |           |           |          |
|  Console  | <==AMQP==>  |  Console  | <==JMX==> | Operator |
|  Server   |             |  Client   |           |   Appl   |
|           |             |           |           |          |
`-----------'             `-----------'           `----------'
  • The console consists of a server component and a client component.
  • The console server is an application that is embedded into the AMQ server.
  • The console client is an application written in an arbitrary language.
  • The console client and server communicate using AMQP.

The server schema

We specify formally that:

  • The console works on a set of entity definitions we call "classes", and a set of live entities we call "objects".
  • The collection of classes that the server supports is its "schema".
  • Schemas are given globally-unique names and versions.

Every AMQP server can implement its own schema, depending on its specific functionality. We do not assume that all console clients know all schemas in advance.

This is an example of a schema structure:

 :-- vhost
 :    :
 :    :-- exchange
 :    :
 :    `-- queue
 :        :
 :        `-- consumer
 `-- connection

Classes, fields, and methods

The schema is an arbitrarily-complex hierarchical structure representing the classes of entities in the server.

An object class is defined as follows:

  • The class has a name, e.g. "server", unique within the schema.
  • Each object instance has a numeric identifier.
  • The class is composed of zero or more data fields (the object's properties).
  • The class may allow one or more methods.

A data field is defined as follows:

  • The field has a name.
  • The field has a data type.
  • The field may be restricted to a set of named values.
  • The field has a label, used to construct a user interface.
  • The field has a description, used to construct a user interface.
  • The field is marked as readable and/or writeable.
  • The field may contain one or more child fields.

Methods accept a number of arguments and perform some action on an object, and return a status value. A method is defined as follows:

  • The method has an internal name.
  • The method has a label, used to construct a user interface.
  • The method carries zero or more data fields (the method's arguments).
  • The method has a description, used to construct a user interface.


The API consists of these commands:

  • "schema-request" - requests the server schema.
  • "schema-reply" - returns the server schema.
  • "inspect-request" - requests the properties of a specific object.
  • "inspect-reply" - returns the properties of a specific object.
  • "modify-request" - requests changes to a specific object.
  • "modify-reply" - confirms changes to a specific object.
  • "method-request" - executes a method on a specific object.
  • "method-reply" - returns result of a method-request.
  • "notify" - (from server to client) send a notification.

Object identification

Each object has a unique 64-bit identifier assigned by the server when it creates the object. This identifier is used in all messages when referring to an object.

ID 0 (zero) always represents the root object.

The console API


The 'console API' is a remote API that lets an application query and manipulate entities on the server. The API consists of a set of commands passed between the client (console) and the server.

General design

The console API consists of two pieces:

  • Execute a command on a given object. This consists of a request from the client to the server, and a reply back from the server to the client.
  • Get a notification from the server. Notifications are sent asynchronously using the AMQP topic routing mechanisms.

The console API consist of Basic content messages, exchanged using these AMQP methods:

  • Basic.Publish
  • Basic.Consume and Basic.Deliver
  • Basic.Browse and Basic.Browse-Ok / Browse-Empty.

The request-reply mechanism uses standard queues. The client creates a temporary, private queue and binds this to using the queue name as routing key. It then sends CML commands to the amq.system exchange, specifying "amq.console" as the routing key, and its queue name as the reply-to field. To match up responses with requests, it can set the message-id in requests - the Console will use the same value in responses.

Every request generates a response, on the condition that the reply-to field correctly refers to a queue.

We can show the client's request-reply logic using PAL scripting:

  • The client creates a temporary, private reply queue and binds this to the exchange:
<queue_declare queue = "" />
    queue = "$queue"
    exchange = ""
    routing_key = "$queue" />
  • The client formats a request (in this case we read a test CML message from a text file):
    read = "console.txt"
    reply_to = "$queue"
    message_id = "id-001" />
  • The client publishes the request to the amq.system exchange:
    exchange = "amq.system"
    routing_key = "amq.console" />
  • The client waits for a response on its queue:
    <basic_browse queue = "$queue" />
        <echo>Message was returned: $message_id</echo>
        <echo>Response arrived from console</echo>
    <wait timeout = "100" />

The notification mechanism uses topic routing and subscription queues. The client creates a temporary, private queue and binds this to the amq.notify exchange (a topic exchange), with a routing key that specifies which notifications it wants to receive.

We can show the client's notification logic using PAL scripting:

  • The client creates a temporary, private reply queue and binds this to the amq.notify exchange:
<queue_declare queue = "" />
<queue_bind queue = "$queue" exchange = "amq.notify" routing_key = "amq.*" />
  • The client defines a consumer on the queue:
<basic_consume queue = "$queue" />
  • The client waits for notifications on its queue:
        <echo>Response arrived from console</echo>

Console message language

All messages between the console client and the server are formatted using an XML language we call "CML", the Console Message Language. CML uses a minimalistic XML syntax - no stylesheets, namespaces, document types, etc.

Here are some examples of CML:

<cml version = "1.0">
    <schema-request />
<cml version = "1.0">
    <inspect-request object = "0" />
<cml version = "1.0">
    <modify-request object = "0">
        <field name = "active">0</field>

CML has a grammar that covers all possible server schemas. This is the overall grammar for CML messages:

cml             = <cml version = "1.0">
                     client-message | server-message

This is the grammar for client messages:

cml             = schema-request
                | inspect-request
                | modify-request
                | method-request
schema-request  = <schema-request />
inspect-request = <inspect-request object = "object-id" />
object-id       = 0..maxlongint-1
modify-request  = <modify-request object = "object-id">
                    [ field-data ] ...
field-data      = <field name = "field-name">field-value</field>
field-name      = valid-name
valid-name      = {A-Za-z0-9-_.}...
field-value     = string representation of field value
method-request  = <method-request object = "object-id" name = "method-name">
                    [ field-data ] ...
method-name     = valid-name

This is the grammar for server messages:

cml-command     = schema-reply
                | inspect-reply
                | modify-reply
                | method-reply
                | invalid
                | notify
schema-reply    = <schema-reply name = "schema-name" version = "schema-version"
                    status = "reply-status" >
                   [ schema-class ]...
schema-name     = valid-name
schame-version  = valid-name
reply-status    = ok | notfound | noaccess | invalid
schema-class    = <class name = "class-name" label = "class-label">
                   [ schema-field ]...
                   [ schema-method ]...
class-name      = valid-name
class-label     = valid-text
valid-text      = {printable}...
schema-field    = group-field | simple-field
group-field     = <group name = "field-name"
                   [ inspect = "inspect-flag" ] [ modify = "modify-flag" ]
                   [ label = "field-label" ] >
                   [ field-text ]
                   [ schema-field ]...
inspect-flag    = 0 | (1)
modify-flag     = (0) | 1
field-label     = valid-text
field-text      = valid-text
simple-field    = <field name = "field-name"
                   [ type = "field-type" ] [ repeat = "repeat-flag" ]
                   [ inspect = "inspect-flag" ] [ modify = "modify-flag" ]
                   [ label = "field-label" ] >
                   [ field-text ]
                   [ enum-value ] ...
field-type      = string | int | bool | time | objref
repeat-flag     = (0) | 1
enum-value      = <value name = "value-name">field-value</value>
value-name      = valid-text
schema-method   = <method name = "method-name" label = "method-label">
                   [ schema-field ]...
method-label    = valid-text
inspect-reply   = <inspect-reply class = "class-name" object = "object-id"
                     status   = "reply-status"
                   [ notice = "notice-text" ] >
                    [ field-data ]...
modify-reply    = <modify-reply
                     class = "class-name"
                     object = "object-id"
                     status = "reply-status"
                   [ notice = "notice-text" ] />
notice          = valid-text
method-reply    = <method-reply
                     class = "class-name"
                     object = "object-id"
                     status = "reply-status"
                   [ notice = "notice-text" ] />
invalid         = <invalid />
notify          = <notify>

Field types

The goal of defining fields is to allow the automatic production of user interface forms without too much work. We allow these types of field:

  • string: defines a string field. The maximum value of a string field is 255 octets when an object is modified, and no limit on output. This is the default type.
  • int: defines an integer. Integers are unsigned 32 bits.
  • bool: defines a boolean value, which can be shown as a check box.
  • time: defines a date/time, held as a UTC time_t format.
  • object: defines a relationship to another object.

String and integer fields can be enumerated, with one or more values. These would show as radio options (for 3-4 or fewer fields) or select boxes (for 5 or more options), e.g.:

<field name = "status" type = "int" label = "Operational status">
    <value name = "not ready"    >0</value>
    <value name = "active"       >1</value>
    <value name = "shutting down">2</value>

This is a minimalistic typing model that we will most likely refine over time, e.g. defining visible and internal size limits for strings and integers, and allowing multiline text fields.

Object names

All objects must have a field called "name" that specifies a unique name for the object within the current set of objects of a particular type.

The 'schema' command

The 'schema' commmand asks the server for the server schema. Any AMQP server implements exactly one schema. Schemas are named and versioned so that clients can either download schemas fully dynamically, or work with in-built schemas and verify that their servers are compatible.

An example of the schema command:

C: <cml version = "1.0">
      <schema-request />
S: <cml version = "1.0">
      <schema-reply name = "" version = "0.1" status = "ok">
         <class name = "server">
            <field name = "ip-address" label = "Server IP address" />
            <field name = "port"       label = "Port for connections" />
            <field name = "version"    label = "Server software version" />
            <field name = "platform"   label = "Server platform" />
         <class name = "vhost">
         <class name = "connection">

The reply-status field defines whether the command was successful or not. This field has these possible values:

  • 'ok' means the command completed successfully.
  • 'notfound' means the specified class (or object, for other commands) did not exist.
  • 'noaccess' means the client application was not allowed to execute the command.
  • 'invalid' means the command was wrongly formatted or incorrect.

The 'inspect' command

The 'inspect' command asks the server for a specific object. The command takes an object ID as argument, and returns all readable fields for the object, with optionally a list of all child objects.

The top-level object always has an ID zero, so the client will inspect this object first, in order to navigate the object tree.

For example:

C: <cml version = "1.0">
      <inspect-request object = "0" />
S: <cml version = "1.0">
      <inspect-reply class = "broker" object = "0" status = "ok">
         <field name = "ip-address"></field>
         <field name = "port">5672</field>
         <field name = "version">0.9c2</field>
         <field name = "platform">Linux</field>
         <field name = "exchange" id = "1" />
         <field name = "exchange" id = "2" />

The 'modify' command

The 'modify' command asks the server to set certain fields of an object. These must be fields with the "modify" attribute set to 1 in the schema. For example:

C: <cml version = "1.0">
      <modify-request object = "2">
         <field name = "enabled">0</field>
S: <cml version = "1.0">
      <modify-reply object = "2" status = "ok" />

If the client specifies fields that are not valid (not in the modify view), the server will respond with an "invalid" status.

The 'method' command

The 'method' command provides a set of fields and a method name and asks the server to execute that method. Methods do not return values except a status code. For example:

C: <cml version = "1.0">
      <method-request name = "purge" object = "32" />
S: <cml version = "1.0">
      <method-reply name = "purge" object = "32" status = "ok" />

If the client specifies fields that are not valid (not in the modify view), the server will respond with an "invalid" status.

The 'notify' command

The server broadcasts informational, warning and error messages using 'notify' commands. Any correctly subscribed AMQP client can get these notifications.

The notification consists of a textual message:

S: <cml version = "1.0">
        E: queue exceeded configured limit of 5000.


Add a New Comment

Edit | Files | Tags | Source | Print

rating: +1+x


iMatix Corporation

Installing and using OpenAMQ

Introduction to OpenAMQ: This document is an introduction to the concept of business messaging in general, and to OpenAMQ in particular. It is intended for new OpenAMQ users who wish to understand the problems that OpenAMQ solves, and how OpenAMQ can be useful in software applications.

Basic use of OpenAMQ: This document explains how to get OpenAMQ running on your system. It explains how to download the software, how to unpack and build it (if you are using a source package), and how to run basic tests on the resulting software.

Advanced use of OpenAMQ: This guide is for people who need to configure and manage OpenAMQ servers. We explain how to configure and tune an OpenAMQ server, covering these topics: logging, monitoring, high-availability failover, and joining OpenAMQ servers into wide-area federations.

Writing applications

Programming WireAPI: This is the main guide for developers who wish to use OpenAMQ in their applications. We describe WireAPI, the C/C++ API that OpenAMQ provides for accessing AMQP. Expert WireAPI users may wish to read the iMatix iCL guide, but this document is otherwise self-complete.

Programming PAL: This guide is for OpenAMQ developers who need a quick way to write test cases and simple scenarios. We explain the PAL language, an XML scripting tool that gives you a fast way to construct AMQP applications to test routing models, performance and stability tests, and other test cases.

Programming the Console: This document explains how to write applications that automate management of OpenAMQ servers via console automation. The OpenAMQ console automation architecture offers developers different ways of accessing the functionality of the console API and integrating it with their own preferred tools and management facilities.

Technical library

Developer's Guide to ASL: This is a technical guide for protocol developers who wish to use the iMatix ASL framework for the development of connected client-server protocols. ASL is a generic framework that uses a protocol modeling language to construct the whole infrastructure for a given protocol. ASL was built primarily to support AMQP.

Developer's Guide to iCL: This is a technical guide for developers who wish to understand how the iMatix iCL framework works. iCL is a class-oriented modelling language for C applications and is one of the basic frameworks used in iMatix applications such as OpenAMQ.

Developer's Guide to MOP: This is a technical guide for developers who wish to understand how the iMatix code generation frameworks are constructed. We explain the principles of model oriented programming, and the basics of code generation using the iMatix GSL language. This provides essential basic knowledge for anyone intending to modify the OpenAMQ software.

Developer's Guide to SMT: This is a technical guide for developers who wish to understand how the iMatix SMT framework works. To use this guide the reader should be familiar with the iMatix iCL framework, and the iMatix Model Oriented Programming principles.


The CML Request for Comments: We describe a generic technique for managing AMQP servers from a remote client application. This technique consists of a standard transport mechanism built over AMQP, and a standard XML language used to exchange information between a management component built-in to the server, and a management application. This is a request for comments, it is not a standard.