An Introduction to PowerFlex 4.x RestAPI Calls

When trying to come up with blog content that customers will find both interesting and useful, it can be difficult to predict which subjects will “go viral” and which posts will quickly get consigned to the “scrapbook of history”! However, previous posts that have given readers an introduction to PowerFlex REST API calls appear to have been some of my most widely & repeatedly read blogs. This comes as no surprise, because automation and the integration of infrastructure with external software platforms is a topic of critical importance for most customers. Automation is often near the top of the list of “things they need to do better”. Hence why PowerFlex customers continue to have an interest in understanding PowerFlex API calls.

I will admit that this blog is long overdue. Since my original posts on the topic of “Introduction to PowerFlex REST API calls”, version 4.x has been released, which introduced the ‘PowerFlex Management Platform’ – aka ‘pfmp’ – to the world. This provided our customers with a unified Management & Operations platform for their entire PowerFlex infrastructure. This fundamentally changed the way that users interact with PowerFlex, because the ‘pfmp’ replaced not one but two management stacks that existed in the previous PowerFlex 3.x days. It has replaced both the PowerFlex Gateway & GUI that was familiar to all legacy software-only customers, as well as the “PowerFlex Manager” LCM stack used by PowerFlex rack and appliance customers. While most of the API calls themselves have not changed, the introduction of the new management stack has necessitated an update on the “How To Get Started With PowerFlex API Calls” series. So here it is, at long last!

As mentioned previously, the new management platform unified what in effect was two different management platforms. With PowerFlex 3.x, we would issue REST calls via the PowerFlex Gateway, whereas PowerFlex Manager Life Cycle Management (LCM) automation tasks would be driven via its own REST endpoint. With PowerFlex 4.x, we now have a management platform that runs a whole host of micro-services, each handling different management tasks. The PowerFlex Gateway has been replaced by the “block-legacy-gateway” service; while the “asmui” service now handles the RESTful calls that drive the PowerFlex Manager Platform LCM capabilities. Other features such as user authentication and management are handled by PowerAPI, which is a standard defined for REST API calls. Every API call to PowerFlex (except for the “login” and “refresh token” operations) must have a valid access token provided, or else the API call will be rejected.

So it can be seen that there are multiple REST services running within the PowerFlex 4.x Management Platform. For the purposes of this blog, we will focus on the “block-legacy-gateway” service, as this is the service that most admin users who need to perform Storage Administration tasks will be interested in: for example, creating volumes, mapping/un-mapping volumes to SDCs, managing Storage Pools and so on are done via API calls to this service. We will discuss managing PowerFlex Manager LCM activities – for example, adding new nodes or amending/deleting services/Resource Groups – via REST API calls to the “asmui” gateway in a future blog.

In my previous blogs, I used the Chrome web browser and the “RESTED” Chrome extension, as this was a great way for beginners – that is to say, people unused to using tools such as ‘curl’ – to issue API commands using RESTful interfaces. However, I am sorry to say that it looks as though “RESTED” has not been maintained by its developers since I last visited this subject. However, all is not lost – there are several other Chrome extensions available that try to make it easy to issue REST API calls. The one that I have found easiest to use is YARC – ‘Yet Another REST Client’. YARC is easy to find and install – just visit the Chrome Web Store, search for it, then add it to your browser. Make sure that it is enabled before proceeding with reading the rest of this blog. I would recommend pinning it in Chrome, thus making it easier to access directly from the Chrome menu bar. With that done, let us have some fun and issue API calls to PowerFlex!

Before we can issue API commands via the REST Gateway, we need to login with a valid username & password combination. All API requests require OAUTH2 access tokens for command authorization. Once the user credentials have been authenticated, access tokens are generated and are returned as the response. The valid access token must then be used when issuing further API calls to the block gateway service. The access token expires in 5 minutes unless it is refreshed, using the standard OIDC refresh operation. Alternatively, the same user can login again after 5 minutes and get issued with a new access token – clearly this will be ok for the purposes of our blog, but in a real-life automation scenario it is likely that the OIDC refresh mechanism would be used.

So, to begin, we need to login via the “sso” service that was mentioned previously. To do this, we issue the ‘/rest/auth/login’ POST request to the PowerFlex Management Platform ‘host’ – the ‘host’ will usually be the same address that is used to access the PowerFlex Manager 4.x GUI. My lab environment is accessed via the URL ‘pf03.vdi.xtremio’, so I need to issue the ‘/rest/auth/login’ POST request to this URL.

We also need to pass the user credentials – the ‘username’ and ‘password’ of the user we wish to login with – as the text payload of the ‘/auth/login’ request. This payload is sent as text in .json format. Now that we know what is needed to login to the PowerFlex system, let us do this via YARC. We type in the REST POST request to the ‘pfmp’ host address in the URL: field, then supply the ‘username’ and ‘password’ credentials in the command payload – see the figure below to see how this is setup correctly in YARC. Note that the application headers are left with the default of “Accept: application/json”. I have deliberately blocked out the ‘password’ string used in my lab in the figure below.

Figure 1: PowerFlex User Authentication API Call Using YARC

Once we are happy, we click on the Green “Send Request” button to issue the request. Assuming that all goes well, YARC should get a response back from the “sso” service pretty much almost immediately:

Figure 2 : Successful Authentication Response

The Green “200” response tells us that the API call request has been successful. The user credentials that we supplied as the payload of the API call have been authenticated and a set of credential tokens have been issued. These are shown under the “Response Body” tab in YARC.  We need to take note of the “access_token” – or, to be more specific, the long string between the “” – as we will need this token when we issue further API calls.

Now that our “admin” user has been successfully authenticated, we can move onto trying out a couple of PowerFlex Block API calls.

As mentioned previously, the ‘/rest/auth/login’ POST request was an example of a PowerAPI call. Having had our credentials authenticated and been issued with an access token, we can now get on with issuing API calls via the PowerFlex Block Gateway. A good first call is the ‘/api/Configuration’ call. This API call verifies whether the MDM IP addresses have been configured. This is a simple GET request – the call is issued, we pass no parameters (other than our access token) to the Gateway and in return, we should receive a response back.

We type this REST call into the URL field of YARC. This should end up containing the PowerFlex Management Platform ‘host’ URL, followed by the ‘/api/Configuration’ call, as shown below:

Figure 3: YARC – /api/Configuration – GET Request Setup

However, we also need to pass the valid ‘access_token’ for our ‘admin’ user to the Gateway as part of this call as well. This is done within YARC by clicking on the “Add Credentials” button under the “Authentication” section of YARC and then supplying the username and the access token that we noted for that user (ensure that you have stripped the double quotes from the beginning and end of the ‘access_token’ string):

Figure 4: Adding User Credentials into YARC

Click “Save” to save these credentials. Do not be put off by YARC seemingly showing an incorrect Authorization string once you have saved your users credentials: this is normal and to be expected!

Figure 5: This is Normal!

We are now good to go – click on the “Send Request” button to issue this API call. If successful, we should receive a “200” response back almost immediately:

Figure 6: /api/Configuration – Response

The response includes the all-important MDM IP addresses, confirming that they exist.

YARC makes it easy to copy both the Requests that are sent and the Responses that are received – there is a button for doing each of these at the bottom of the YARC Response window. I tried out both and pasted them below to confirm that they really “do what they say”!

YARC – ‘Copy Request ‘Buffer:

https://pf03.vdi.xtremio/api/Configuration

YARC – ‘Copy Response’ Buffer:

{
  "systemId": "9b469ffdf454d40f",
  "mdmPort": "6611",
  "snmpResendFrequency": "0",
  "upgradeSdrInMM": "null",
  "snmpSamplingFrequency": "60",
  "featuresEnableSnmp": "false",
  "cipherSuites": null,
  "featuresEnableIM": "true",
  "keycloakPublicClient": "10.181.99.111,10.181.99.112,172.16.0.109,172.16.8.109",
  "snmpPort": "162",
  "bypassCertificateCheck": "true",
  "upgradeSdtInMM": "null",
  "mdmUsername": "admin",
  "featuresEnableCollectAutoLogs": "false",
  "mdmAddresses": [
    "10.181.99.111",
    "10.181.99.112",
    "172.16.0.109",
    "172.16.8.109"
  ],
  "keycloakHostUrl": "10.181.99.111,10.181.99.112,172.16.0.109,172.16.8.109",
  "keycloakRealm": "10.181.99.111,10.181.99.112,172.16.0.109,172.16.8.109",
  "snmpTrapsReceiverIps": [
    "127.0.0.1"
  ],
  "allowNonSecureCommunication": "false"
}

Now that we have learned how to authenticate a user and issued a ‘simple’ command to prove that things are working correctly, the time has come to throw off the training wheels and do something more interesting. One useful command is the ‘/api/types/System/instances’ GET command, as this handy call retrieves a list of all of the objects that exist within our PowerFlex system. Beware – the output from this command will be long, even on small PowerFlex systems. As this is a GET request, it is a simple command that does not need to be provided with any additional data payload, save our user credentials. We just need to update the URL in YARC with the correct request, as show below, before clicking on the “Send Request” button:

Figure 7: ‘/api/types/System/instances’ – GET Request

The response for this should be similar to that shown below. It can be seen that the output from this command has a scroll bar at the righthand side of the YARC Response Body to allow us to scroll down and see all of the output.

Figure 8: ‘/api/types/System/instances’ – YARC Response

The data returned by the ‘/api/types/System/instances’ command will provide useful information regarding the PowerFlex MDM cluster, connectivity status of components, which version of PowerFlex is installed, and so on. The output gathered from this command can therefore be very useful for those wishing to document systems via automated calls, for example, for population of CMDBs.

Clearly, from a Storage Administration point of view, we are also going to be interested in things such as creation & deletion of storage volumes, as well as mapping those volumes. In the interests of keeping this blog to a sensible length, I will show the following:

  • Obtaining a list of all currently existing PowerFlex volumes,
  • Add a new volume and verify that it has been created using PowerFlex Manager,
  • Delete a volume.

So let us start with obtaining a list of all existing PowerFlex volumes. Such a list can be generated by issuing the ‘/api/types/Volume/instances’ GET request from our YARC console:

Figure 9: ‘/api/types/Volume/instances’ – GET Request

The response that was obtained from my lab system is shown below. Note that at present, there is only one volume in this system; it is a volume with the ID “5e66406a00000000”, which is a 96GB,  thin-provisioned volume which has been given the name “Test”. I have highlighted those four pieces of information in the full response below:

[
  {
    "originalExpiryTime": 0,
    "retentionLevels": [],
    "snplIdOfSourceVolume": null,
    "volumeReplicationState": "UnmarkedForReplication",
    "replicationJournalVolume": false,
    "replicationTimeStamp": 0,
    "managedBy": "ScaleIO",
    "mappedSdcInfo": null,
    "name": "Test",
    "creationTime": 1721209479,
    "storagePoolId": " f76c5b0900000000",
    "dataLayout": "MediumGranularity",
    "compressionMethod": "NotApplicable",
    "vtreeId": "a6e618d900000000",
    "sizeInKb": 100663296,
    "volumeClass": "defaultclass",
    "accessModeLimit": "ReadWrite",
    "pairIds": null,
    "volumeType": "ThinProvisioned",
    "consistencyGroupId": null,
    "ancestorVolumeId": null,
    "notGenuineSnapshot": false,
    "secureSnapshotExpTime": 0,
    "useRmcache": false,
    "snplIdOfAutoSnapshot": null,
    "lockedAutoSnapshot": false,
    "lockedAutoSnapshotMarkedForRemoval": false,
    "autoSnapshotGroupId": null,
    "timeStampIsAccurate": false,
    "nsid": 1,
    "id": "5e66406a00000000",
    "links": [
      {
        "rel": "self",
        "href": "/api/instances/Volume::5e66406a00000000"
      },
      {
        "rel": "/api/Volume/relationship/Statistics",
        "href": "/api/instances/Volume::5e66406a00000000/relationships/Statistics"
      },
      {
        "rel": "/api/parent/relationship/vtreeId",
        "href": "/api/instances/VTree::a6e618d900000000"
      },
      {
        "rel": "/api/parent/relationship/storagePoolId",
        "href": "/api/instances/StoragePool::f76c5b0900000000"
      }
    ]
  }
]

We are now ready to create a volume. This can be done by, issuing the ‘/api/types/Volume/instances’ command again, however this time it is issued as a POST request, with a payload attached to it. Within the payload for this command, we specify what characteristics the volume needs. At the bare minimum, we need to specify the Storage Pool that the volume needs to be provisioned from, as well as the size of the volume. Full details can be found in the PowerFlex REST API documentation (I will provide the link for this at the end of this blog).

In this example, we will create the volume “simon_volume_01”, which be 40GB in size, be thin provisioned, not use compression and belong to the Storage Pool with the ID ending in “0000”.  Those details are listed in the Payload, in .json format, as can be seen in the YARC screen capture below:

Figure 10: ‘/api/types/Volume/instances’ – POST Request

Assuming that there are no errors or typos in the payload, we should receive a “200 – OK” response, along with the volume ID of the newly created volume:

Figure 11: ‘/api/types/Volume/instances’ – Successful Response

Issuing the ‘/api/types/Volume/instances’ GET command to retrieve the volume instances, will confirm the details for the newly created ‘simon_volume_01’, as seen with the response output below:

[
  {
    ...
    ... Details for volume "Test" removed for brevity! 
    ...
    "id": "5e66406a00000000",
    "links": [
      {
        "rel": "self",
        "href": "/api/instances/Volume::5e66406a00000000"
      },
      {
        "rel": "/api/Volume/relationship/Statistics",
        "href": "/api/instances/Volume::5e66406a00000000/relationships/Statistics"
      },
      {
        "rel": "/api/parent/relationship/vtreeId",
        "href": "/api/instances/VTree::a6e618d900000000"
      },
      {
        "rel": "/api/parent/relationship/storagePoolId",
        "href": "/api/instances/StoragePool::f76c5b0900000000"
      }
    ]
  },
  {
    "originalExpiryTime": 0,
    "retentionLevels": [],
    "snplIdOfSourceVolume": null,
    "volumeReplicationState": "UnmarkedForReplication",
    "replicationJournalVolume": false,
    "replicationTimeStamp": 0,
    "managedBy": "ScaleIO",
    "mappedSdcInfo": null,
    "name": "simon_volume_01",
    "creationTime": 1724426815,
    "storagePoolId": "f76c5b0900000000",
    "dataLayout": "MediumGranularity",
    "compressionMethod": "NotApplicable",
    "vtreeId": "a6e63fe900000001",
    "sizeInKb": 41943040,
    "volumeClass": "defaultclass",
    "accessModeLimit": "ReadWrite",
    "pairIds": null,
    "volumeType": "ThinProvisioned",
    "consistencyGroupId": null,
    "ancestorVolumeId": null,
    "notGenuineSnapshot": false,
    "secureSnapshotExpTime": 0,
    "useRmcache": false,
    "snplIdOfAutoSnapshot": null,
    "lockedAutoSnapshot": false,
    "lockedAutoSnapshotMarkedForRemoval": false,
    "autoSnapshotGroupId": null,
    "timeStampIsAccurate": false,
    "nsid": 2,
    "id": "5e66677a00000001",
    "links": [
      {
        "rel": "self",
        "href": "/api/instances/Volume::5e66677a00000001"
      },
      {
        "rel": "/api/Volume/relationship/Statistics",
        "href": "/api/instances/Volume::5e66677a00000001/relationships/Statistics"
      },
      {
        "rel": "/api/parent/relationship/vtreeId",
        "href": "/api/instances/VTree::a6e63fe900000001"
      },
      {
        "rel": "/api/parent/relationship/storagePoolId",
        "href": "/api/instances/StoragePool::f76c5b0900000000"
      }
    ]
  }
]

We can also confirm the creation of our new volume by checking the Block –> Volumes tab from within the PowerFlex Manager GUI as well. It can be clearly seen in the GUI as shown in Figure 12 below:

Figure 12: PowerFlex Manager – Volumes List

So, having confirmed that the test volume that we created using a REST API call does indeed exist – and having queried the PowerFlex Gateway to confirm all of its details – we could map this volume to a host if we wanted to, using the ‘/api/instances/Volume::{id}/action/addMappedHost’ POST API call. However, for the purposes of this blog, we will instead remove the volume, using the ‘/api/instances/Volume::{id}/action/removeVolume’ POST command. We must pass the id of the volume being removed as part of the call itself, then pass any parameters for the command via the .json payload. The ‘removeMode’ parameter is required for this command. The option shown in the example below – removeMode = ONLY_ME – ensures that this command will only remove the specified volume.

Figure 13: /api/instances/Volume::{id}/action/removeVolume – POST Request
Figure 14: /api/instances/Volume::{id}/action/removeVolume – Response

We can confirm that the volume “simon_volume_01” has been deleted by checking again from the PowerFlex Manager GUI:

Figure 15: PowerFlex Manager – Volumes List, again…

Having removed the volume using API calls, it brings this blog to a close. I hope that I have managed to show how easy it is to issue REST API calls to the legacy PowerFlex Block Gateway in PowerFlex 4.x. The full list of API calls are listed in the “PowerFlex (software only) API” documentation, which can be found on the Dell Developer site – https://developer.dell.com/apis . If you search under “Storage”, you will find 2 PowerFlex API documents. In this blog I have been focusing on the API calls covered in the ‘PowerFlex (software only) API’ document, but I promise to visit the PowerFlex Manager REST API in a future blog.

You can jump directly to the Introduction page of the PowerFlex 4.6 Software Only API documentation here: https://developer.dell.com/apis/4008/versions/4.6.0/docs/Introduction/1-Introduction.md .