12.3. Remote Administration Platform¶
This section describes details of the RTI Remote Administration Platform, which represents the foundation of the remote access capabilities available in RTI Routing Service, RTI Recording Service, and RTI Queuing Service. The RTI Remote Administration Platform provides a common infrastructure that unifies and consolidates the remote interface to all RTI services.
Note
Remote administration of RTI services requires an understanding of the application resource model. We recommend that you read Application Resource Model (Application Resource Model) before continuing with this section.
The RTI Remote Administration Platform addresses two areas:
Resource Interface: How to perform operations on a set of resource objects that are available as part of the public interface of the remote service.
Communication: How the remote service receives and sends information.
The combination of these two areas provides the general view of the RTI Remote Administration Platform, as shown in Figure 12.3. The RTI Remote Administration Platform is defined as a request/reply architecture. In this architecture, the service is modeled as a set of resources upon which the requester client can perform operations. Resources represent objects that have both state and behavior.
![Routing Service Adapter Overview](../_images/RapGeneralView.png)
Figure 12.3 General View of the RTI Remote Administration Platform Architecture¶
Clients issue requests indicating the desired operation and receive replies from the service with the result of the requests. If multiple clients issue multiple requests to one or more services, the client will receive only replies to its own requests.
12.3.1. Remote Interface¶
Services offer their available functionality through their set of resources. The RTI Remote Administration Platform defines a Representational State Transfer (REST)-like interface to address service resources and perform operations on them. A resource operation is determined by a REST request and the associated result by a REST reply.
Element |
Description |
---|---|
REST Request |
|
REST Reply |
|
12.3.1.1. Standard Methods¶
The RTI Remote Administration Platform defines the methods listed in Table 12.3.
Method |
URI |
Request Body |
Reply Body |
---|---|---|---|
|
Parent collection resource identifier |
Resource representation |
N/A |
|
Resource identifier |
N/A |
Resource representation |
|
Resource identifier |
Resource representation |
N/A |
|
Resource identifier |
Undefined |
N/A |
12.3.1.2. Custom Methods¶
There are certain cases in which an operation on a service resource cannot be mapped intuitively to a standard method and resource identifier. Custom methods address this limitation.
A custom method can be specified as part of the resource identifier, after the
resource path, separated by a :
.
|
It is up to each service implementation to define which custom methods are available and on what resources they apply. Custom methods follow these conventions:
They are invoked through the
UPDATE
standard method.They are named using lower snake_case.
They may use the request body and reply body if necessary.
12.3.1.2.1. Example: Database Rollover¶
This example shows the REST request to perform a file rollover operation on a file-based database:
UPDATE /databases/MyDatabase:rollover
12.3.2. Communication¶
The information exchange between client and server is based on the DDS request-reply pattern, as shown in Figure 12.4. The client maps to a Requester, whereas the server maps to a Replier.
![Routing Service Adapter Overview](../_images/RapCommunication.png)
Figure 12.4 Communication in RTI Remote Administration Platform is Based on DDS Request-Reply¶
The communication is performed over a single request-reply channel, composed of two topics:
Command Request Topic: Topic through which the client sends the requests to the server.
Command Reply Topic: Topic through which the server sends the replies to the received requests.
The definition of these topics is shown in Table 12.4:
Topic |
Name |
Top-level Type Name |
---|---|---|
CommandRequestTopic |
rti/service/administration/command_request |
|
CommandReplyTopic |
rti/service/administration/command_reply |
|
The definition for each Topic type is described below.
@appendable
struct CommandRequest {
@key int32 instance_id;
@optional string<BOUNDED_STRING_LENGTH_MAX> application_name;
CommandActionKind action;
ResourceIdentifier resource_identifier;
StringBody string_body;
OctetBody octet_body;
};
Field Name |
Description |
---|---|
|
Associates a request with a given instance in the CommandRequestTopic. This can be used if your requester application model wants to leverage outstanding requests. In general, this member is always set to zero, so all requests belong to the same CommandRequestTopic instance. |
|
Optional member that indicates the target service instance where the
request is sent. If |
|
Indicates the resource operation. |
|
Addresses a service resource. |
|
Contains content represented as a string. |
|
Contains content represented as binary. |
@appendable
struct CommandReply {
CommandReplyRetcode retcode;
int32 native_retcode;
StringBody string_body;
OctetBody octet_body;
};
Field Name |
Description |
---|---|
|
Indicates the result of the operation. |
|
Provides extra information about the result of the operation. |
|
Return value of the operation, represented as a string. |
|
Return value of the operation, represented as binary. |
The type definitions for both the CommandRequestTopic and CommandReplyTopic are in the file
[NDDSHOME]/resource/idl/ServiceAdmin.idl
.
The definition of the request and reply topics is independent of any specific service implementation. In fact, the topic names are fixed, unique, and shared across all services that rely on the RTI Remote Administration Platform. Clients can target specific services through two mechanisms:
Specifying a concrete service instance by providing its application name. The application name is a service attribute and can be set at service creation time.
Specifying the configuration name loaded by the target services. The target service configuration shall be present in the service resource part of the
resource_identifier
.
12.3.2.1. Reply Sequence¶
Usually a request is expected to generate a single reply. Sometimes, however, a request may trigger the generation of multiple replies, all associated with the same request.
The RTI Remote Administration Platform communication architecture allows services to respond to certain
requests with a reply sequence. All the samples in a reply sequence use the
the metadata SampleFlagBits
to indicate whether it belongs to a reply
sequence and whether there are more replies pending.
The SampleFlagBits
may contain different flags that indicate the status
of the reply procedure. For a given reply sequence, the associated sample flags
for each reply may contain:
SEQUENTIAL_REPLY
: If present, this indicates that the sample is the first reply of a reply sequence and there are more on the way.
FINAL_REPLY
: If present, this indicates that the sample is the last one belonging to a reply sequence. This flag is valid only if theSEQUENTIAL_REPLY
is also set.
For more on SampleFlagBits, see documentation on the DDS_SampleInfo structure in the Connext DDS API Reference HTML documentation.
12.3.2.2. Example: Accessing from Connext DDS Application¶
This example shows a Modern C++ snippet on how to use Connext DDS Request-Reply to disable a Routing Service instance.
The first step is to generate code for administration types in
[NDDSHOME]/resource/idl/ServiceAdmin.idl
(which has a dependency on
[NDDSHOME]/resource/idl/ServiceCommon.idl
):
rtiddsgen -language C++11 -unboundedSupport -qualifiedEnumerator ServiceCommon.idl
rtiddsgen -language C++11 -unboundedSupport -qualifiedEnumerator ServiceAdmin.idl
Note that there are two important options in the generation command:
-unboundedSupport
is required to support unbounded length for the request’s and reply’s octet and string bodies. This allows sending and receiving any-size data in a single sample. Because of the unbounded support, you will need to make sure that the requester’s DataWriter and DataReader are configured with a QoS that sets the buffer pools’ memory settings (in addition to any other QoS). For example:<!-- For requester's request DW --> <datawriter_qos> <property> <value> <element> <name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name> <value>16384</value> </element> </value> </property> </datawriter_qos> <!-- For requester's reply DR --> <datareader_qos> <reader_resource_limits> <dynamically_allocate_fragmented_samples>true</dynamically_allocate_fragmented_samples> </reader_resource_limits> <property> <value> <element> <name>dds.data_reader.history.memory_manager.fast_pool.pool_buffer_max_size</name> <value>16384</value> </element> </value> </property> </datareader_qos>
-qualifiedEnumerator
generates enum labels with the proper namespace based on the IDL modules.
Then you create your requester application that handles the requests and replies. For example:
#include "ServiceAdmin.hpp"
#include "ServiceCommon.hpp"
using namespace rti::request;
using namespace dds::core;
using namespace RTI::Service;
using namespace RTI::Service::Admin;
const unsigned int WAIT_TIMEOUT_SEC_MAX = 10;
const unsigned int ADMIN_DOMAIN_ID = 55;
int main(int, char *[]) {
try {
dds::domain::DomainParticipant participant(ADMIN_DOMAIN_ID);
// create requester params
rti::request::RequesterParams requester_params(participant);
requester_params.request_topic_name(COMMAND_REQUEST_TOPIC_NAME);
requester_params.reply_topic_name(COMMAND_REPLY_TOPIC_NAME);
// Wait for Routing Service Discovery
dds::core::status::PublicationMatchedStatus matched_status;
unsigned int wait_count = 0;
std::cout << "Waiting for a matching replier..." << std::endl;
while (matched_status.current_count() < 1
&& wait_count < WAIT_TIMEOUT_SEC_MAX) {
matched_status = requester.request_datawriter().publication_matched_status();
wait_count++;
rti::util::sleep(Duration(1));
}
if (matched_status.current_count() < 1) {
throw dds::core::Error("No matching replier found.");
}
/*
* Setup command
*/
CommandRequest request;
request.action(CommandActionKind::UPDATE_ACTION);
request.resource_identifier("/routing_services/MyRouter/state");
dds::topic::topic_type_support<EntityState>::to_cdr_buffer(
reinterpret_cast<std::vector<char> &>(request.octet_body()),
EntityState(EntityStateKind::DISABLED));
/*
* Send disable
*/
requester.send_request(request);
CommandReply reply = requester.receive_reply(
Duration(WAIT_TIMEOUT_SEC_MAX));
if (reply.retcode() == CommandReplyRetcode::OK_RETCODE) {
std::cout << "Command returned: " << reply.string_body() << std::endl;
} else {
std::cout << "Unsuccessful command returned value "
<< reply.retcode() << "." << std::endl;
throw dds::core::Error("Error in replier");
}
} catch (const std::exception& ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
return 0;
}
You will need to compile your application code along with the generated files
and link with the standard Connext DDS libraries required for the Modern C++ API
in addition to the message API (rticonnextmsgcpp2
).
In RTI Community Examples Repository you can see a full example for an administration requester that shows how to send different commands to RTI Recording Service.
12.3.3. Common Operations¶
The set of services that use the RTI Remote Administration Platform to implement remote administration also share a base remote interface that consolidates and unifies the semantics and behavior of certain common operations.
Services containing resources that implement the common operations conform to the base remote interface, making sure that signatures, semantics, behavior, and conditions are respected.
The following sections describe each of these common operations.
12.3.3.1. Create Resource¶
-
CREATE [resource_identifier]
Creates a resource object from its configuration in XML representation.
This operation creates a resource object and its contained entities. The created object becomes a child of the parent specified in the
resource_identifier
.After successful creation, the resource object is fully addressable for additional remote access, and the associated object configuration is inserted into the currently loaded full XML configuration.
Request body
string_body
: XML representation of the resource object provided asfile://
orstr://
.Example
str://
request body:str://"<my_resource name="NewResourceObject"> ... </my_resource>"
Example
file://
request body:file:///home/rti/config/service_my_resource.xml
Reply body
Empty.
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
The specified configuration is schematically invalid.
There was an error creating the resource object.
12.3.3.2. Get Resource¶
-
GET [resource_identifier]
Returns an equivalent XML string that represents the current state of the resource object configuration, including any updates performed during its lifecycle.
Request body
Empty.
Reply body
string_body
: XML representation of the resource object.Example reply body:
<my_resource name="MyObject"> ... </my_resource>
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
12.3.3.3. Update Resource¶
-
UPDATE [resource_identifier]
Updates the specified resource object from its configuration in XML representation.
This operation modifies the properties of the resource object, including the associated configuration. Only the mutable properties of the resource class can be updated while the object is enabled. To update immutable properties, the resource object must be disabled first.
Note
Properties of a child resource cannot be updated as part of a parent resource. Instead, child resources must be addressed and updated independently.
Implementations may validate the received configuration against a scheme (DTD or XSD) that defines the valid set of accepted parameters (for example, only mutable elements).
The update content should only include only the properties to be updated or changed. You are not required to provide the full representation of the object being updated.
For example, consider the XML full representation of an object as follows:
<my_resource> <nested_resource_A>initial_A</nested_resource_A> <nested_resource_B>initial_B</nested_resource_B> <nested_resource_C>initial_C</nested_resource_C> ... </my_resource>
The update should only contain the content for the properties you want to modify. For example, the following will only update
nested_resource_B
to a new value, leaving the other nested resources unchanged:<my_resource> <nested_resource_B>updated_B</nested_resource_B> ... </my_resource>
Request body
string_body
: XML representation of the resource object provided asfile://
orstr://
.Example
str://
request body:str://"<my_resource name="MyResourceObject"> ... </my_resource>"
Example
file://
request body:file:///home/rti/config/service_update_my_resource.xml
Reply body
Empty.
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
The specified configuration is schematically invalid.
The specified configuration contains changes in immutable properties.
There was an error updating the resource object.
12.3.3.4. Set Resource State¶
-
UPDATE [resource_identifier]/state
Sends a state change request to the specified resource object.
This operation attempts to change the state of the specified resource object and propagates the request to the resource object’s contained entities.
The target state must be one of the resource class’s valid accepted states.
Request body
octet_body
: CDR representation of an entity state.
Reply body
Empty.
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
The target request is invalid.
The resource object reported an error while performing the state transition.
12.3.3.5. Get Resource State¶
-
GET [resource_identifier]/state
Gets the current state of the specified resource object.
This operation attempts to fetch the state of the specified resource object.
The target’s state is returned as a part of the reply.
Request body
Empty
Reply body
octet_body
: CDR representation of an entity’s current state.
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
The target request is invalid.
The resource object reported an error while fetching its current state.
12.3.3.6. Delete Resource¶
-
DELETE [resource_identifier]
Deletes the specified resource object.
This operation deletes a resource object and its contained entities. The deleted object is removed from its parent resource object.
The associated object configuration is removed from the currently loaded full XML configuration.
After a successful deletion, the resource object is no longer addressable for additional remote access.
Request body
Empty.
Reply body
Empty.
Return codes
The operation may return a reply with error if:
The specified resource identifier does not exist.
There was an error deleting the resource object.