Chapter 4 Additional Utilities Exposed in the WS-API

Utility methods that are not directly related to core Oracle VM Manager behavior are exposed through a second endpoint available via the Web Services API. The Oracle VM Web Service Utilities API provides additional methods both for obtaining information within Oracle VM Manager and for configuring or triggering particular Oracle VM Manager functionality. Typical examples include determining which Oracle VM Servers are available to be added to a new server pool; obtaining a list of all file systems which are on local storage; setting statistics collection attributes used to configure how often statistics are gathered and for how long they are stored; and starting a backup process.

Java examples providing a fully implemented REST client is included in the SDK. This is available in com.oracle.ovm.mgr.ws.client:

  1. OvmWsRestUtilitiesClient.java contains the source code for the REST implementation of the Utilities Client

4.1 Authentication

Authentication for the REST interface to the Web Services Utilities API follows the same approach as that used to authenticate against the Oracle VM Manager REST API, see Section 3.2, “How do I Authenticate?” for more information. If your client is already authenticated, there should be no reason to perform authentication again in order to access the Utilities API.

The Utilities API can be accessed by appending "/Utilities" to the URI. Therefore, the base URI to access the utilities via the REST interface is:

https://hostname:port/ovm/core/wsapi/rest/Utilities

In this URI, replace hostname with the host name or IP address of Oracle VM Manager, and replace port with the number of the port where the REST web service is available - the default is 7002 (SSL).

4.2 Utilities Paths and Examples

In terms of the REST interface to the Web Services Utilities API, different methods exposed by the API are grouped together based on their functional relationships to Oracle VM Manager to create separate utilities. Each utility has its own relative path beyond the base URI that provides access to the methods that are available for that utility. The relative paths and a description of the utility is provided below:

  • /ArchiveManagement: utility to control the event and job logs housekeeping schedule

  • /BackupManagement: utility to access the Oracle VM Manager backup configuration and to provide the ability to start a backup operation on demand

  • /BusinessManagement: utility that provides tools to extend the functionality provided by the core API

  • /Certificate: utility to manage certificate registration for certificate-based authentication

  • /EventManagement: utility to manage internal events within Oracle VM Manager

  • /JobManagement: utility to manage jobs that are running or have completed within Oracle VM Manager

  • /LogManagement: utility to control runtime selection of which OVM software components (identified by the java package name) can write to the system log file and the level of detail of the messages written.

  • /MacManagement: utility to control how MAC addresses are generated for VNICs

  • /ModelManagement: utility to refresh and export the data model used by Oracle VM Manager to represent objects in the internal database

  • /StatisticsManagement: utility to control the statistics configuration, including how often statistics are collected and how long they are stored for

  • /UserPreferenceManagement: utility to manage variables within Oracle VM Manager used to control user specific preferences within the web-based user interface, such as accessibility settings

The methods available for each of the utilities is documented fully in the documentation provided with the SDK. The reader is encouraged to refer to this documentation to discover the full range of functionality provided by the Web Services Utilities API.

The Java example source code provided in OvmWsUtilitiesRestClient.java, in the SDK, provides excellent examples of how to access the methods exposed through the REST API using the Jersey Bundle tools. In the highly truncated sample below, it is easy to see that the different utility paths defined above are set as string values that can be combined to construct the correct URI to access each utility:

...
public class OvmWsUtilitiesRestClient extends RestClient implements OvmWsUtilitiesClient
{
    private static final String ATTRIBUTES_PATH            = "attributes";

    private static final String UTILITIES_PATH             = "Utilities";
    private static final String BUSINESS_MANAGEMENT_PATH   = "BusinessManagement";
    private static final String STATISTICS_MANAGEMENT_PATH = "StatisticsManagement";
    private static final String STATISTICS_ATTRIBUTES_PATH = ATTRIBUTES_PATH;
    private static final String MAC_MANAGEMENT_PATH        = "MacManagement";
    private static final String MAC_ATTRIBUTES_PATH        = ATTRIBUTES_PATH;
    private static final String ARCHIVE_MANAGEMENT_PATH    = "ArchiveManagement";
    private static final String ARCHIVE_ATTRIBUTES_PATH    = ATTRIBUTES_PATH;
    private static final String BACKUP_MANAGEMENT_PATH     = "BackupManagement";
    private static final String BACKUP_ATTRIBUTES_PATH     = ATTRIBUTES_PATH;
    private static final String EVENT_MANAGEMENT_PATH      = "EventManagement";
    private static final String EVENT_ATTRIBUTES_PATH      = ATTRIBUTES_PATH;
    private static final String SVR_EVENT_ATTRIBUTES_PATH  = "serverAttributes";
    private static final String JOB_MANAGEMENT_PATH        = "JobManagement";
    private static final String JOB_ATTRIBUTES_PATH        = ATTRIBUTES_PATH;
    private static final String LOG_MANAGEMENT_PATH        = "LogManagement";
    private static final String LOG_LOGGERATTRIBUTES_PATH  = ATTRIBUTES_PATH;
    private static final String RAS_MANAGEMENT_PATH        = "RasManagement";
    private static final String MODEL_MANAGEMENT_PATH      = "ModelManagement";
    private static final String USER_PREFERENCE_PATH       = "UserPreference";

    private final URI           businessManagementURI;
    private final URI           backupManagementURI;
    private final URI           logManagementURI;
    private final URI           jobManagementURI;
    private final URI           modelManagementURI;

    public OvmWsUtilitiesRestClient(final RestClient parentClient)
    {
        super(parentClient, UTILITIES_PATH);

        businessManagementURI = UriBuilder.fromUri(getBaseURI()).segment(BUSINESS_MANAGEMENT_PATH).build();
        backupManagementURI = UriBuilder.fromUri(getBaseURI()).segment(BACKUP_MANAGEMENT_PATH).build();
        logManagementURI = UriBuilder.fromUri(getBaseURI()).segment(LOG_MANAGEMENT_PATH).build();

        jobManagementURI = UriBuilder.fromUri(getBaseURI()).segment(JOB_MANAGEMENT_PATH).build();
        modelManagementURI = UriBuilder.fromUri(getBaseURI()).segment(MODEL_MANAGEMENT_PATH).build();
    }

    @Override
    public BusinessSelection<EthernetPort> utilGetAvailableEthernetPorts(final Id<Server> serverId, 
               final Id<Network> networkId)
        throws WsException
    {
        try
        {
            final Map<String, Object> queryParameters = createQueryParameterMap("serverId", serverId.getValue());
            if (networkId != null)
            {
                queryParameters.put("networkId", networkId.getValue());
            }
            final Builder b =
                    getResourceFromUriAndPathElementsWithQueryParameters(businessManagementURI, queryParameters,
                                                                         "availableEthernetPorts");

            @SuppressWarnings("unchecked")
            final BusinessSelection<EthernetPort> ethernetPorts = b.get(BusinessSelection.class);

            return ethernetPorts;
        }
        catch (final UniformInterfaceException ex)
        {
            throw convertException(ex);
        }
    }

...
}

In the code above, also included, is an example definition for the utilGetAvailableEthernetPorts method. Here you can see that since this class extends the RestClient class, it is able to use the getResourceFromUriAndPathElementsWithQueryParameters method in conjunction with the Jersey Builder to submit an HTTP GET request that returns the available Ethernet ports.

According to the documentation provided with the SDK, and extrapolating from the Java code, it should be easy to replicate this example in Python. The sample presented below provides a complete example of the Python code required to construct a similar query:

# import the requests library to handle HTTP requests and session maintenance
import requests
# import the json library for JSON translation (not required for this example)
import json

# instantiate a session object and populate it with authentication credentials
s=requests.Session()
s.auth=('user','password')
s.verify=False #disables SSL certificate verification
# configure the session to always use JSON
s.headers.update({'Accept': 'application/json', 'Content-Type': 'application/json'})

# set up a baseUri object to contain the URI to the Utilities API
baseUri='https://127.0.0.1:7002/ovm/core/wsapi/rest/Utilities'

# construct the URI according to the requirements set out in the documentation
uri='{base}/BusinessManagement/availableEthernetPorts'.format(
    base=baseUri)

# configure the query parameters
params={
    "serverId": "00:e0:81:4d:40:f5:00:e0:81:4d:40:be:00:e0:81:4d",
    "networkId": "0aac4c00"
}

# submit a get request to the uri and store the response
r=s.get(uri,params=params)
# use the requests library's native json parser to obtain a usable python object
availPorts=r.json()

4.3 Certificate Management for Certificate-based Authentication Using REST

The Utilities API significantly includes a set of methods that allow you to manage certificate generation and registration within Oracle VM Manager. This is important as the WS-API also allows for certificate-based authentication, allowing you to further secure how custom-developed applications authenticate and interact with Oracle VM Manager. This section explores some of these methods briefly in the context of the REST API.

Certificate management within Oracle VM Manager is discussed in a variety of contexts throughout the documentation. For more information on authenticating using an SSL certificate using REST, please see Section 3.6.2, “Authenticating”. Please also refer to Setting Up SSL in the Oracle VM Administrator's Guide for more information on SSL certificate management.

4.3.1 How to Obtain the CA Certificate Using REST

Once authenticated, either using an existing SSL certificate, or using the HTTP BASIC authentication mechanism, it is possible to query the Utility API to obtain the internal Oracle VM Manager CA certificate. This is achieved by simply sending an HTTP GET request to the following URI:

https://hostname:port/ovm/core/wsapi/rest/Utilities/Certificate/CaCertificate

This method simply returns the CA certificate as a string.

It is useful to obtain the CA certificate and to add it to your trusted certificates or to your keystore, so that it can be used to validate SSL interactions with Oracle VM Manager.

4.3.2 How to Sign and Register a Certificate Using REST

The API provides options to sign and register an SSL certificate using the internal Oracle VM Manager CA certificate. There are equally options to only sign a certificate, or to register an already signed certificate. This can be useful if you have added a trusted third-party CA certificate to Oracle VM Manager's own keystore, and wish to use a certificate issued by that third-party. These additional API methods are discussed in the API documentation. In this case, we assume that you need to sign and register a certificate with the internal CA.

The REST API allows you to sign and register a certificate by sending a POST request to the following URI:

https://hostname:port/ovm/core/wsapi/rest/Utilities/Certificate

The body of the POST request can contain either a JSON or XML representation of a loginCertificate object. Only the certificate element of the object need be populated. If no object is submitted within the POST request, the API automatically generates a certificate and passphraseless key that can be used for authentication. For security reasons, it is usually a good idea to generate a certificate locally and to set a passphrase for the key beforehand, so that the certificate can be passed in the body of the request.

Important

By default, the API only registers a certificate sent in the body of a POST request sent to this URI. This is to enable the possibility of using certificates already signed by a third party. To force the API to also sign a certificate submitted using this method, the boolean sign parameter must also be set to true within the URI. Therefore, in this case, you should post to the URI:

https://hostname:port/ovm/core/wsapi/rest/Utilities/Certificate?sign=True

Examples on creating a signing your certificates are provided below to show how you would go about doing this in Java and in Python.

Java

First create a key and certificate. If you are using Java, you would probably do this by generating a keystore using the Java keytool command:

$ keytool -genkey

Once you have set up a keystore and certificate, you can use the keytool to export your certificate in PEM format, so that you have it available for signing:

$ keytool -export -rfc

In your web services client, you must create a new LoginCertificate object and place your new certificate into the certificate field. For example:

LoginCertificate cert = new LoginCertificate();
cert.setCertificate("-----BEGIN CERTIFICATE-----" +
    "MIIDTzCCAw2gAwIBAgIEIIUUWjALBgcqhkjOOAQDBQAweTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT" +
    "AkNBMRUwEwYDVQQHEwxSZWR3b29kIENpdHkxDzANBgNVBAoTBk9yYWNsZTEaMBgGA1UECxMRT3Jh" +
    "Y2xlIFZNIE1hbmFnZXIxGTAXBgNVBAMTEENlcnRpZmljYXRlIERlbW8wHhcNMTMwODIxMTYzOTUz" +
    "WhcNMTMxMTE5MTYzOTUzWjB5MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFTATBgNVBAcTDFJl" +
    "ZHdvb2QgQ2l0eTEPMA0GA1UEChMGT3JhY2xlMRowGAYDVQQLExFPcmFjbGUgVk0gTWFuYWdlcjEZ" +
    "MBcGA1UEAxMQQ2VydGlmaWNhdGUgRGVtbzCCAbgwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUS" +
    "KVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3" +
    "a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/Ii" +
    "Axmd0UgBxwIVAJdgUI8VIwvMspK5gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrq" +
    "gvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1" +
    "k$ keytool -import -file newcertW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi" +
    "6bc9ozDyK1cgNyZWl4kq1efzjsyolIr1i4CiM/MqnEZO43hVVtXex3V+VWd9i/CLn0I/ZC9Lfi5X" +
    "HlQOEzWKK/esvf64Mv96DbZna/XRj6JhTEPGoStizNhXrVJCF4DaiIP+l53qYKJEtrNoR+tToRt8" +
    "OimE3PzLCXILvwwaCaMhMB8wHQYDVR0OBBYEFAtyjCpfkznpsUf2Lj8iBmRS3/0oMAsGByqGSM44" +
    "BAMFAAMvADAsAhRTm5NW8HDcM8jG5a7QIowNLN+fEQIUZXMogTvKbcXu6NN6fh0KY09hokI=" +
    "-----END CERTIFICATE-----");

Now you can invoke the method to sign and register your certificate, this returns the signed version of the certificate:

LoginCertificate signed = ovmUtil.certificateSignAndRegister(cert);
System.out.println(signed.getCertificate());

The output returned contains the newly signed certificate. You can dump this output to file, so that you can use it to import the newly signed certificate into your keystore:

$ keytool -import -file newcert

Note that you should also import the CA certificate into your keystore, so that your certificates can be validated. Be sure to use a different alias when importing the CA certificate into your keystore, to avoid overwriting your newly signed certificate and key.

Python

To generate a key and certificate locally for use in a Python application, use a tool like OpenSSL.

$ openssl genrsa -des3 -out mykey.pem 2048
$ openssl req -new -key mykey.pem -out mycertreq.csr
$ openssl x509 -req -days 365 -in mycertreq.csr -signkey mykey.pem -out mycert.pem

For security reasons, it is advisable to set a passphrase for your key. Note that this is a typical self-signed certificate, so you first generate a Certificate Signing Request (CSR) and then use your key to sign the certificate that you intend to generate from this CSR.

Once you have created a certificate, you can use the REST API to sign it. In Python, the following code could be used, assuming that you have already set up a Requests session and authenticated as described in Section 3.6.2.2, “Python”:

cert=open('/path/to/mycert.pem').read()
body={'certificate': cert}
r=s.post('https://127.0.0.1:7002/ovm/core/wsapi/rest/Utilities/Certificate?sign=True',
          data=json.dumps(body))
signed_cert=r.json()['certificate']
f=open('/path/to/signed.pem','w')
f.write(signed_cert)
f.close()

In the above example, we read the contents of the self-signed certificate into a variable named 'cert' and use this to create a python data structure that we can convert to a JSON string similar to the content that the API expects in the body of the request. We submit the POST request and set the sign parameter to True in the URI. We extract the newly signed certificate from the body of the response and then write the content of this into a file at /path/to/signed.pem.

To use this certificate to authenticate to the REST API using Python, it should be combined with its key. You can do this easily on the command line:

$ cat /path/to/signed.pem /path/to/mykey.pem >> /path/to/OVMSignedCertificate.pem

You can now use this new certificate to authenticate against the REST API from within any of your programs, as described in Section 3.6.2.2, “Python”.