281 lines
9.1 KiB
C#
281 lines
9.1 KiB
C#
// Copyright (c) 2011, Outercurve Foundation.
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification,
|
|
// are permitted provided that the following conditions are met:
|
|
//
|
|
// - Redistributions of source code must retain the above copyright notice, this
|
|
// list of conditions and the following disclaimer.
|
|
//
|
|
// - Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
//
|
|
// - Neither the name of the Outercurve Foundation nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
using System;
|
|
using System.Management;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace WebsitePanel.VmConfig
|
|
{
|
|
public class SetupNetworkAdapterModule : IProvisioningModule
|
|
{
|
|
internal const string RegistryKey = @"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}";
|
|
#region IProvisioningModule Members
|
|
|
|
public ExecutionResult Run(ref ExecutionContext context)
|
|
{
|
|
ExecutionResult ret = new ExecutionResult();
|
|
ret.ResultCode = 0;
|
|
ret.ErrorMessage = null;
|
|
ret.RebootRequired = false;
|
|
|
|
context.ActivityDescription = "Configuring network adapter...";
|
|
context.Progress = 0;
|
|
if (!CheckParameter(context, "MAC"))
|
|
{
|
|
ProcessError(context, ret, null, 2, "Parameter 'MAC' is not specified");
|
|
return ret;
|
|
}
|
|
string macAddress = context.Parameters["MAC"];
|
|
if (!IsValidMACAddress(macAddress))
|
|
{
|
|
ProcessError(context, ret, null, 2, "Parameter 'MAC' has invalid format. It should be in 12:34:56:78:90:ab format.");
|
|
return ret;
|
|
}
|
|
|
|
string adapterId = null;
|
|
ManagementObject objAdapter = null;
|
|
ManagementObjectCollection objAdapters = null;
|
|
int attempts = 0;
|
|
try
|
|
{
|
|
WmiUtils wmi = new WmiUtils("root\\cimv2");
|
|
string query = string.Format("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE MACAddress = '{0}' AND IPEnabled = True", macAddress);
|
|
//try to find adapter for 10 times
|
|
while (true)
|
|
{
|
|
|
|
objAdapters = wmi.ExecuteQuery(query);
|
|
|
|
if (objAdapters.Count > 0)
|
|
{
|
|
foreach (ManagementObject adapter in objAdapters)
|
|
{
|
|
objAdapter = adapter;
|
|
adapterId = (string)adapter["SettingID"];
|
|
}
|
|
break;
|
|
|
|
}
|
|
if (attempts > 9)
|
|
{
|
|
ProcessError(context, ret, null, 2, "Network adapter not found");
|
|
return ret;
|
|
}
|
|
|
|
attempts++;
|
|
Log.WriteError(string.Format("Attempt #{0} to find network adapter failed!", attempts));
|
|
// wait 1 min
|
|
System.Threading.Thread.Sleep(60000);
|
|
//repeat loop
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ProcessError(context, ret, ex, 2, "Network adapter configuration error: ");
|
|
return ret;
|
|
}
|
|
|
|
if (CheckParameter(context, "EnableDHCP", "True"))
|
|
{
|
|
try
|
|
{
|
|
EnableDHCP(objAdapter);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ProcessError(context, ret, ex, 2, "DHCP error: ");
|
|
return ret;
|
|
}
|
|
|
|
}
|
|
else if (CheckParameter(context, "EnableDHCP", "False"))
|
|
{
|
|
if (!CheckParameter(context, "DefaultIPGateway"))
|
|
{
|
|
ProcessError(context, ret, null, 2, "Parameter 'DefaultIPGateway' is not specified");
|
|
return ret;
|
|
}
|
|
if (!CheckParameter(context, "IPAddress"))
|
|
{
|
|
ProcessError(context, ret, null, 2, "Parameter 'IPAddresses' is not specified");
|
|
return ret;
|
|
}
|
|
if (!CheckParameter(context, "SubnetMask"))
|
|
{
|
|
ProcessError(context, ret, null, 2, "Parameter 'SubnetMasks' is not specified");
|
|
return ret;
|
|
}
|
|
try
|
|
{
|
|
DisableDHCP(context, objAdapter);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ProcessError(context, ret, ex, 2, "Network adapter configuration error: ");
|
|
return ret;
|
|
}
|
|
}
|
|
if (CheckParameter(context, "PreferredDNSServer"))
|
|
{
|
|
try
|
|
{
|
|
SetDNSServer(context, objAdapter);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ProcessError(context, ret, ex, 2, "DNS error: ");
|
|
return ret;
|
|
}
|
|
|
|
}
|
|
context.Progress = 100;
|
|
return ret;
|
|
}
|
|
|
|
private void SetDNSServer(ExecutionContext context, ManagementObject objAdapter)
|
|
{
|
|
string[] dnsServers = ParseArray(context.Parameters["PreferredDNSServer"]);
|
|
Log.WriteStart("Configuring DNS...");
|
|
ManagementBaseObject objDNS = objAdapter.GetMethodParameters("SetDNSServerSearchOrder");
|
|
objDNS["DNSServerSearchOrder"] = dnsServers;
|
|
if (dnsServers.Length == 1 && dnsServers[0] == "0.0.0.0")
|
|
{
|
|
objDNS["DNSServerSearchOrder"] = new string[] { };
|
|
}
|
|
ManagementBaseObject objRet = objAdapter.InvokeMethod("SetDNSServerSearchOrder", objDNS, null);
|
|
Log.WriteEnd("DNS configured");
|
|
}
|
|
|
|
private static string[] ParseArray(string array)
|
|
{
|
|
if (string.IsNullOrEmpty(array))
|
|
throw new ArgumentException("array");
|
|
string[] ret = array.Split(';');
|
|
return ret;
|
|
}
|
|
|
|
private static void ProcessError(ExecutionContext context, ExecutionResult ret, Exception ex, int errorCode, string errorPrefix)
|
|
{
|
|
ret.ResultCode = errorCode;
|
|
ret.ErrorMessage = errorPrefix;
|
|
if (ex != null)
|
|
ret.ErrorMessage += ex.ToString();
|
|
Log.WriteError(ret.ErrorMessage);
|
|
context.Progress = 100;
|
|
}
|
|
|
|
private static void EnableDHCP(ManagementObject adapter)
|
|
{
|
|
Log.WriteStart("Enabling DHCP...");
|
|
object ret1 = adapter.InvokeMethod("EnableDHCP", new object[] { });
|
|
object ret2 = adapter.InvokeMethod("RenewDHCPLease", new object[] { });
|
|
Log.WriteEnd("DHCP enabled");
|
|
}
|
|
|
|
private static void DisableDHCP(ExecutionContext context, ManagementObject adapter)
|
|
{
|
|
string[] ipGateways = ParseArray(context.Parameters["DefaultIPGateway"]);
|
|
string[] ipAddresses = ParseArray(context.Parameters["IPAddress"]);
|
|
string[] subnetMasks = ParseArray(context.Parameters["SubnetMask"]);
|
|
if (subnetMasks.Length != ipAddresses.Length)
|
|
{
|
|
throw new ArgumentException("Number of Subnet Masks should be equal to IP Addresses");
|
|
}
|
|
|
|
ManagementBaseObject objNewIP = null;
|
|
ManagementBaseObject objSetIP = null;
|
|
ManagementBaseObject objNewGateway = null;
|
|
|
|
|
|
objNewIP = adapter.GetMethodParameters("EnableStatic");
|
|
objNewGateway = adapter.GetMethodParameters("SetGateways");
|
|
|
|
|
|
//Set DefaultGateway
|
|
objNewGateway["DefaultIPGateway"] = ipGateways;
|
|
int[] cost = new int[ipGateways.Length];
|
|
for (int i = 0; i < cost.Length; i++)
|
|
cost[i] = 1;
|
|
objNewGateway["GatewayCostMetric"] = cost;
|
|
|
|
|
|
//Set IPAddress and Subnet Mask
|
|
objNewIP["IPAddress"] = ipAddresses;
|
|
objNewIP["SubnetMask"] = subnetMasks;
|
|
|
|
Log.WriteStart("Configuring static IP...");
|
|
objSetIP = adapter.InvokeMethod("EnableStatic", objNewIP, null);
|
|
Log.WriteEnd("IP configured");
|
|
|
|
Log.WriteStart("Configuring default gateway...");
|
|
objSetIP = adapter.InvokeMethod("SetGateways", objNewGateway, null);
|
|
Log.WriteEnd("Default gateway configured");
|
|
}
|
|
|
|
private static bool IsValidMACAddress(string mac)
|
|
{
|
|
|
|
return Regex.IsMatch(mac, "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$");
|
|
}
|
|
|
|
|
|
|
|
private static bool CheckParameter(ExecutionContext context, string name)
|
|
{
|
|
return (context.Parameters.ContainsKey(name) && !string.IsNullOrEmpty(context.Parameters[name]));
|
|
}
|
|
|
|
private static bool CheckParameter(ExecutionContext context, string name, string value)
|
|
{
|
|
return (context.Parameters.ContainsKey(name) && context.Parameters[name] == value);
|
|
}
|
|
|
|
private void ChangeMACAddress(string adapterId, string mac)
|
|
{
|
|
string[] sets = RegistryUtils.GetRegistrySubKeys(RegistryKey);
|
|
foreach (string set in sets)
|
|
{
|
|
string key = string.Format("{0}\\{1}", RegistryKey, set);
|
|
string netCfgInstanceId = RegistryUtils.GetRegistryKeyStringValue(key, "NetCfgInstanceId");
|
|
if (netCfgInstanceId == adapterId)
|
|
{
|
|
Log.WriteStart("Changing MAC address...");
|
|
RegistryUtils.SetRegistryKeyStringValue(key, "NetworkAddress", mac);
|
|
Log.WriteEnd("MAC address has been changed successfully");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|