This is a sample application that is written in C#. It queries entities in Mirage, centralizes endpoints, and migrates a CVD operating system.
//This is the C# sample code of Mirage API, which includes three parts.
//1. Query entities in Mirage, such as policy, volume, pending device, CVD, base layer and app layer
//2. Centralize endpoints.
//3. Migrate CVD Operating System.
//4. CVD assign base layer.
//5. CVD update app layer.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.Threading;
using vmware.mirage.mit.faults;
using vmware.mirage.mit.query;
using vmware.mirage.mit.types;
namespace SampleCode
{
class MirageApiSample
{
private static MitServiceClient Client;
private static int Main(string[] args)
{
if (args.Length < 4)
{
Console.WriteLine(
"Usage: SampleCode <Web_Management_Server_IP> <Username> <Password> <migration_domain>");
return -1;
}
Console.WriteLine("---------------- Login ----------------");
Login(args[0], args[1], args[2]);
Console.WriteLine("--------------VolumeQuery--------------");
VolumeQuery("Default");
Console.WriteLine("--------------PolicyQuery--------------");
PolicyQuery("VMware Mirage default CVD policy");
Console.WriteLine("----------------CvdQuery---------------");
CvdQuery(10001, "MIRAGEDOMAIN");
Console.WriteLine("-----------PendingDeviceQuery----------");
PendingDeviceQuery(23);
Console.WriteLine("----------------CeFlow-----------------");
CeFlow();
Console.WriteLine("------------OsMigrationFlow------------");
OsMigrationFlow(args[1], args[2], args[3]);
Console.WriteLine("----------ProvisioningFlow-------------");
ProvisioningFlow(args[1], args[2], args[3]);
Console.WriteLine("---------CvdAssignBaseLayerFlow---------");
CvdAssignBaseLayerFlow();
Console.WriteLine("--------CvdUpdateAppLayerFlow-----------");
CvdUpdateAppLayerFlow();
return 0;
}
//Login Mirage API server with address, username and password.
public static void Login(string address, string username, string password)
{
// Trust all certificates. This is just for sample code.
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
BasicHttpBinding binding = new BasicHttpBinding
{
AllowCookies = true,
Security =
{
Mode = BasicHttpSecurityMode.Transport
}
};
//Connect to Mirage Web Management Server, default port is 7443
EndpointAddress endpoint =
new EndpointAddress(string.Format("https://{0}:7443/mirageapi/MitService.svc", address));
Client = new MitServiceClient(binding, endpoint);
Client.Login(username, password);
Console.WriteLine("Login success!");
}
// Query pending devices whose device id is deviceId, only the first page returns.
public static void PendingDeviceQuery(long deviceId)
{
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterEquals
{
Field = FilterField.DEVICE_ID,
Value = new Id
{
IdValue = deviceId
}
},
Page = 1 //Page index starts from 1, not 0
};
QueryResult result = Client.PendingDevice_Query(query);
if (result.Elements.Length == 0)
{
return;
}
foreach (DeviceDetails deviceDetails in result.Elements)
{
Console.WriteLine(
"ID: {0}, name: {1}, user name: {2}, OS version: {3}, vendor name {4}, model name {5}, connected: {6}, last connected time: {7}, operation time: {8}",
deviceDetails.Id.IdValue, deviceDetails.Name, deviceDetails.UserName,
deviceDetails.Os, deviceDetails.VendorName,
deviceDetails.ModelName, deviceDetails.Connected, deviceDetails.LastConnectedTime,
deviceDetails.OperationTime);
}
}
// Query volumes whose name is volumeName, only the first page returns.
public static void VolumeQuery(string volumeName)
{
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterBeginsWith
{
Field = FilterField.VOLUME_NAME,
Value = volumeName
},
Page = 1
};
QueryResult result = Client.Volume_Query(query);
if (result.Elements.Length == 0)
{
return;
}
foreach (VolumeDetails volumeDetails in result.Elements)
{
Console.WriteLine("ID: {0}, name: {1}, path: {2}", volumeDetails.Id.IdValue, volumeDetails.Name,
volumeDetails.Path);
}
}
// Query polices whose name is policyName, only the first page returns.
public static void PolicyQuery(string policyName)
{
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterContains
{
Field = FilterField.POLICY_NAME,
Value = policyName
},
Page = 1
};
QueryResult result = Client.Policy_Query(query);
if (result.Elements.Length == 0)
{
return;
}
foreach (PolicyDetails policyDetails in result.Elements)
{
Console.WriteLine("ID: {0}, version: {1}.{2}, name: {3}",
policyDetails.ImageId.Id.IdValue, policyDetails.ImageId.Version.Major,
policyDetails.ImageId.Version.Minor, policyDetails.Name);
}
}
// Query Cvd with cvdId. It will throw FaultException<InvalidArgument> when the cvdId is not the Id type.
public static void CvdQuery(long cvdId)
{
QueryFilterEquals filter = new QueryFilterEquals
{
Field = FilterField.CVD_ID,
Value = cvdId //Invalid value type for CVD_ID, expected type: Id
};
QueryDefinition query = new QueryDefinition
{
Filter = filter,
Page = 1
};
try
{
Client.Cvd_Query(query);
}
catch (FaultException<InvalidArgument> e)
{
InvalidArgument detail = e.Detail;
if (detail.GetType() == typeof(InvalidArgument))
{
Console.WriteLine("InvalidArgument fault, detail message: " + detail.Message);
//Expected output:
//InvalidArgument fault, detail message: Bad value for queryDefinition: "Filter value for CVD_ID must be of type Id
//Parameter name: queryDefinition
}
}
}
// Query Cvd, whose Id isn't cvdId, and cvd name begins with cvdUsername.
public static void CvdQuery(long cvdId, string cvdUsername)
{
QueryFilterNotEquals filterNotEquals = new QueryFilterNotEquals
{
Field = FilterField.CVD_ID,
Value = new Id
{
IdValue = cvdId
}
};
QueryFilterBeginsWith filterBeginsWith = new QueryFilterBeginsWith
{
Field = FilterField.CVD_USER_NAME,
Value = cvdUsername
};
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterAnd
{
Filters = new QueryFilter[] { filterNotEquals, filterBeginsWith }
},
Page = 1
};
QueryResult result = Client.Cvd_Query(query);
if (result.Elements.Length == 0)
{
return;
}
foreach (CvdDetails cvdDetails in result.Elements)
{
Console.WriteLine("ID: {0}, device ID: {1}, policy ID: {2}, machine version: {3}.{4}",
cvdDetails.Id.IdValue, cvdDetails.DeviceId.IdValue, cvdDetails.PolicyId.IdValue,
cvdDetails.MachineVersion.Major, cvdDetails.MachineVersion.Minor);
}
}
// Centralization endpoint flow.
public static void CeFlow()
{
QueryResult result = Client.PendingDevice_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
DeviceDetails pendingDevice = (DeviceDetails)result.Elements[0];
result = Client.Volume_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
VolumeDetails volume = (VolumeDetails)result.Elements[0];
result = Client.Policy_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
PolicyDetails policy = (PolicyDetails)result.Elements[0];
Console.WriteLine("Creating new Cvd...");
Id[] ids = { pendingDevice.Id };
BatchResult batchResult = Client.PendingDevice_CreateNewCvd(ids, policy.ImageId, volume.Id);
OperationResult opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to create cvd, error: {0}", opResult.Fault);
return;
}
// Check the centralization endpoint flow complete.
while (true)
{
result = Client.Cvd_Query(new QueryDefinition
{
Filter = new QueryFilterEquals
{
Field = FilterField.CVD_ID,
Value = new Id
{
IdValue = (long)opResult.Result
}
},
Page = 1
});
if (result.Elements.Length == 0)
{
return;
}
CvdDetails cvdDetails = (CvdDetails)result.Elements[0];
if (cvdDetails.MachineVersion.Major > 1 || cvdDetails.MachineVersion.Minor > 0)
{
Console.WriteLine("ID: {0}, device ID: {1}, policy ID: {2}, machine version: {3}.{4}",
cvdDetails.Id.IdValue, cvdDetails.DeviceId.IdValue, cvdDetails.PolicyId.IdValue,
cvdDetails.MachineVersion.Major, cvdDetails.MachineVersion.Minor);
break;
}
Thread.Sleep(TimeSpan.FromMinutes(2));
}
}
//Pending device provisioning flow
public static void ProvisioningFlow(string username, string password, string domain)
{
QueryResult result = Client.PendingDevice_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
DeviceDetails pendingDevice = (DeviceDetails)result.Elements[0];
result = Client.Volume_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
VolumeDetails volume = (VolumeDetails)result.Elements[0];
result = Client.Policy_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
PolicyDetails policy = (PolicyDetails)result.Elements[0];
result = Client.BaseLayer_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
LayerDetails baseLayer = (LayerDetails)result.Elements[0];
result = Client.AppLayer_Query(new QueryDefinition { Filter = null, Page = 1 });
if (result.Elements.Length == 0)
{
return;
}
LayerDetails appLayer = (LayerDetails)result.Elements[0];
Console.WriteLine("Provisioning new Cvd...");
Id[] ids = { pendingDevice.Id };
ImageId[] appLayers = { appLayer.ImageId };
MachineIdentityInfo identityInfo = new MachineIdentityInfo
{
DomainMember = true,
DomainOrWorkgroupName = domain,
User = username,
Password = password
};
BatchResult batchResult = Client.PendingDevice_Provision(ids, policy.ImageId, baseLayer.ImageId, appLayers,
identityInfo, volume.Id, false);
OperationResult opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to provision cvd, error: {0}", opResult.Fault);
return;
}
//Wait for provision complete
//Assignments include both base layer and app layer assignment.
WaitForAssignmentsComplete("DeviceProvisioning", new Id{ IdValue = (long)opResult.Result });
}
// OS migration flow.
public static void OsMigrationFlow(string username, string password, string domain)
{
// Suppose we have one win7 32bit base layer and one xp cvd
QueryDefinition query = new QueryDefinition
{
Filter = null,
Page = 1
};
QueryResult result = Client.Cvd_Query(query);
if (result.Elements.Length == 0)
{
return;
}
CvdDetails cvd = (CvdDetails)result.Elements[0];
result = Client.BaseLayer_Query(query);
if (result.Elements.Length == 0)
{
return;
}
LayerDetails baseLayer = (LayerDetails)result.Elements[0];
ImageId[] appLayerImageIds = GetAppLayerImageIds();
MigrationTarget target = new MigrationTarget
{
CvdId = cvd.Id,
IdentityInfo = new MachineIdentityInfo
{
DomainMember = true,
DomainOrWorkgroupName = domain,
User = username,
Password = password
}
};
OperationResult operationResult =
Client.OsMigration_BeginDownloadOnly(new[] { target }, baseLayer.ImageId, appLayerImageIds, true).results[0];
if (!operationResult.Success)
{
return;
}
WaitForOsMigrationDownloadInProgress();
WaitForOsMigrationDownloadCompleted();
operationResult = Client.OsMigration_ApplyDownloadOnlyMigration(new[] { cvd.Id }).results[0];
if (!operationResult.Success)
{
return;
}
Console.WriteLine("Applying migration...");
//Wait for migration complete
WaitForAssignmentsComplete("Migration", cvd.Id);
}
//Cvd assign base layer flow
public static void CvdAssignBaseLayerFlow()
{
const string baselayerDownloadOnlyTaskName = "BaseImageDownloadOnly";
const string applyLayerTaskName = "ApplyLayers";
QueryResult result = Client.Cvd_Query(new QueryDefinition
{
Filter = null,
Page = 1
});
if (result.Elements.Length == 0)
{
return;
}
CvdDetails cvd = (CvdDetails)result.Elements[0];
result = Client.BaseLayer_Query(new QueryDefinition
{
Filter = null,
Page = 1
});
if (result.Elements.Length == 0)
{
return;
}
LayerDetails baseLayer = (LayerDetails)result.Elements[0];
//Download only assign base layer
Console.WriteLine("Base layer download...");
BatchResult batchResult = Client.Cvd_AssignBaseLayerDownloadOnly(new[]{cvd.Id}, baseLayer.ImageId, true);
OperationResult opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to assign base layer for cvd, error: {0}", opResult.Fault);
return;
}
WaitForAssignmentsComplete(baselayerDownloadOnlyTaskName, cvd.Id);
//Query Assignment and apply
result = AssignmentQueryWithTaskAndCvdId(baselayerDownloadOnlyTaskName, cvd.Id);
if (result.Elements.Length == 0)
{
return;
}
AssignmentDetails assignmentDetails = (AssignmentDetails) result.Elements[0];
Console.WriteLine("Apply base layer assignment...");
batchResult = Client.Assignment_ApplyDownloadOnly(new[]{assignmentDetails.Id}, true);
opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to apply layers for cvd, error: {0}", opResult.Fault);
return;
}
//Wait for assignment complete
//Apply assignment will create a new assignment with task name "ApplyLayers"
WaitForAssignmentsComplete(applyLayerTaskName, cvd.Id);
}
//Cvd update app layer flow
public static void CvdUpdateAppLayerFlow()
{
const string applayerDownloadOnlyTaskName = "AppLayerDownloadOnly";
const string applyLayerTaskName = "ApplyLayers";
QueryResult result = Client.Cvd_Query(new QueryDefinition
{
Filter = null,
Page = 1
});
if (result.Elements.Length == 0)
{
return;
}
CvdDetails cvd = (CvdDetails)result.Elements[0];
result = Client.AppLayer_Query(new QueryDefinition
{
Filter = null,
Page = 1
});
if (result.Elements.Length == 0)
{
return;
}
LayerDetails appLayer = (LayerDetails)result.Elements[0];
//Download only update app layer
Console.WriteLine("App layer download...");
BatchResult batchResult = Client.Cvd_UpdateAppLayerDownloadOnly(new[] { cvd.Id }, new []{ appLayer.ImageId }, null, true);
OperationResult opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to update app layer for cvd, error: {0}", opResult.Fault);
return;
}
WaitForAssignmentsComplete(applayerDownloadOnlyTaskName, cvd.Id);
//Query assignment and apply
result = AssignmentQueryWithTaskAndCvdId(applayerDownloadOnlyTaskName, cvd.Id);
if (result.Elements.Length == 0)
{
return;
}
AssignmentDetails assignmentDetails = (AssignmentDetails)result.Elements[0];
Console.WriteLine("Apply app layer assignment...");
batchResult = Client.Assignment_ApplyDownloadOnly(new[] { assignmentDetails.Id }, true);
opResult = batchResult.results[0];
if (opResult.Success == false)
{
Console.WriteLine("failed to apply layers for cvd, error: {0}", opResult.Fault);
return;
}
//Wait for assignment complete
//Apply assignment will create a new assignment with task name "ApplyLayers"
WaitForAssignmentsComplete(applyLayerTaskName, cvd.Id);
}
// Check the Cvd completes to download base layer and app layers for migration.
private static void WaitForOsMigrationDownloadCompleted()
{
while (true)
{
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterEquals
{
Field = FilterField.DOWNLOAD_ONLY_MIGRATION_STATUS,
Value = "Complete"
},
Page = 1
};
QueryResult result = Client.OsMigrationCvd_QueryDownloadOnly(query);
if (result.Elements.Length != 0)
{
Console.WriteLine("Migration download success!");
break;
}
Thread.Sleep(TimeSpan.FromMinutes(2));
}
}
// Check the Cvd is downloading base layer or app layers for migration.
private static void WaitForOsMigrationDownloadInProgress()
{
while (true)
{
QueryDefinition query = new QueryDefinition
{
Filter = new QueryFilterEquals
{
Field = FilterField.DOWNLOAD_ONLY_MIGRATION_STATUS,
Value = "Downloading"
},
Page = 1
};
QueryResult result = Client.OsMigrationCvd_QueryDownloadOnly(query);
if (result.Elements.Length != 0)
{
Console.WriteLine("Migration downloading...");
break;
}
Thread.Sleep(TimeSpan.FromMinutes(2));
}
}
//Wait for assignment complete
private static void WaitForAssignmentsComplete(string taskName, Id cvdId)
{
while (true)
{
QueryResult result = AssignmentQueryWithTaskAndCvdId(taskName, cvdId);
if (result.Elements != null && result.Elements.Length > 0)
{
AssignmentDetails[] assignments = result.Elements.Select(e => (AssignmentDetails)e).ToArray();
if (IsAssignmentComplete(assignments))
{
break;
}
}
Thread.Sleep(TimeSpan.FromMinutes(2));
}
}
//Query assignment
private static QueryResult AssignmentQueryWithTaskAndCvdId(string taskName, Id cvdId)
{
QueryFilter taskNameFilter = new QueryFilterEquals
{
Field = FilterField.ASSIGNMENT_TASK_NAME,
Value = taskName
};
QueryFilter cvdIdFilter = new QueryFilterEquals
{
Field = FilterField.ASSIGNMENT_CVD_ID,
Value = cvdId
};
QueryFilterAnd filter = new QueryFilterAnd { Filters = new[] { taskNameFilter, cvdIdFilter } };
return Client.Assignment_Query(new QueryDefinition { Filter = filter, Page = 1 });
}
//Check if all assignments complete
private static bool IsAssignmentComplete(AssignmentDetails[] assignments)
{
if (assignments == null || assignments.Length == 0)
{
return false;
}
HashSet<string> statusFailed = new HashSet<string>(new[] { "Cancelled", "Rejected", "Blocked" });
const string statusDone = "Done";
bool assignmentsDone = true;
foreach (AssignmentDetails assignment in assignments)
{
if (statusFailed.Contains(assignment.Status))
{
Console.WriteLine("Assignment failed, operation failed!");
return true;
}
assignmentsDone &= assignment.Status.Equals(statusDone);
}
if (assignmentsDone)
{
Console.WriteLine("Assignment done, operation succeed!");
}
return assignmentsDone;
}
// Get App layers.
private static ImageId[] GetAppLayerImageIds()
{
QueryResult result = Client.AppLayer_Query(new QueryDefinition { Filter = null, Page = 1 });
ImageId[] appLayerImageIds;
if (result.Elements.Length != 0)
{
LayerDetails[] appLayers = Array.ConvertAll(result.Elements, a => (LayerDetails)a);
appLayerImageIds = appLayers.Select(a => a.ImageId).ToArray();
}
else
{
appLayerImageIds = null;
}
return appLayerImageIds;
}
}
}