Contributor
Contributor

VROPS Rest API Post

Jump to solution

Hi All,

We have a powershell script push non vsphere data to VROPS. It's now working with HTTP post method and I am trying to covert it to Rest API.

HTTP Post will just create a resource under "HTTP post" adaptor, and adaptor kind for the resource is "external"

1) For Rest API, is there an adaptor preexisting in VROPS (Similer to HTTP Post) ?

2) Or will it be created automatically like it did for HTTP Post?

If this is the case, we also need to pass adaptor details in the json I hope. Below if the json I am using to try pushing data. How can I add the adaptor details there

{

  "property-content" : [ {

    "statKey" : "SQL01|Log_Size",

    "timestamps" : [ "1512100141523" ],

    "values" : [ "12.0" ],

    "others" : [ ],

    "otherAttributes" : {

    }

  } ]

}

3) I couldn't find any so tried to create one with the below (using Postman), but I am getting an error "No such Adapter Kind - SQL-Perf"

Is there any adapterKindKey that we need to use for custom once?

{

"name" : "DataBasePerf",

"description" : "SQL Server Performance",

"collectorId" : "1",

"adapterKindKey" : "SQL-Perf",

"adapterKindType" : "GENERAL"

}

0 Kudos
1 Solution

Accepted Solutions
Hot Shot
Hot Shot

Can you clarify what you mean when you say HTTP post method vs. Rest API?  Are these not the same?  What URI are you referencing in the "HTTP post" method?  Is it going to the https://vrops-server/suite-api/api/some/operation path?

In any case, if you create a resource and specify the adapterKindKey and resourceKindKey in the request, these will get created for you if they don't already exist.  If you create the adapter kind and instance in the initial resource request, it is a good idea to grab the adapterInstanceId that got created and use it for subsequent resource creation calls to avoid any ambiguity for which adapter instance the resource should be associated with.

Per the vROPS API documentation (available at https://vrops-server/suite-api) to create a resource while automatically creating the adapter kind and instance:

POST /api/resources/adapterkinds/{adapterKindKey}

Creates a new Resource in the system associated with the specified adapter kind.
This adapter kind (referred to as 'Push' adapter kind) will be created if it does not exist in the system and an instance of it will be associated with the Resource being created. This adapter kind if it already exists must of OPENAPI adapter kind type.
The API will also create the missing Adapter Kind and Resource Kind contained within the ResourceKey of the Resource if they do not exist.
  Additional implementation notes:

  • When creating a Resource, if the Resource Identifiers that are unique and required are not specified, the API would return an error with HTTP status code of 500 and an error message indicating the set of missing Resource Identifiers.
  • When creating a Resource, if the Resource Identifiers that are unique but not required are not specified, the Resource is created where the uniquely identifying Resource Identifiers that were not specified will have their value as an empty string.

When you post the stats (to /api/resources/{resourceId}/stats), you apply it to the resource identified by {resourceId} which is already associated with an adapterInstance which is already associated with an adapterKindKey.  Thus you do not need to specify anything about the adapter when posting stats to a resource.

You can control which resources are assigned to which adapter instances by creating the resource with a call to (which will also create the missing adapter kind and resource kind):

POST /api/resources/adapters/{adapterInstanceId}

Creates a new Resource in the system associated with an existing adapter instance.
The API will create the missing Adapter Kind and Resource Kind contained within the ResourceKey of the Resource if they do not exist.
The API will return an error if the adapter instance specified does not exist.
  Additional implementation notes:

  • When creating a Resource, if the Resource Identifiers that are unique and required are not specified, the API would return an error with HTTP status code of 500 and an error message indicating the set of missing Resource Identifiers.
  • When creating a Resource, if the Resource Identifiers that are unique but not required are not specified, the Resource is created where the uniquely identifying Resource Identifiers that were not specified will have their value as an empty string.

The hierarchy of objects would look like this:

  • AdapterKind = Custom-SQL-Collector
    • AdapterInstance = Custom-SQL-Collector-A
      • ResourceKind = SQL-Server
        • Resource - Identifier = SQL-A-Resource-ID-1
        • Resource - Identifier = SQL-A-Resource-ID-2
    • AdapterInstance = Custom-SQL-Collector-B
      • ResourceKind = SQL-Server
        • Resource - Identifier = SQL-B-Resource-ID-1

This is to be flexible and scalable, but most likely you'll just end up with a structure that only has a single adapter instance.

Example: POST to /suite-api/api/resources/adapterkinds/LTXSYSTEMSTEST:

{

  "description" : "test",

  "creationTime" : null,

  "resourceKey" : {

    "name" : "Test1",

    "adapterKindKey" : "LTXSYSTEMSTEST",

    "resourceKindKey" : "TestResourceKind",

    "resourceIdentifiers" : [ {

      "identifierType" : {

        "name" : "SpecialID",

        "dataType" : "STRING",

        "isPartOfUniqueness" : true

      },

      "value" : "test-id-1"

    } ]

  },

  "credentialInstanceId" : null,

  "resourceStatusStates" : [ ],

  "dtEnabled" : true

}

Response:

{"description":"test","resourceKey":{"name":"Test1","adapterKindKey":"LTXSYSTEMSTEST","resourceKindKey":"TestResourceKind","resourceIdentifiers":[{"identifierType":{"name":"SpecialID","dataType":"STRING","isPartOfUniqueness":true},"value":"test-id-1"}]},"resourceStatusStates":[],"dtEnabled":true,"badges":[],"relatedResources":[],"links":[{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8","rel":"SELF","name":"linkToSelf"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/relationships","rel":"RELATED","name":"relationsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"propertiesOfResource"},{"href":"/suite-api/api/alerts?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"alertsOfResource"},{"href":"/suite-api/api/symptoms?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"symptomsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/statkeys","rel":"RELATED","name":"statKeysOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/stats/latest","rel":"RELATED","name":"latestStatsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"latestPropertiesOfResource"},{"href":"/suite-api/api/credentials/","rel":"RELATED","name":"credentialsOfResource"}],"identifier":"1da84075-ef10-4895-976a-d0c000da9db8"}

In the vROPS admin console:

pastedImage_16.png

After you get that far, once you push stats in for the resource they'll show up under all metrics.

Justin Snyder ___________________ Blog/Content/Consulting - https://www.ltx.systems Youtube - https://www.youtube.com/channel/UCvaigQrBZx-yfWh-ULiN_ug I love solving a good problem. If you find my effort helpful and time saving, please mark it as the correct answer or helpful.

View solution in original post

0 Kudos
7 Replies
Hot Shot
Hot Shot

Can you clarify what you mean when you say HTTP post method vs. Rest API?  Are these not the same?  What URI are you referencing in the "HTTP post" method?  Is it going to the https://vrops-server/suite-api/api/some/operation path?

In any case, if you create a resource and specify the adapterKindKey and resourceKindKey in the request, these will get created for you if they don't already exist.  If you create the adapter kind and instance in the initial resource request, it is a good idea to grab the adapterInstanceId that got created and use it for subsequent resource creation calls to avoid any ambiguity for which adapter instance the resource should be associated with.

Per the vROPS API documentation (available at https://vrops-server/suite-api) to create a resource while automatically creating the adapter kind and instance:

POST /api/resources/adapterkinds/{adapterKindKey}

Creates a new Resource in the system associated with the specified adapter kind.
This adapter kind (referred to as 'Push' adapter kind) will be created if it does not exist in the system and an instance of it will be associated with the Resource being created. This adapter kind if it already exists must of OPENAPI adapter kind type.
The API will also create the missing Adapter Kind and Resource Kind contained within the ResourceKey of the Resource if they do not exist.
  Additional implementation notes:

  • When creating a Resource, if the Resource Identifiers that are unique and required are not specified, the API would return an error with HTTP status code of 500 and an error message indicating the set of missing Resource Identifiers.
  • When creating a Resource, if the Resource Identifiers that are unique but not required are not specified, the Resource is created where the uniquely identifying Resource Identifiers that were not specified will have their value as an empty string.

When you post the stats (to /api/resources/{resourceId}/stats), you apply it to the resource identified by {resourceId} which is already associated with an adapterInstance which is already associated with an adapterKindKey.  Thus you do not need to specify anything about the adapter when posting stats to a resource.

You can control which resources are assigned to which adapter instances by creating the resource with a call to (which will also create the missing adapter kind and resource kind):

POST /api/resources/adapters/{adapterInstanceId}

Creates a new Resource in the system associated with an existing adapter instance.
The API will create the missing Adapter Kind and Resource Kind contained within the ResourceKey of the Resource if they do not exist.
The API will return an error if the adapter instance specified does not exist.
  Additional implementation notes:

  • When creating a Resource, if the Resource Identifiers that are unique and required are not specified, the API would return an error with HTTP status code of 500 and an error message indicating the set of missing Resource Identifiers.
  • When creating a Resource, if the Resource Identifiers that are unique but not required are not specified, the Resource is created where the uniquely identifying Resource Identifiers that were not specified will have their value as an empty string.

The hierarchy of objects would look like this:

  • AdapterKind = Custom-SQL-Collector
    • AdapterInstance = Custom-SQL-Collector-A
      • ResourceKind = SQL-Server
        • Resource - Identifier = SQL-A-Resource-ID-1
        • Resource - Identifier = SQL-A-Resource-ID-2
    • AdapterInstance = Custom-SQL-Collector-B
      • ResourceKind = SQL-Server
        • Resource - Identifier = SQL-B-Resource-ID-1

This is to be flexible and scalable, but most likely you'll just end up with a structure that only has a single adapter instance.

Example: POST to /suite-api/api/resources/adapterkinds/LTXSYSTEMSTEST:

{

  "description" : "test",

  "creationTime" : null,

  "resourceKey" : {

    "name" : "Test1",

    "adapterKindKey" : "LTXSYSTEMSTEST",

    "resourceKindKey" : "TestResourceKind",

    "resourceIdentifiers" : [ {

      "identifierType" : {

        "name" : "SpecialID",

        "dataType" : "STRING",

        "isPartOfUniqueness" : true

      },

      "value" : "test-id-1"

    } ]

  },

  "credentialInstanceId" : null,

  "resourceStatusStates" : [ ],

  "dtEnabled" : true

}

Response:

{"description":"test","resourceKey":{"name":"Test1","adapterKindKey":"LTXSYSTEMSTEST","resourceKindKey":"TestResourceKind","resourceIdentifiers":[{"identifierType":{"name":"SpecialID","dataType":"STRING","isPartOfUniqueness":true},"value":"test-id-1"}]},"resourceStatusStates":[],"dtEnabled":true,"badges":[],"relatedResources":[],"links":[{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8","rel":"SELF","name":"linkToSelf"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/relationships","rel":"RELATED","name":"relationsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"propertiesOfResource"},{"href":"/suite-api/api/alerts?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"alertsOfResource"},{"href":"/suite-api/api/symptoms?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"symptomsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/statkeys","rel":"RELATED","name":"statKeysOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/stats/latest","rel":"RELATED","name":"latestStatsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"latestPropertiesOfResource"},{"href":"/suite-api/api/credentials/","rel":"RELATED","name":"credentialsOfResource"}],"identifier":"1da84075-ef10-4895-976a-d0c000da9db8"}

In the vROPS admin console:

pastedImage_16.png

After you get that far, once you push stats in for the resource they'll show up under all metrics.

Justin Snyder ___________________ Blog/Content/Consulting - https://www.ltx.systems Youtube - https://www.youtube.com/channel/UCvaigQrBZx-yfWh-ULiN_ug I love solving a good problem. If you find my effort helpful and time saving, please mark it as the correct answer or helpful.

View solution in original post

0 Kudos
Contributor
Contributor

jasnyderThanks a ton!

HTTP post method that meant was using "Invoke-WebRequest" with URI ponting to "/HttpPostAdapter/OpenAPIServlet"

Adaptor for that gets created under Http Post -> External

pastedImage_0.png

I actually wanted to change that piece of code to use Rest API instead. I was able to post data in to the same adaptor using Rest API, but was just wondering where the rest API adaptor should be sitting. Last one in the above list kind of confused me, and thought this is where it would end up in Smiley Happy.

But from your example it looks like I can create a custom adaptor and thanks for explaining it!

I am trying it now and will let you know how it goes.. Thanks once again!

0 Kudos
Contributor
Contributor

Hi jasnyder

In your example, can you please explain how to create "LTXSYSTEMSTEST" in the first place?

This is where I was stuck..

0 Kudos
Hot Shot
Hot Shot

If you POST to /suite-api/api/resources/adapterkinds/{newAdapterKind} the API will see that the {newAdapterKind} doesn't exist yet and create it at the same time that it creates the new resource kind and the new resource as well as a new adapter instance of the adapter kind.  This is all in one shot, and it automatically associates the resource to the resource kind and to the adapter instance it creates.  In my example, the adapter kind was LTXSYSTEMSTEST, the resource kind was "TestResourceKind" and the resource name was "Test1."  This one call created all of those.

If you are going to have more than one adapter instance of this kind, then you would want to add resources using the call that associates it with an adapterinstanceID which is a POST to /api/resources/adapters{adapterInstanceId}.  That call only works if the adapter instance has already been created.

From my original example, this is the call that creates all of the items specified.

POST to /suite-api/api/resources/adapterkinds/LTXSYSTEMSTEST:

{

  "description" : "test",

  "creationTime" : null,

  "resourceKey" : {

    "name" : "Test1",

    "adapterKindKey" : "LTXSYSTEMSTEST",

    "resourceKindKey" : "TestResourceKind",

    "resourceIdentifiers" : [ {

      "identifierType" : {

        "name" : "SpecialID",

        "dataType" : "STRING",

        "isPartOfUniqueness" : true

      },

      "value" : "test-id-1"

    } ]

  },

  "credentialInstanceId" : null,

  "resourceStatusStates" : [ ],

  "dtEnabled" : true

}

Response:

{"description":"test","resourceKey":{"name":"Test1","adapterKindKey":"LTXSYSTEMSTEST","resourceKindKey":"TestResourceKind","resourceIdentifiers":[{"identifierType":{"name":"SpecialID","dataType":"STRING","isPartOfUniqueness":true},"value":"test-id-1"}]},"resourceStatusStates":[],"dtEnabled":true,"badges":[],"relatedResources":[],"links":[{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8","rel":"SELF","name":"linkToSelf"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/relationships","rel":"RELATED","name":"relationsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"propertiesOfResource"},{"href":"/suite-api/api/alerts?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"alertsOfResource"},{"href":"/suite-api/api/symptoms?resourceId=1da84075-ef10-4895-976a-d0c000da9db8","rel":"RELATED","name":"symptomsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/statkeys","rel":"RELATED","name":"statKeysOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/stats/latest","rel":"RELATED","name":"latestStatsOfResource"},{"href":"/suite-api/api/resources/1da84075-ef10-4895-976a-d0c000da9db8/properties","rel":"RELATED","name":"latestPropertiesOfResource"},{"href":"/suite-api/api/credentials/","rel":"RELATED","name":"credentialsOfResource"}],"identifier":"1da84075-ef10-4895-976a-d0c000da9db8"}

Justin Snyder ___________________ Blog/Content/Consulting - https://www.ltx.systems Youtube - https://www.youtube.com/channel/UCvaigQrBZx-yfWh-ULiN_ug I love solving a good problem. If you find my effort helpful and time saving, please mark it as the correct answer or helpful.
0 Kudos
Contributor
Contributor

Perfect ! Thanks! Smiley Happy

0 Kudos
Contributor
Contributor

Hi jasnyder Thanks ! It worked Smiley Happy

I am trying to re-point my script to the new adaptor and looking forward to see all the metrics created there.

Just another thing after the tests is there a way to delete the custom one created? I mean the top "LTXSYSTEMSTEST" one in your example..

0 Kudos
Hot Shot
Hot Shot

As far as I know there is no API or way in the GUI to delete the adapter kind.  You can delete the instance via a DELETE action to /suite-api/api/adapters/{adapterInstanceId}

To find the adapter instance, you can do a GET to /suite-api/api/adapters/?adapterKindKey={kindKey} find the adapter instance you want to delete and use the id in the above DELETE call.

You can also clean out resources and adapter instances through the GUI:

pastedImage_1.png

As I mentioned, you can't use the GUI or API to clean out the adapter kind.  Check this KB for info on removing adapter kinds from the database manually in 5.x against a SQL or Oracle database.  I haven't tried it on vROPS 6.x so I don't know if it still works, but I assume at least some adaptation would be required to make it work.

Justin Snyder ___________________ Blog/Content/Consulting - https://www.ltx.systems Youtube - https://www.youtube.com/channel/UCvaigQrBZx-yfWh-ULiN_ug I love solving a good problem. If you find my effort helpful and time saving, please mark it as the correct answer or helpful.
0 Kudos