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; } } }