// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft. All rights reserved. namespace Microsoft.Samples.HyperV.Networking { using System; using System.Management; using System.Globalization; using System.Collections.Generic; using Microsoft.Samples.HyperV.Common; static class ConnectVmToSwitchSample { /// /// For the given virtual machine, this sample adds a new Network Adapter device and /// connects it to the specified switch. Note that in order to add a new Network Adapter /// device to the virtual machine, the virtual machine must be in the power off state. /// Also note that the maximum number of Network Adapter devices that may be configured /// on a virtual machine is 8. /// /// The name of the virtual machine. /// The name of the switch to connect to. static void ConnectVmToSwitch( string virtualMachineName, string switchName) { ManagementScope scope = new ManagementScope(@"root\virtualization\v2"); using (ManagementObject managementService = WmiUtilities.GetVirtualMachineManagementService(scope)) // // Find the Ethernet switch we want to connect to. // using (ManagementObject ethernetSwitch = NetworkingUtilities.FindEthernetSwitch(switchName, 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 Network Adapter device to the virtual machine. // using (ManagementObject syntheticAdapter = NetworkingUtilities.AddSyntheticAdapter(virtualMachine, scope)) // // Now that we have added a network adapter to the virtual machine we can configure its // connection settings. // using (ManagementObject connectionSettingsToAdd = NetworkingUtilities.GetDefaultEthernetPortAllocationSettingData(scope)) { connectionSettingsToAdd["Parent"] = syntheticAdapter.Path.Path; connectionSettingsToAdd["HostResource"] = new string[] { ethernetSwitch.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); } } } Console.WriteLine(string.Format(CultureInfo.CurrentCulture, "Successfully connected virtual machine '{0}' to switch '{1}'.", virtualMachineName, switchName)); } /// /// Disconnects the virtual machine from the specified switch. /// /// The name of the virtual machine. /// The name of the switch to disconnect from. static void DisconnectVmFromSwitch( string virtualMachineName, string switchName) { ManagementScope scope = new ManagementScope(@"root\virtualization\v2"); using (ManagementObject managementService = WmiUtilities.GetVirtualMachineManagementService(scope)) // // Find the Ethernet switch we want to disconnect from. // using (ManagementObject ethernetSwitch = NetworkingUtilities.FindEthernetSwitch(switchName, scope)) // // Find the virtual machine we want to disconnect. // using (ManagementObject virtualMachine = WmiUtilities.GetVirtualMachine(virtualMachineName, scope)) { // // Find all of the connections to this switch. // IList connectionsToSwitch = NetworkingUtilities.FindConnectionsToSwitch(virtualMachine, ethernetSwitch, scope); // // Now that we have found all of the connections to the switch we can go through and // disable each connection so that it is not connected to anything. Note that you can also // delete the connection object, but disabling the connection is sometimes preferable because // it preserves all of the connection's configuration options along with any metrics // associated with the connection. // try { foreach (ManagementObject connection in connectionsToSwitch) { connection["EnabledState"] = 3; // 3 means "Disabled" using (ManagementBaseObject inParams = managementService.GetMethodParameters("ModifyResourceSettings")) { inParams["ResourceSettings"] = new string[] { connection.GetText(TextFormat.WmiDtd20) }; using (ManagementBaseObject outParams = managementService.InvokeMethod("ModifyResourceSettings", inParams, null)) { WmiUtilities.ValidateOutput(outParams, scope); } } } } finally { // Dispose of the connectionsToSwitch. foreach (ManagementObject connection in connectionsToSwitch) { connection.Dispose(); } } } Console.WriteLine(string.Format(CultureInfo.CurrentCulture, "Successfully disconnected virtual machine '{0}' from switch '{1}'.", virtualMachineName, switchName)); } /// /// Modifies the connections of the specified virtual machine from the provided current switch /// to a new switch. /// /// The virtual machine name. /// The name of the switch we are disconnecting from. /// The name of the switch we are connecting to. static void ModifyConnection( string virtualMachineName, string currentSwitchName, string newSwitchName) { ManagementScope scope = new ManagementScope(@"root\virtualization\v2"); using (ManagementObject managementService = WmiUtilities.GetVirtualMachineManagementService(scope)) // // Find the Ethernet switch we want to disconnect from and the one we want to connect to. // using (ManagementObject currentEthernetSwitch = NetworkingUtilities.FindEthernetSwitch(currentSwitchName, scope)) using (ManagementObject newEthernetSwitch = NetworkingUtilities.FindEthernetSwitch(newSwitchName, scope)) // // Find the virtual machine we want to modify. // using (ManagementObject virtualMachine = WmiUtilities.GetVirtualMachine(virtualMachineName, scope)) { // // Find the connections to the current switch. // Note that this method finds all connections to the switch, including those connections // that are configured to dynamically select a switch from a switch resource pool and // reconfigures them to always connect to the new switch. If you only want to modify // connections that are configured with a hard-affinity to the original switch, modify the // NetworkingUtilities.FindConnectionsToSwitch method. // IList currentConnections = NetworkingUtilities.FindConnectionsToSwitch(virtualMachine, currentEthernetSwitch, scope); // // Set each connection to connect to the new switch. If the virtual machine is currently // running, then it will immediately connect to the new switch. If it is not running, then // it will connect to the switch when it is turned on. // try { foreach (ManagementObject connection in currentConnections) { connection["HostResource"] = new string[] { newEthernetSwitch.Path.Path }; using (ManagementBaseObject inParams = managementService.GetMethodParameters("ModifyResourceSettings")) { inParams["ResourceSettings"] = new string[] { connection.GetText(TextFormat.WmiDtd20) }; using (ManagementBaseObject outParams = managementService.InvokeMethod("ModifyResourceSettings", inParams, null)) { WmiUtilities.ValidateOutput(outParams, scope); } } } } finally { // Dispose of the connections. foreach (ManagementObject connection in currentConnections) { connection.Dispose(); } } } Console.WriteLine(string.Format(CultureInfo.CurrentCulture, "Successfully modified virtual machine '{0}' so that every connection to '{1}' is now " + "connected to '{2}'.", virtualMachineName, currentSwitchName, newSwitchName)); } /// /// Entry point for the connect virtual machine to switch sample. /// /// The command line arguments. internal static void ExecuteSample( string[] args) { if (args.Length == 0 || args[0] == "/?") { DisplayUsage(); return; } string sample = args[0]; if (string.Equals(sample, "Connect", StringComparison.OrdinalIgnoreCase)) { if (args.Length != 3) { DisplayUsage(); return; } try { ConnectVmToSwitch(args[1], args[2]); } catch (Exception ex) { Console.WriteLine("Failed to connect to the switch. Error message details:\n"); Console.WriteLine(ex.Message); } } else if (string.Equals(sample, "Disconnect", StringComparison.OrdinalIgnoreCase)) { if (args.Length != 3) { DisplayUsage(); return; } try { DisconnectVmFromSwitch(args[1], args[2]); } catch (Exception ex) { Console.WriteLine("Failed to disconnect the virtual machine from the switch. Error message details:\n"); Console.WriteLine(ex.Message); } } else if (string.Equals(sample, "Modify", StringComparison.OrdinalIgnoreCase)) { if (args.Length != 4) { Console.WriteLine("Must supply the names of both the switch we are disconnecting from and " + "the switch we are connecting to.\n"); Console.WriteLine("Example: ConnectVmToSwitch Modify MyVm CurrentSwitch NewSwitch"); return; } try { ModifyConnection(args[1], args[2], args[3]); } catch (Exception ex) { Console.WriteLine("Failed to modify the virtual machine's connection to the new switch. Error message details:\n"); Console.WriteLine(ex.Message); } } else { DisplayUsage(); } } /// /// Displays the command line usage for the sample. /// static void DisplayUsage() { Console.WriteLine("Usage: ConnectVmToSwitch (Connect|Disconnect|Modify) VirtualMachineName SwitchName [NewSwitchName]\n"); Console.WriteLine("When connecting, this sample adds a new Network Adapter to the virtual machine, " + "which requires that the virtual machine is off"); Console.WriteLine("When disconnecting, or modifying a current connection, the virtual machine can be running\n"); Console.WriteLine("The NewSwitchName parameter is only used when modifying a connection from the current SwitchName to the NewSwitchName\n"); Console.WriteLine("Example: ConnectVmToSwitch Connect MyVm MySwitch"); } } }