148 Cluster Information Specification

148.1 Introduction

Modern enterprise applications are most often deployed on distributed infrastructure such as a private or public cloud environment, instead of on a single server. This is done to distribute the application load, to replicate the application to guarantee availability or to exploit dedicated hardware for certain application functionality (for example, a database server).

The unit of management is often no longer a single physical machine. Server infrastructure is nowadays mostly offered in a virtualized fashion, such as hardware virtualization using a hypervisor or operating system virtualization using containers. Potentially these can also be hierarchically managed, for example having multiple containers running inside a virtual machine. Therefore, it becomes key to manage an application running on a cluster of such (virtual) machines and/or containers.

Also in the context of the Internet of Things (IoT), often a number of gateway devices is deployed in the network that connect various sensors and actuators creating a smart environment. Again, it becomes key to discover and manage these devices, and query their capabilities.

The OSGi specification already provides chapters describing how to deploy software on remote infrastructure, how to call remote services or how manage a remote OSGi framework. In this chapter we define an API for a management agent to discover, list and inspect available nodes in the cluster.

148.1.1 Essentials

  • Cluster - A cluster is a collection of nodes connected by a network. Most often the nodes are managed by a public or private cloud provider.

  • Node - A node is a discoverable entity in the cluster, for example a physical machine, a virtual machine (VM), a container or an OSGi framework.

148.1.2 Entities

  • NodeStatus - The Node Status service represents a node in the cluster. This can be any entity in the cluster such as a database server, a virtual machine, a container, an OSGi framework, etc.

  • FrameworkNodeStatus - The Framework Node Status service represents an OSGi framework in the cluster.

  • FrameworkManager - The FrameworkManager service provides an interface to manage an OSGi framework in the cluster.

Figure 148.1 Clusterinfo Entity overview

Clusterinfo Entity overview

148.2 OSGi frameworks in a cluster

We distinguish two types of nodes in a cluster. On the one hand we have OSGi frameworks, which publish their presence using a Framework Node Status service. On the other hand there can be other nodes in the cluster, such as the virtual machines or containers the OSGi frameworks are running on, or an external server such as a database. These can be represented using a Node Status service.

When an OSGi framework is part of a cluster, this means it gets access to remote services of any other OSGi framework in that cluster. Ensuring the discovery, visibility and access of remote services within the cluster is the responsibility of the Remote Service Admin Service Specification.

An example cluster deployment is shown in Figure 148.2 on page . Here, a cluster consisting of three virtual machines or containers has deployed a total of four OSGi frameworks. Each OSGi framework has a Cluster Information implementation running that exposes a Framework Node Status service. Besides these, there can also be an entity managing the virtual machines/containers (for example, the cloud provider), that exposes three Node Status services, one for each VM/container. In this case, each Framework Node Status will have a parent id pointing to the id of the Node Status of the VM/container it is deployed on.

Figure 148.2 Example cluster deployment

Example cluster deployment

148.3 Node Status Service

The NodeStatus service advertises the availability of a node in the cluster. This node can be any entity in the cluster such as a physical machine, a virtual machine, a container or an OSGi framework.

The Node Status service provides metadata about the node via its service properties. Each Node Status must provide an id and cluster name. Optionally additional service properties can be provided such as the physical location of the node, the endpoints at which this node can be accessed, etc. These service properties can be converted to a NodeStatusDTO to have type-safe access to these properties using the Converter Specification.

Table 148.1 Service properties of the NodeStatus service

Service Property Name Type Description
osgi.clusterinfo.id String

The globally unique ID for this node. For example the Docker ID if this node is a Docker container, or the framework UUID if this node is an OSGi framework.

osgi.clusterinfo.cluster String

The name of the cluster this node belongs to.

osgi.clusterinfo.parent String

In the case this node is part of or embedded in another node, this field contains the id of the parent node. For example multiple virtual machines could run on the same physical node.

osgi.clusterinfo.endpoint String+

The endpoint(s) at which this node can be accessed from the viewpoint of the consumer of the service.

osgi.clusterinfo.endpoint.private String+

Private endpoint(s) at which this node can be accessed from within the cluster only.

osgi.clusterinfo.vendor String

The vendor name of the cloud/environment in which the node operates.

osgi.clusterinfo.version String

The version of the cloud/environment in which the node operates. The value follows the versioning scheme of the cloud provider and may therefore not comply with the OSGi versioning syntax.

osgi.clusterinfo.country String

ISO 3166-1 alpha-3 location where this node is running, if known.

osgi.clusterinfo.location String

ISO 3166-2 location where this node is running, if known. This location is more detailed than the country code as it may contain province or territory.

osgi.clusterinfo.region String

Something smaller than a country and bigger than a location (for example, us-east-1 or other cloud-specific location)

osgi.clusterinfo.zone String

Regions are often subdivided in zones that represent different physical locations. The zone can be provided here.

osgi.clusterinfo.tags String+

Tags associated with this node that can be contributed to by the provider and also by bundles.


The Node Status service can also provide access to some dynamic properties of the node. The getMetrics method allows to query key-value pairs, that are specific for that node. For example, for an OSGi framework these could be CPU and memory usage, for a database node these could be the number of database reads and writes, and for a VM these could be metrics made accessible by the cloud provider. In this case the service implementor can provide DTOs to have a type-safe way to access these metrics by converting the returned map to one of these DTOs. For example, an implementation could expose JMX metrics together with a type-safe DTO:

public class JMXMetricsDTO extends DTO {
  /**
   * The number of processors available
   */
  public int availableProcessors;

  /**
   * The average system load
   */
  public float systemLoadAverage; 

  /**
   * The maximal amount of heap memory available to the JVM
   */
  public long heapMemoryMax;

  /**
   * The amount of heap memory used by the JVM
   */
  public long heapMemoryUsed;

  /**
   * The maximal amount of non-heap memory available to the JVM
   */
  public long nonHeapMemoryMax;

  /**
   * The amount of non-heap memory used by the JVM
   */
  public long nonHeapMemoryUsed; 
}

Such DTO can be used to obtain metrics from a NodeStatus service as follows:

// From service registry
NodeStatus ns = ...;
// Obtain all metrics for this node
Map<String, Object> metrics = ns.getMetrics();

// Convert the metrics map to a DTO for type-safe access
JMXMetricsDTO dto = Converters.standardConverter().convert(metrics)
                              .to(JMXMetricsDTO.class);

// Use metrics
System.out.println("System Load Average: " + dto.systemLoadAverage);

148.4 Framework Node Status Service

In case the cluster node is an OSGi framework, the FrameworkNodeStatus service is used to represent the node. FrameworkNodeStatus extends NodeStatus, and the node id is the OSGi framework UUID. Next to the Node Status service properties, this service has some additional service properties describing the OSGi and Java runtime:

Table 148.2 Additional service properties of the FrameworkNodeStatus service

Service Property Name Type Description
org.osgi.framework.version String

The OSGi framework version.

org.osgi.framework.processor String

The OSGi framework processor architecture.

org.osgi.framework.os_name String

The OSGi framework operating system name.

java.version String

The Java version.

java.runtime.version String

The Java runtime version.

java.specification.version String

The Java specification version.

java.vm.version String

The Java VM version.


Similar to the Node Status service, the service properties of the Framework Node Status service can be converted to a FrameworkNodeStatusDTO to have type-safe access to these properties using the Converter Specification.

The Framework Node Status service also extends the FrameworkManager interface, which provides a management interface for the OSGi framework. This allows a remote management agent to interact with the OSGi framework. The Framework Node Status service can be exported remotely with Remote Services, however alternative mechanisms to distribute this service are also permitted. For example, the FrameworkManager interface can also be made available through the REST Management Service Specification.

The following example uses the NodeStatus properties from a FrameworkNodeStatus service to see what country the framework is running in. If it is running in Germany a bundle specific for that country is installed:

@Component
public class FrameworkProvisioner {
    private static final Converter CONVERTER = Converters.standardConverter();

    @Reference(cardinality = MULTIPLE, policy = DYNAMIC)
    void addFramework(FrameworkNodeStatus fns, Map<String,Object> props) {
        // Convert the properties to the DTO for type safe access
        NodeStatusDTO dto = CONVERTER.convert(props).to(NodeStatusDTO.class);

        // Check the ISO 3166-1 alpha 3 country code
        if ("DEU".equals(dto.country)) {
            // If this framework runs in Germany, install a special bundle into it
            try {
                fns.installBundle("... Germany specific bundle ...");
            } catch (Exception e) {
                // log
            }
        }
    }
}

148.5 Application-specific Node Status metadata

The Node Status service provides a osgi.clusterinfo.tags property. Here, application specific tags can be assigned to the NodeStatus services. For example, one could assign different roles to the nodes such as "worker", "database", "storage", "gateway", etc. These roles are application-specific and should be defined by the application developer.

Bundles can specify additional tags to be included in the FrameworkNodeStatus service representing the current framework by registering any service with the service property org.osgi.service.clusterinfo.tags providing a custom String[] of tags. The Cluster Information implementation will add those to the tags property of the FrameworkNodeStatus service that represents the OSGi framework. For example:

// Register an arbitrary service that communicates the tags 
// to be added to the osgi.clusterinfo.tags service property.
Dictionary<String, Object> props = new Hashtable<>();
props.put("org.osgi.service.clusterinfo.tags", 
    new String [] {"database", "large_box"});
bundleContext.registerService(MyClass.class, this, props);

148.6 Security

148.6.1 Cluster Tag Permission

The ClusterTagPermission class allows fine-grained control over which bundles may add which tags to the Framework Node Status service. A bundle can be granted to add a certain tag to the Framework Node Status, or be granted to add any tag using the * wildcard.

148.6.2 Required Permissions

The Cluster Information Specification should only be implemented by trusted bundles. These bundles require ServicePermission[NodeStatus|FrameworkNodeStatus|FrameworkManager, REGISTER].

All bundles accessing the Cluster Information services should get ServicePermission[NodeStatus|FrameworkNodeStatus|FrameworkManager, GET].

Only trusted bundles who must be able to add Node Status tags should be assigned ClusterTagPermission[ClusterTag, ADD].

148.6.3 Remote service visibility in a cluster

By default, all remote OSGi services are visible within a cluster. This is handled by the Remote Service Admin Service Specification.

148.7 org.osgi.service.clusterinfo

Version 1.0

ClusterInfo Services Package Version 1.0.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.clusterinfo; version="[1.0,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.clusterinfo; version="[1.0,1.1)"

148.7.1 Summary

  • ClusterTagPermission - A bundle's authority to add a tag to a NodeStatus service.

  • FrameworkManager - Provides a management interface for accessing and managing a remote OSGi framework.

  • FrameworkNodeStatus - The FrameworkNodeStatus service represents a node in the cluster that is also an OSGi framework.

  • NodeStatus - The NodeStatus service represents a node in the cluster.

148.7.2 public final class ClusterTagPermission
extends Permission

A bundle's authority to add a tag to a NodeStatus service.

148.7.2.1 public static final String ADD = "add"

The action string add.

148.7.2.2 public ClusterTagPermission(String tag, String actions)

Give permission to add this tag, use * wildcard to give permission to add any tag.

add.

Defines the authority to add a tag to the NodeStatus service.

148.7.2.3 public boolean equals(Object obj)

The object to test for equality with this ClusterTagPermission object.

Determines the equality of two ClusterTagPermission objects. This method checks that specified ClusterTagPermission has the same tag as this ClusterTagPermission object.

true if obj is a ClusterTagPermission, and has the same tag as this ClusterTagPermission object; false otherwise.

148.7.2.4 public String getActions()

Returns the canonical string representation of the ClusterTagPermission action.

Always returns the ADD action.

Canonical string representation of the ClusterTagPermission actions.

148.7.2.5 public int hashCode()

Returns the hash code value for this object.

A hash code value for this object.

148.7.2.6 public boolean implies(Permission p)

The target permission to interrogate.

Determines if the specified permission is implied by this object.

This method checks that the tag of the target is implied by the tag name of this object.

true if the specified ClusterTagPermission action is implied by this object; false otherwise.

148.7.2.7 public PermissionCollection newPermissionCollection()

Returns a new PermissionCollection object suitable for storing ClusterTagPermission objects.

A new PermissionCollection object.

148.7.3 public interface FrameworkManager

Provides a management interface for accessing and managing a remote OSGi framework. This interface can be accessed remotely via Remote Services.

148.7.3.1 public BundleDTO getBundle(long id) throws Exception

Addresses the bundle by its identifier.

Retrieve the bundle representation for a given bundle Id.

A BundleDTO for the requested bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.2 public Map<String, String> getBundleHeaders(long id) throws Exception

Addresses the bundle by its identifier.

Get the header for a bundle given by its bundle Id.

Returns the map of headers entries.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.3 public Collection<BundleDTO> getBundles() throws Exception

Get the bundle representations for all bundles currently installed in the managed framework.

Returns a collection of BundleDTO objects.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.4 public BundleStartLevelDTO getBundleStartLevel(long id) throws Exception

Addresses the bundle by its identifier.

Get the start level for a bundle given by its bundle Id.

Returns a BundleStartLevelDTO describing the current start level of the bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.5 public int getBundleState(long id) throws Exception

Addresses the bundle by its identifier.

Get the state for a given bundle Id.

Returns the current bundle state as defined in org.osgi.framework.Bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.6 public FrameworkStartLevelDTO getFrameworkStartLevel() throws Exception

Retrieves the current framework start level.

Returns the current framework start level in the form of a FrameworkStartLevelDTO.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.7 public ServiceReferenceDTO getServiceReference(long id) throws Exception

Addresses the service by its identifier.

Get the service representation for a service given by its service Id.

The service representation as ServiceReferenceDTO.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.8 public Collection<ServiceReferenceDTO> getServiceReferences() throws Exception

Get the service representations for all services.

Returns the service representations in the form of ServiceReferenceDTO objects.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.9 public Collection<ServiceReferenceDTO> getServiceReferences(String filter) throws Exception

Passes a filter to restrict the result set.

Get the service representations for all services.

Returns the service representations in the form of ServiceReferenceDTO objects.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.10 public BundleDTO installBundle(String location) throws Exception

Passes the location string to retrieve the bundle content from.

Install a new bundle given by an externally reachable location string, typically describing a URL.

Returns the BundleDTO of the newly installed bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.11 public void setBundleStartLevel(long id, int startLevel) throws Exception

Addresses the bundle by its identifier.

The target start level.

Set the start level for a bundle given by its bundle Id.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.12 public void setFrameworkStartLevel(FrameworkStartLevelDTO startLevel) throws Exception

set the framework start level to this target.

Sets the current framework start level.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.13 public void startBundle(long id) throws Exception

Addresses the bundle by its identifier.

Start a bundle given by its bundle Id.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.14 public void startBundle(long id, int options) throws Exception

Addresses the bundle by its identifier.

Passes additional options as defined in org.osgi.framework.Bundle.start(int)

Start a bundle given by its bundle Id.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.15 public void stopBundle(long id) throws Exception

Addresses the bundle by its identifier.

Stop a bundle given by its bundle Id.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.16 public void stopBundle(long id, int options) throws Exception

Addresses the bundle by its identifier.

Passes additional options as defined in org.osgi.framework.Bundle.stop(int)

Stop a bundle given by its bundle Id.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.17 public BundleDTO uninstallBundle(long id) throws Exception

Addresses the bundle by its identifier.

Uninstall a bundle given by its bundle Id.

Returns the BundleDTO of the uninstalled bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.18 public BundleDTO updateBundle(long id) throws Exception

Addresses the bundle by its identifier.

Updates a bundle given by its bundle Id using the bundle-internal update location.

Returns the BundleDTO of the updated bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.3.19 public BundleDTO updateBundle(long id, String url) throws Exception

Addresses the bundle by its identifier.

The URL whose content is to be used to update the bundle.

Updates a bundle given by its URI path using the content at the specified URL.

Returns the BundleDTO of the updated bundle.

Exception– An exception representing a failure in the underlying remote call.

148.7.4 public interface FrameworkNodeStatus
extends NodeStatus, FrameworkManager

The FrameworkNodeStatus service represents a node in the cluster that is also an OSGi framework.

148.7.5 public interface NodeStatus

The NodeStatus service represents a node in the cluster.

A node could represent an entity available in the network that is not necessarily running an OSGi framework, such as a database or a load balancer.

148.7.5.1 public Map<String, Object> getMetrics(String... names)

a set of metric names that have to be obtained from the node. Of no names are specified all available metrics will be obtained. If a metric is requested that is not available by the node this metric is ignored and not present in the returned map.

Get the current metrics or other dynamic data from the node. Nodes may support custom metrics and as such the caller can request those metrics by name. The caller can specify the metric names to avoid having to compute and send all metrics over, if the caller is only interested in a subset of the available metrics.

Map with the current node metrics

148.8 org.osgi.service.clusterinfo.dto

Version 1.0

ClusterInfo DTO Package Version 1.0.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.clusterinfo.dto; version="[1.0,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.clusterinfo.dto; version="[1.0,1.1)"

148.8.1 Summary

148.8.2 public class FrameworkNodeStatusDTO
extends NodeStatusDTO

Data Transfer Object for a FrameworkNodeStatus Service.

148.8.2.1 public String java_runtime_version

The Java runtime version.

148.8.2.2 public String java_specification_version

The Java specification version.

148.8.2.3 public String java_version

The Java version.

148.8.2.4 public String java_vm_version

The Java VM version.

148.8.2.5 public String org_osgi_framework_os_name

The OSGi framework operating system name.

148.8.2.6 public String org_osgi_framework_processor

The OSGi framework processor architecture.

148.8.2.7 public String org_osgi_framework_version

The OSGi framework version.

148.8.2.8 public FrameworkNodeStatusDTO()

This DTO can be used to provide type safe access to properties of the FrameworkNodeStatus service.

148.8.3 public class NodeStatusDTO
extends DTO

Data Transfer Object for a NodeStatus Service.

148.8.3.1 public String cluster

The name of the cluster this node belongs to.

148.8.3.2 public String country

ISO 3166-1 alpha-3 location where this node instance is running, if known.

148.8.3.3 public String[] endpoints

The endpoint(s) at which this node can be accessed from the viewpoint of the consumer of the service.

148.8.3.4 public String id

The globally unique ID for this node. For example the Docker ID if this node is a Docker container, or the framework UUID if this node is an OSGi framework.

148.8.3.5 public String location

ISO 3166-2 location where this node instance is running, if known. This location is more detailed than the country code as it may contain province or territory.

148.8.3.6 public String parentid

An optional parentID indicating this node is part of or embedded in another node. For example multiple virtual machines could run on the same physical node.

148.8.3.7 public static final String PREFIX_ = "osgi.clusterinfo."

Prefix used for the converter

148.8.3.8 public String[] privateEndpoints

Private endpoint(s) at which this node can be accessed from within the cluster only.

148.8.3.9 public String region

Something smaller than a country and bigger than a location (e.g. us-east-1 or other cloud-specific location)

148.8.3.10 public String[] tags

Tags associated with this node that can be contributed to by the provider and also by bundles.

148.8.3.11 public String vendor

The vendor name of the cloud/environment in which the node operates.

148.8.3.12 public String version

The version of the cloud/environment in which the node operates. The value follows the versioning scheme of the cloud provider and may therefore not comply with the OSGi versioning syntax.

148.8.3.13 public String zone

Regions are often subdivided in zones that represent different physical locations. The zone can be provided here.

148.8.3.14 public NodeStatusDTO()

This DTO can be used to provide type safe access to properties of the NodeStatus service.