GetResourcesToRemove(
            ManagementObject managementService,
            ManagementObject virtualMachine,
            WorldWideName wwnA,
            WorldWideName wwnB)
        {
            using (ManagementObject virtualMachineSettings =
                   WmiUtilities.GetVirtualMachineSettings(virtualMachine))
            {
                ManagementObjectCollection fcPortCollection = virtualMachineSettings.GetRelated(
                    "Msvm_SyntheticFcPortSettingData",
                    "Msvm_VirtualSystemSettingDataComponent",
                    null, null, null, null, false, null);

                List<string> portsToRemove = new List<string>();
                foreach (ManagementObject fcPort in fcPortCollection)
                {
                    string primaryWwpn = fcPort["VirtualPortWWPN"].ToString();
                    string primaryWwnn = fcPort["VirtualPortWWNN"].ToString();
                    string secondaryWwpn = fcPort["SecondaryWWPN"].ToString();
                    string secondaryWwnn = fcPort["SecondaryWWNN"].ToString();

                    if (string.Equals(primaryWwpn, wwnA.PortName, StringComparison.OrdinalIgnoreCase) &&
                        string.Equals(primaryWwnn, wwnA.NodeName, StringComparison.OrdinalIgnoreCase) &&
                        string.Equals(secondaryWwpn, wwnB.PortName, StringComparison.OrdinalIgnoreCase) &&
                        string.Equals(secondaryWwnn, wwnB.NodeName, StringComparison.OrdinalIgnoreCase))
                    {
                        portsToRemove.Add(fcPort.Path.Path);
                    }
                }
                return portsToRemove.ToArray();
            }
        }
        DeleteVirtualFcPort(
            string virtualMachineName,
            WorldWideName wwnA,
            WorldWideName wwnB)
        {
            Console.WriteLine("Removing virtual FC port(s) with following WWNs from VM {0}:", virtualMachineName);
            Console.WriteLine("\tVirtualPortWWPN {0}, VirtualPortWWNN {1}", wwnA.PortName, wwnA.NodeName);
            Console.WriteLine("\tSecondaryWWPN {0}, SecondaryWWNN {1}", wwnB.PortName, wwnB.NodeName);

            ManagementScope scope = FibreChannelUtilities.GetFcScope();

            using (ManagementObject managementService =
                            WmiUtilities.GetVirtualMachineManagementService(scope))
            //
            // Find the virtual machine we want to connect.
            //
            using (ManagementObject virtualMachine =
                            WmiUtilities.GetVirtualMachine(virtualMachineName, scope))
            {
                string[] portsToRemove = GetResourcesToRemove(managementService,
                                                              virtualMachine,
                                                              wwnA,
                                                              wwnB);

                if (portsToRemove.Length == 0)
                {
                    Console.WriteLine("The specified world wide names were not found in VM {0}", virtualMachineName);
                    return;
                }

                using (ManagementBaseObject inParams =
                                managementService.GetMethodParameters("RemoveResourceSettings"))
                {
                    inParams["ResourceSettings"] = portsToRemove;

                    using (ManagementBaseObject addAdapterOutParams =
                                managementService.InvokeMethod("RemoveResourceSettings",
                                                                inParams,
                                                                null))
                    {
                       WmiUtilities.ValidateOutput(addAdapterOutParams, scope, true, true);
                    }
                }
            }

            Console.WriteLine("Successfully deleted the virtual FC port on VM {0}.", virtualMachineName);
        }
        ExecuteSample(
            string[] args)
        {
            if (args.Length < 3 || (args.Length > 0 && args[0] == "/?"))
            {
                Console.WriteLine("Usage: CreateSan <SanName> <[WWPN WWNN]+> [SanNotes]");
                return;
            }

            try
            {
                string sanName = args[0];
                string sanNotes = @"Notes for virtual SAN - " + sanName;
                List<string> hostResources = new List<string>();

                if (args.Length % 2 == 0)
                {
                    sanNotes = args[args.Length - 1];
                }

                for (int index = 2; index < args.Length; index += 2)
                {
                    WorldWideName wwn = new WorldWideName();
                    wwn.PortName = args[index - 1];
                    wwn.NodeName = args[index];
                    //
                    // Convert the WWN to the path of the corresponding Virtual FC Switch to be used
                    // as HostResources for the ResourcePool.
                    //
                    hostResources.Add(FibreChannelUtilities.GetHostResourceFromWwn(wwn));
                }

                CreateSan(sanName, sanNotes, hostResources.ToArray());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to create san. Error message details:\n");
                Console.WriteLine(ex.Message);
            }
        }
        AddSyntheticFcAdapter(
            ManagementObject virtualMachine,
            ManagementScope scope,
            WorldWideName wwnA,
            WorldWideName wwnB)
        {
            using (ManagementObject managementService =
                   WmiUtilities.GetVirtualMachineManagementService(scope))
            using (ManagementObject virtualMachineSettings =
                   WmiUtilities.GetVirtualMachineSettings(virtualMachine))
            //
            // Get the default Synthetic Adapter object, then modify its properties.
            //
            using (ManagementObject adapterToAdd = GetDefaultSyntheticFcAdapter(scope))
            {
                adapterToAdd["ElementName"] = FibreChannelUtilities.FcDeviceName;
                adapterToAdd["VirtualPortWWPN"] = wwnA.PortName;
                adapterToAdd["VirtualPortWWNN"] = wwnA.NodeName;
                adapterToAdd["SecondaryWWPN"] = wwnB.PortName;
                adapterToAdd["SecondaryWWNN"] = wwnB.NodeName;

                //
                // Now add it to the virtual machine.
                //
                using (ManagementBaseObject addAdapterInParams =
                       managementService.GetMethodParameters("AddResourceSettings"))
                {
                    addAdapterInParams["AffectedConfiguration"] = virtualMachineSettings.Path.Path;
                    addAdapterInParams["ResourceSettings"] = new string[] { adapterToAdd.GetText(
                                                                            TextFormat.WmiDtd20) };

                    using (ManagementBaseObject addAdapterOutParams =
                           managementService.InvokeMethod("AddResourceSettings",
                                                          addAdapterInParams,
                                                          null))
                    {
                        WmiUtilities.ValidateOutput(addAdapterOutParams, scope);

                        //
                        // Get the created FC adapter from the output parameters.
                        //
                        ManagementObject addedAdapter;
                        if (addAdapterOutParams["ResultingResourceSettings"] != null)
                        {
                            addedAdapter = new ManagementObject(
                                ((string[])addAdapterOutParams["ResultingResourceSettings"])[0]);

                            addedAdapter.Get();
                        }
                        else
                        {
                            using (ManagementObject job =
                                   new ManagementObject((string)addAdapterOutParams["Job"]))
                            {
                                addedAdapter =
                                    WmiUtilities.GetFirstObjectFromCollection(job.GetRelated(null,
                                        "Msvm_AffectedJobElement", null, null, null, null, false, null));
                            }
                        }

                        return addedAdapter;
                    }
                }
            }
        }
        ExecuteSample(
            string[] args)
        {
            if (args.Length < 2 || (args.Length > 0 && args[0] == "/?"))
            {
                Console.WriteLine("Usage: CreateVirtualFcPort <VM Name> <SAN Name> [WWPN-A WWNN-A WWPN-B WWNN-B]");
                Console.WriteLine();
                Console.WriteLine("Note:  The 2 sets of WWNs for the virtual port are optional and if omitted");
                Console.WriteLine("       will be auto generated using the WWPN Generator and the CurrentWWNNAddress.");
                return;
            }

            try
            {
                WorldWideName wwnA = new WorldWideName();
                WorldWideName wwnB = new WorldWideName();
                if (args.Length == 6)
                {
                    wwnA.PortName = args[2];
                    wwnA.NodeName = args[3];
                    wwnB.PortName = args[4];
                    wwnB.NodeName = args[5];
                }
                else
                {
                    Console.WriteLine("Auto Generating WWNs for Virtual FC Port to be added...");
                    FibreChannelUtilities.GenerateWorldWideNames(
                        FibreChannelUtilities.GetFcScope(),
                        ref wwnA,
                        ref wwnB);
                }

                CreateVirtualFcPort(args[0], args[1], wwnA, wwnB);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to create a virtual FC port. Error message details:\n");
                Console.WriteLine(ex.Message);
            }
        }
        CreateVirtualFcPort(
            string virtualMachineName,
            string sanName,
            WorldWideName wwnA,
            WorldWideName wwnB)
        {
            Console.WriteLine("Adding Virtual FC Port to VM {0} :", virtualMachineName);
            Console.WriteLine("\tVirtualWWPN: {0}, VirtualWWNN {1}", wwnA.PortName, wwnA.NodeName);
            Console.WriteLine("\tSecondaryWWPN: {0}, SecondaryWWNN {1}", wwnB.PortName, wwnB.NodeName);
            Console.WriteLine("\tProviding connectivity to Virtual SAN {0}", sanName);

            ManagementScope scope = FibreChannelUtilities.GetFcScope();

            using (ManagementObject managementService = 
                   WmiUtilities.GetVirtualMachineManagementService(scope))

            //
            // Find the virtual machine we want to connect.
            //
            using (ManagementObject virtualMachine = 
                   WmiUtilities.GetVirtualMachine(virtualMachineName, scope))

            //
            // Get the virtual machine's settings object which is used
            // to make configuration changes.
            //
            using (ManagementObject virtualMachineSettings =
                   WmiUtilities.GetVirtualMachineSettings(virtualMachine))

            //
            // Add a new synthetic FC Adapter device to the virtual machine.
            //
            using (ManagementObject syntheticAdapter = AddSyntheticFcAdapter(virtualMachine,
                                                                             scope,
                                                                             wwnA,
                                                                             wwnB))

            //
            // Now that we have added a FC adapter to the virtual machine we can configure its
            // connection settings.
            //
            using (ManagementObject connectionSettingsToAdd =
                   FibreChannelUtilities.GetDefaultFcPortAllocationSettingData(scope, sanName))
            {
                connectionSettingsToAdd["PoolID"] = sanName;
                connectionSettingsToAdd["Parent"] = syntheticAdapter.Path.Path;

                //
                // Now add the connection settings.
                //
                using (ManagementBaseObject addConnectionInParams =
                       managementService.GetMethodParameters("AddResourceSettings"))
                {
                    addConnectionInParams["AffectedConfiguration"] = virtualMachineSettings.Path.Path;
                    addConnectionInParams["ResourceSettings"] =
                        new string[] { connectionSettingsToAdd.GetText(TextFormat.WmiDtd20) };

                    using (ManagementBaseObject addConnectionOutParams =
                           managementService.InvokeMethod("AddResourceSettings",
                                                          addConnectionInParams,
                                                          null))
                    {
                        WmiUtilities.ValidateOutput(addConnectionOutParams, scope, true, true);
                    }
                }
            }

            Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
                "Successfully created virtual FC port on VM '{0}' and connected to san '{1}'.",
                virtualMachineName, sanName));
        }
        ExecuteSample(
            string[] args)
        {
            if (args.Length == 0 || args[0] == "/?")
            {
                Console.WriteLine("Usage: ModifySanPorts <SanName> [WWPN WWNN]*");
                return;
            }

            try
            {
                string sanName = args[0];
                List<string> switchPaths = new List<string>();

                if (args.Length >= 3 && args.Length % 2 == 1)
                {
                    for (int index = 2; index < args.Length; index += 2)
                    {
                        WorldWideName wwn = new WorldWideName();
                        wwn.PortName = args[index - 1];
                        wwn.NodeName = args[index];
                        //
                        // Convert the WWN to the path of the corresponding Virtual FC Switch to be used
                        // as HostResources for the ResourcePool.
                        //
                        switchPaths.Add(FibreChannelUtilities.GetHostResourceFromWwn(wwn));
                    }
                }
                else if (args.Length != 1)
                {
                    Console.WriteLine("Usage: ModifySanPorts sanName [WWPN WWNN]*");
                    return;
                }

                ModifySanResources(sanName, switchPaths.ToArray());
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to modify san ports. Error message details:\n");
                Console.WriteLine(ex.Message);
            }
        }
        BuildPortInfo()
        {
            List<FcPortInfo> portInfoList = new List<FcPortInfo>();

            ManagementScope scope = FibreChannelUtilities.GetFcScope();
            using (ManagementClass portClass = new ManagementClass("Msvm_ExternalFcPort"))
            {
                portClass.Scope = scope;
                using (ManagementObjectCollection fcPorts = portClass.GetInstances())
                {
                    foreach (ManagementObject port in fcPorts)
                    {
                        WorldWideName wwn = new WorldWideName();
                        wwn.NodeName = (string)port["WWNN"];
                        wwn.PortName = (string)port["WWPN"];

                        FcPortInfo portInfo = new FcPortInfo();
                        portInfo.PortWwn = wwn;

                        //
                        // Convert the WWN to the path of the corresponding Virtual FC Switch to be used
                        // as HostResources for the ResourcePool.
                        //
                        portInfo.HostResource = FibreChannelUtilities.GetHostResourceFromWwn(wwn);
                        portInfo.Status = GetPortStatus(port);

                        portInfoList.Add(portInfo);
                    }
                }
            }

            if (portInfoList.Count == 0)
            {
                Console.WriteLine("No FibreChannel Ports found in the system.");
            }

            return portInfoList;
        }
        GetHostResourceFromWwn(
            WorldWideName wwn
            )
        {
            ManagementScope scope = GetFcScope();

            //
            // If the wwn is for a valid ExternalFcPort, we should be able to get
            // the FcEndpoint for the VirtualFcSwitch for the ExternalFcPort.
            // For every valid ExternalFcPort, there is guaranteed to be a corresponding
            // unique VirtualFcSwitch.
            //
            string queryString = string.Format(CultureInfo.InvariantCulture,
                "SELECT * FROM Msvm_FcEndpoint WHERE SystemCreationClassName = '{0}'" +
                " AND WWNN = '{1}' AND WWPN = '{2}'",
                "Msvm_VirtualFcSwitch", wwn.NodeName, wwn.PortName);

            ObjectQuery query = new ObjectQuery(queryString);
            
            using (ManagementObjectSearcher switchEndpointSearcher =
                   new ManagementObjectSearcher(scope, query))
            using (ManagementObject switchEndpoint =
                   WmiUtilities.GetFirstObjectFromCollection(switchEndpointSearcher.Get()))
            {
                string switchQueryString = string.Format(CultureInfo.InvariantCulture,
                    "SELECT * FROM Msvm_VirtualFcSwitch WHERE Name = '{0}'",
                    switchEndpoint["SystemName"]);

                ObjectQuery switchQuery = new ObjectQuery(switchQueryString);
            
                using (ManagementObjectSearcher switchSearcher =
                       new ManagementObjectSearcher(scope, switchQuery))
                using (ManagementObjectCollection fcSwitches = switchSearcher.Get())
                //
                // There is only 1 VirtualFcSwitch for an ExternalFcPort.
                //
                using (ManagementObject fcSwitch =
                       WmiUtilities.GetFirstObjectFromCollection(fcSwitches))
                {
                    return fcSwitch.Path.Path;
                }
            }
        }
        GenerateWorldWideNames(
            ManagementScope scope,
            ref WorldWideName wwnA,
            ref WorldWideName wwnB)
        {
            using (ManagementObject settings =
                   WmiUtilities.GetVirtualMachineManagementServiceSettings(scope))
            using (ManagementObject managementService =
                   WmiUtilities.GetVirtualMachineManagementService(scope))
            using (ManagementBaseObject inParams = 
                   managementService.GetMethodParameters("GenerateWwpn"))
            {
                // Set WWNN.
                string assignedWwnn = settings["CurrentWWNNAddress"].ToString();
                wwnA.NodeName = assignedWwnn;
                wwnB.NodeName = assignedWwnn;

                // Generate 2 WWPNs for the 2 sets.
                inParams["NumberOfWwpns"] = 2;
                using (ManagementBaseObject outParams =
                       managementService.InvokeMethod("GenerateWwpn", inParams, null))
                {
                    WmiUtilities.ValidateOutput(outParams, scope);

                    // Requested for 2 WWPNs to be generated.
                    string[] wwpnArray = outParams["GeneratedWwpn"] as string[];
                    wwnA.PortName = wwpnArray[0];
                    wwnB.PortName = wwpnArray[1];
                }
            }
        }
        ExecuteSample(
            string[] args)
        {
            if (args.Length != 5 || (args.Length > 0 && args[0] == "/?"))
            {
                Console.WriteLine("Usage: DeleteVirtualFcPort <VM Name> <WWPN-A> <WWNN-A> <WWPN-B> <WWNN-B>");
                return;
            }

            try
            {
                WorldWideName wwnA = new WorldWideName();
                wwnA.PortName = args[1];
                wwnA.NodeName = args[2];

                WorldWideName wwnB = new WorldWideName();
                wwnB.PortName = args[3];
                wwnB.NodeName = args[4];

                DeleteVirtualFcPort(args[0], wwnA, wwnB);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to delete virtual FC port. Error message details:\n");
                Console.WriteLine(ex.Message);
            }
        }