REST API

The Solution Manager provides a REST API to perform programmatically certain tasks. This is useful to automate the creating and deployment of revisions, automate the management of the licenses, etc. The operations to register and deregister servers from the Solution Manager can be used in combination with the auto-scaling capabilities of your cloud provider, to start and stop Denodo servers when necessary. The article Configuring Auto Scaling of Denodo in AWS of the Knowledge Base explains how to do this.

Considerations to use this API:

  • The base URL for all the operations (except externalShutdown and pingLicenseManager) is this:

    https://<host of the Solution Manager server>:10090
    

    10090 is the default port of the Solution Manager server.

  • Authentication:

    • If you installed the update of March 2020 or a more recent one in the Solution Manager:

      • The authentication protocols supported are HTTP Basic and Kerberos (SPNEGO).

      • The authentication is stateless so the requests do not depend on cookies nor sessions. This is the usual pattern followed by REST APIs, in which each request is independent from the previous ones.

    • In previous updates, first you have to send a request to an operation to obtain a cookie and then, include that cookie in all the requests. See more about this in the section Authentication with State in Solution Manager below.

      The authentication with state (a cookie) is deprecated but it will be supported during the full life of Denodo 7.0. Therefore, you can still use it even if you install the update of March 2020 or a more recent one.

List of operations:

Some operations are available since an update version. You can see the update version in the operation description.

Get the List of Environments

You can get the list of environments defined in the Solution Manager executing the following request:

  • URL: /environments

  • Method: GET

If the request has been successfully executed, the server sends the status code 200. The response body includes the list of environments in JSON format. Each environment can contain the following information:

{
    "id": <number>,
    "name": <text>,
    "description": <text>,
    "minimumUpdateValue":<number>  /* format yyyymmdd */,
    "minimumUpdateMandatory": <boolean> /* the minimum update is mandatory in the Virtual DataPort Administration Tool */,
    "minimumUpdateDownloadUrl": <URL>,
    "licenseAlias": <text>
}

The following example represents a list of 2 environments.

[
    {
        "id": 1,
        "name": "Environment 1",
        "description": "First environment",
        "minimumUpdateMandatory": false,
        "licenseAlias": "PRODUCTION"
    },
    {
        "id": 2,
        "name": "Environment 2",
        "description": "Second environment",
        "minimumUpdateMandatory": false,
        "licenseAlias": "DEVELOPMENT"
    }
]

Create an Environment

Available since 7.0 update 20190903.

Endpoint to create an environment:

  • URL: /environments

  • Method: POST

  • Syntax of the body of the request:

{
    "name": <text>,
    "description": <text>,  /* optional */
    "minimumUpdateValue":<number>  /* /* optional, format yyyymmdd */,
    "minimumUpdateMandatory": <boolean> /* optional, the minimum update is mandatory in the Virtual DataPort Administration Tool */,
    "minimumUpdateDownloadUrl": <URL> /* optional */,
    "licenseAlias": <text>    /* optional, assign a license to this environment */
}

Note

To assign a license to the environment, indicate the license alias. To obtain it, use the operation licenseAlias.

If the request succeeds, the service returns the HTTP code 201 and a response that contains the id of the new environment.

Example

In this example, we create a file “new_environment.json” with the body of the request and then, use cURL to send a request with the content of this file.

Content of the file “new_environment.json”
{
    "name": "finance-development",
    "description": "Environment for the development servers allocated to the finance department",
    "minimumUpdateValue": "20190312",
    "minimumUpdateDownloadUrl": "https://denodo-repository.acme.com/denodo-v70-update-20190903.zip",
    "minimumUpdateMandatory": true,
    "licenseAlias": "DEVELOPMENT"
}
Example of a request to the operation “create environment” using “cURL”
curl --data @new_environment.json --header "Content-Type: application/json" --header "Cookie: JSESSIONID=C02DD094790C29740C080A8A9202DB61" "https://solution-manager.acme.com:10090/environments"
Example of a response of the operation “create environment”
{
    "id": 1,
    "name": "finance-development",
    "description": "Environment for the development servers allocated to the finance department",
    "minimumUpdateValue": "20190312",
    "minimumUpdateDownloadUrl": "https://denodo-repository.acme.com/denodo-v70-update-20190903.zip",
    "minimumUpdateMandatory": true,
    "licenseAlias": "DEVELOPMENT"
}

Get the List of Licenses Available

Available since 7.0 update 20190903.

Get the list of licenses available license loaded in the Solution Manager.

  • URL: /licenseAlias

  • Method: GET

If the request succeeds, the service returns the HTTP code 200 and the body of the response contains the list of licenses in JSON format. Each license can contain the following information:

{
    "alias": <text>,  /* license alias name */
    "licenseType": <license type>,  /* license type */
    "version": <text>,  /* licence version number, i.e: 7.0 */
    "uniqueLicenseType": boolean /* indicates if there is more than one license with the same type */
}

<license type> ::=
      "PRODUCTION"
    | "STAGING"
    | "HOT_BACKUP"
    | "COLD_BACKUP"
    | "DEVELOPMENT"
    | "PERSONAL_DEVELOPER"
    | "TRAINING"
    | "EVALUATION"
    | "EXPRESS"
    | "TESTING"

Example of response

[{
        "alias": "DEVELOPMENT",
        "licenseType": "DEVELOPMENT",
        "version": "7.0",
        "uniqueLicenseType": true
    }, {
        "alias": "PERSONAL_DEVELOPER",
        "licenseType": "PERSONAL_DEVELOPER",
        "version": "7.0",
        "uniqueLicenseType": true
    }, {
        "alias": "PRODUCTION",
        "licenseType": "PRODUCTION",
        "version": "7.0",
        "uniqueLicenseType": true
    }
]

Update an Environment

Available since 7.0 update 20190903.

Operation to modify the configuration of an environment.

  • URL: /environments/{number:environmentId}

  • Method: PUT

  • Syntax of the body of the request:

    {
        "name": <text>,
        "description": <text>,  /* optional */
        "minimumUpdateValue":<number>  /* /* optional, format yyyymmdd */,
        "minimumUpdateMandatory": <boolean> /* optional, the minimum update is mandatory in the Virtual DataPort Administration Tool */,
        "minimumUpdateDownloadUrl": <URL> /* optional */,
        "licenseAlias": <text>    /* optional, associate the environemnt with a license */
    }
    

If the request succeeds, the service returns the HTTP code 200 and the body of the response contains a JSON document with the settings of the environment.

Example

Example of a PUT request:

{
    "name": "env",
    "description": "new description of the environment",
    "minimumUpdateValue": "20190312",
    "minimumUpdateDownloadUrl": "http://denodo.com/update20190312.zip",
    "minimumUpdateMandatory": false,
    "licenseAlias": "DEVELOPMENT"
}

Sample response:

{
    "id": 1,
    "name": "env",
    "description": "sample updated environment",
    "minimumUpdateValue": "20190312",
    "minimumUpdateMandatory": false,
    "minimumUpdateDownloadUrl": "http://denodo.com/update20190312.zip",
    "licenseAlias": "DEVELOPMENT"
}

Delete an Environment

Available since 7.0 update 20190903.

Delete an environment, and all the clusters and servers within the environment:

  • URL: /environments/{number:environmentId}

  • Method: DELETE

Example

The following request deletes the environment with identifier 1 and its clusters and servers:

DELETE https://solution-manager.acme.com:10090/environments/1

If the request succeeds, the service returns the HTTP code 204.

Get the List of Virtual DataPort Properties Associated to an Environment

Obtain the list of the Virtual DataPort properties defined on an environment.

  • URL: /environments/{number:environmentId}/vdpProperties

  • Method: GET

  • URL parameters. All of them are optional and can be combined:

  • propertyName: this parameter specifies an exact property name. If the URL contains this parameter, the operation ignores the parameters below.

  • databaseName: filters properties by database name.

  • elementType: filters properties by element type (for example, view or data source).

  • elementTypeName: filters properties by element type name (for example, JDBC, XML, etc.).

  • elementName: filters properties by element name.

The URL path must include the environment identifier.

The response has this format:

{
    "environmentProperties": [
        {
            "id": <number>,
            "name": <text>,
            "value": <text>,
            "propertyType": "VDP",
            "parentId": <number>,
            "undefined": <boolean>
        },
        { ... }
   ]
}

Example #1

The following example represents a response that returns the properties of the environment with identifier 4.

curl --header "Cookie: JSESSIONID=7A97C05B36D5496B0E509AE12E70965C" "https://solution-manager.acme.com:10090/environments/4/vdpProperties"
Response
 {
     "environmentProperties": [
         {
             "id": 30,
             "name": "users.smadmin.PASSWORD",
             "value": "mYgfbAayggeImPPOGfklFLfgt ...",
             "propertyType": "VDP",
             "parentId": 3,
             "undefined":false
         },
         {
             "id": 32,
             "name": "users.smadmin.PASSWORD.ALGORITHM",
             "value": "SHA512",
             "propertyType": "VDP",
             "parentId": 3,
             "undefined":false
         },
         {
             "id": 31,
             "name": "users.smadmin.PASSWORD.ENCRYPTED",
             "value": "ENCRYPTED",
             "propertyType": "VDP",
             "parentId": 3,
             "undefined":false
         },
         {
             "id": 32,
             "name": "undefinedProperty",
             "value": "",
             "propertyType": "VDP",
             "parentId": 1,
             "undefined": true
         }
     ]
}

Example #2

The following URL uses the parameter propertyName to obtain the value of the property users.smadmin.PASSWORD.ALGORITHM in the environment with id #2.

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?propertyName=users.smadmin.PASSWORD.ALGORITHM

This parameter cannot be combined with others.

Example #3

The following URL uses the parameter databaseName to obtain the properties defined for the database “admin”:

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?databaseName=admin

Example #4

The following URL uses the parameter elementType to obtain the properties of the data sources:

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?elementType=datasources

Example #5

The following URL uses the parameter elementTypeName to obtain the properties of all the JDBC data sources:

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?elementTypeName=jdbc

Example #6

The following URL uses the parameter elementName to obtain the properties of the elements whose name is “oracle12c”:

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?elementName=oracle12c

Example #7

The following URL uses the parameters databaseName, elementType and elementTypeName to obtain the properties of the LDAP data sources of the database admin:

GET https://solution-manager.acme.com:10090/environments/2/vdpProperties?databaseName=admin&elementType=datasources&elementTypeName=ldap

Create and Delete Environment Properties

If you execute a POST request to the following URL you can create an environment property:

  • URL: /environments/{number:environmentId}/vdpProperties

  • Method: POST

The request body must include the list of properties, according to the following format:

[
   {
        "name" : <text>,
        "value" : <text>
        "undefined" : <boolean>, /* optional (false by default) */
        "valueEncrypted" : <boolean> /* optional */
   },
   { ... }
]

The undefined property is optional; if you do not indicate it, this value is false by default.

About the attribute valueEncrypted, consider this:

  • The Solution Manager stores encrypted the values of properties that represent passwords of data sources, user accounts and other values. However, when you use the API to define these properties, you can send their value encrypted or in clear text.

    The values the Solution Manager stores encrypted are the ones that if you export the VQL of that element, it has the token ENCRYPTED next to the value.

  • If valueEncrypted is true, it indicates that value is encrypted.

    To encrypt a value, use the script <SOLUTION_MANAGER_HOME>/bin/encrypt_password.

  • If valueEncrypted is false, value is treated as clear text.

  • valueEncrypted is optional; if it is not defined and this property represents a password, the API tries to decrypt the password. If the password cannot be decrypted, it is treated as clear text.

The example below shows a POST request which creates some properties:

[
    {
        "name": "users.smadmin.PASSWORD",
        "value": "mYgfbAayggeImPPOGfklFLfgt2Azb/5TVjDtYQChCE29k6tjDru7 ... "
    }, {
        "name": "users.smadmin.PASSWORD.ALGORITHM",
        "value": "SHA512"
    }, {
        "name": "users.acme.PASSWORD",
        "value": "mypassword",
        "valueEncrypted" : false
    }, {
        "name": "users.acme.PASSWORD.ALGORITHM",
        "value": "SHA512"
    }, {
        "name": "undefinedProperty",
        "value": "",
        "undefined": true
    }, {
        "name": "databases.admin.datasources.jdbc.acmeOracle10gDs.USERPASSWORD",
        "value": "+W+33sO24bVxvswlAuCFzrdaSC0m9n7Psuq7NzIsPBcku6yxaRlEc ..."
    }, {
        "name": "databases.admin.datasources.jdbc.dsAcmeOracle11g.USERPASSWORD",
        "value": "+W+33sO24bVxvswlAuCFzrdaSC0m9n7Psuq7NzIsPBcku6yxaRlEc ...",
        "valueEncrypted": true
    }, {
        "name": "databases.admin.datasources.jdbc.dsAcmeOracle12c.USERPASSWORD",
        "value": "VKvBccVYr3HaJOEqqwKFxw=="
    }, {
        "name": "databases.admin.datasources.jdbc.dsAcmeSqlServer.USERPASSWORD",
        "value": "VKvBccVYr3HaJOEqqwKFxw==",
        "valueEncrypted": true
    }, {
        "name": "databases.admin.datasources.jdbc.dsAcmeMySql4.USERPASSWORD",
        "value": "password_not_encrypted"
    }, {
        "name": "databases.admin.datasources.jdbc.dsAcmeMySql5.USERPASSWORD",
        "value": "password_not_encrypted",
        "valueEncrypted": false
    }
]

This example shows the different way of sending the password of a user account and the password of a data source:

  • The password of the user account “acme” is sent in clear text (the property valueEncrypted is false).

  • The password of the user account “smadmin” is sent encrypted. The property valueEncrypted is not included so the API checks if it is an encrypted password and because it is, it is processed as an encrypted value.

  • The password of the data sources “dsAcmeMySql4” and “dsAcmeMySql5” is sent in clear text. Note that for one, the attribute “valueEncrypted” is explicitly set to false and for the other it is not.

The response body contains the new properties with their identifiers:

[
    {
        "id": 30,
        "name": "users.smadmin.PASSWORD",
        "value": "BmdTQex9b2RVp5GXMYDPRUvZz1pj4OjSQ7paWMSctugWxRA+k27e ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 31,
        "name": "users.smadmin.PASSWORD.ALGORITHM",
        "value": "SHA512",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 32,
        "name": "users.acme.PASSWORD",
        "value": "8N8RqgTx1WmmgZjf3Fdu3spgviZiTaeFXnnN4xKqxEaEAZFx87Ph ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 33,
        "name": "users.acme.PASSWORD.ALGORITHM",
        "value": "SHA512",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 34,
        "name": "undefinedProperty",
        "value": "",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": true
    }, {
        "id": 35,
        "name": "databases.admin.datasources.jdbc.acmeOracle10gDs.USERPASSWORD",
        "value": "+W+33sO24bVxvswlAuCFzrdaSC0m9n7Psuq7NzIsPBcku6yxaRlE ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 37,
        "name": "databases.admin.datasources.jdbc.dsAcmeOracle11g.USERPASSWORD",
        "value": "+W+33sO24bVxvswlAuCFzrdaSC0m9n7Psuq7NzIsPBcku6yxaRlE ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 39,
        "name": "databases.admin.datasources.jdbc.dsAcmeOracle12c.USERPASSWORD",
        "value": "8/2uLS4oYBFzNtRukE39tI0MFaoyMzkq86RMmxtn0bFZiIPMGFVK ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 41,
        "name": "databases.admin.datasources.jdbc.dsAcmeSqlServer.USERPASSWORD",
        "value": "1A3sQGU0ENO0PgwaFocti+1tZoWdpydcwmgfkzVYYfOrouu7aGLP ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 43,
        "name": "databases.admin.datasources.jdbc.dsAcmeMySql4.USERPASSWORD",
        "value": "UoiCsYFfmYhQsuv1BVpDBmjtj2nilgfvWt9By/+RZ6AwTICU71an ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }, {
        "id": 45,
        "name": "databases.admin.datasources.jdbc.dsAcmeMySql5.USERPASSWORD",
        "value": "aOI1DL1vYxZq5YJLzKYKfKyW6v9BEBR6M8ibVFby5Yh1Ij46LMwz ... ",
        "propertyType": "VDP",
        "parentId": 4,
        "undefined": false
    }
]

This operation returns the passwords encrypted.

If you send a DELETE request to the following URL, you can delete an environment property:

  • URL: /vdpProperties/{number:vdpPropertyId}

  • Method: DELETE

The next example deletes a property with the identifier 5:

DELETE https://solution-manager.acme.com:10090/vdpProperties/5

If the property has been successfully deleted, the response status code is 204.

Get the List of Clusters

The following request returns the list of clusters of an environment:

  • URL: /environments/{number:environmentId}/clusters

  • Method: GET

If the request has been successfully executed, the server sends the status code 200. The response body includes the list of clusters in JSON format. Each cluster can contain the following information:

{
    "clusters": [
        {
            "id": <number>,
            "name": <text>,
            "enabled": <boolean>
        },
        { ... }
    ]
}

The following example returns a list with 2 clusters.

{
    "clusters": [
        {
            "id": 7,
            "name": "Cluster 2",
            "enabled": true
        },
        {
            "id": 8,
            "name": "Cluster 3",
            "enabled": false
        }
    ]
}

Create a Cluster

Available since 7.0 update 20190903.

If you execute a POST request to the following URL you can create a cluster:

  • URL: /clusters

  • Method: POST

The request body has to follow this format:

{
    "name": <text>,
    "description": <text>, /* optional */
    "environmentId": <number>,
    "enabled": boolean
}

The environmentId is the environment identifier that can be obtained in Get the List of Environments

If the cluster has been successfully inserted, the response status code is 201.

The next example shows a POST request which create a cluster:

{
    "name": "clusterSample",
    "description": "A cluster sample",
    "environmentId": 1,
    "enabled": true
}

The response body contains the added cluster with its identifier:

{
    "id": 10,
    "name": "clusterSample",
    "description": "A cluster sample",
    "order": 1,
    "environmentId": 1,
    "enabled": true
}

The returned order indicates the order of the cluster within the environment.

Get a Cluster

Available since 7.0 update 20190903.

The following request returns the list of clusters of an environment:

  • URL: /clusters/{number:clusterId}

  • Method: GET

If the request has been successfully executed, the server sends the status code 200. The response body includes the cluster in JSON format with the following information:

{
    "id": <number>,
    "name": <text>,
    "description": <text>,
    "order": <number>,
    "environmentId": <number>,
    "enabled": boolean
}

The following example returns the cluster with id 10.

{
    "id": 10,
    "name": "clusterSample",
    "description": "A cluster sample",
    "order": 1,
    "environmentId": 1,
    "enabled": true
}

Update a Cluster

Available since 7.0 update 20190903.

If you execute a PUT request to the following URL you can update a cluster:

  • URL: /clusters/{number:clusterId}

  • Method: PUT

The request body has to follow this format:

{
    "name": <text>,
    "description": <text>,  /* optional */
    "environmentId": <number>,
    "enabled": boolean
}

If the cluster has been successfully updated, the response status code is 200.

The next example shows a PUT request which update the cluster with id 10:

{
    "name": "clusterSample updated",
    "description": "A cluster sample updated",
    "environmentId": 1,
    "enabled": true
}

The response body contains the udpated cluster:

{
    "id": 10,
    "name": "clusterSample updated",
    "description": "A cluster sample updated",
    "order": 1,
    "environmentId": 1,
    "enabled": true
}

Delete a Cluster

Available since 7.0 update 20190903.

If you send a DELETE request to the following URL, you can delete a cluster:

  • URL: /clusters/{number:clusterId}

  • Method: DELETE

The next example deletes a cluster with the identifier 10:

DELETE https://solution-manager.acme.com:10090/clusters/10

If the cluster has been successfully deleted, the response status code is 204. This operation deletes all the servers contained in the cluster.

Get the List of Scheduler Properties Associated to a Cluster

The following URL returns the list of Scheduler properties for a given cluster:

  • URL: /clusters/{number:clusterId}/schProperties

  • Method: GET

  • Parameters:

    • propertyName: this parameter specifies an exact property name.

    • projectName: this parameter filters properties by project name.

    • elementType: this parameter filters properties by element type (for example, data source).

    • elementTypeName: this parameter filters properties by element type name (for example, VDP).

    • elementName: this parameter filters properties by element name.

The URL path must include the cluster identifier. The following URL returns the Scheduler properties for the cluster with the identifier 3.

GET https://solution-manager.acme.com:10090/cluster/3/schProperties

Optional Request Parameters to Filter Cluster Properties

The following URL specifies the parameter propertyName and returns a Scheduler property with name SolutionManager.dataSource.ITP.itpds.dbName.

GET https://solution-manager.acme.com:10090/clusters/4/schProperties?propertyName=SolutionManager.dataSource.ITP.itp.dbName

Note

If propertyName is specified, the other parameters are ignored.

The parameter projectName filters properties by project. The following URL returns all properties matching SolutionManager.*

GET https://solution-manager.acme.com:10090/clusters/2/schProperties?projectName=SolutionManager

The parameter elementType filters properties by element type. The following URL returns all properties matching *.datasource.*. Example: SolutionManager.dataSource.ITP.itpds.host.

GET https://solution-manager.acme.com:10090/clusters/2/schProperties?elementType=datasource

The parameter elementTypeName filters properties by element type name. The following URL returns all properties related with ITP. Example: SolutionManager.dataSource.ITP.itpds.host.

GET https://solution-manager.acme.com:10090/clusters/2/schProperties?elementTypeName=ITP

The parameter elementName filters properties by element name. The following URL returns the properties of the data source named itpds.

GET https://solution-manager.acme.com:10090/clusters/2/schProperties?elementName=itpds

Except the parameter propertyName, the others can be combined in the same request. For example, the following URL returns all data source properties of the project SolutionManager.

GET https://solution-manager.acme.com:10090/clusters/2/schProperties?projectName=SolutionManager&elementType=datasource

Create and Delete Cluster Properties

You can execute a POST request to the following URL to create cluster properties:

  • URL: /clusters/{number:clusterId}/schProperties

  • Method: POST

The request body must include the list of properties, according to the following format:

[
   {
        "name" : <text>,
        "value" : <text>,
        "undefined" : <boolean>, /* optional */
        "valueEncrypted" : <boolean> /* optional */
   },
   { ... }
]

The undefined attribute is optional; if you do not indicate it, this value is false by default.

About the attribute valueEncrypted, consider this:

  • The Solution Manager stores encrypted the values of properties that represent passwords of data sources, user accounts and other values. However, when you use the API to define these properties, you can send their value encrypted or in clear text.

    The values the Solution Manager stores encrypted are the ones that if you export the VQL of that element, it has the token ENCRYPTED next to the value.

  • If valueEncrypted is true, it indicates that value is encrypted.

    To encrypt a value, use the script <SOLUTION_MANAGER_HOME>/bin/encrypt_password.

  • If valueEncrypted is false, value is treated as clear text.

  • valueEncrypted is optional; if it is not defined and this property represents a password, the API tries to decrypt the password. If the password cannot be decrypted, it is treated as clear text.

The next example shows a POST request which creates some properties:

[
    {
        "name": "default.dataSource.VDP.vdp.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp.password",
        "value": "TXnmQ/CtG8ijoA0JteoAOA="
    }, {
        "name": "default.dataSource.VDP.vdp2.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp2.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp2.password",
        "value": "TXnmQ/CtG8ijoA0JteoAOA=",
        "valueEncrypted": true
    }, {
        "name": "default.dataSource.VDP.vdp3.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp3.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp3.password",
        "value": "y+jVDz0Im7m+5Utu3DnRrA=="
    }, {
        "name": "default.dataSource.VDP.vdp4.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp4.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp4.password",
        "value": "y+jVDz0Im7m+5Utu3DnRrA==",
        "valueEncrypted": true
    }, {
        "name": "default.dataSource.VDP.vdp5.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp5.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp5.password",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp6.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin"
    }, {
        "name": "default.dataSource.VDP.vdp6.login",
        "value": "admin"
    }, {
        "name": "default.dataSource.VDP.vdp6.password",
        "value": "admin",
        "valueEncrypted": false
    }, {
        "name": "undefinedProperty",
        "value": "",
        "undefined": true
    }
]

This example shows the different ways of sending the password of data sources defined in Scheduler:

  • The password of the data sources “vdp”, “vdp2”, “vdp3” and “vdp4” is encrypted.

  • The password of the data sources “vdp5” and “vdp6” is in clear text.

The response body contains the new properties with their identifiers:

[
    {
        "id": 45,
        "name": "default.dataSource.VDP.vdp.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 46,
        "name": "default.dataSource.VDP.vdp.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 47,
        "name": "default.dataSource.VDP.vdp.password",
        "value": "TXnmQ/CtG8ijoA0JteoAOA=",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 49,
        "name": "default.dataSource.VDP.vdp2.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 50,
        "name": "default.dataSource.VDP.vdp2.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 51,
        "name": "default.dataSource.VDP.vdp2.password",
        "value": "TXnmQ/CtG8ijoA0JteoAOA=",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 53,
        "name": "default.dataSource.VDP.vdp3.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 54,
        "name": "default.dataSource.VDP.vdp3.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 55,
        "name": "default.dataSource.VDP.vdp3.password",
        "value": "0Ka6pzSh0moIW9TfJuOZGQ==",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 57,
        "name": "default.dataSource.VDP.vdp4.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 58,
        "name": "default.dataSource.VDP.vdp4.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 59,
        "name": "default.dataSource.VDP.vdp4.password",
        "value": "JZePPEsbrn1TBYiocvUK8g==",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 61,
        "name": "default.dataSource.VDP.vdp5.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 62,
        "name": "default.dataSource.VDP.vdp5.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 63,
        "name": "default.dataSource.VDP.vdp5.password",
        "value": "F2S5clF8KtbS9xpa0b9AWQ==",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 65,
        "name": "default.dataSource.VDP.vdp6.connectionURI",
        "value": "//solution-manager.acme.com:19999/admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 66,
        "name": "default.dataSource.VDP.vdp6.login",
        "value": "admin",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 67,
        "name": "default.dataSource.VDP.vdp6.password",
        "value": "x9NDwbCwYG/3CREydSxNGA==",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": false
    },
    {
        "id": 69,
        "name": "undefinedProperty",
        "value": "",
        "propertyType": "SCHEDULER",
        "parentId": 5,
        "undefined": true
    }
]

This operation returns the passwords encrypted.

If you send a DELETE request to the following URL, you can delete a cluster property:

  • URL: /schProperties/{number:schPropertyId}

  • Method: DELETE

The next example deletes a property with identifier 5:

DELETE https://solution-manager.acme.com:10090/schProperties/5

If the property has been successfully deleted, the response status code is 204.

Get the List of Servers

Available since 7.0 update of March 2020.

The following request returns the list of servers in an environment:

  • URL: /environments/{number:environmentId}/servers

  • Method: GET

If the request has been successfully executed, the server sends the status code 200. The response body includes the list of servers with basic information in JSON format. Each server can contain the following information:

{
    "servers": [
        {
            "id": <number>,
            "name": <text>,
            "typeNode": <type-node>,
            "clusterId": <number>,  /* id of the cluster to which it belongs */
            "enabled": <boolean>
        },
        { ... }
    ]
}

<type-node> ::= "VDP" | "SCHEDULER" | "ITP_BROWSER_POOL" | "ITP_VERIFICATION" | "VDP_DATA_CATALOG"

The following example get the servers of the environment with identifier 6.

curl --header "Cookie: JSESSIONID=7A97C05B36D5496B0E509AE12E70965C" "https://solution-manager.acme.com:10090/environments/6/servers"
Response
 {
     "servers": [
         {
             "id": 9,
             "name": "vdpServer",
             "typeNode": "VDP",
             "clusterId": 7,
             "enabled": true
         },
         {
             "id": 10,
             "name": "schedulerServer",
             "typeNode": "SCHEDULER",
             "clusterId": 7,
             "enabled": true
         }
     ]
 }

See get server to get more info about a server.

Create a server

Available since 7.0 update 20190903.

If you execute a POST request to the following URL you can create a server:

  • URL: /servers

  • Method: POST

The request body has to follow this format:

{
    "id": <number>,
    "name": <text>,
    "description": <text>, /* optional */
    "typeNode": <node type>,
    "urlIP": <text>,
    "urlPort": <number>,
    "clusterId": <number>,
    "useKerberos": <boolean>,
    "usePassThrough": <boolean>,
    "username": <text>,
    "password": <text>,
    "defaultDatabase": <text>,
    "enabled": <boolean>,
    "licenseAlias": <text>, /* optional */
    "useDefaultLicenseAlias": <boolean>
}

<node type> ::=
      "VDP"
    | "SCHEDULER"
    | "ITP_BROWSER_POOL"
    | "ITP_VERIFICATION"
    | "VDP_DATA_CATALOG"

The clusterId must be the cluster identifier that can be obtained in Get the List of Clusters.

The password accepts the following values:

  • clear password

  • password encrypted with the encrypt_password script located in <SOLUTION_MANAGER_HOME>/bin

If useDefaultLicenseAlias is true, you can ommit the licenseAlias field or use an empty string. If useDefaultLicenseAlias is false, then you must indicate the license alias that can be obtained in Get the List of Licenses Available. If the server has been successfully inserted, the response status code is 201.

The next example shows a POST request which create a server:

{
    "name": "vdpLocal",
    "description": "",
    "typeNode": "VDP",
    "urlIP": "cajun",
    "urlPort": 9999,
    "clusterId": 11,
    "useKerberos": false,
    "usePassThrough": false,
    "username": "admin",
    "password": "admin",
    "defaultDatabase": "admin",
    "enabled": true,
    "licenseAlias": "",
    "useDefaultLicenseAlias": true
}

In this example password is a clear password. If the password is generated with the encrypt_password script, the password will be similar to:

"password": "8seLz7OWe6SRc9ivmekrkE+NTn8DzGxy",

The response body contains the added server with its identifier:

{
    "id": 12,
    "name": "vdpLocal",
    "description": "",
    "typeNode": "VDP",
    "urlIP": "cajun",
    "urlPort": 9999,
    "clusterId": 11,
    "useKerberos": false,
    "usePassThrough": false,
    "username": "admin",
    "defaultDatabase": "admin",
    "enabled": true,
    "licenseAlias": "",
    "useDefaultLicenseAlias": true
}

Get a Server

Available since 7.0 update 20190903.

The following request returns a server:

  • URL: /servers/{number:serverId}

  • Method: GET

If the request has been successfully executed, the server sends the status code 200. The response body includes the server in JSON format with the following information:

{
    "id": <number>,
    "name": <text>,
    "description": <text>,
    "typeNode": <node type>,
    "urlIP": <text>,
    "urlPort": <number>,
    "clusterId": <number>,
    "useKerberos": <boolean>,
    "usePassThrough": <boolean>,
    "username": <text>,
    "defaultDatabase": <text>,
    "enabled": <boolean>,
    "licenseAlias": <text>,
    "useDefaultLicenseAlias": <boolean>
}

<node type>::=
      "VDP"
    | "SCHEDULER"
    | "ITP_BROWSER_POOL"
    | "ITP_VERIFICATION"
    | "VDP_DATA_CATALOG"

Any property with null value will not be included in the JSON.

The following example returns the server with id 12.

{
    "id": 12,
    "name": "vdpLocal",
    "description": "",
    "typeNode": "VDP",
    "urlIP": "cajun",
    "urlPort": 9999,
    "clusterId": 11,
    "useKerberos": false,
    "usePassThrough": false,
    "username": "admin",
    "defaultDatabase": "admin",
    "enabled": true,
    "licenseAlias": "",
    "useDefaultLicenseAlias": true
}

Update a Server

Available since 7.0 update 20190903.

If you execute a PUT request to the following URL you can update a server:

  • URL: /servers/{number:serverId}

  • Method: PUT

The request body has to follow this format:

{
    "name": <text>,
    "description": <text>,  /* optional */
    "typeNode": <node type>,
    "urlIP": <text>,
    "urlPort": <number>,
    "clusterId": <number>,
    "useKerberos": <boolean>,
    "usePassThrough": <boolean>,
    "username": <text>,
    "password": <text>,
    "defaultDatabase": <text>,
    "enabled": <boolean>,
    "licenseAlias": <text>,  /* optional */
    "useDefaultLicenseAlias": <boolean>
}

<node type>::=
      "VDP"
    | "SCHEDULER"
    | "ITP_BROWSER_POOL"
    | "ITP_VERIFICATION"
    | "VDP_DATA_CATALOG"

Note

The password accepts the following values:

  • ********” (8 asterisks), this values does not modify the password value

  • Clear password

  • A password encrypted with the encrypt_password script located in <SOLUTION_MANAGER_HOME>/bin

If the server has been successfully updated, the response status code is 200.

The next example shows a PUT request which update the server with id 12:

{
    "name": "vdpLocal-modif",
    "description": "",
    "typeNode": "VDP",
    "urlIP": "cajun",
    "urlPort": 9999,
    "clusterId": 11,
    "useKerberos": false,
    "usePassThrough": false,
    "username": "admin",
    "password": "********",
    "defaultDatabase": "admin",
    "enabled": true,
    "licenseAlias": "",
    "useDefaultLicenseAlias": true
}

The response body contains the updated server:

{
    "id": 12,
    "name": "vdpLocal-modif",
    "description": "",
    "typeNode": "VDP",
    "urlIP": "cajun",
    "urlPort": 9999,
    "clusterId": 11,
    "useKerberos": false,
    "usePassThrough": false,
    "username": "admin",
    "defaultDatabase": "admin",
    "enabled": true,
    "licenseAlias": "",
    "useDefaultLicenseAlias": true
}

Delete a Server

Available since 7.0 update 20190903.

If you send a DELETE request to the following URL, you can delete a server:

  • URL: /servers/{number:serverId}

  • Method: DELETE

The next example deletes a property with the identifier 12:

DELETE https://solution-manager.acme.com:10090/servers/12

If the server has been successfully deleted, the response status code is 204.

Get the List of Revisions

The following URL returns the list of revisions:

  • URL: /revisions

  • Method: GET

  • Parameters:

    • start: this parameter specifies the first element of the collection to be returned.

    • count: this parameter specifies the maximum number of results to be returned.

The response body includes the list of revisions according to the following format:

{
    "start": <number>, /* specifies the first revision of the collection to be returned */
    "count": <number>, /* maximum number of revisions to be returned */
    "numElements": <number>, /* total number of revisions included in the response */
    "revisions": [{
            "id": <number>,
            "description": <text>,
            "name": <text>,
            "type": { "INSERT" | "DELETE" }, /* alias for CREATE and DROP */
            "replace": <replace-drop Virtual DataPort elements>,
            "creationUser": <text>,
            "creationTime": <date>, /* date format: yyyy-MM-dd'T'HH:mm:ss.SSZ */
            "lastModifiedUser": < admin >,
            "lastModifiedTime": <date>, /* date format: yyyy-MM-dd'T'HH:mm:ss.SSZ */
            "hasVql": <boolean>,
            "hasScheduler": <boolean>,
            "includeJars": <boolean>,
            "includeI18N": <boolean>,
            "includeStatistics": <boolean>,
            "includeServerProperties": <boolean>,
            "includeWebContainerProperties": <boolean>,
            "includeJdbcWrapperProperties": <boolean>,
            "includeVdpDependencies": <boolean>,
            "includeUsersAndPrivileges": <boolean>,
            "useDefaultDatabase": <boolean>,
            "deployedOn": [/* list of environments in which the revision was already deployed */
                {
                    "id": <number>,
                    "name": <text>,
                    "description": <text>,
                    "minimumUpdateMandatory": < bool >
                }, {
                    ...
                }
            ]
        }, {
            ...
        }
    ]
}

<replace-drop Virtual DataPort elements>::=
      "DO_NOT_REPLACE_EXISTING"
    | "REPLACE_EXISTING"
    | "DROP_ELEMENTS_BEFORE"

The following example represents two revisions in JSON format. The first one was deployed on 2 environment, the second one was not deployed on any environment:

{
   "start": 0,
   "count": 10,
   "numElements": 2,
   "revisions": [
        {
            "id": 3,
            "description": "Third revision",
            "name": "Revision 3",
            "type": "INSERT",
            "replace": "DO_NOT_REPLACE_EXISTING",
            "creationUser": "smadmin",
            "creationTime": "2017-11-11T00:15:34.507+0000",
            "lastModifiedUser": "smadmin",
            "lastModifiedTime": "2017-11-11T00:15:34.507+0000",
            "hasVql": true,
            "hasScheduler": false,
            "includeJars": false,
            "includeI18N": false,
            "includeStatistics": false,
            "includeServerProperties": false,
            "includeWebContainerProperties": false,
            "includeJdbcWrapperProperties": true,
            "includeVdpDependencies": false,
            "includeUsersAndPrivileges": false,
            "useDefaultDatabase": true,
            "deployedOn": [
                {
                    "id": 2,
                    "name": "Environment 2",
                    "description": "Second environment",
                    "minimumUpdateMandatory": false
                },
                {
                    "id": 3,
                    "name": "Environment 3",
                    "description": "Third environment",
                    "minimumUpdateMandatory": false
                }
            ]
        },
        {
            "id": 2,
            "description": "Second revision",
            "name": "Revision 2",
            "type": "DELETE",
            "replace": "DROP_ELEMENTS_BEFORE",
            "creationUser": "smadmin",
            "creationTime": "2017-11-11T00:15:34.429+0000",
            "lastModifiedUser": "smadmin",
            "lastModifiedTime": "2017-11-11T00:15:34.429+0000",
            "hasVql": true,
            "hasScheduler": false,
            "includeJars": false,
            "includeI18N": false,
            "includeStatistics": false,
            "includeServerProperties": false,
            "includeWebContainerProperties": false,
            "includeJdbcWrapperProperties": true,
            "includeVdpDependencies": false,
            "includeUsersAndPrivileges": false,
            "useDefaultDatabase": true
        }
    ]
}

Create a Revision from a VQL file

Available since 7.0 update 20190903.

You can execute a POST request to the following URL to create a revision from a VQL file:

  • URL: /revisions/loadFromVQL

  • Method: POST

The request body has to follow this format:

{
    "name": <text>, /* descriptive name for the revision*/
    "description": <text>,  /* optional. Extensive description about the revision. */
    "content": <text> /* vql file content as **xsd:base64Binary** encoded in **UTF-8** */
}

Note

The field content must be the content of the vql file as xsd:base64Binary encoded in UTF-8. The revision will be created even if the vql is not parameterized with environment properties. We strongly recommend that you always generate vql files with specific environment properties separately. If the vql is generated using the VDP Admin Tool, you should select the option Export environment specific properties separately in the Export and Export database dialogs, otherwise check that the vql does not contain environment property values. Take into account that deploying a revision created from a vql without separate environment properties can generate unexpected results.

Note

The vql files generated when exporting elements using VDP Admin Tool includes the BOM mark to indicate that they are encoded in UTF-8. The BOM mark must be skipped.

The response body contains the added revision with its identifier:

{
    "id": 4,
    "description": "Creating revision using exportTestDB-WithProperties",
    "name": "revFromVQLWithProperties",
    "type": "VQL",
    "replace": "REPLACE_EXISTING",
    "creationUser": "admin",
    "creationTime": "2019-08-27T15:22:59.292+0000",
    "lastModifiedUser": "admin",
    "lastModifiedTime": "2019-08-27T15:22:59.292+0000",
    "hasVql": false,
    "hasScheduler": false,
    "includeJars": false,
    "includeI18N": false,
    "includeStatistics": false,
    "includeServerProperties": false,
    "includeWebContainerProperties": false,
    "includeJdbcWrapperProperties": true,
    "includeVdpDependencies": false,
    "includeUsersAndPrivileges": false,
    "useDefaultDatabase": true
}

Get the List of Deployments

The following URL returns the list of deployments:

  • URL: /deployments

  • Method: GET

  • Parameters:

    • start: this parameter specifies the first deployment of the collection to be returned.

    • count: this parameter specifies the maximum number of deployments to be returned.

    • environmentId: this parameter filters deployments by target environment.

    • status: this parameter filters deployments by execution status (OK, ERROR, IN_PROGRESS).

    • description: this parameter filters deployments by description.

    • user: this parameter filters deployments by user.

    • startDeploymentTime: this parameter filters deployments by start deployment time. Date format is yyyy-MM-dd’T’HH:mm:ssZ.

    • endDeploymentTime: this parameter filters deployments by end deployment time. Date format is yyyy-MM-dd’T’HH:mm:ssZ.

The response body includes the deployments in JSON format, according to the following template:

{
    "start": <number>,
    "count": <number>,
    "numElements": <number>,
    "deployments": [{
            "id": <number>,
            "user": <text>,
            "deploymentTime": <date>, /* date format: yyyy-MM-dd'T'HH:mm:ss.SSZ */
            "description": <text>,
            "state": <deployment status>,
            "targetEnvironment": {
                "id": <number>,
                "name": <text>,
            },
            "revisions": [{
                    "id": <number>,
                    "description": <text>,
                    "name": <text>,
                    "includeJars": <boolean>,
                    "includeI18N": <boolean>,
                    "includeStatistics": <boolean>,
                    "includeServerProperties": <boolean>,
                    "includeWebContainerProperties": <boolean>,
                    "includeJdbcWrapperProperties": <boolean>,
                    "includeVdpDependencies": <boolean>,
                    "includeUsersAndPrivileges": <boolean>
                }, { ... }
            ],
        }, { ... }
    ]
}

<deployment status>::=
      "OK"
    | "ERROR"
    | "IN_PROGRESS"
    | "PENDING"
    | "CANCELLED"

The following example returns a list of 2 deployments:

{
    "start": 0,
    "count": 10,
    "numElements": 2,
    "deployments": [{
            "id": 28,
            "user": "admin",
            "deploymentTime": "2017-11-12T23:05:53.179+0000",
            "description": "",
            "targetEnvironment": {
                "id": 3,
                "name": "Environment 3",
            },
            "revisions": [{
                    "id": 3,
                    "description": "Third revision",
                    "name": "Revision 3",
                    "includeJars" : false,
                    "includeI18N" : false,
                    "includeStatistics" : false,
                    "includeServerProperties" : false,
                    "includeWebContainerProperties" : false,
                    "includeJdbcWrapperProperties" : true,
                    "includeVdpDependencies" : false,
                    "includeUsersAndPrivileges" : false
                }
            ],
            "state": "OK"
        }, {
            "id": 27,
            "user": "admin",
            "deploymentTime": "2017-11-12T23:05:40.838+0000",
            "description": "",
            "targetEnvironment": {
                "id": 3,
                "name": "Environment 3"
            },
            "revisions": [{
                    "id": 3,
                    "description": "Third revision",
                    "name": "Revision 3",
                    "includeJars" : false,
                    "includeI18N" : false,
                    "includeStatistics" : false,
                    "includeServerProperties" : false,
                    "includeWebContainerProperties" : false,
                    "includeJdbcWrapperProperties" : true,
                    "includeVdpDependencies" : false,
                    "includeUsersAndPrivileges" : false
                }
            ],
            "state": "OK"
        }
    ]
}

The following URL returns the list of deployments between 2017-11-07T16:50:32+0100 and 2017-11-15T16:50:33+0100. You must specify both parameters, startDeploymentTime and endDeploymentTime, together.

GET https://solution-manager.acme.com:10090/deployments?startDeploymentTime=2017-11-07T16%3A50%3A32%2B0100&endDeploymentTime=2017-11-15T16%3A50%3A33%2B0100

The following URL returns the list of deployments in progress.

GET https://solution-manager.acme.com:10090/deployments?status=IN_PROGRESS

Start a New Deployment from a List of Revisions

You can execute a new deployment sending a POST request to the following URL:

  • URL: /deployments

  • Method: POST

The request body must follow the template below.

{
    "revisionIds": [ <number>, ... ],
    "environmentId": <number>,
    "description": <text>
}

This request must include the list of revision identifiers (revisionIds) and also the identifier of the target environment (environmentId). The following example creates a deployment from the revisions 1 and 2, on the target environment identified with the id 3.

{
    "revisionIds": [1, 2],
    "environmentId": 3,
    "description": "My first deployment"
}

It the deployment has been successfully created, the response body returns the numeric deployment identifier.

If some property is missing in the target environment, the deployment process fails and the response body returns the result of the validation.

{
    "validationResponse": {
        "validation": {
            "resultVqlValidation": "ERROR",
            "outputVqlValidation": "Error validating revision 'Third revision'.\n Missing VQL properties: \ndatabases.admin.datasources.jdbc.oracle_ds.DATABASEURI\ndatabases.admin.datasources.jdbc.oracle_ds.USERNAME\ndatabases.admin.datasources.jdbc.oracle_ds.USERPASSWORD\ndatabases.admin.datasources.jdbc.oracle_ds.USERPASSWORD.ENCRYPTED\nusers.user1.PASSWORD\nusers.user1.PASSWORD.ALGORITHM\nusers.user1.PASSWORD.ENCRYPTED\n\n",
            "errorVqlValidation": "Error validating revision 'Third revision'.\n Some Virtual DataPort properties required by the revision are not defined in the target environment\n\n",
            "missingVqlPropertiesWithServerValues": {
                "users.user1.PASSWORD": "ISTcnym4dJECzqYlA7+Xv6+RJo5s0VupzxEhXqoXC9XHu+5+M03kn3ftHGwW57FB5Q1d4Glcad4g54l9iBdEm55U431gIeob",
                "users.user1.PASSWORD.ALGORITHM": "SHA512",
                "databases.admin.datasources.jdbc.oracle_ds.USERPASSWORD.ENCRYPTED": "ENCRYPTED",
                "databases.admin.datasources.jdbc.oracle_ds.USERPASSWORD": "hJfznA24IFFPM8Z+6qCDO6Kg2Z3OSjP8W+uooHqFUpp8MoJT1FC3gdgsFe8cyh+Xmvu0dPIkFY21fidp75fqE4euFqx9QpH4Y8gcRE3CaeszFlB97AXg4dJ99eJFbWZ7",
                "users.user1.PASSWORD.ENCRYPTED": "ENCRYPTED",
                "databases.admin.datasources.jdbc.oracle_ds.USERNAME": "dblogin",
                "databases.admin.datasources.jdbc.oracle_ds.DATABASEURI": "jdbc:oracle:thin:@host:port:database"
            },
            "resultSchValidation": "OK",
            "outputSchValidation": "",
            "errorSchValidation": "",
            "targetEnvironment": {
                "id": 1,
                "name": "env1",
                "description": "",
                "minimumUpdateValue": "",
                "minimumUpdateMandatory": false,
                "minimumUpdateDownloadUrl": "",
                "licenseAlias": "PRODUCTION_1"
            },
            "state": "ERROR",
            "messageResult": "Some of the Virtual DataPort properties included in the revision are not defined in the target environment. "
        },
        "scriptValidationsResult": []
    }
}

Get the Progress of a Deployment

The following URL returns the deployment status and the list of deployment tasks:

  • URL: /deployments/{number:deploymentId}/progress

  • Method: GET

  • Parameters

    • lastUpdate: filters deployment tasks by last update date.

The response body includes the deployment progress and the list of deployment tasks according to the following template:

{
    "deploymentId": <number>,
    "state": <deployment state>,
    "progress": <number>, /* percent between 0 and 100 */
    "tasks": [{
            "id": <number>,
            "name": <text>,
            "state": <deployment task state>,
            "startDate": <date>,
            "endDate": <date>,
            "deploymentExecutionType": <deployment execution type>,
            "output": <text>,
            "cluster": {
                "id": <number>,
                "name": <text>
            },
            "server": {
                "id": <number>,
                "name": <text>
            }
        }, { ... }
    ]
}

<deployment state> ::=
      "OK"
    | "ERROR"
    | "IN_PROGRESS"

<deployment task state> ::=
      "OK"
    | "ERROR"
    | "IN_PROGRESS"
    | "PENDING"
    | "WARNING"
    | "SKIPPED"
    | "CANCELLED"

 <deployment execution type> ::=
      "VQL"
    | "SCH"
    | "CACHE"
    | "DATACATALOG_SYNC"
    | "SCRIPT_CLUSTER"
    | "SCRIPT_SERVER"
    | "BACKUP"
    | "ROLLBACK"
    | "SERVER_DEPLOYMENT"
    | "CLUSTER_DEPLOYMENT"

The optional request parameter lastUpdate filters tasks by last update date. If it is specified, the response body only include tasks modified since this date.

The following example shows an example of deployment progress with 1 execution task:

{
    "deploymentId": 1,
    "state": "OK",
    "progress": 100,
    "tasks": [{
            "id": 1,
            "name": "Revision Revision 1 VQL deployment",
            "state": "OK",
            "startDate": "2017-11-13T11:18:40.999+0000",
            "endDate": "2017-11-13T11:18:41.065+0000",
            "deploymentExecutionType": "VQL",
            "output": " - Executed 1 of 1 VQL commands",
            "cluster": {
                "id": 7,
                "name": "Cluster 2"
            },
            "server": {
                "id": 8,
                "name": "Server 3"
            }
        }
    ]
}

Free License Usage

Available since 7.0 update 20181011.

When you stop a Denodo server (e.g. Virtual DataPort server, Scheduler server, etc.), it sends an HTTP request to the License Manager, to notify that is going to stop. When the License Manager receives this request, it frees the corresponding license so it can be used by another server.

If a Denodo server stops working unexpectedly (e.g. the machine where it runs is restarted unexpectedly), you have to manually notify the License Manager that the license that this Denodo server was using, is no longer in use. Otherwise, the license will be considered in use until the grace period expires (5 days since the last time this Denodo server renewed its license).

To free up a license, log in to the Solution Manager. In the Elements Tree, open the definition of the server whose license you want to free up and copy the field Host .

Then, send a request to this endpoint:

  • URL: /externalShutdown

  • Method: GET

  • URL parameters:

    • nodeIp: if the field Host in the Solution Manager is an IP address - not a host name - the value of this parameter has to be this IP address.

    • hostDomainName: if the field Host in the Solution Manager is a host name, the value of this parameter has to be this host name.

    • port: port of the Denodo server.

    • product: the value has to be VDP.

Consider these:

  • The names of the parameters are case sensitive.

  • In the Solution Manager 7.0 update 20190312 and previous ones, all the parameters are mandatory. If you provide a value for hostDomainName, the value of the parameter nodeIp has to be empty but you still have to add it to the URL (&nodeIp=); If you provide a value for nodeIp, the value of hostDomainName has to be empty but you still have to add it to the URL (&hostDomainName=).

    With newer updates of the Solution Manager, you have to add nodeIp or hostDomainName, not both.

  • If a parameter is missing, the service returns the HTTP code 400 (Bad Request).

  • Unlike with the other endpoints described in this page, do not add the HTTP header Cookie to the requests.

  • Unlike the other endpoints described in this page, the endpoint is the License Manager server, not the Solution Manager server. Therefore, the port is different (by default, 10091, not 10090 like the other operations)

Examples

Example #1

Free the license associated with the Virtual DataPort server that runs on the host denodo-dv1-prod.denodo.com.

GET https://solution-manager.acme.com:10091/externalShutdown?hostDomainName=denodo-dv1-prod.denodo.com&port=9999&product=VDP

Note

If you are working with a Solution Manager with the update 20190312 or previous, you also have to add the parameter nodeIp to the URL, without any value (&nodeIp=).

Example #2

Free the license associated with the Virtual DataPort server that runs on the host with IP 192.168.0.120.

GET https://solution-manager.acme.com:10091/externalShutdown?nodeIp=192.168.0.120&port=9999&product=VDP

Note

If you are working with a Solution Manager update 20190312 or previous, you also have to add the parameter hostDomainName to the URL, without any value (&hostDomainName=).

The response from the service includes a summary of the operation with the result and a message:

{
    "result": { "OK" | "ERROR" },
    "message": <text>
}

Ping License Manager Server

Available since 7.0 update 20190903.

Use the endpoint “ping License Manager” to check the health of the License Manager.

  • URL: https://denodo-server.acme.com:10091/pingLicenseManager

  • Method: GET

Note that you need to send the request to the License Manager (its default port is 10091), not the Solution Manager.

This endpoint returns the HTTP code 200 and the text OK if the server is up and the connection to the database where its metadata is stored is up. Otherwise, the request fails.

Ping to Solution Manager Server

Available since 7.0 update 20190903.

Use the endpoint “ping Solution manager” to check the health of the Solution Manager server.

  • URL: https://denodo-server.acme.com:10090/pingSolutionManager

  • Method: GET

This endpoint returns the HTTP code 200 and the text OK if the server is up and the connection to the database where its metadata is stored is up. Otherwise, the request fails.


Authentication with State in Solution Manager

Starting with 7.0 update of March 2020, the REST API of the Solution Manager supports stateless authentication so the requests do not depend on cookies nor sessions. This is the usual pattern followed by REST APIs, in which each request is independent from the previous ones.

In previous updates, the authentication process is the following:

  1. Send a request to the operation /login to create a session. This operation will return a JSESSIONID. Note that the Solution Manager closes the sessions automatically after 30 minutes so you cannot reuse the same JSESSIONID.

  2. The following requests have to include the Cookie header with the JSESSIONID obtained when opening the session.

  3. Send a request to the operation /logout to close the session.

Important

Authentication with session has been deprecated.

Creating a Session with the Solution Manager

This operation returns a header JSESSIONID, which you have to include in all the requests.

  • URL: login

  • Method: GET

  • Authentication: you can invoke this operation with HTTP Basic or Kerberos (SPNEGO).

If the credentials are correct, this operations returns this:

  • The HTTP code 200.

  • The header Set-Cookie. This header includes the parameter “JSESSIONID”; all subsequent requests to the other operations of this API have to include the JSESSIONID in the header Cookie.

The body of the response has this format:

Syntax of the responses of the operation “login”
{
    "userName": <text>,
    "promotionAdminEnvironments": null | [ <list_of_environments> ], /* list of environments in which the promotion administrator is able to deploy a revision. Null implies no limitations */
    "promotionEnvironments": null | [ <list_of_environments> ], /* list of environments in which the promotion user is able to deploy a revision. Null implies no limitations */
     "promotion": <boolean>,
     "vdpAdmin": <boolean>,
    "jmxAdmin": <boolean>,
    "solutionManagerAdmin": <boolean>,
    "promotionAdmin": <boolean>
}

 <environment> ::= "DEVELOPMENT" | "PRODUCTION" | "STAGING"

 <list_of_environments> ::= <environment> [ ,<environment> ]*

If the request fails, the operations return the HTTP code 401 (Unauthorized) or 500 if there is another error. When there is an error, the body of the response has this format:

Syntax of the error messages returned by the operation login
{
    "status" : <number>,
    "message" : <text>
}

For example:

{
    "status" : 401,
    "message" : "The user name or password is incorrect"
}

Example of creating a session

The following example uses the tool “cURL” to create a session for the user “jsmith” with password “my_password”.

Example of a request to the operation “login” using “cURL”
curl --include --user "jsmith:my_password" "https://solution-manager.acme.com:10090/login"

With the parameter --include, cURL prints the headers of the response.

Example of a response of the operation “login”
HTTP/1.1 200
X-Application-Context: application:30090
Set-Cookie: JSESSIONID=24319EFA0F45145B64A5F9321F2DA6FB; Path=/; HttpOnly
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 04 Oct 2019 20:11:16 GMT

{
    "userName" : "jsmith",
    "promotionAdminEnvironments" : null,
    "promotionEnvironments" : null,
    "promotion" : true,
    "promotionAdmin" : true,
    "solutionManagerAdmin" : true,
    "vdpAdmin" : true,
    "jmxAdmin" : true
}

All the subsequent request to this API have to include this header:

Cookie: JSESSIONID=24319EFA0F45145B64A5F9321F2DA6FB

Note you have to obtain the value JSESSIONID=... from the response and ignore everything else after the first ;. That is, you have to ignore ; Path=/; HttpOnly.


Closing a Session with the Solution Manager

Operation to close a session.

  • URL: /logout

  • Method: GET

  • HTTP headers:

    • Cookie: <JSESSIONID cookie>

If the session is closed successfully, the API returns the HTTP code 200 and the body of the response is empty.

Example

Example of a request to the operation “logout” using “cURL”
curl --include --header "Cookie: JSESSIONID=DDD0656CF7F8D259966E443CD81903B5" "https://solution-manager.acme.com:10090/logout"