Prerequisites
To use the SCMB, 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 SCMB 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 state change messages are published to the HPE OneView SCMB exchange name. To subscribe to messages, you must create a queue or connect to an existing queue that receives messages from the SCMB exchange based on a routing key.
When you create a queue, you define the routing key associated with the queue to receive specific messages.
scmb. where:resource-category.change-type.resource-uri
|
The category of resource. For a complete list of resources, see the HPE OneView REST API Reference. |
|
|
The type of change that is reported. Valid values are |
|
|
The URI of the specific resource associated with the state-change message. |
|
|
|
![]() |
NOTE: The task resources routing key syntax is |
|
|
Sample queues
| Subscription | Example | ||||||
|---|---|---|---|---|---|---|---|
| Receive all SCMB messages for physical servers | scmb.server-hardware.#
|
||||||
| Receive all messages for created connections | scmb.connections.Created.# |
||||||
| Receive all messages for the enclosure with the URI /rest/enclosures/Enc1234 | scmb.enclosures.*./rest/enclosures/Enc1234
|
||||||
| Receive all created messages (for all resource categories and types) | scmb.*.Created.# |
The following table lists the attributes included in the JSON payload of each message from the SCMB. 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. For details, see “ChangeType values”. |
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 |
Object | 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. |
ChangeType values
ChangeType value |
Description |
|---|---|
Created |
The resource is created or is added to HPE OneView. |
Updated |
The resource state, attributes, or both are updated. |
Deleted |
The resource is permanently removed from HPE OneView. |
JSON example
{
"resourceUri" : "/rest/enclosures/123xyz",
"changeType" : "Created",
"newState" : "Managed",
"eTag" : "123456",
"timestamp" : "2013-07-10T18:30:44Z",
"newSubState" : "null",
"resource" : {
"category" : "enclosures",
"created" : "2013-07-10T18:30:00Z",
...
},
"associatedTask" : "/rest/tasks/4321",
"userInitiatedTask" : "true",
"changedAttributes" : [],
"data" : {},
}
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
scmb.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 scmb.crt -out scmb.p12
public void Connect()
{
string exchangeName = "scmb";
string hostName = "OneView.domain";
string queueName = "";
string routingKey = "scmb.#";
ConnectionFactory factory = new ConnectionFactory();
factory.AuthMechanisms = new RabbitMQ.Client.AuthMechanismFactory[] { new ExternalMechanismFactory() };
factory.HostName = hostname;
factory.Port = 5671;
factory.Ssl.CertPath = @".\scmb.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 scmb.crt into your preferred Windows certificate store.
public void Connect()
{
string exchangeName = "scmb";
string hostName = "OneView.domain";
string queueName = "";
string routingKey = "scmb.#";
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 SCMB 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(), "scmb", "scmb.#");
//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 code examples show how to connect and subscribe to the SCMB. For more information about Python (Pika AMQP client library and AMQP client library), see http://pika.readthedocs.org/, http://www.python.org/, and https://pypi.python.org/pypi/amqplib/.
-
Install the pika and amqp libraries.
-
Download and install the setuptools (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 = "scmb"
ROUTING_KEY = "scmb.#"
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, 'scmb', 'scmb.#')
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.
Prerequisites
| Re-creating and downloading the client certificate, private key, and root CA certificate | |||||||
|---|---|---|---|---|---|---|---|
|
|||||||







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