Month: March 2016

Setting VMstore Maintenance Mode

Greetings,

It has been a while since I’ve written a blog, but here is one that sets the VMstore maintenance mode. Hopefully there will be more coming at a faster pace.

One of Tintri’s customers wanted to set the VMstore’s maintenance mode. When the VMstore maintenance mode is enabled, alert e-mails are not sent except to support@tintri.com.  Theses support@tintri.com e-mails are marked with “maintenance mode”.

Setting maintenance mode allows you to change network configuration or upgrade VMstore without the VMstore sending alert e-mails.  That way the administrator will not be bothered with extraneous e-mails.  Tintri support still receives e-mails just in case something really important occurs, like a disk failure.

I wrote Python and PowerShell examples. Both are interactive, that is, they ask the user if the maintenance mode should be flipped before flipping the enable flag. The maintenance mode flag is located in the maintenance mode data transfer object (DTO) in the appliance DTO.
ApplianceMaintenanceMode DTO:

 
{ "typeId": "com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceMaintenaneMode", "endTime": DateTime, "isEnabled": <Boolean>, "startTime": DateTime, }

Appliance DTO:


{ "typeId": "com.tintri.api.rest.v310.dto.domain.Appliance",
  "errorString": <String>,
  "fanDescription": <String>,
  "lastUpdatedTime": DateTime,
  "localAlias": <String>,
  "localPassword": <String>,
  "powerDescription": <String>,
  "redundancyDescription": <String>,
  "temperatureDescription": <String>,
  "alertCounts": ApplianceAlertCounts,
  "allowSnapshotIncompleteVm": ApplianceAllowSnapshotIncompleteVm,
  "components": [ApplianceComponent],
  "configIps": [ApplianceIp],
  "controllers": [ApplianceController],
  "customizationInfo": ApplianceCustomizationInfo,
  "dateTimeConfig": ApplianceDateTime,
  "disks": [ApplianceDisk],
  "diskEncryptionInfo": ApplianceDiskEncryptionInfo,
  "dnsConfig": ApplianceDns,
  "emailConfig": ApplianceEmail,
  "info": ApplianceInfo,
  "ipmiConfig": ApplianceIpmi,
  "lacpConfig": ApplianceLacp,
  "maintenanceMode": ApplianceMaintenanceMode,
  "operationalInfo": ApplianceOperationalInfo,
  "rbacExternalConfig": RbacExternalConfig,
  "snmpConfig": ApplianceSnmp,
  "supportConfig": ApplianceSupport,
  "syslogForwarding": ApplianceSyslogForwarding,
  "temperatures": [Temperature],
  "upgradeInfo": ApplianceUpgradeInfo,
  "uuid": Uuid,
 }

First let’s look at the Python example. The code uses the Setting DNS Primary at Scale as an example, because both perform a PUT on the /v310/appliance resource.  When setting the maintenance mode, start and end times are required.  The VMstore GUI sets a 6 hour duration and the code follows this precedent.


 now = datetime.datetime.now()
 add_6 = now + datetime.timedelta(hours=6)
 time_zone = my_timezone()
 now_str = now.isoformat() + time_zone
 add_6_str = add_6.isoformat() + time_zone

When resetting the maintenance mode the start and end times should not be present, so the code reflects this.


if (new_is_enabled):
    # Create the maintenance mode DTO for enabling.
    new_maint_mode_info = \
      {"typeId": "com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceMaintenanceMode",
       "endTime" : add_6_str,
       "isEnabled" : new_is_enabled,
       "startTime" : now_str
      }
else:
    # Create the maintenance mode DTO for disabling.
    new_maint_mode_info = \
      {"typeId": "com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceMaintenanceMode",
       "isEnabled" : new_is_enabled,
      }

The request DTO is used to send to the Appliance DTO with the new maintenance mode DTO filled with values to set.


# Create the Appliance object wit the new ApplianceDns DTO.
new_appliance = \
  {"typeId": "com.tintri.api.rest.v310.dto.domain.Appliance",
   "maintenanceMode": new_maint_mode_info
  }

# Create the Request object with the Appliance DTO.
request = \
  {"typeId": "com.tintri.api.rest.v310.dto.Request",
   "objectsWithNewValues": [new_appliance],
   "propertiesToBeUpdated": ["maintenanceMode"]
  }

# Invoke the appliance API to set the maintenance mode.
url = APPLIANCE_URL
r = tintri.api_put(server_name, url, request, session_id)

The rest of the code gets and prints the maintenance mode. The code is locate on our GitHub site at set_maintenance_mode.py.

The PowerShell example follows the Python example closely.  This is due to bug 42915 in the PowerShell Toolkit and the fact that I was unable to use the Tintri Session ID from the toolkit in Invoke-RestMethod().  For me this example was a lesson in using Invoke-RestMethod().  I used Mircosoft’s library and trial and error.

One of things I did was create some helper functions, like tintriVersion(), tintriLogin(), and tintriLogout().  Here is tintriLogin():


Set-Variable JSON_CONTENT "application/json; charset=utf-8"
Set-Variable APPLIANCE_URL "/api/v310/appliance/default"

function tintriLogin
{
param([String]$server)
$loginUri = "https://$($server)/api/v310/session/login"
$loginDict = @{typeId="com.tintri.api.rest.vcommon.dto.rbac.RestApiCredentials";
               username=$user; 
               password=$password
              }
$loginBody = $loginDict | ConvertTo-Json 
$resp = Invoke-RestMethod -sessionVariable session -Method Post -Uri $loginUri -Body $loginBody -ContentType $JSON_CONTENT
return $session
}

The key here is to obtain the session variable which is done with -sessionVariable session. See the code snippet above in the login invoke. Note, the sessionVariable parameter value, session, doesn't have a dollar sign. Later Invoke-RestMethod() calls use the session variable with the WebSession parameter. An example is below.


$url = "https://$($server)$($APPLIANCE_URL)/maintenanceMode"
$resp = Invoke-RestMethod -Uri $url -Method Get -WebSession $session -ContentType $JSON_CONTENT

Again, we get the time and a six hour delta:


$now = Get-Date
$add6 = $now.AddHours(6)
$nowStr = $now.ToString("yyyy-MM-ddTHH:mmzzz")
$add6Str = $add6.ToString("yyyy-MM-ddTHH:mmzzz")

And we build the ApplianceMaintenanceMode DTO depending on whether the maintenance mode is enabled or not.


if ($newIsEnabled) {
    # Create the maintenance mode object for enabling.
    $newMaintModeInfo = @{typeId = "com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceMaintenanceMode";
                          endTime = $add6Str;
                          isEnabled = $newIsEnabled;
                          startTime = $nowStr
                         }
}
else {
    # Create the maintenance mode object for disabling.
    $newMaintModeInfo = @{typeId = "com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceMaintenanceMode"; 
                          isEnabled = $newIsEnabled
                         }
}

Finally, the Request DTO is created, and the /v310/appliance resource is invoked.