The Metric Streaming Message Bus (MSMB) is an interface that uses asynchronous messaging to notify subscribers about the most recent metrics of the managed resources. You can configure the interval and the metrics that you want to receive using the REST APIs.
Prerequisites
To use the MSMB, you must do the following tasks:
-
Use REST APIs to create and download an Advanced Message Queuing Protocol (AMQP) certificate from the appliance.
-
Connect to the MSMB using one or both of these methods:
-
Use the “EXTERNAL” authentication mechanism
-
Connect without sending a user name and password
Using one of these methods ensures that certificate-based authentication is used.
-
-
Set up a queue with an empty queue name.
AMQP generates a unique queue name. You use this queue name to bind to exchanges and receive messages.
Create and download the AMQP client certificate
| Creating and downloading the client certificate, private key, and root CA certificate | ||
|---|---|---|
|
The metric streaming messages are published to the HPE OneView MSMB exchange name. To subscribe to messages, you must create a queue or connect to an existing queue that receives messages from the MSMB exchange based on a routing key.
When you create a queue, you define the routing key associated with the queue to receive specific messages.
Sample queues
The following table lists the attributes included in the JSON payload of each message from the MSMB. The resource model for the HPE OneView resource is included in the resource attribute. To view all resource models, see the HPE OneView REST API Reference.
| Attribute | Data type | Description |
|---|---|---|
resourceUri |
String | The URI for the resource. |
changeType |
String | The state-change type: Created, Updated, or Deleted. |
newState |
String | The new state of the resource. |
eTag |
String | The ETag for the resource when the state change occurred. |
timestamp |
String | The time the message was sent. |
newSubState |
String | If substate messages are required (for substate machines associated with a primary state), this is the resource-specific substate. |
resource |
MetricData | The resource model. |
associatedTask |
String | If a task is not associated with this message, the value is null. |
userInitiatedTask |
String | The value of the userInitiated attribute included in the associatedTask attribute. |
changedAttributes |
Array | A list of top-level attributes that have changed based on the POST or PUT call that caused the state-change message to be sent. |
data |
Object | Additional information about the resource state change. |
MetricData
| Attribute | Data type | Description |
|---|---|---|
startTime |
String | The starting time of the metric collection. |
sampleIntervalInSeconds |
Integer | Interval between samples. |
numberOfSamples |
Integer | Number of samples in the list for each metric type. |
resourceType |
String | Identifies the category of resource. The supported devices are server-hardware, enclosures, and power-devices. |
resourceDataList |
List | Metric sample list. |
uri |
String | Canonical URI of the resource. |
category |
String | Identifies the category of resource. The supported devices are server-hardware, enclosures, and power-devices. |
created |
Timestamp | Date and time when the resource was created. |
modified |
Timestamp | Date and time when the resource was last modified. |
eTag |
String | Entity tag/version ID of the resource, the same value that is returned in the ETag header on a GET of the resource. |
type |
String | Uniquely identifies the type of the JSON object. |
Structure of message received from the MSMB
{
"eTag": null,
"resourceUri": "/rest/enclosures/09SGH100X6J1",
"changeType": "Updated",
"newState": null,
"newSubState": null,
"associatedTask": null,
"userInitiatedTask": false,
"changedAttributes": null,
"data": null,
"resource": {
"type": "MetricData",
"resourceType": "enclosures",
"resourceDataList": [
{
"metricSampleList": [
{
"valueArray": [
null
],
"name": "RatedCapacity"
},
{
"valueArray": [
523
],
"name": "AveragePower"
},
{
"valueArray": [
573
],
"name": "PeakPower"
},
{
"valueArray": [
null
],
"name": "PowerCap"
},
{
"valueArray": [
23
],
"name": "AmbientTemperature"
},
{
"valueArray": [
null
],
"name": "DeratedCapacity"
}
],
"resourceId": "09SGH100X6J1"
}
],
"numberOfSamples": 1,
"sampleIntervalInSeconds": 300,
"startTime": "2014-09-17T08:43:36.294Z",
"eTag": null,
"modified": null,
"created": null,
"category": "enclosures",
"uri": "/rest/enclosures/09SGH100X6J1"
},
"timestamp": "2014-09-17T08:48:36.819Z"
}
Prerequisites
In addition to completing the prerequisites, you must complete the example-specific prerequisites before using the .NET C# examples.
To use the .Net C# examples, add the following to the Windows certificate store:
To try the .Net C# examples, do the following:
-
Save the contents in the response body into a text file named
rootCA.crt. You must copy and paste everything from-----BEGIN CERTIFICATE-----to-----END CERTIFICATE-----, including the dashes, but not including the quotes. -
Import the
rootCA.crtfile into the Windows certificate store underTrusted Root Certification Authorities. -
Save the contents of the client certificate and private key in the response body into a text file named
msmb.crt.You must copy and paste everything from
-----BEGIN CERTIFICATE-----to-----END CERTIFICATE-----for the client certificate. Next, copy and paste everything from-----BEGIN RSA PRIVATE KEY-----to-----END RSA PRIVATE KEY-----for the private key. You must include the dashes, but do not include the quotes.
Using .Net C# to directly reference client certificate
Convert the client certificate and private key to PKCS format for .Net.
openssl.exe pkcs12 -passout pass:default -export -in msmb.crt -out msmb.p12
public void Connect()
{
string exchangeName = "msmb";
string hostName = "OneView.domain";
string queueName = "";
string routingKey = "msmb.#";
ConnectionFactory factory = new ConnectionFactory();
factory.AuthMechanisms = new RabbitMQ.Client.AuthMechanismFactory[] { new ExternalMechanismFactory() };
factory.HostName = hostname;
factory.Port = 5671;
factory.Ssl.CertPath = @".\msmb.p12";
factory.Ssl.CertPassphrase = "default";
factory.Ssl.ServerName = hostname;
factory.Ssl.Enabled = true;
IConnection connection = factory.CreateConnection();
IModel model = connection.CreateModel();
queueName = model.QueueDeclare(queueName, false, false, false, null);
model.QueueBind(queueName, exchangeName, routingKey, null);
using (Subscription sub = new Subscription(model, queueName))
{
foreach (BasicDeliverEventArgs ev in sub)
{
DoSomethingWithMessage(ev);
sub.Ack();
}
}
}
Using .Net C# to import certificate to Microsoft Windows certificate store
Import the msmb.crt into your preferred Windows certificate store.
public void Connect()
{
string exchangeName = "msmb";
string hostName = "OneView.domain";
string queueName = "";
string routingKey = "msmb.#";
string userName = "rabbitmq_readonly";
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
X509Certificate cert = store.Certificates
.Find(X509FindType.FindBySubjectName, userName, false)
.OfType<X509Certificate>()
.First();
ConnectionFactory factory = new ConnectionFactory();
factory.AuthMechanisms = new RabbitMQ.Client.AuthMechanismFactory[] { new ExternalMechanismFactory() };
factory.HostName = hostname;
factory.Port = 5671;
factory.Ssl.Certs = new X509CertificateCollection(new X509Certificate[] { cert });
factory.Ssl.ServerName = hostname;
factory.Ssl.Enabled = true;
IConnection connection = factory.CreateConnection();
IModel model = connection.CreateModel();
queueName = model.QueueDeclare(queueName, false, false, false, null);
model.QueueBind(queueName, exchangeName, routingKey, null);
using (Subscription sub = new Subscription(model, queueName))
{
foreach (BasicDeliverEventArgs ev in sub)
{
DoSomethingWithMessage(ev);
sub.Ack();
}
}
}
-
Save the contents of the client certificate in the response body into a text file named
default-client.crt.You must copy and paste everything from
-----BEGIN CERTIFICATE-----to-----END CERTIFICATE-----, including the dashes, but not including the quotes. -
Save the contents of the private key in the response body into a text file named
default-client.key.You must copy and paste everything from
-----BEGIN RSA PRIVATE KEY-----to-----END RSA PRIVATE KEY-----, including the dashes, but not including the quotes. -
Create a PKCS12 keystore from the private key and the public certificate.
openssl pkcs12 -export -name myclientcert -in default-client.crt -inkey default-client.key -out myclient.p12
-
Convert the PKCS12 keystore into a JKS keystore.
keytool -importkeystore -destkeystore c:\\MyKeyStore -srckeystore myclient.p12 -srcstoretype pkcs12 -alias myclient
Example to connect and subscribe to MSMB using Java
//c://MyKeyStore contains client certificate and private key. Load it into Java Keystore
final char[] keyPassphrase = "MyKeyStorePassword".toCharArray();
final KeyStore ks = KeyStore.getInstance("jks");
ks.load(new FileInputStream("c://MyKeyStore"), keyPassphrase);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keyPassphrase);
//c://MyTrustStore contains CA certificate. Load it into Java Trust Store
final char[] trustPassphrase = "MyTrustStorePassword".toCharArray();
final KeyStore ks = KeyStore.getInstance("jks");
tks.load(new FileInputStream("c:\\MyTrustStore"), trustPassphrase);
final TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(tks);
//load SSLContext with keystore and truststore.
final SSLContext c = SSLContext.getInstance("SSL");
c.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
final ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.2.144");
//Set Auth mechanism to "EXTERNAL" so that commonName of the client certificate is mapped to AMQP user name. Hence, No need to set userId/Password here.
factory.setSaslConfig(DefaultSaslConfig.EXTERNAL);
factory.setPort(5671);
factory.useSslProtocol(c);
final Connection conn = factory.newConnection();
final Channel channel = conn.createChannel();
//do not specify queue name. AMQP will create a queue with random name starting with amq.gen* e.g. amq.gen-32sfQz95QJ85K_lMBhU6HA
final DeclareOk queue = channel.queueDeclare("", true, false, true, null);
//Now get the queue name from above call and bind it to required Exchange with required routing key.
channel.queueBind(queue.getQueue(), "msmb", "msmb.#");
//Now you should be able to receive messages from queue
final GetResponse chResponse = channel.basicGet(queue.getQueue(), false);
if (chResponse == null)
{
System.out.println("No message retrieved");
}
else
{
final byte[] body = chResponse.getBody();
System.out.println("Received: " + new String(body));
}
channel.close();
conn.close();
The Python examples show how to connect and subscribe to the MSMB. For more information about Python (Pika AMQP client library and AMQP client library), see Introduction to Pika (http://pika.readthedocs.org/, http://www.python.org/), and AMQP Client Library (https://pypi.python.org/pypi/amqplib/).
-
Install the pika and amqp libraries.
-
Download and install the setup tools (
Python setup.py install) at https://pypi.python.org/pypi/setuptools#downloads. -
When you install the pika or amqp libraries, run the same
python setup.py installcommand from the downloaded pika or amqp directory.
-
-
POST /rest/certificates/client/rabbitmqRequest body:
{"type":"RabbitMqClientCertV2","commonName":"default"} -
Save the contents of the client certificate in the response body into a text file named
client.pem.You must copy and paste everything from
-----BEGIN CERTIFICATE-----to-----END CERTIFICATE-----, including the dashes, but not including the quotes. You must replace all instances of\nwith CR/LF (carriage return / line feed). -
Save the contents of the private key in the response body into a text file named
key.pem.You must copy and paste everything from
-----BEGIN RSA PRIVATE KEY-----to-----END RSA PRIVATE KEY-----, including the dashes, but not including the quotes. You must replace all instances of\nwith CR/LF (carriage return / line feed). -
Save the contents in the response body into a text file named
caroot.pem. You must copy and paste everything from-----BEGIN CERTIFICATE-----to-----END CERTIFICATE-----, including the dashes, but not including the quotes. You must replace all instances of\nwith CR/LF (carriage return / line feed).
Pika example
When you invoke the script, you must pass –host:. See the following examples:{hostname or IP}
-
--host:192.168.1.1 -
–host:my-appliance.example.com
|
|
|
![]() |
IMPORTANT: If the connection fails on the first attempt to invoke this script after an appliance reboot, try invoking the script again. |
|
|
import pika, ssl
from optparse import OptionParser
from pika.credentials import ExternalCredentials
import json
import logging
logging.basicConfig()
###############################################
# Callback function that handles messages
def callback(ch, method, properties, body):
msg = json.loads(body)
timestamp = msg['timestamp']
resourceUri = msg['resourceUri']
resource = msg['resource']
changeType = msg['changeType']
print
print ("%s: Message received:" %(timestamp))
print ("Routing Key: %s" %(method.routing_key))
print ("Change Type: %s" %(changeType))
print ("Resource URI: %s" %(resourceUri))
print ("Resource: %s" %(resource))
# Pem Files needed, be sure to replace the \n returned from the APIs with CR/LF
# caroot.pem - the CA Root certificate - GET /rest/certificates/ca
# client.pem, first POST /rest/certificates/client/rabbitmq Request body: {"type":"RabbitMqClientCert","commonName":"default"}
# GET /rest/certificates/client/rabbitmq/keypair/default
# client.pem is the key with -----BEGIN CERTIFICATE-----
# key.pem is the key with -----BEGIN RSA PRIVATE KEY-----
# Setup our ssl options
ssl_options = ({"ca_certs": "caroot.pem",
"certfile": "client.pem",
"keyfile": "key.pem",
"cert_reqs": ssl.CERT_REQUIRED,
"server_side": False})
parser = OptionParser()
parser.add_option('--host', dest='host',
help='Pika server to connect to (default: %default)',
default='localhost',
)
options, args = parser.parse_args()
# Connect to RabbitMQ
host = options.host
print ("Connecting to %s:5671, to change use --host hostName " %(host))
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host, 5671, credentials=ExternalCredentials(),
ssl=True, ssl_options=ssl_options))
# Create and bind to queue
EXCHANGE_NAME = "msmb"
ROUTING_KEY = "msmb.#"
channel = connection.channel()
result = channel.queue_declare()
queue_name = result.method.queue
channel.queue_bind(exchange=EXCHANGE_NAME, queue=queue_name, routing_key=ROUTING_KEY)
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
# Start listening for messages
channel.start_consuming()
AMQP example
When you invoke the script, you must pass –host:. See the following examples:{hostname or IP}
-
--host:192.168.1.1 -
–host:my-appliance.example.com
|
|
|
![]() |
IMPORTANT: If the connection fails on the first attempt to invoke this script after an appliance reboot, try invoking the script again. |
|
|
#!/usr/bin/env python
from optparse import OptionParser
from functools import partial
import amqplib.client_0_8 as amqp
def callback(channel, msg):
for key, val in msg.properties.items():
print ('%s: %s' % (key, str(val)))
for key, val in msg.delivery_info.items():
print ('> %s: %s' % (key, str(val)))
print ('')
print (msg.body)
print ('-------')
print msg.delivery_tag
channel.basic_ack(msg.delivery_tag)
#
# Cancel this callback
#
if msg.body == 'quit':
channel.basic_cancel(msg.consumer_tag)
def main():
parser = OptionParser()
parser.add_option('--host', dest='host',
help='AMQP server to connect to (default: %default)',
default='localhost',
)
options, args = parser.parse_args()
host = options.host+":5671"
# Pem Files needed, be sure to replace the \n returned from the APIs with CR/LF
# caroot.pem - the CA Root certificate - GET /rest/certificates/ca
# client.pem, first POST /rest/certificates/client/rabbitmq Request body: {"type":"RabbitMqClientCert","commonName":"default"}
# GET /rest/certificates/client/rabbitmq/keypair/default
# client.pem is the key with -----BEGIN CERTIFICATE-----
# key.pem is the key with -----BEGIN RSA PRIVATE KEY-----
ssl_options = ({"ca_certs": "caroot.pem",
"certfile": "client.pem",
"keyfile": "key.pem",
# "cert_reqs": CERT_REQUIRED,
"server_side": False})
print ('Connecting to host %s, to change use --host hostName ' %host)
conn = amqp.Connection(host, login_method='EXTERNAL',
ssl=ssl_options)
print ('Successfully connected, creating and binding to queue')
ch = conn.channel()
qname, _, _ = ch.queue_declare()
ch.queue_bind(qname, 'msmb', 'msmb.#')
ch.basic_consume(qname, callback=partial(callback, ch))
print ('Successfully bound to queue, waiting for messages')
#pyamqp://
#
# Loop as long as the channel has callbacks registered
#
while ch.callbacks:
ch.wait()
ch.close()
conn.close()
if __name__ == '__main__':
main()
If you change the appliance name, you must re-create the AMQP client certificate.
|
|
|
![]() |
NOTE: If the certificates are already created, you can skip this step. |
|
|
Prerequisites
| Re-creating and downloading the client certificate, private key, and root CA certificate | |||||||
|---|---|---|---|---|---|---|---|
|
|||||||







![[NOTE: ]](images/note.gif)
![[IMPORTANT: ]](images/important.gif)