Generating the default VVol Storage Container ID

A VVol datastore, is not a file system, so it is not a traditional datastore. It is just a capacity quota. So when you “mount” a VVol datastore, you aren’t really performing a traditional mounting operation as there is no underlying physical storage to address during the mount. So instead of mounting some storage device, you are mounting what is called a storage container. This is the meta data object that represents the certain amount of capacity that can be provisioned from a given array. An array can have more than one storage containers, for reasons of multi-tenancy or whatever.

In a VMFS world, when you go to create a new datastore, you pass it the serial number of the storage you want to format with VMFS. You know that serial, because, well, you created the storage device. When you “mount” a VVol datastore, instead of a device serial, you supply the storage container UUID. It comes in the form of vvol:e0ad83893ead3681-b1b7f56a45ff64f1. Of course the characters will vary a bit.

On the FlashArray, we currently have a single default storage container. We generate the UUID based off of the array serial number–this is so we can always regenerate it in the same way (it will be unique, but not random). In short we take a double hash, replace two bits in order to specify it is a type-3 UUID, and then return it in the form VMware requests.

When we add support for multiple VVol datastores, the process to get those UUIDs from the array will be different, and more streamlined.

Normally, you don’t need to understand this. In vCenter, you just go to new datastore, you see the storage container, and go on your merry way selecting it and mounting it.

If you want to script it though, it could be helpful to know what this ID is (duh). There is an API in the SMS API to queryContainer() that when left with no parameters, will return all available storage containers. If the storage container has not been mounted yet, that is the only way to find out the UUID. Unfortunately, the ability to call this API is almost nowhere in the commonly used tools (AFAIK). vRO might be the exception.

So, in PowerShell, I have made it easy, by writing a PowerShell cmdlet for you. But here is the code if you want it. And also in two other languages. We are running the assumption you have the array ID and it comes in the form of 184b1c58-c285-4eba-8ac7-2e7ac3618bf9

PowerShell

Here is an example script that generates the correct UUID. PowerShell was a little goofy because the GUID generator seems to flips some of the bits so I had to flip them back.

Find it here on GitHub:

https://github.com/codyhosterman/powercli/blob/master/getScIDfromArrayID.ps1

$arrayID = Read-Host "Enter a FlashArray ID"
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = new-object -TypeName System.Text.UTF8Encoding
$hash = $md5.ComputeHash($utf8.GetBytes($arrayID))
$hash2 = $md5.ComputeHash(($hash))
$hash2[6] = $hash2[6] -band 0x0f
$hash2[6] = $hash2[6] -bor 0x30
$hash2[8] = $hash2[8] -band 0x3f
$hash2[8] = $hash2[8] -bor 0x80
$newGUID = (new-object -TypeName System.Guid -ArgumentList (,$hash2)).Guid
$fixedGUID = $newGUID.Substring(18)
$scId = $newGUID.Substring(6,2) + $newGUID.Substring(4,2) + $newGUID.Substring(2,2) + $newGUID.Substring(0,2) + "-" + $newGUID.Substring(11,2) + $newGUID.Substring(9,2) + "-" + $newGUID.Substring(16,2) + $newGUID.Substring(14,2) + $fixedGUID
$scId = $scId.Replace("-","")
$scId = "vvol:" + $scId.Insert(16,"-")
write-host $scId

GoLang

I don’t know how many will use this, but I have been getting into a Go a bit, so I figured I’d use this as an exercise to learn. Note you need to install the UUID package to get this to work.

This is posted on my Github here:

https://github.com/codyhosterman/VVolsGoLang/blob/master/getScIDfromArrayID.go

package main

import (
	"bufio"
	"crypto/md5"
	"fmt"
	"os"
	"strings"

	"github.com/google/uuid"
)

func main() {
	fmt.Println("Please enter a FlashArray ID:")
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')
	text = strings.TrimRight(text, "\r\n")
	h1 := md5.New()
	h1.Write([]byte(text))
	firstHash := h1.Sum([]byte{})
	namespaceUUID, _ := uuid.FromBytes(firstHash)
	result_uuid := uuid.NewMD5(namespaceUUID, []byte{})
	returnValue := "vvol:" + result_uuid.String()
	returnValue = strings.Replace(returnValue, "-", "", -1)
	finalValue := returnValue[:21] + "-" + returnValue[21:]
	fmt.Println(finalValue)
}

Python 2.7

And now in Python 2.7. Very similar to Go

Find it here on GitHub:

https://github.com/codyhosterman/PythonVVolExamples/blob/master/getScIDfromArrayID.py

import hashlib
import uuid
arrayID = raw_input("Please enter a FlashArray ID: ") 
def scid_uuid(farrayID):
   m = hashlib.md5().update(farrayID)
   b = m.digest()
   m = hashlib.md5().update(b)
   b = bytearray(m.digest())
   b[6] &= 0x0f 
   b[6] |= 0x30 
   b[8] &= 0x3f 
   b[8] |= 0x80 
   return uuid.UUID(bytes=str(b))

a = scid_uuid(arrayID)
newStr = str(a).replace('-', '')
myUuid = newStr[:16] + "-" + newStr[16:]
print "vvol:" + myUuid

JavaScript/Node.js

Okay one more because why not?

Find it here on GitHub:

https://github.com/codyhosterman/JavaScriptVVolExamples/blob/master/getScIDfromArrayID.js

const crypto = require('crypto');
var readlineSync = require('readline-sync');
var arrayID = readlineSync.question('Please enter a FlashArray ID: ');
var hash = crypto.createHash('md5').update(arrayID).digest('byte');
var hashA = crypto.createHash('md5').update(hash).digest('byte');
hashA[6] = hashA[6] & 0x0f 
hashA[6] = hashA[6] | 0x30 
hashA[8] = hashA[8] & 0x3f 
hashA[8] = hashA[8] | 0x80
var scID = toHexString(hashA);
console.log("vvol:" + scID.substring(0,16) + "-" + scID.substring(16,32)); 

function toHexString(byteArray) {
    return Array.from(byteArray, function(byte) {
      return ('0' + (byte & 0xFF).toString(16)).slice(-2);
    }).join('')
  }

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.