websitepanel/WebsitePanel/Sources/WebsitePanel.Providers.OS.Windows2012/Windows2012.cs
2014-11-19 05:45:10 -08:00

522 lines
19 KiB
C#

// Copyright (c) 2014, 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.IO;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Reflection;
using System.Globalization;
using Microsoft.Win32;
using WebsitePanel.Providers;
using WebsitePanel.Providers.HostedSolution;
using WebsitePanel.Providers.Utils;
using WebsitePanel.Server.Utils;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using WebsitePanel.Providers.Common;
using System.Runtime.InteropServices;
using System.Linq;
using WebsitePanel.Providers.DomainLookup;
using WebsitePanel.Providers.DNS;
namespace WebsitePanel.Providers.OS
{
public class Windows2012 : Windows2003
{
#region Properties
internal string PrimaryDomainController
{
get { return ProviderSettings["PrimaryDomainController"]; }
}
#endregion Properties
public override bool IsInstalled()
{
Server.Utils.OS.WindowsVersion version = WebsitePanel.Server.Utils.OS.GetVersion();
return version == WebsitePanel.Server.Utils.OS.WindowsVersion.WindowsServer2012
|| version == WebsitePanel.Server.Utils.OS.WindowsVersion.Windows8
|| version == WebsitePanel.Server.Utils.OS.WindowsVersion.WindowsServer2012R2
|| version == WebsitePanel.Server.Utils.OS.WindowsVersion.Windows81;
}
public override void SetQuotaLimitOnFolder(string folderPath, string shareNameDrive, QuotaType quotaType, string quotaLimit, int mode, string wmiUserName, string wmiPassword)
{
Log.WriteStart("SetQuotaLimitOnFolder");
Log.WriteInfo("FolderPath : {0}", folderPath);
Log.WriteInfo("ShareNameDrive : {0}", shareNameDrive);
Log.WriteInfo("QuotaLimit : {0}", quotaLimit);
string path = Path.Combine(shareNameDrive + @":\", folderPath);
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1)
{
if (!FileUtils.DirectoryExists(path))
FileUtils.CreateDirectory(path);
if (quotaLimit.Contains("-"))
{
RemoveOldQuotaOnFolder(runSpace, path);
}
else
{
var quota = CalculateQuota(quotaLimit);
switch (mode)
{
//deleting old quota and creating new one
case 0:
{
RemoveOldQuotaOnFolder(runSpace, path);
ChangeQuotaOnFolder(runSpace, "New-FsrmQuota", path, quotaType, quota);
break;
}
//modifying folder quota
case 1:
{
ChangeQuotaOnFolder(runSpace, "Set-FsrmQuota", path, quotaType, quota);
break;
}
}
}
}
}
catch (Exception ex)
{
Log.WriteError("SetQuotaLimitOnFolder", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
Log.WriteEnd("SetQuotaLimitOnFolder");
}
public override Quota GetQuotaOnFolder(string folderPath, string wmiUserName, string wmiPassword)
{
Log.WriteStart("GetQuotaLimitOnFolder");
Log.WriteInfo("FolderPath : {0}", folderPath);
Runspace runSpace = null;
Quota quota = new Quota();
try
{
runSpace = OpenRunspace();
if (folderPath.IndexOfAny(Path.GetInvalidPathChars()) == -1)
{
Command cmd = new Command("Get-FsrmQuota");
cmd.Parameters.Add("Path", folderPath);
var result = ExecuteShellCommand(runSpace, cmd, false);
if (result.Count > 0)
{
quota.Size = ConvertBytesToMB(Convert.ToInt64(GetPSObjectProperty(result[0], "Size")));
quota.QuotaType = Convert.ToBoolean(GetPSObjectProperty(result[0], "SoftLimit")) ? QuotaType.Soft : QuotaType.Hard;
quota.Usage = ConvertBytesToMB(Convert.ToInt64(GetPSObjectProperty(result[0], "usage")));
}
}
}
catch (Exception ex)
{
Log.WriteError("GetQuotaLimitOnFolder", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
Log.WriteEnd("GetQuotaLimitOnFolder");
return quota;
}
public override Dictionary<string, Quota> GetQuotasForOrganization(string folderPath, string wmiUserName, string wmiPassword)
{
Log.WriteStart("GetQuotasLimitsForOrganization");
Runspace runSpace = null;
Quota quota = null;
var quotas = new Dictionary<string, Quota>();
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Get-FsrmQuota");
cmd.Parameters.Add("Path", folderPath + "\\*");
var result = ExecuteShellCommand(runSpace, cmd, false);
if (result.Count > 0)
{
foreach (var element in result)
{
quota = new Quota();
quota.Size = ConvertBytesToMB(Convert.ToInt64(GetPSObjectProperty(element, "Size")));
quota.QuotaType = Convert.ToBoolean(GetPSObjectProperty(element, "SoftLimit")) ? QuotaType.Soft : QuotaType.Hard;
quota.Usage = ConvertBytesToMB(Convert.ToInt64(GetPSObjectProperty(element, "usage")));
quotas.Add(Convert.ToString(GetPSObjectProperty(element, "Path")), quota);
}
}
}
catch (Exception ex)
{
Log.WriteError("GetQuotasLimitsForOrganization", ex);
throw;
}
finally
{
CloseRunspace(runSpace);
}
Log.WriteEnd("GetQuotasLimitsForOrganization");
return quotas;
}
public UInt64 CalculateQuota(string quota)
{
UInt64 OneKb = 1024;
UInt64 OneMb = OneKb * 1024;
UInt64 OneGb = OneMb * 1024;
UInt64 result = 0;
// Quota Unit
if (quota.ToLower().Contains("gb"))
{
result = UInt64.Parse(quota.ToLower().Replace("gb", "")) * OneGb;
}
else if (quota.ToLower().Contains("mb"))
{
result = UInt64.Parse(quota.ToLower().Replace("mb", "")) * OneMb;
}
else
{
result = UInt64.Parse(quota.ToLower().Replace("kb", "")) * OneKb;
}
return result;
}
public int ConvertMegaBytesToGB(int megabytes)
{
int OneGb = 1024;
if (megabytes == -1)
return megabytes;
return (int)(megabytes/ OneGb);
}
public int ConvertBytesToMB(long bytes)
{
int OneKb = 1024;
int OneMb = OneKb * 1024;
if (bytes == 0)
return 0;
return (int)(bytes / OneMb);
}
public void RemoveOldQuotaOnFolder(Runspace runSpace, string path)
{
try
{
runSpace = OpenRunspace();
if (!string.IsNullOrEmpty(path))
{
Command cmd = new Command("Remove-FsrmQuota");
cmd.Parameters.Add("Path", path);
ExecuteShellCommand(runSpace, cmd, false);
}
}
catch { /* do nothing */ }
}
public void ChangeQuotaOnFolder(Runspace runSpace, string command, string path, QuotaType quotaType, UInt64 quota)
{
Command cmd = new Command(command);
cmd.Parameters.Add("Path", path);
cmd.Parameters.Add("Size", quota);
if (quotaType == QuotaType.Soft)
{
cmd.Parameters.Add("SoftLimit", true);
}
ExecuteShellCommand(runSpace, cmd, false);
}
#region Domain LookUp
public override DnsRecordInfo[] GetDomainDnsRecords(string domain, string dnsServer, DnsRecordType recordType)
{
List<DnsRecordInfo> records = new List<DnsRecordInfo>();
Runspace runSpace = null;
try
{
runSpace = OpenRunspace();
Command cmd = new Command("Resolve-DnsName");
cmd.Parameters.Add("Name", domain);
cmd.Parameters.Add("Server", dnsServer);
cmd.Parameters.Add("Type", recordType.ToString());
var dnsRecordsPs = ExecuteShellCommand(runSpace, cmd, false);
if (dnsRecordsPs != null)
{
foreach (var dnsRecordPs in dnsRecordsPs)
{
DnsRecordInfo newRecord = null;
switch (recordType)
{
case DnsRecordType.MX: { newRecord = CreateDnsRecordFromPsObject(dnsRecordPs, "NameExchange"); break; }
case DnsRecordType.NS: { newRecord = CreateDnsRecordFromPsObject(dnsRecordPs, "NameHost"); break; }
default: continue;
}
if (newRecord != null)
{
newRecord.DnsServer = dnsServer;
newRecord.RecordType = recordType;
records.Add(newRecord);
}
}
}
}
finally
{
CloseRunspace(runSpace);
}
return records.ToArray();
}
private DnsRecordInfo CreateDnsRecordFromPsObject(PSObject psObject, string valueName)
{
if (!psObject.Members.Any(x => x.Name == valueName))
{
return null;
}
var dnsRecord = new DnsRecordInfo
{
Value = Convert.ToString(GetPSObjectProperty(psObject, valueName)),
};
return dnsRecord;
}
#endregion
#region PowerShell integration
private static InitialSessionState session = null;
internal virtual Runspace OpenRunspace()
{
Log.WriteStart("OpenRunspace");
if (session == null)
{
session = InitialSessionState.CreateDefault();
session.ImportPSModule(new string[] { "FileServerResourceManager" });
}
Runspace runSpace = RunspaceFactory.CreateRunspace(session);
//
runSpace.Open();
//
runSpace.SessionStateProxy.SetVariable("ConfirmPreference", "none");
Log.WriteEnd("OpenRunspace");
return runSpace;
}
internal void CloseRunspace(Runspace runspace)
{
try
{
if (runspace != null && runspace.RunspaceStateInfo.State == RunspaceState.Opened)
{
runspace.Close();
}
}
catch (Exception ex)
{
Log.WriteError("Runspace error", ex);
}
}
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd)
{
return ExecuteShellCommand(runSpace, cmd, true);
}
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController)
{
object[] errors;
return ExecuteShellCommand(runSpace, cmd, useDomainController, out errors);
}
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, out object[] errors)
{
return ExecuteShellCommand(runSpace, cmd, true, out errors);
}
internal Collection<PSObject> ExecuteShellCommand(Runspace runSpace, Command cmd, bool useDomainController, out object[] errors)
{
Log.WriteStart("ExecuteShellCommand");
List<object> errorList = new List<object>();
if (useDomainController)
{
CommandParameter dc = new CommandParameter("DomainController", PrimaryDomainController);
if (!cmd.Parameters.Contains(dc))
{
cmd.Parameters.Add(dc);
}
}
Collection<PSObject> results = null;
// Create a pipeline
Pipeline pipeLine = runSpace.CreatePipeline();
using (pipeLine)
{
// Add the command
pipeLine.Commands.Add(cmd);
// Execute the pipeline and save the objects returned.
results = pipeLine.Invoke();
// Log out any errors in the pipeline execution
// NOTE: These errors are NOT thrown as exceptions!
// Be sure to check this to ensure that no errors
// happened while executing the command.
if (pipeLine.Error != null && pipeLine.Error.Count > 0)
{
foreach (object item in pipeLine.Error.ReadToEnd())
{
errorList.Add(item);
string errorMessage = string.Format("Invoke error: {0}", item);
Log.WriteWarning(errorMessage);
}
}
}
pipeLine = null;
errors = errorList.ToArray();
Log.WriteEnd("ExecuteShellCommand");
return results;
}
internal object GetPSObjectProperty(PSObject obj, string name)
{
return obj.Members[name].Value;
}
/// <summary>
/// Returns the identity of the object from the shell execution result
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
internal string GetResultObjectIdentity(Collection<PSObject> result)
{
Log.WriteStart("GetResultObjectIdentity");
if (result == null)
throw new ArgumentNullException("result", "Execution result is not specified");
if (result.Count < 1)
throw new ArgumentException("Execution result is empty", "result");
if (result.Count > 1)
throw new ArgumentException("Execution result contains more than one object", "result");
PSMemberInfo info = result[0].Members["Identity"];
if (info == null)
throw new ArgumentException("Execution result does not contain Identity property", "result");
string ret = info.Value.ToString();
Log.WriteEnd("GetResultObjectIdentity");
return ret;
}
internal string GetResultObjectDN(Collection<PSObject> result)
{
Log.WriteStart("GetResultObjectDN");
if (result == null)
throw new ArgumentNullException("result", "Execution result is not specified");
if (result.Count < 1)
throw new ArgumentException("Execution result does not contain any object");
if (result.Count > 1)
throw new ArgumentException("Execution result contains more than one object");
PSMemberInfo info = result[0].Members["DistinguishedName"];
if (info == null)
throw new ArgumentException("Execution result does not contain DistinguishedName property", "result");
string ret = info.Value.ToString();
Log.WriteEnd("GetResultObjectDN");
return ret;
}
#endregion
}
}