There are some new REST API’s for vVols objects in Pure Storage’s FlashArray REST API 2.14! Specifically operations for virtual-machines and virtual-machine-snapshots. The hardest part for me was figuring out how to use REST 2.0 with the FlashArray. I had a lot of fun playing around and learning about them and want to share that process!
For my examples in the post I am going to be using PowerShell to issue the REST calls by invoking web requests.
Authenticating with FlashArray for REST API 2.14 Requests
In order to issue REST Requests from PowerShell I first need to be able to get the authentication header constructed. I found a few ways that I could issue REST API 2.x requests. I cover those processes in this a blog post covering my journey and discovery. I’ll keep it simple and just use the Pure Storage PowerShell SDK to get my header constructed.
$flasharray = new-pfaarray -endpoint 10.21.149.39 -credentials (get-credential) -ignoreCertificateError $ApiToken =@{"api-token"=$flasharray.ApiToken} $AuthResponse = Invoke-webrequest -Method Post -Uri "https://$($flasharray.Endpoint)/api/2.2/login" -Headers $ApiToken -SkipCertificateCheck $AuthHeader = @{"x-auth-token" = ($AuthResponse.Headers."x-auth-token")[0]}
From this point forward all of my web requests will be using this $AuthHeader in the Invoke-WebRequest.
Virtual-Machines REST Call
When I was looking through the REST API release notes I noticed that we had added quite a bit of documentation for some new cals. I really recommend looking through the 2.14 reference guide if possible. It does require a support.purestorage.com account and login though. I specifically wanted to look at /api/2.14/virtual-machines
and /api/2.14/virtual-machine-snapshots
. I wanted to dig at what an end user could get from them. Starting with the virtual-machines, I want to find out what ends up getting returned back from it?
$faVMs = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machines?vm_type=vvol" -Headers $AuthHeader -SkipCertificateCheck $faVMs
PS C:\Users\alex> $faVMs = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machines?vm_type=vvol" -Headers $AuthHeader -SkipCertificateCheck PS C:\Users\alex> $faVMs StatusCode : 200 StatusDescription : OK Content : {"continuation_token":null,"items":[{"created":1620680626452,"vm_id":"500d8e95-237f-263b-1a31-f5409ef4da39","name":"vvol-w2k16-no-cbt-b-3","id":"500d8e95-237f-263b-1a31-f5409ef4da39","time_remaining":… RawContent : HTTP/1.1 200 OK Server: nginx Date: Mon, 15 Aug 2022 22:49:35 GMT Connection: keep-alive Strict-Transport-Security: max-age=31536000; includeSubDomains; X-Frame-Options: DENY X-Content-Type-Opti… Headers : {[Server, System.String[]], [Date, System.String[]], [Connection, System.String[]], [Strict-Transport-Security, System.String[]]…} Images : {} InputFields : {} Links : {} RawContentLength : 4078 RelationLink : {}
Right away that’s a lot of not much that I can use. So I played around with selecting specific sections of that call and then converting from JSON to something readable. That’s why I set the initial output to $faVMs. Test out some different forms of selecting and converting the data. Here was kind of my progression through it.
$faVMs $faVMs.content $faVMs.content | convertfrom-json ($faVMs.content | convertfrom-json).items
Here is just what it looked like when selecting the items on that last line.
($faVMs.content | convertfrom-json).items created : 1620680626452 vm_id : 500d8e95-237f-263b-1a31-f5409ef4da39 name : vvol-w2k16-no-cbt-b-3 id : 500d8e95-237f-263b-1a31-f5409ef4da39 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=; id=} created : 1655305922937 vm_id : 500d9a18-d4eb-9648-46a9-43503caa6c85 name : c05-vVol-DB-VM-01 id : 500d9a18-d4eb-9648-46a9-43503caa6c85 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=; id=} created : 1620681512770 vm_id : 500de701-15ec-2ab8-9843-58564ec95f84 name : vvol-w2k16-nor-b-3 id : 500de701-15ec-2ab8-9843-58564ec95f84 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=; id=}
I cut it off after a few VMs. As you can see, it can get pretty overwhelming fast. Playing around with a bit more and I came up with this as an easy way to find the vms.
($faVMs.content | convertfrom-json).items | Select-Object Name, vm_id, destroyed
($faVMs.content | convertfrom-json).items | Select-Object Name, vm_id, destroyed name vm_id destroyed ---- ----- --------- vvol-w2k16-no-cbt-b-3 500d8e95-237f-263b-1a31-f5409ef4da39 False c05-vVol-DB-VM-01 500d9a18-d4eb-9648-46a9-43503caa6c85 False vvol-w2k16-nor-b-3 500de701-15ec-2ab8-9843-58564ec95f84 False vvol-w2k16-no-cbt-b-4 50126c72-a347-6a3d-517a-c5c588e7a6ca False vvol-load-vm-b-2 50385376-475b-7094-d837-8f00578cdf90 False vvol-w2k16-res-b-1 50387c83-4c42-eaa6-da86-5651b518dc17 False vvol-w2k16-nor-b-1 5038868e-f4d6-4f91-67e3-f2dde5a63d50 False vvol-w2k16-no-cbt-b-1 50389bdd-8787-ad28-4c54-2adcb66f9346 False vvol-w2k16-light-b-1 5038b0a4-10b3-4619-41c2-0611c5087af4 False vvol-w2k16-cbt-b-1 5038e5ad-3c45-25e6-ec27-f2f97406cc5e False vVol-VM-LOAD-B 5038f4eb-5016-4f96-1ddc-60aebee9e09e False MSSQL-VM-02 5039814f-113e-8e1f-f678-be7bcbe2a001 False vvol-w2k16-no-cbt-b-2 5039ab78-91f8-f257-2bda-a52b3eb0b37e False vvol-w2k16-tiny-b-2 5039d9b7-3567-f2b8-593d-26e2a2309d73 False .vSphere-HA ffff0000-2da8-8e2f-9e28-e3b15939db0f False catalog ffff0000-bac9-fe86-e118-f92e309b7641 False
From there I can do more filtering, sorting, etc. However, I want to go ahead and move on to the snapshots.
Virtual-Machine-Snapshots REST CALL
After playing around with virtual-machines
I started to play around with virtual-machine-snapshots
. At first the content was pretty overwhelming and depending on the scale of the environment it could be even more.
$vmSnaps = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machine-snapshots?vm_type=vvol" -Headers $AuthHeader -SkipCertificateCheck $vmSnaps $vmSnaps.content $vmSnaps.content | ConvertFrom-Json ($vmSnaps.content | ConvertFrom-Json).items
I actually ended up running out of scroll back with some of my arrays. Just too many VM snapshots stored over a long period of time. Here is just a small look at what the formatted items look like.
($vmSnaps.content | ConvertFrom-Json).items created : 1660590060018 vm_id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 name : MSSQL-VM-01 id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.805; id=116aaf8d-cc56-1c67-279b-40141bbb6088} created : 1660564860022 vm_id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 name : MSSQL-VM-01 id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.798; id=ecfcf700-1d20-e119-ba61-5a8501bb247b} created : 1660539660023 vm_id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 name : MSSQL-VM-01 id : 500d0e5a-6bfb-5dda-b558-c3b3a47fb978 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.791; id=bc8028dd-80d8-0791-58f3-51495bbf2516}
I ended up needing to play around a lot with filtering, selecting the right objects and sorting. Here I just went ahead an listed out the name, vm_id and recover_context.
($vmSnaps.Content | ConvertFrom-Json).items | Select-Object Name, recover_context name recover_context ---- --------------- MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.661; id=6d3829c7-74f0-917f-91d2-d6864401e98b} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.786; id=a0523f9a-39a2-da48-8961-4688ef901c40} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.745; id=c457003f-4321-7d39-9d5c-457a80cda3f1} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.619; id=8db11afa-79ca-39d4-e901-3652c2cd49d6} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.804; id=eaefa2fe-5ee3-a9b2-7aa1-bbb42b1ca7e2} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.797; id=72ddcb8a-925b-5d45-38b4-3e1a7260b394} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.727; id=b9fa6de0-2532-9670-084a-40b0c7a2ad67} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.790; id=76e6c359-b5b1-00ad-f453-c0053e9b54e5} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.685; id=fcd9a995-a3d6-69e1-9636-316b63a77bfb} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.769; id=64aadecb-5fee-df11-dcad-2cf9c05ece17} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.643; id=2dc491fe-9406-777f-d6eb-889cac5dcfc9} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.baseline-powered-on; id=0ca0b803-c16c-1bdd-c90e-bab98b175f50} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.808; id=fa728001-3de9-126a-aa0f-836a219510c8} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.801; id=45f866c7-b6f0-e0ca-2c53-bf90dd175088} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.794; id=33765419-2366-63ec-810f-0f7bc50146fd} MSSQL-VM-01 @{name=sn1-x70-b05-33:vvols-mssql-replication-1-hour-01.709; id=e5fed2b3-9c8a-4689-7163-7d4d2399daa2} MSSQL-VM-02 @{name=vvols-mssql-replication-1-hour-02.799; id=b2ce4252-46d4-a27d-9d2b-2b63b9222305}
Overall it’s a lot of data and I found that filtering out by VM was for sure the easiest way to have it be something useful.
Putting it all Together!
Putting all of that together here is what I came up with!
$faVMs = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machines?vm_type=vvol" -Headers $AuthHeader -SkipCertificateCheck $vmid = (($faVMs.Content | ConvertFrom-Json).items | where-object {$_.name -eq "MSSQL-VM-02"}).vm_id $vmSnapshots = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machine-snapshots?vm_type=vvol&filter=vm_id='$vmid'" -Headers $AuthHeader -SkipCertificateCheck ($vmSnapshots.content | ConvertFrom-Json).items ($vmSnapshots.content | ConvertFrom-Json).items |Sort-Object -Property Created
$faVMs = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machines?vm_type=vvol" -Headers $AuthHeader -SkipCertificateCheck $vmid = (($faVMs.Content | ConvertFrom-Json).items | where-object {$_.name -eq "MSSQL-VM-02"}).vm_id $vmSnapshots = Invoke-WebRequest -Method Get -Uri "https://$flasharray/api/2.14/virtual-machine-snapshots?vm_type=vvol&filter=vm_id='$vmid'" -Headers $AuthHeader -SkipCertificateCheck ($vmSnapshots.content | ConvertFrom-Json).items ($vmSnapshots.content | ConvertFrom-Json).items |Sort-Object -Property Created ---- created : 1660605450010 vm_id : 5039814f-113e-8e1f-f678-be7bcbe2a001 name : MSSQL-VM-02 id : 5039814f-113e-8e1f-f678-be7bcbe2a001 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=vvols-mssql-replication-1-hour-02.800; id=3bc97095-4cf7-b27c-b3d1-a2890487c80c} created : 1660605450010 vm_id : 5039814f-113e-8e1f-f678-be7bcbe2a001 name : MSSQL-VM-02 id : 5039814f-113e-8e1f-f678-be7bcbe2a001 time_remaining : destroyed : False vm_type : vvol recover_context : @{name=vvols-mssql-replication-1-hour-02.800; id=3bc97095-4cf7-b27c-b3d1-a2890487c80c}
That got me a very simple output for the two snapshots that existed on this array for the vm ‘MSSQL-VM-02’. I can create some nice outputs which include what VMs are on the array, what their vm_id is and if it’s destroyed. Then you can also use that same kind of workflow to find out what source or target vm snapshots are there.
In the end this is the exact API that we needed to create to make the vSphere Remote Plugin’s VM Undelete workflow work correctly. In addition to that, we were also able to get the Point in Time Revert and Point in Time undelete to work because of these APIs! It’s super exciting stuff from the engineering teams at Pure!