Pure Storage Zero Touch Provisioning API Simulator in Azure Functions

Brandon Showers
5 min readJul 18, 2020

In this post I want to demonstrate how I used Microsoft Azure Functions to build an online Pure Storage FlashArray simulator to test my code against while writing the ZTP tool.

So what are Azure Functions?

Azure Functions are a serverless compute service that enables event-triggered code to run without explicitly provisioning the underlying framework, runtime or infrastructure.

Azure functions supports several types of triggers:

  • Timer . This trigger is called on a predefined schedule
  • Blob . This trigger will get fired when a new or updated blob is detected
  • Event Hub
  • HTTP Trigger
  • Queue
  • Generic Webhook
  • GitHub Webhook
  • Service Bus Trigger

How did I use Functions for a simulator?

For my use case, I decided to build out several HTTP Triggered PowerShell functions that will essentially behave like the FlashBlade and FlashArray ZTP API endpoints. Essentially these are stateless API’s that respond to standard Restful HTTP methods like GET, POST, PATCH, etc.

Ultimately, I had to build out about 13 API Functions for FlashBlade and 1 for FlashArray.

Here are the API endpoints for the simulator:

Let’s take a look at the FlashArray function.

FlashArray array-initial-config

The FlashArray Zero Touch Provisioning API accepts the following information to initialize the array from the array-initial-config endpoint.

So an example JSON body would look like this:

{
"array_name": "tmefa10",
"ct0.eth0":
{
"address": "10.21.1.183",
"netmask": "255.255.255.0",
"gateway": "10.21.1.1"
},
"ct1.eth0":
{
"address": "10.21.1.184",
"netmask": "255.255.255.0",
"gateway": "10.21.1.1"
},
"vir0":
{
"address": "10.21.1.182",
"netmask": "255.255.255.0",
"gateway": "10.21.1.1"
},
"dns":
{
"domain": "dev.purestorage.com",
"nameservers":
[
"10.14.240.240"
]
},
"ntp_servers":
[
"time1.purestorage.com"
],
"timezone": "America/Los_Angeles",
"smtp":
{
"relay_host": "blackhole-smtp2.dev.purestorage.com",
"sender_domain": "purestorage.com"
},
"alert_emails":
[
"amin@purestorage.com"
],
"eula_acceptance":
{
"accepted": true,
"accepted_by":
{
"organization": "Pure Storage",
"full_name": "Syed Amin",
"job_title": "TME"
}
}
}

Once the body is posted (well, patched to be clear) to the array-initial-config api you should receive a response like this:

{
"status": "initializing",
"array_id": "",
"ct0.eth0":
{
"netmask": "255.255.255.0",
"address": "10.21.1.183",
"gateway": "10.21.1.1",
"mac_address": "24:a9:37:00:34:33"
},
"smtp":
{
"relay_host": "blackhole-smtp2.dev.purestorage.com",
"sender_domain": "purestorage.com"
},
"vir0":
{
"netmask": "255.255.255.0",
"address": "10.21.1.182",
"gateway": "10.21.1.1",
"mac_address": ""
},
"alert_emails":
[
"amin@purestorage.com"
],
"ct1.eth0":
{
"netmask": "255.255.255.0",
"gateway": "10.21.1.1",
"address": "10.21.1.184"
},
"ntp_servers":
[
"time1.purestorage.com"
],
"version": "5.2.4",
"eula_acceptance":
{
"accepted_by":
{
"organization": "Pure Storage",
"full_name": "Syed Amin",
"job_title": "TME"
},
"accepted": true
},
"progress": 0.01,
"dns":
{
"nameservers":
[
"10.14.240.240"
],
"domain": "dev.purestorage.com"
},
"timezone": "America/Los_Angeles",
"serial_number": "PCHFL17320104",
"os": "Purity//FA",
"array_name": "tmefa10"
}

In order to simulate this using Functions, I took the following steps:

In the Azure Portal I created a new Function App.

Create New -> Function App

Created a RG to store the function app, named it, and most importantly, selected PowerShell Core as the runtime stack.

Hosting: create a new storage account and choose the plan type.

Then decide if you want monitoring and tags then create the Function app.

Now that we have our Function App in place we can begin creating the functions.

Open your new Function App resource from the portal and click on the Functions tab on the right side blade.

Click + Add to create a new function.

Here is where you will choose you function trigger (what will execute you function). Choose HTTP trigger for this example.

Name your function. This name will be included in the URL so give it then api endpoint name of array-initial-config and choose the Anonymous authorization level. Click Create.

Your function is now created and enabled.

Now click on the Code + Test tab on the right blade.

You will now see to basic powershell function code for this api.

You can test by clicking on the Test/Run button

Notice this test will post to your api using a body of name: Azure.

The response will be Hello Azure!

You now have a base function and are ready to start adding you own custom logic.

For the FlashArray simulator I used the following powershell to simulate a real FlashArray.

First I build the logic to handle a RESTful GET request.

If the request method is GET, then I will always return this static response.

Testing this with I can see it works:

Next I need to add the handler for the PATCH method.

Notice I first check if the request method is PATCH, then in look through each of the elements of the request body and store them as variables. Finally I build a body variable and insert the respective variable elements in the body string.

Finally, I send the response back to the requestor:

Now if we test this with Postman you can see the behavior.

And that is that! Now I just did the same thing for each of the 13 FlashBlade endpoints needed but I think you get the idea on how to do this. :)

Here is the GitHub repo with the code for this entire project:
https://github.com/btshowers/pureapisim

Please post any questions in the comments below.

--

--

Brandon Showers

Technology fanatic, leadership enthusiast, and all around decent human being. *The statements and opinions on this site are my own and only my own.