CP-4816: Initial commit to git repo
Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
281
CFUValidator/CFUValidator.cs
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using CFUValidator.CommandLineOptions;
|
||||||
|
using CFUValidator.OutputDecorators;
|
||||||
|
using CFUValidator.Updates;
|
||||||
|
using CFUValidator.Validators;
|
||||||
|
using Moq;
|
||||||
|
using XenAdmin;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdminTests;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
namespace CFUValidator
|
||||||
|
{
|
||||||
|
public class CFUValidationException : Exception
|
||||||
|
{
|
||||||
|
public CFUValidationException(string message) : base(message){}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CFUValidator
|
||||||
|
{
|
||||||
|
private readonly MockObjectManager mom = new MockObjectManager();
|
||||||
|
private readonly XmlRetrieverFactory xmlFactory = new XmlRetrieverFactory();
|
||||||
|
private const string id = "id";
|
||||||
|
private string XmlLocation { get; set; }
|
||||||
|
private string ServerVersion { get; set; }
|
||||||
|
private OptionUsage UrlOrFile { get; set; }
|
||||||
|
private List<string> InstalledHotfixes { get; set; }
|
||||||
|
private bool CheckHotfixContents{ get; set; }
|
||||||
|
|
||||||
|
public CFUValidator(OptionUsage urlOrFile, string xmlLocation, string serverVersion,
|
||||||
|
List<string> installedHotfixes, bool checkHotfixContents)
|
||||||
|
{
|
||||||
|
if(urlOrFile != OptionUsage.File && urlOrFile != OptionUsage.Url)
|
||||||
|
throw new ArgumentException("urlOrFile option should be either File or Url");
|
||||||
|
|
||||||
|
mom.CreateNewConnection(id);
|
||||||
|
ConnectionsManager.XenConnections.AddRange(mom.AllConnections);
|
||||||
|
XmlLocation = xmlLocation;
|
||||||
|
ServerVersion = serverVersion;
|
||||||
|
InstalledHotfixes = installedHotfixes;
|
||||||
|
UrlOrFile = urlOrFile;
|
||||||
|
CheckHotfixContents = checkHotfixContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
List<XenServerPatch> xenServerPatches;
|
||||||
|
List<XenServerVersion> xenServerVersions;
|
||||||
|
List<XenCenterVersion> xenCenterVersions;
|
||||||
|
|
||||||
|
Status = "Getting check for updates XML from " + XmlLocation + "...";
|
||||||
|
ReadCheckForUpdatesXML(out xenServerPatches, out xenServerVersions, out xenCenterVersions);
|
||||||
|
|
||||||
|
List<string> versionToCheck = GetVersionToCheck(xenServerVersions);
|
||||||
|
|
||||||
|
foreach (string ver in versionToCheck)
|
||||||
|
{
|
||||||
|
ServerVersion = ver;
|
||||||
|
RunTestsForGivenServerVersion(xenServerVersions, xenServerPatches, xenCenterVersions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<string> GetVersionToCheck(List<XenServerVersion> xenServerVersions)
|
||||||
|
{
|
||||||
|
if(ServerVersion == CFUCommandLineOptionManager.AllVersions)
|
||||||
|
return xenServerVersions.ConvertAll(i => i.Version.ToString()).Distinct().ToList();
|
||||||
|
|
||||||
|
return new List<string>{ServerVersion};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunTestsForGivenServerVersion(List<XenServerVersion> xenServerVersions,
|
||||||
|
List<XenServerPatch> xenServerPatches,
|
||||||
|
List<XenCenterVersion> xenCenterVersions)
|
||||||
|
{
|
||||||
|
CheckProvidedVersionNumber(xenServerVersions);
|
||||||
|
|
||||||
|
Status = String.Format("Generating server {0} mock-ups...", ServerVersion);
|
||||||
|
SetupMocks(xenServerPatches, xenServerVersions);
|
||||||
|
|
||||||
|
Status = "Determining XenCenter update required...";
|
||||||
|
XenCenterUpdateAlert xcupdateAlert = XenAdmin.Core.Updates.NewXenCenterVersionAlert(xenCenterVersions, new Version(ServerVersion), false);
|
||||||
|
|
||||||
|
Status = "Determining XenServer update required...";
|
||||||
|
XenServerUpdateAlert updateAlert = XenAdmin.Core.Updates.NewServerVersionAlert(xenServerVersions, false);
|
||||||
|
|
||||||
|
Status = "Determining patches required...";
|
||||||
|
List<XenServerPatchAlert> patchAlerts = XenAdmin.Core.Updates.NewServerPatchesAlerts(xenServerVersions,
|
||||||
|
xenServerPatches, false);
|
||||||
|
|
||||||
|
//Build patch checks list
|
||||||
|
List<AlertFeatureValidator> validators = new List<AlertFeatureValidator>
|
||||||
|
{
|
||||||
|
new CorePatchDetailsValidator(patchAlerts),
|
||||||
|
new PatchURLValidator(patchAlerts),
|
||||||
|
new ZipContentsValidator(patchAlerts)
|
||||||
|
};
|
||||||
|
|
||||||
|
Status = "Running patch check(s), this may take some time...";
|
||||||
|
RunValidators(validators);
|
||||||
|
|
||||||
|
Status = "Generating summary...";
|
||||||
|
GeneratePatchSummary(patchAlerts, validators, updateAlert, xcupdateAlert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckProvidedVersionNumber(List<XenServerVersion> xenServerVersions)
|
||||||
|
{
|
||||||
|
if (!xenServerVersions.Any(v => v.Version.ToString() == ServerVersion))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder("\nAvailable versions are:\n");
|
||||||
|
xenServerVersions.ConvertAll(i=>i.Version.ToString()).Distinct().ToList().ForEach(v=>sb.AppendLine(v));
|
||||||
|
throw new CFUValidationException("Could not find the version in the check for updates file: " + ServerVersion + sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Output { get; private set; }
|
||||||
|
|
||||||
|
#region Status event code
|
||||||
|
public delegate void StatusChangedHandler(object sender, EventArgs e);
|
||||||
|
|
||||||
|
public event StatusChangedHandler StatusChanged;
|
||||||
|
|
||||||
|
protected virtual void OnStatusChanged()
|
||||||
|
{
|
||||||
|
if (StatusChanged != null)
|
||||||
|
StatusChanged(Status, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string status;
|
||||||
|
private string Status
|
||||||
|
{
|
||||||
|
get { return status; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
status = value;
|
||||||
|
OnStatusChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void RunValidators(List<AlertFeatureValidator> validators)
|
||||||
|
{
|
||||||
|
int count = 1;
|
||||||
|
foreach (AlertFeatureValidator validator in validators)
|
||||||
|
{
|
||||||
|
if (validator is ZipContentsValidator && !CheckHotfixContents)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Status = count++ + ". " + validator.Description + "...";
|
||||||
|
|
||||||
|
validator.StatusChanged += validator_StatusChanged;
|
||||||
|
validator.Validate();
|
||||||
|
validator.StatusChanged -= validator_StatusChanged;
|
||||||
|
}
|
||||||
|
Status = "Validator checks complete";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validator_StatusChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Status = sender as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GeneratePatchSummary(List<XenServerPatchAlert> alerts, List<AlertFeatureValidator> validators,
|
||||||
|
XenServerUpdateAlert updateAlert, XenCenterUpdateAlert xcupdateAlert)
|
||||||
|
{
|
||||||
|
OuputComponent oc = new OutputTextOuputComponent(XmlLocation, ServerVersion);
|
||||||
|
XenCenterUpdateDecorator xcud = new XenCenterUpdateDecorator(oc, xcupdateAlert);
|
||||||
|
XenServerUpdateDecorator xsud = new XenServerUpdateDecorator(xcud, updateAlert);
|
||||||
|
PatchAlertDecorator pad = new PatchAlertDecorator(xsud, alerts);
|
||||||
|
AlertFeatureValidatorDecorator afdCoreFields = new AlertFeatureValidatorDecorator(pad,
|
||||||
|
validators.First(v => v is CorePatchDetailsValidator),
|
||||||
|
"Core fields in patch checks:");
|
||||||
|
AlertFeatureValidatorDecorator afdPatchUrl = new AlertFeatureValidatorDecorator(afdCoreFields,
|
||||||
|
validators.First(v => v is PatchURLValidator),
|
||||||
|
"Required patch URL checks:");
|
||||||
|
AlertFeatureValidatorDecorator afdZipContents = new AlertFeatureValidatorDecorator(afdPatchUrl,
|
||||||
|
validators.First(v => v is ZipContentsValidator),
|
||||||
|
"Required patch zip content checks:");
|
||||||
|
|
||||||
|
if(CheckHotfixContents)
|
||||||
|
Output = afdZipContents.Generate().Insert(0, Output).ToString();
|
||||||
|
else
|
||||||
|
Output = afdPatchUrl.Generate().Insert(0, Output).ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadCheckForUpdatesXML(out List<XenServerPatch> patches, out List<XenServerVersion> versions, out List<XenCenterVersion> xcVersions)
|
||||||
|
{
|
||||||
|
ICheckForUpdatesXMLSource checkForUpdates = xmlFactory.GetAction(UrlOrFile, XmlLocation);
|
||||||
|
checkForUpdates.RunAsync();
|
||||||
|
|
||||||
|
ConsoleSpinner spinner = new ConsoleSpinner();
|
||||||
|
while(!checkForUpdates.IsCompleted)
|
||||||
|
{
|
||||||
|
spinner.Turn(checkForUpdates.PercentComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkForUpdates.ErrorRaised != null)
|
||||||
|
throw checkForUpdates.ErrorRaised;
|
||||||
|
|
||||||
|
patches = checkForUpdates.XenServerPatches;
|
||||||
|
versions = checkForUpdates.XenServerVersions;
|
||||||
|
xcVersions = checkForUpdates.XenCenterVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupMocks(List<XenServerPatch> xenServerPatches, List<XenServerVersion> xenServerVersions)
|
||||||
|
{
|
||||||
|
Mock<Host> master = mom.NewXenObject<Host>(id);
|
||||||
|
Mock<Pool> pool = mom.NewXenObject<Pool>(id);
|
||||||
|
XenRef<Host> masterRef = new XenRef<Host>("ref");
|
||||||
|
pool.Setup(p => p.master).Returns(masterRef);
|
||||||
|
mom.MockCacheFor(id).Setup(c => c.Resolve(It.IsAny<XenRef<Pool>>())).Returns(pool.Object);
|
||||||
|
mom.MockConnectionFor(id).Setup(c => c.Resolve(masterRef)).Returns(master.Object);
|
||||||
|
master.Setup(h => h.software_version).Returns(new Dictionary<string, string>());
|
||||||
|
master.Setup(h => h.ProductVersion).Returns(ServerVersion);
|
||||||
|
master.Setup(h => h.AppliedPatches()).Returns(GenerateMockPoolPatches(xenServerPatches));
|
||||||
|
|
||||||
|
//Currently build number will be referenced first so if it's present hook it up
|
||||||
|
string buildNumber = xenServerVersions.First(v => v.Version.ToString() == ServerVersion).BuildNumber;
|
||||||
|
master.Setup(h=>h.BuildNumberRaw).Returns(buildNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Pool_patch> GenerateMockPoolPatches(List<XenServerPatch> xenServerPatches)
|
||||||
|
{
|
||||||
|
List<Pool_patch> patches = new List<Pool_patch>();
|
||||||
|
|
||||||
|
foreach (string installedHotfix in InstalledHotfixes)
|
||||||
|
{
|
||||||
|
string hotfix = installedHotfix;
|
||||||
|
XenServerPatch match = xenServerPatches.Find(m => m.Name.Contains(hotfix));
|
||||||
|
|
||||||
|
if(match == null)
|
||||||
|
throw new CFUValidationException("No patch could be found in the XML matching " + hotfix);
|
||||||
|
|
||||||
|
Mock<Pool_patch> pp = mom.NewXenObject<Pool_patch>(id);
|
||||||
|
pp.Setup(p => p.uuid).Returns(match.Uuid);
|
||||||
|
patches.Add(pp.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return patches;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
147
CFUValidator/CFUValidator.csproj
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{39308480-78C3-40B4-924D-06914F343ACD}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>CFUValidator</RootNamespace>
|
||||||
|
<AssemblyName>CFUValidator</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\NUnit\Moq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml.Linq">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data.DataSetExtensions">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="CFUValidator.cs" />
|
||||||
|
<Compile Include="CommandLineOptions\CommandLineArgument.cs" />
|
||||||
|
<Compile Include="CommandLineOptions\CFUCommandLineOptionManager.cs" />
|
||||||
|
<Compile Include="CommandLineOptions\CommandLineParser.cs" />
|
||||||
|
<Compile Include="ConsoleSpinner.cs" />
|
||||||
|
<Compile Include="OutputDecorators\AlertFeatureValidatorDecorator.cs" />
|
||||||
|
<Compile Include="OutputDecorators\OuputComponent.cs" />
|
||||||
|
<Compile Include="OutputDecorators\Decorator.cs" />
|
||||||
|
<Compile Include="OutputDecorators\PatchAlertDecorator.cs" />
|
||||||
|
<Compile Include="OutputDecorators\XenCenterUpdateDecorator.cs" />
|
||||||
|
<Compile Include="OutputDecorators\XenServerUpdateDecorator.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Updates\AlternativeUrlDownloadUpdatesXmlSourceAction.cs" />
|
||||||
|
<Compile Include="Updates\ReadFromFileUpdatesXmlSource.cs" />
|
||||||
|
<Compile Include="Updates\ICheckForUpdatesXMLSource.cs" />
|
||||||
|
<Compile Include="Updates\XmlRetrieverFactory.cs" />
|
||||||
|
<Compile Include="Validators\AlertFeatureValidator.cs" />
|
||||||
|
<Compile Include="Validators\CorePatchDetailsValidator.cs" />
|
||||||
|
<Compile Include="Validators\PatchURLValidator.cs" />
|
||||||
|
<Compile Include="Validators\ZipContentsValidator.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Windows Installer 3.1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\XenAdminTests\XenAdminTests.csproj">
|
||||||
|
<Project>{21B9482C-D255-40D5-ABA7-C8F00F99547C}</Project>
|
||||||
|
<Name>XenAdminTests</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\XenAdmin\XenAdmin.csproj">
|
||||||
|
<Project>{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}</Project>
|
||||||
|
<Name>XenAdmin</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\XenCenterLib\XenCenterLib.csproj">
|
||||||
|
<Project>{9861DFA1-B41F-432D-A43F-226257DEBBB9}</Project>
|
||||||
|
<Name>XenCenterLib</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\XenModel\XenModel.csproj">
|
||||||
|
<Project>{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}</Project>
|
||||||
|
<Name>XenModel</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
131
CFUValidator/CommandLineOptions/CFUCommandLineOptionManager.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CFUValidator.CommandLineOptions
|
||||||
|
{
|
||||||
|
internal class CFUCommandLineOptionManager
|
||||||
|
{
|
||||||
|
private readonly List<CommandLineArgument> clas;
|
||||||
|
public CFUCommandLineOptionManager(List<CommandLineArgument> clas)
|
||||||
|
{
|
||||||
|
this.clas = clas;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Not to be called from inside this class to keep IoC
|
||||||
|
public static List<CommandLineArgument> EmptyArguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new List<CommandLineArgument>
|
||||||
|
{
|
||||||
|
new CommandLineArgument( OptionUsage.Help, 'h', "Display this help" ),
|
||||||
|
new CommandLineArgument( OptionUsage.CheckZipContents, 'c', "Optionally check the zip contents of the hotfixes" ),
|
||||||
|
new CommandLineArgument( OptionUsage.Url, 'u', "<URL to extract XML from> Cannot be used with -f flag"),
|
||||||
|
new CommandLineArgument( OptionUsage.File, 'f', "<File name to extract XML from> Cannot be used with -u flag" ),
|
||||||
|
new CommandLineArgument( OptionUsage.ServerVersion, 's', "<Server version to test> eg. 6.0.2" ),
|
||||||
|
new CommandLineArgument( OptionUsage.Hotfix, 'p', "<List of patches/hotfixes that server has> eg. XS602E001 (space delimited)" )
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AllVersions = "999.999.999";
|
||||||
|
|
||||||
|
public string XmlLocation { get { return GetFileUsageCLA().Options.First(); } }
|
||||||
|
|
||||||
|
public bool CheckHotfixContents { get { return clas.First(c => c.Usage == OptionUsage.CheckZipContents).IsActiveOption; } }
|
||||||
|
|
||||||
|
private CommandLineArgument GetFileUsageCLA()
|
||||||
|
{
|
||||||
|
CommandLineArgument claForUrl = clas.First(c => c.Usage == OptionUsage.Url);
|
||||||
|
CommandLineArgument claForFle = clas.First(c => c.Usage == OptionUsage.File);
|
||||||
|
if (claForUrl.IsActiveOption && claForFle.IsActiveOption)
|
||||||
|
throw new CFUValidationException(String.Format("Switches '-{0}' and '-{1}' cannot be used at the same time", claForFle.Switch, claForUrl.Switch));
|
||||||
|
|
||||||
|
if (!claForUrl.IsActiveOption && !claForFle.IsActiveOption)
|
||||||
|
throw new CFUValidationException(String.Format("You must provide either option '-{0}' or '-{1}'", claForFle.Switch, claForUrl.Switch));
|
||||||
|
|
||||||
|
if (claForFle.IsActiveOption)
|
||||||
|
return claForFle;
|
||||||
|
|
||||||
|
return claForUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionUsage FileSource { get {return GetFileUsageCLA().Usage; } }
|
||||||
|
|
||||||
|
public string ServerVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CommandLineArgument cla = clas.First(c => c.Usage == OptionUsage.ServerVersion);
|
||||||
|
return !cla.IsActiveOption ? AllVersions : cla.Options.First();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> InstalledHotfixes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CommandLineArgument cla = clas.First(c => c.Usage == OptionUsage.Hotfix);
|
||||||
|
if (!cla.IsActiveOption)
|
||||||
|
return new List<string>();
|
||||||
|
return cla.Options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsHelpRequired
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return clas.First(c => c.Usage == OptionUsage.Help).IsActiveOption;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Help
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder("Execute the command with the following command line options\n\nOptions:\n");
|
||||||
|
foreach (CommandLineArgument cla in clas.OrderBy(c => c.Switch))
|
||||||
|
{
|
||||||
|
sb.AppendLine(String.Format("-{0} {1}", cla.Switch, cla.Description));
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
63
CFUValidator/CommandLineOptions/CommandLineArgument.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CFUValidator.CommandLineOptions
|
||||||
|
{
|
||||||
|
public enum OptionUsage
|
||||||
|
{
|
||||||
|
Help,
|
||||||
|
Url,
|
||||||
|
File,
|
||||||
|
Hotfix,
|
||||||
|
ServerVersion,
|
||||||
|
CheckZipContents
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandLineArgument
|
||||||
|
{
|
||||||
|
public CommandLineArgument(OptionUsage usage, char commandSwitch, string description)
|
||||||
|
{
|
||||||
|
Switch = commandSwitch;
|
||||||
|
Description = description;
|
||||||
|
Usage = usage;
|
||||||
|
Options = null;
|
||||||
|
IsActiveOption = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionUsage Usage { get; private set; }
|
||||||
|
public char Switch { get; private set; }
|
||||||
|
public List<string> Options { get; set; }
|
||||||
|
public string Description { get; private set; }
|
||||||
|
public bool IsActiveOption { get; set; }
|
||||||
|
}
|
||||||
|
}
|
72
CFUValidator/CommandLineOptions/CommandLineParser.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace CFUValidator.CommandLineOptions
|
||||||
|
{
|
||||||
|
public class CommandLineParser
|
||||||
|
{
|
||||||
|
private readonly string[] args;
|
||||||
|
|
||||||
|
public List<CommandLineArgument> ParsedArguments { get; private set; }
|
||||||
|
|
||||||
|
public CommandLineParser(string[] args, List<CommandLineArgument> argsToParse)
|
||||||
|
{
|
||||||
|
this.args = args;
|
||||||
|
ParsedArguments = argsToParse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Parse()
|
||||||
|
{
|
||||||
|
string[] recastArgs = Regex.Split(string.Join(" ", args).Trim(), @"(?=[-])(?<=[ ])");
|
||||||
|
foreach (string arg in recastArgs)
|
||||||
|
{
|
||||||
|
if(String.IsNullOrEmpty(arg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string optionSwitch = Regex.Match(arg, "[-]{1}[a-z]{1}").Value.Trim();
|
||||||
|
char switchChar = Convert.ToChar(optionSwitch.Substring(1, 1));
|
||||||
|
string[] splitArgs = arg.Replace(optionSwitch, "").Trim().Split(' ');
|
||||||
|
|
||||||
|
CommandLineArgument cla = ParsedArguments.FirstOrDefault(c => c.Switch == switchChar);
|
||||||
|
if (cla != null)
|
||||||
|
{
|
||||||
|
cla.Options = splitArgs.Where(s=>!String.IsNullOrEmpty(s)).ToList();
|
||||||
|
cla.IsActiveOption = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
CFUValidator/ConsoleSpinner.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Threading;
|
||||||
|
|
||||||
|
namespace CFUValidator
|
||||||
|
{
|
||||||
|
public class ConsoleSpinner
|
||||||
|
{
|
||||||
|
int counter;
|
||||||
|
private const string working = "Working ";
|
||||||
|
|
||||||
|
public ConsoleSpinner()
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Turn()
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
switch (counter % 4)
|
||||||
|
{
|
||||||
|
case 0: WriteAtOrigin(working + "/"); break;
|
||||||
|
case 1: WriteAtOrigin(working + "-"); break;
|
||||||
|
case 2: WriteAtOrigin(working + "\\"); break;
|
||||||
|
case 3: WriteAtOrigin(working + "|"); break;
|
||||||
|
}
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Turn(double percentageComplete)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
switch (counter % 4)
|
||||||
|
{
|
||||||
|
case 0: WriteAtOrigin(working + "/ (" + percentageComplete + "%)"); break;
|
||||||
|
case 1: WriteAtOrigin(working + "- (" + percentageComplete + "%)"); break;
|
||||||
|
case 2: WriteAtOrigin(working + "\\ (" + percentageComplete + "%)"); break;
|
||||||
|
case 3: WriteAtOrigin(working + "| (" + percentageComplete + "%)"); break;
|
||||||
|
}
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteAtOrigin(string toWrite)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.SetCursorPosition(0, Console.CursorTop);
|
||||||
|
Console.Write(toWrite);
|
||||||
|
Console.SetCursorPosition(0, Console.CursorTop);
|
||||||
|
}
|
||||||
|
catch (SystemException){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Text;
|
||||||
|
using CFUValidator.Validators;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
class AlertFeatureValidatorDecorator : Decorator
|
||||||
|
{
|
||||||
|
private readonly string header;
|
||||||
|
private readonly AlertFeatureValidator validator;
|
||||||
|
public AlertFeatureValidatorDecorator(OuputComponent ouputComponent, AlertFeatureValidator validator, string header)
|
||||||
|
{
|
||||||
|
SetComponent(ouputComponent);
|
||||||
|
this.validator = validator;
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
StringBuilder sb = base.Generate();
|
||||||
|
sb.AppendLine(header);
|
||||||
|
if (validator.ErrorsFound)
|
||||||
|
validator.Results.ForEach(v => sb.AppendLine(v));
|
||||||
|
else
|
||||||
|
sb.AppendLine("all OK");
|
||||||
|
return sb.AppendLine(String.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
CFUValidator/OutputDecorators/Decorator.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Text;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
abstract class Decorator : OuputComponent
|
||||||
|
{
|
||||||
|
private OuputComponent ouputComponent;
|
||||||
|
public void SetComponent(OuputComponent ouputComponentToSet)
|
||||||
|
{
|
||||||
|
ouputComponent = ouputComponentToSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
if(ouputComponent != null)
|
||||||
|
return ouputComponent.Generate();
|
||||||
|
|
||||||
|
throw new NullReferenceException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
CFUValidator/OutputDecorators/OuputComponent.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
public abstract class OuputComponent
|
||||||
|
{
|
||||||
|
public abstract StringBuilder Generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OutputTextOuputComponent : OuputComponent
|
||||||
|
{
|
||||||
|
private readonly string location;
|
||||||
|
private readonly string serverVersion;
|
||||||
|
public OutputTextOuputComponent(string location, string serverVersion)
|
||||||
|
{
|
||||||
|
this.location = location;
|
||||||
|
this.serverVersion = serverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
string header = String.Format("\nSummary for server version {0}, XML from {1}, generated on {2}\n\n", serverVersion,
|
||||||
|
location, Date.ToLocalTime());
|
||||||
|
return new StringBuilder(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime Date
|
||||||
|
{
|
||||||
|
get { return DateTime.Now; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
CFUValidator/OutputDecorators/PatchAlertDecorator.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
|
||||||
|
class PatchAlertDecorator : Decorator
|
||||||
|
{
|
||||||
|
private readonly List<XenServerPatchAlert> alerts;
|
||||||
|
private const string header = "Patches required ({0}):";
|
||||||
|
private const string zeroResults = "No patches required";
|
||||||
|
private const string hotfixRegex = "XS[0-9]+E[A-Z]*[0-9]+";
|
||||||
|
private const string unknown = "Name unknown (uuid={0})";
|
||||||
|
|
||||||
|
public PatchAlertDecorator(OuputComponent ouputComponent, List<XenServerPatchAlert> alerts)
|
||||||
|
{
|
||||||
|
SetComponent(ouputComponent);
|
||||||
|
this.alerts = alerts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
StringBuilder sb = base.Generate();
|
||||||
|
sb.AppendLine(String.Format(header, alerts.Count));
|
||||||
|
AddAlertSummary(sb);
|
||||||
|
return sb.AppendLine(String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddAlertSummary(StringBuilder sb)
|
||||||
|
{
|
||||||
|
if (alerts.Count == 0)
|
||||||
|
sb.AppendLine(zeroResults);
|
||||||
|
|
||||||
|
foreach (XenServerPatchAlert alert in alerts.OrderBy(a => a.Patch.Name))
|
||||||
|
{
|
||||||
|
string patchName = Regex.Match(alert.Patch.Name, hotfixRegex).Value;
|
||||||
|
string nameToReturn = String.IsNullOrEmpty(patchName) ? alert.Patch.Name.Trim() : patchName;
|
||||||
|
|
||||||
|
sb.AppendLine(!String.IsNullOrEmpty(nameToReturn)
|
||||||
|
? nameToReturn
|
||||||
|
: String.Format(unknown, alert.Patch.Uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
CFUValidator/OutputDecorators/XenCenterUpdateDecorator.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Text;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
class XenCenterUpdateDecorator: Decorator
|
||||||
|
{
|
||||||
|
private readonly XenCenterUpdateAlert alert;
|
||||||
|
private const string header = "XenCenter updates required:";
|
||||||
|
private const string updateNotFound = "XenCenter update could not be found";
|
||||||
|
|
||||||
|
public XenCenterUpdateDecorator(OuputComponent ouputComponent, XenCenterUpdateAlert alert)
|
||||||
|
{
|
||||||
|
SetComponent(ouputComponent);
|
||||||
|
this.alert = alert;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
StringBuilder sb = base.Generate();
|
||||||
|
sb.AppendLine(header);
|
||||||
|
sb.AppendLine(alert == null ? updateNotFound : alert.NewVersion.VersionAndLang);
|
||||||
|
return sb.AppendLine(String.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
CFUValidator/OutputDecorators/XenServerUpdateDecorator.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.OutputDecorators
|
||||||
|
{
|
||||||
|
class XenServerUpdateDecorator : Decorator
|
||||||
|
{
|
||||||
|
private readonly XenServerUpdateAlert alert;
|
||||||
|
private const string header = "XenServer updates required:";
|
||||||
|
private const string updateNotFound = "XenServer update could not be found";
|
||||||
|
|
||||||
|
public XenServerUpdateDecorator(OuputComponent ouputComponent, XenServerUpdateAlert alert)
|
||||||
|
{
|
||||||
|
SetComponent(ouputComponent);
|
||||||
|
this.alert = alert;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StringBuilder Generate()
|
||||||
|
{
|
||||||
|
StringBuilder sb = base.Generate();
|
||||||
|
sb.AppendLine(header);
|
||||||
|
sb.AppendLine(alert == null ? updateNotFound : alert.Version.Name);
|
||||||
|
return sb.AppendLine(String.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
CFUValidator/Program.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 CFUValidator.CommandLineOptions;
|
||||||
|
|
||||||
|
namespace CFUValidator
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
CFUValidator cfuValidator = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CommandLineParser parser = new CommandLineParser(args, CFUCommandLineOptionManager.EmptyArguments);
|
||||||
|
parser.Parse();
|
||||||
|
|
||||||
|
CFUCommandLineOptionManager manager = new CFUCommandLineOptionManager(parser.ParsedArguments);
|
||||||
|
|
||||||
|
if(manager.IsHelpRequired || args.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine(manager.Help);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfuValidator = new CFUValidator(manager.FileSource, manager.XmlLocation,
|
||||||
|
manager.ServerVersion, manager.InstalledHotfixes,
|
||||||
|
manager.CheckHotfixContents);
|
||||||
|
cfuValidator.StatusChanged += cfuValidator_StatusChanged;
|
||||||
|
cfuValidator.Run();
|
||||||
|
Console.WriteLine(cfuValidator.Output);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (CFUValidationException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n **** Unexpected exception occured ****: " + ex.Message);
|
||||||
|
Console.WriteLine(ex.StackTrace);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (cfuValidator != null)
|
||||||
|
cfuValidator.StatusChanged -= cfuValidator_StatusChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cfuValidator_StatusChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(sender as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
CFUValidator/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("CFUValidator")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("CFUValidator")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("1fc53fff-32d6-4775-a913-203c3410d388")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@ -0,0 +1,79 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Net;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
namespace CFUValidator.Updates
|
||||||
|
{
|
||||||
|
class AlternativeUrlDownloadUpdatesXmlSourceAction : DownloadUpdatesXmlAction, ICheckForUpdatesXMLSource
|
||||||
|
{
|
||||||
|
private readonly string newLocation;
|
||||||
|
public AlternativeUrlDownloadUpdatesXmlSourceAction(string url)
|
||||||
|
{
|
||||||
|
newLocation = url;
|
||||||
|
ErrorRaised = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override XmlDocument FetchCheckForUpdatesXml(string location)
|
||||||
|
{
|
||||||
|
XmlDocument xdoc;
|
||||||
|
using (Stream xmlstream = GetXmlDoc())
|
||||||
|
{
|
||||||
|
xdoc = Helpers.LoadXmlDocument(xmlstream);
|
||||||
|
}
|
||||||
|
return xdoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream GetXmlDoc()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebRequest wr = WebRequest.Create(newLocation);
|
||||||
|
return wr.GetResponse().GetResponseStream();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
ErrorRaised = new CFUValidationException("Failed to wget the URL: " + newLocation);
|
||||||
|
throw ErrorRaised;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception ErrorRaised { get; private set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
48
CFUValidator/Updates/ICheckForUpdatesXMLSource.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
namespace CFUValidator.Updates
|
||||||
|
{
|
||||||
|
interface ICheckForUpdatesXMLSource
|
||||||
|
{
|
||||||
|
List<XenServerPatch> XenServerPatches { get; }
|
||||||
|
List<XenServerVersion> XenServerVersions{ get; }
|
||||||
|
List<XenCenterVersion> XenCenterVersions { get; }
|
||||||
|
bool IsCompleted { get; }
|
||||||
|
void RunAsync();
|
||||||
|
int PercentComplete { get; }
|
||||||
|
Exception ErrorRaised { get; }
|
||||||
|
}
|
||||||
|
}
|
76
CFUValidator/Updates/ReadFromFileUpdatesXmlSource.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Xml;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
|
||||||
|
namespace CFUValidator.Updates
|
||||||
|
{
|
||||||
|
class ReadFromFileUpdatesXmlSource : DownloadUpdatesXmlAction, ICheckForUpdatesXMLSource
|
||||||
|
{
|
||||||
|
private readonly string newLocation;
|
||||||
|
public ReadFromFileUpdatesXmlSource(string location)
|
||||||
|
{
|
||||||
|
newLocation = location;
|
||||||
|
ErrorRaised = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override XmlDocument FetchCheckForUpdatesXml(string location)
|
||||||
|
{
|
||||||
|
if (!File.Exists(newLocation))
|
||||||
|
{
|
||||||
|
ErrorRaised = new CFUValidationException("File not found at: " + newLocation);
|
||||||
|
throw ErrorRaised;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlDocument xdoc = new XmlDocument();
|
||||||
|
using (StreamReader sr = new StreamReader(newLocation))
|
||||||
|
{
|
||||||
|
xdoc.Load(sr);
|
||||||
|
}
|
||||||
|
return xdoc;
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
ErrorRaised = new CFUValidationException("Could not read/parse file: " + newLocation);
|
||||||
|
throw ErrorRaised;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception ErrorRaised { get; private set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
50
CFUValidator/Updates/XmlRetrieverFactory.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 CFUValidator.CommandLineOptions;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
|
||||||
|
namespace CFUValidator.Updates
|
||||||
|
{
|
||||||
|
class XmlRetrieverFactory
|
||||||
|
{
|
||||||
|
public ICheckForUpdatesXMLSource GetAction(OptionUsage usage, string location)
|
||||||
|
{
|
||||||
|
if (usage == OptionUsage.Url)
|
||||||
|
return new AlternativeUrlDownloadUpdatesXmlSourceAction(location);
|
||||||
|
if (usage == OptionUsage.File)
|
||||||
|
return new ReadFromFileUpdatesXmlSource(location);
|
||||||
|
|
||||||
|
throw new ArgumentException("No action was found for the provided usage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
74
CFUValidator/Validators/AlertFeatureValidator.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.Validators
|
||||||
|
{
|
||||||
|
abstract class AlertFeatureValidator
|
||||||
|
{
|
||||||
|
protected List<XenServerPatchAlert> alerts;
|
||||||
|
|
||||||
|
protected AlertFeatureValidator(List<XenServerPatchAlert> alerts)
|
||||||
|
{
|
||||||
|
this.alerts = alerts;
|
||||||
|
Results = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Validate();
|
||||||
|
public abstract string Description { get; }
|
||||||
|
public List<string> Results { get; protected set; }
|
||||||
|
public bool ErrorsFound { get { return Results.Count > 0; } }
|
||||||
|
|
||||||
|
public delegate void StatusChangedHandler(object sender, EventArgs e);
|
||||||
|
|
||||||
|
public event StatusChangedHandler StatusChanged;
|
||||||
|
|
||||||
|
protected virtual void OnStatusChanged()
|
||||||
|
{
|
||||||
|
if (StatusChanged != null)
|
||||||
|
StatusChanged(Status, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string status;
|
||||||
|
protected string Status
|
||||||
|
{
|
||||||
|
get { return status; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
status = value;
|
||||||
|
OnStatusChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
CFUValidator/Validators/CorePatchDetailsValidator.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.Validators
|
||||||
|
{
|
||||||
|
class CorePatchDetailsValidator : AlertFeatureValidator
|
||||||
|
{
|
||||||
|
public CorePatchDetailsValidator(List<XenServerPatchAlert> alerts) : base(alerts){}
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
foreach (XenServerPatchAlert alert in alerts)
|
||||||
|
{
|
||||||
|
VerifyPatchDetailsMissing(alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifyPatchDetailsMissing(XenServerPatchAlert alert)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(alert.Patch.Uuid))
|
||||||
|
Results.Add("Missing patch uuid for patch: " + alert.Patch.Name);
|
||||||
|
if(string.IsNullOrEmpty(alert.Patch.Name))
|
||||||
|
Results.Add("Missing patch name for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
if(string.IsNullOrEmpty(alert.Patch.PatchUrl))
|
||||||
|
Results.Add("Missing patch patch-url for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
if (string.IsNullOrEmpty(alert.Patch.Description))
|
||||||
|
Results.Add("Missing patch description for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
if (string.IsNullOrEmpty(alert.Patch.Url))
|
||||||
|
Results.Add("Missing patch webpage url for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
if (string.IsNullOrEmpty(alert.Patch.Guidance))
|
||||||
|
Results.Add("Missing patch guidance for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
if (string.IsNullOrEmpty(alert.Patch.TimeStamp.ToString()))
|
||||||
|
Results.Add("Missing patch timestamp for patch with UUID: " + alert.Patch.Uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get { return "Verify core patch details"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
CFUValidator/Validators/PatchURLValidator.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Net;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
|
||||||
|
namespace CFUValidator.Validators
|
||||||
|
{
|
||||||
|
class PatchURLValidator : AlertFeatureValidator
|
||||||
|
{
|
||||||
|
private readonly BackgroundWorker workerThread;
|
||||||
|
public PatchURLValidator(List<XenServerPatchAlert> alerts) : base(alerts)
|
||||||
|
{
|
||||||
|
workerThread = new BackgroundWorker();
|
||||||
|
workerThread.DoWork += CheckAllPatchURLs;
|
||||||
|
workerThread.RunWorkerCompleted += RunWorkerCompletedMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isComplete;
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
isComplete = false;
|
||||||
|
ConsoleSpinner spinner = new ConsoleSpinner();
|
||||||
|
workerThread.RunWorkerAsync();
|
||||||
|
|
||||||
|
while(!isComplete)
|
||||||
|
spinner.Turn();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunWorkerCompletedMethod(object sender, RunWorkerCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
isComplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckAllPatchURLs(object sender, DoWorkEventArgs e)
|
||||||
|
{
|
||||||
|
foreach (XenServerPatchAlert alert in alerts)
|
||||||
|
{
|
||||||
|
if(String.IsNullOrEmpty(alert.Patch.PatchUrl))
|
||||||
|
{
|
||||||
|
Results.Add(String.Format("Patch '{0}' URL is missing", alert.Patch.Name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpWebResponse response = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WebRequest request = WebRequest.Create(alert.Patch.PatchUrl);
|
||||||
|
request.Method = "HEAD";
|
||||||
|
response = (HttpWebResponse)request.GetResponse();
|
||||||
|
if (response == null || response.StatusCode != HttpStatusCode.OK)
|
||||||
|
Results.Add(String.Format("Patch '{0}' URL '{1}' is invalid", alert.Patch.Name, alert.Patch.PatchUrl));
|
||||||
|
}
|
||||||
|
catch(WebException ex)
|
||||||
|
{
|
||||||
|
Results.Add(String.Format("Patch '{0}' URL '{1}' failed: {2}", alert.Patch.Name, alert.Patch.PatchUrl, ex.Message));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if(response != null)
|
||||||
|
response.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get { return "Checking the patch URLs return a suitable http response"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
98
CFUValidator/Validators/ZipContentsValidator.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
using XenCenterLib.Archive;
|
||||||
|
|
||||||
|
namespace CFUValidator.Validators
|
||||||
|
{
|
||||||
|
class ZipContentsValidator : AlertFeatureValidator
|
||||||
|
{
|
||||||
|
public ZipContentsValidator(List<XenServerPatchAlert> alerts) : base(alerts){}
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
foreach (XenServerPatchAlert alert in alerts.OrderBy(a=>a.Patch.Name))
|
||||||
|
{
|
||||||
|
DownloadPatchFile(alert);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get { return "Downloading and checking the contents of the zip files in the patch"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NewTempPath()
|
||||||
|
{
|
||||||
|
return Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DownloadPatchFile(XenServerPatchAlert patch)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(patch.Patch.PatchUrl))
|
||||||
|
{
|
||||||
|
Results.Add("Patch conatined no URL: " + patch.Patch.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string tempFileName = NewTempPath();
|
||||||
|
DownloadAndUnzipXenServerPatchAction action = new DownloadAndUnzipXenServerPatchAction(patch.Patch.Name,
|
||||||
|
new Uri(patch.Patch.PatchUrl),
|
||||||
|
tempFileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Status = "Download and unzip patch " + patch.Patch.Name;
|
||||||
|
|
||||||
|
ConsoleSpinner spinner = new ConsoleSpinner();
|
||||||
|
action.RunAsync();
|
||||||
|
while(!action.IsCompleted)
|
||||||
|
{
|
||||||
|
spinner.Turn(action.PercentComplete);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!action.Succeeded)
|
||||||
|
Results.Add("Patch download and unzip unsuccessful: " + action.Exception.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Results.Add("Patch download error: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
CONTRIB
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
How to submit changes
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Please try to follow the guidelines below. They will make things
|
||||||
|
easier on the maintainers. Not all of these guidelines matter for every
|
||||||
|
trivial change so apply some common sense.
|
||||||
|
|
||||||
|
If you are unsure about something written here, ask on the mailing list
|
||||||
|
xs-devel@lists.xenserver.org.
|
||||||
|
|
||||||
|
0. Before starting a big project, discuss it on the list first :-)
|
||||||
|
|
||||||
|
1. Always test your changes, however small, by both targetted
|
||||||
|
manual testing and by running the unit tests.
|
||||||
|
|
||||||
|
2. When adding new functionality, include test cases for any
|
||||||
|
* important; or
|
||||||
|
* difficult to manually test; or
|
||||||
|
* easy to break
|
||||||
|
new code.
|
||||||
|
|
||||||
|
3. All submissions must be made under the terms of the "Developer's
|
||||||
|
Certificate of Origin" (DCO) and should include a Signed-off-by:
|
||||||
|
line.
|
||||||
|
|
||||||
|
4. All contributions to the project must be sent as patches to the
|
||||||
|
xs-devel@lists.xenserver.org mailing list.
|
||||||
|
|
||||||
|
5. Each patch should include a descriptive commit comment that helps
|
||||||
|
understand why the patch is necessary and why it works. This will
|
||||||
|
be used both for initial review and for new people to understand
|
||||||
|
how the code works later.
|
||||||
|
|
||||||
|
6. For bonus points, ensure the project still builds in between every
|
||||||
|
patch in a set: this helps hunt down future regressions with 'bisect'.
|
||||||
|
|
||||||
|
7. Make sure you have the right to submit any changes you make. If you
|
||||||
|
do changes at work you may find your employer owns the patches
|
||||||
|
instead of you.
|
||||||
|
|
||||||
|
Mailing list
|
||||||
|
============
|
||||||
|
Please note that mailing list xs-devel@lists.xenserver.org is not live yet;
|
||||||
|
for any questions, or if you wish to sumbit code, we recommend reaching
|
||||||
|
out to the maintainers, who will attempt to steer you in the right direction.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For a list of maintainers, please see MAINTAINERS file.
|
60
CommandLib/CommandLib.csproj
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>CommandLib</RootNamespace>
|
||||||
|
<AssemblyName>CommandLib</AssemblyName>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<OldToolsVersion>2.0</OldToolsVersion>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="export.cs" />
|
||||||
|
<Compile Include="io.cs" />
|
||||||
|
<Compile Include="tar.cs" />
|
||||||
|
<Compile Include="thinCLIProtocol.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
64
CommandLib/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("CommandLib")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Citrix")]
|
||||||
|
[assembly: AssemblyProduct("CommandLib")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © @COMPANY_NAME_LEGAL@")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("afe05716-a4d5-415b-8263-9daa8639dc78")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("0000")]
|
226
CommandLib/export.cs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Xml;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
/* Thrown if we fail to verify a block (ie sha1) checksum */
|
||||||
|
public class BlockChecksumFailed : ApplicationException
|
||||||
|
{
|
||||||
|
private string block;
|
||||||
|
private string recomputed;
|
||||||
|
private string original;
|
||||||
|
|
||||||
|
public BlockChecksumFailed(string block, string recomputed, string original)
|
||||||
|
{
|
||||||
|
this.block = block;
|
||||||
|
this.recomputed = recomputed;
|
||||||
|
this.original = original;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "Failed to verify the block checksum: block = " + block + "; recomputed = " + recomputed + "; original = " + original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Export
|
||||||
|
{
|
||||||
|
public static bool verbose_debugging = false;
|
||||||
|
public static void debug(string x)
|
||||||
|
{
|
||||||
|
if (verbose_debugging)
|
||||||
|
Console.WriteLine(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly SHA1 sha = new SHA1CryptoServiceProvider();
|
||||||
|
|
||||||
|
private static char nibble(int x)
|
||||||
|
{
|
||||||
|
if (x < 10)
|
||||||
|
return (char)((int)'0' + x);
|
||||||
|
else
|
||||||
|
return (char)((int)'a' - 10 + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string hex(byte x)
|
||||||
|
{
|
||||||
|
char low = nibble((int)x & 0xf);
|
||||||
|
char high = nibble(((int)x >> 4) & 0xf);
|
||||||
|
char[] chars = { high, low };
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string checksum(byte[] data)
|
||||||
|
{
|
||||||
|
byte[] result = sha.ComputeHash(data);
|
||||||
|
/* convert to a hex string for comparison */
|
||||||
|
string x = "";
|
||||||
|
for (int i = 0; i < result.Length; i++)
|
||||||
|
x = x + hex(result[i]);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Hashtable parse_checksum_table(string checksum_xml)
|
||||||
|
{
|
||||||
|
Hashtable table = new Hashtable();
|
||||||
|
|
||||||
|
XmlDocument xmlDoc = new System.Xml.XmlDocument();
|
||||||
|
xmlDoc.LoadXml(checksum_xml);
|
||||||
|
XmlNodeList members = xmlDoc.GetElementsByTagName("member");
|
||||||
|
string name;
|
||||||
|
string value;
|
||||||
|
foreach (XmlNode member in members)
|
||||||
|
{
|
||||||
|
name = ""; value = "";
|
||||||
|
foreach (XmlNode child in member.ChildNodes)
|
||||||
|
{
|
||||||
|
XmlNode v = child.FirstChild;
|
||||||
|
if (child.Name.Equals("name"))
|
||||||
|
name = v.Value;
|
||||||
|
if (child.Name.Equals("value"))
|
||||||
|
value = v.Value;
|
||||||
|
}
|
||||||
|
debug(String.Format("adding {0} = {1}", name, value));
|
||||||
|
table.Add(name, value);
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compare_tables(Hashtable recomputed, Hashtable original)
|
||||||
|
{
|
||||||
|
foreach (DictionaryEntry x in recomputed)
|
||||||
|
{
|
||||||
|
string ours = (string)x.Value;
|
||||||
|
string theirs = (string)original[x.Key];
|
||||||
|
if (!ours.Equals(theirs))
|
||||||
|
{
|
||||||
|
throw new BlockChecksumFailed((string)x.Key, ours, theirs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debug(String.Format("{0} hash OK", (string)x.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string string_of_byte_array(byte[] payload)
|
||||||
|
{
|
||||||
|
Decoder decoder = Encoding.UTF8.GetDecoder();
|
||||||
|
char[] chars = new char[decoder.GetCharCount(payload, 0, (int)payload.Length)];
|
||||||
|
decoder.GetChars(payload, 0, (int)payload.Length, chars, 0);
|
||||||
|
return new string(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void verifyCallback(uint read);
|
||||||
|
public delegate bool cancellingCallback();
|
||||||
|
|
||||||
|
/* 'input' is the source of the export data, if 'output' is not null then
|
||||||
|
a perfect copy should be echoed there. */
|
||||||
|
public void verify(Stream input, Stream output, cancellingCallback cancelling)
|
||||||
|
{
|
||||||
|
verify(input, output, cancelling, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void verify(Stream input, Stream output, cancellingCallback cancelling, verifyCallback callback)
|
||||||
|
{
|
||||||
|
Hashtable recomputed_checksums = new Hashtable();
|
||||||
|
Hashtable original_checksums = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!cancelling())
|
||||||
|
{
|
||||||
|
Header x = null;
|
||||||
|
byte[] one = IO.unmarshal_n(input, Header.length);
|
||||||
|
if (callback != null) callback(Header.length);
|
||||||
|
if (output != null) output.Write(one, 0, one.Length);
|
||||||
|
|
||||||
|
if (Header.all_zeroes(one))
|
||||||
|
{
|
||||||
|
byte[] two = IO.unmarshal_n(input, Header.length);
|
||||||
|
if (callback != null) callback(Header.length);
|
||||||
|
if (output != null) output.Write(two, 0, two.Length);
|
||||||
|
if (Header.all_zeroes(two))
|
||||||
|
throw new EndOfArchive();
|
||||||
|
x = new Header(two);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = new Header(one);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(x.ToString());
|
||||||
|
byte[] payload = IO.unmarshal_n(input, x.file_size);
|
||||||
|
if (callback != null) callback(x.file_size);
|
||||||
|
if (output != null) output.Write(payload, 0, payload.Length);
|
||||||
|
|
||||||
|
if (x.file_name.Equals("ova.xml"))
|
||||||
|
{
|
||||||
|
debug("skipping ova.xml");
|
||||||
|
}
|
||||||
|
else if (x.file_name.EndsWith(".checksum"))
|
||||||
|
{
|
||||||
|
string csum = string_of_byte_array(payload);
|
||||||
|
string base_name = x.file_name.Substring(0, x.file_name.Length - 9);
|
||||||
|
string ours = (string)recomputed_checksums[base_name];
|
||||||
|
if (!ours.Equals(csum))
|
||||||
|
throw new BlockChecksumFailed(base_name, ours, csum);
|
||||||
|
debug(String.Format("{0} hash OK", base_name));
|
||||||
|
}
|
||||||
|
else if (x.file_name.Equals("checksum.xml"))
|
||||||
|
{
|
||||||
|
string xml = string_of_byte_array(payload);
|
||||||
|
original_checksums = parse_checksum_table(xml);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string csum = checksum(payload);
|
||||||
|
debug(String.Format(" has checksum: {0}", csum));
|
||||||
|
recomputed_checksums.Add(x.file_name, csum);
|
||||||
|
}
|
||||||
|
byte[] padding = IO.unmarshal_n(input, x.paddingLength());
|
||||||
|
if (callback != null) callback(x.paddingLength());
|
||||||
|
if (output != null) output.Write(padding, 0, padding.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (EndOfArchive)
|
||||||
|
{
|
||||||
|
debug("EOF");
|
||||||
|
if(original_checksums != null)
|
||||||
|
compare_tables(recomputed_checksums, original_checksums);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
CommandLib/io.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public class IO{
|
||||||
|
|
||||||
|
public static void unmarshal_n_into(Stream stream, uint n, byte[] buffer){
|
||||||
|
int toread = (int)n;
|
||||||
|
int offset = 0;
|
||||||
|
while (toread > 0){
|
||||||
|
int nread = stream.Read(buffer, offset, toread);
|
||||||
|
if (nread <= 0)
|
||||||
|
throw new EndOfStreamException
|
||||||
|
(String.Format("End of stream reached with {0} bytes left to read", toread));
|
||||||
|
|
||||||
|
offset += nread; toread -= nread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] unmarshal_n(Stream stream, uint n){
|
||||||
|
byte[] buffer = new byte[n];
|
||||||
|
unmarshal_n_into(stream, n, buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void skip(Stream stream, uint n){
|
||||||
|
byte[] buffer = new byte[63356];
|
||||||
|
while(n > 0){
|
||||||
|
uint toread = (uint)buffer.Length;
|
||||||
|
if (n < toread) toread = n;
|
||||||
|
unmarshal_n_into(stream, toread, buffer);
|
||||||
|
n -= toread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
215
CommandLib/tar.cs
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Net;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
/* Thrown if we fail to verify a tar header checksum */
|
||||||
|
public class HeaderChecksumFailed : ApplicationException {
|
||||||
|
private uint expected;
|
||||||
|
private uint received;
|
||||||
|
public HeaderChecksumFailed(uint expected, uint received){
|
||||||
|
this.expected = expected;
|
||||||
|
this.received = received;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
string expected = Convert.ToString(this.expected);
|
||||||
|
string received = Convert.ToString(this.received);
|
||||||
|
|
||||||
|
return "Failed to verify the tar header checksum: received = " + received + "; expected = " + expected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thrown when we find the end of archive marker (two zero blocks) */
|
||||||
|
class EndOfArchive : ApplicationException {
|
||||||
|
public EndOfArchive(){ }
|
||||||
|
|
||||||
|
public override string ToString(){
|
||||||
|
return "End of tar archive";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Header{
|
||||||
|
public string file_name;
|
||||||
|
public int file_mode;
|
||||||
|
public int user_id;
|
||||||
|
public int group_id;
|
||||||
|
public uint file_size;
|
||||||
|
public uint mod_time;
|
||||||
|
public bool link;
|
||||||
|
public int link_name;
|
||||||
|
|
||||||
|
/* Length of a header block */
|
||||||
|
public static uint length = 512;
|
||||||
|
|
||||||
|
/* http://en.wikipedia.org/w/index.php?title=Tar_%28file_format%29&oldid=83554041 */
|
||||||
|
private static int file_name_off = 0;
|
||||||
|
private static int file_name_len = 100;
|
||||||
|
private static int file_mode_off = 100;
|
||||||
|
private static int file_mode_len = 8;
|
||||||
|
private static int user_id_off = 108;
|
||||||
|
private static int user_id_len = 8;
|
||||||
|
private static int group_id_off = 116;
|
||||||
|
private static int group_id_len = 8;
|
||||||
|
private static int file_size_off = 124;
|
||||||
|
private static int file_size_len = 12;
|
||||||
|
private static int mod_time_off = 136;
|
||||||
|
private static int mod_time_len = 12;
|
||||||
|
private static int chksum_off = 148;
|
||||||
|
private static int chksum_len = 8;
|
||||||
|
private static int link_off = 156;
|
||||||
|
private static int link_len = 1;
|
||||||
|
private static int link_name_off = 156;
|
||||||
|
private static int link_name_len = 100;
|
||||||
|
|
||||||
|
/* True if a buffer contains all zeroes */
|
||||||
|
public static bool all_zeroes(byte[] buffer){
|
||||||
|
bool zeroes = true;
|
||||||
|
for (int i = 0; i < buffer.Length && zeroes; i++) {
|
||||||
|
if (buffer[i] != 0) zeroes = false;
|
||||||
|
}
|
||||||
|
return zeroes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return a sub-array of bytes */
|
||||||
|
private byte[] slice(byte[] input, int offset, int length){
|
||||||
|
byte[] result = new byte[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
result[i] = input[offset + i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove NULLs and spaces from the end of a string */
|
||||||
|
private string trim_trailing_stuff(string x){
|
||||||
|
char[] trimmed = { '\0', ' '};
|
||||||
|
return x.TrimEnd(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the byte array into a string (assume UTF8) */
|
||||||
|
private string unmarshal_string(byte[] buffer){
|
||||||
|
Decoder decoder = Encoding.UTF8.GetDecoder();
|
||||||
|
char[] chars = new char[decoder.GetCharCount(buffer, 0, (int)buffer.Length)];
|
||||||
|
decoder.GetChars(buffer, 0, (int)buffer.Length, chars, 0);
|
||||||
|
return trim_trailing_stuff(new string(chars));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmarshal an octal string into an int32 */
|
||||||
|
private uint unmarshal_int32(byte[] buffer){
|
||||||
|
string octal = "0" + unmarshal_string(buffer);
|
||||||
|
return System.Convert.ToUInt32(octal, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmarshal an octal string into an int */
|
||||||
|
private int unmarshal_int(byte[] buffer){
|
||||||
|
string octal = "0" + unmarshal_string(buffer);
|
||||||
|
return System.Convert.ToInt32(octal, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recompute the (weak) header checksum */
|
||||||
|
private uint compute_checksum(byte[] buffer){
|
||||||
|
uint total = 0;
|
||||||
|
for(int i = 0; i < buffer.Length; i++){
|
||||||
|
/* treat the checksum digits as ' ' */
|
||||||
|
if ((i >= chksum_off) && (i < (chksum_off + chksum_len))){
|
||||||
|
total += 32; /* ' ' */
|
||||||
|
} else {
|
||||||
|
total += buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the required length of padding data to follow the data payload */
|
||||||
|
public uint paddingLength(){
|
||||||
|
/* round up to the next whole number of blocks */
|
||||||
|
uint next_block_length = (file_size + length - 1) / length * length;
|
||||||
|
return next_block_length - file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pretty-print a header */
|
||||||
|
public override string ToString(){
|
||||||
|
return String.Format("{0}/{1} {2:000000000000} {3:000000000000} {4}",
|
||||||
|
user_id, group_id, file_size, mod_time, file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmarshal a header from a buffer, throw an exception if the checksum doesn't validate */
|
||||||
|
public Header(byte[] buffer){
|
||||||
|
file_name = unmarshal_string(slice(buffer, file_name_off, file_name_len));
|
||||||
|
file_mode = unmarshal_int(slice(buffer, file_mode_off, file_mode_len));
|
||||||
|
user_id = unmarshal_int(slice(buffer, user_id_off, user_id_len));
|
||||||
|
group_id = unmarshal_int(slice(buffer, group_id_off, group_id_len));
|
||||||
|
file_size = unmarshal_int32(slice(buffer, file_size_off, file_size_len));
|
||||||
|
mod_time = unmarshal_int32(slice(buffer, mod_time_off, mod_time_len));
|
||||||
|
link = unmarshal_string(slice(buffer, link_off, link_len)) == "1";
|
||||||
|
link_name = unmarshal_int(slice(buffer, link_name_off, link_name_len));
|
||||||
|
|
||||||
|
uint chksum = unmarshal_int32(slice(buffer, chksum_off, chksum_len));
|
||||||
|
uint recomputed = compute_checksum(buffer);
|
||||||
|
if (chksum != recomputed)
|
||||||
|
throw new HeaderChecksumFailed(recomputed, chksum);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a tar header from a stream */
|
||||||
|
public static Header fromStream(Stream input){
|
||||||
|
byte[] one = IO.unmarshal_n(input, length);
|
||||||
|
if (all_zeroes(one)){
|
||||||
|
byte[] two = IO.unmarshal_n(input, length);
|
||||||
|
if (all_zeroes(two))
|
||||||
|
throw new EndOfArchive();
|
||||||
|
return new Header(two);
|
||||||
|
}
|
||||||
|
return new Header(one);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Archive{
|
||||||
|
|
||||||
|
public static void list(Stream stream){
|
||||||
|
try {
|
||||||
|
while (true){
|
||||||
|
Header x = Header.fromStream(stream);
|
||||||
|
Console.WriteLine(x);
|
||||||
|
IO.skip(stream, x.file_size);
|
||||||
|
IO.skip(stream, x.paddingLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(EndOfArchive){
|
||||||
|
Console.WriteLine("EOF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
612
CommandLib/thinCLIProtocol.cs
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Net.Security;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace CommandLib
|
||||||
|
{
|
||||||
|
public class Config
|
||||||
|
{
|
||||||
|
public string hostname = ""; // no default hostname
|
||||||
|
public string username = "root";
|
||||||
|
public string password = "";
|
||||||
|
public int port = 443;
|
||||||
|
public int block_size = 65536;
|
||||||
|
public bool nossl = false;
|
||||||
|
public bool debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void delegateGlobalError(String s);
|
||||||
|
public delegate void delegateGlobalUsage();
|
||||||
|
public delegate void delegateGlobalDebug(String s, thinCLIProtocol tCLIprotocol);
|
||||||
|
public delegate void delegateConsoleWrite(String s);
|
||||||
|
public delegate void delegateConsoleWriteLine(String s);
|
||||||
|
public delegate string delegateConsoleReadLine();
|
||||||
|
public delegate void delegateExit(int i);
|
||||||
|
public delegate void delegateProgress(int i);
|
||||||
|
|
||||||
|
public class thinCLIProtocol
|
||||||
|
{
|
||||||
|
public delegateGlobalError dGlobalError;
|
||||||
|
public delegateGlobalUsage dGlobalUsage;
|
||||||
|
public delegateGlobalDebug dGlobalDebug;
|
||||||
|
public delegateConsoleWrite dConsoleWrite;
|
||||||
|
public delegateConsoleWriteLine dConsoleWriteLine;
|
||||||
|
public delegateConsoleReadLine dConsoleReadLine;
|
||||||
|
public delegateProgress dProgress;
|
||||||
|
public delegateExit dExit;
|
||||||
|
public Config conf;
|
||||||
|
public string magic_string = "XenSource thin CLI protocol";
|
||||||
|
public int major = 0;
|
||||||
|
public int minor = 1;
|
||||||
|
public bool dropOut;
|
||||||
|
|
||||||
|
public thinCLIProtocol(delegateGlobalError dGlobalError,
|
||||||
|
delegateGlobalUsage dGlobalUsage,
|
||||||
|
delegateGlobalDebug dGlobalDebug,
|
||||||
|
delegateConsoleWrite dConsoleWrite,
|
||||||
|
delegateConsoleWriteLine dConsoleWriteLine,
|
||||||
|
delegateConsoleReadLine dConsoleReadLine,
|
||||||
|
delegateExit dExit,
|
||||||
|
delegateProgress dProgress,
|
||||||
|
Config conf)
|
||||||
|
{
|
||||||
|
this.dGlobalError = dGlobalError;
|
||||||
|
this.dGlobalUsage = dGlobalUsage;
|
||||||
|
this.dGlobalDebug = dGlobalDebug;
|
||||||
|
this.dConsoleWrite = dConsoleWrite;
|
||||||
|
this.dConsoleWriteLine = dConsoleWriteLine;
|
||||||
|
this.dConsoleReadLine = dConsoleReadLine;
|
||||||
|
this.dExit = dExit;
|
||||||
|
this.dProgress = dProgress;
|
||||||
|
this.conf = conf;
|
||||||
|
dropOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Transport{
|
||||||
|
// The following method is invoked by the RemoteCertificateValidationDelegate.
|
||||||
|
private static bool ValidateServerCertificate(
|
||||||
|
object sender,
|
||||||
|
X509Certificate certificate,
|
||||||
|
X509Chain chain,
|
||||||
|
SslPolicyErrors sslPolicyErrors)
|
||||||
|
{
|
||||||
|
// Do allow this client to communicate with unauthenticated servers.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Stream connect(thinCLIProtocol tCLIprotocol, String hostname, int port)
|
||||||
|
{
|
||||||
|
if (port != 443){
|
||||||
|
TcpClient client = new TcpClient(hostname, port);
|
||||||
|
Stream stream = client.GetStream();
|
||||||
|
return stream;
|
||||||
|
} else {
|
||||||
|
TcpClient client = new TcpClient(hostname, port);
|
||||||
|
// Create an SSL stream that will close the client's stream.
|
||||||
|
SslStream sslStream = new SslStream(
|
||||||
|
client.GetStream(),
|
||||||
|
false,
|
||||||
|
new RemoteCertificateValidationCallback(ValidateServerCertificate),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sslStream.AuthenticateAsClient("");
|
||||||
|
}
|
||||||
|
catch (AuthenticationException e){
|
||||||
|
if (tCLIprotocol.conf.debug) throw e;
|
||||||
|
tCLIprotocol.dGlobalError("Authentication failed - closing the connection.");
|
||||||
|
client.Close();
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (tCLIprotocol.conf.debug) throw e;
|
||||||
|
tCLIprotocol.dGlobalError("Exception during SSL auth - closing the connection.");
|
||||||
|
client.Close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return sslStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HTTP{
|
||||||
|
public static string readLine(Stream stream){
|
||||||
|
StringBuilder messageData = new StringBuilder();
|
||||||
|
do {
|
||||||
|
int i = stream.ReadByte();
|
||||||
|
if (i == -1)
|
||||||
|
{
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char b = (char)i;
|
||||||
|
messageData.Append(b);
|
||||||
|
if (b == '\n') break;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return messageData.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeLine(Stream stream, string line){
|
||||||
|
byte[] message = Encoding.UTF8.GetBytes(line);
|
||||||
|
stream.Write(message, 0, message.Length);
|
||||||
|
stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getResultCode(string line){
|
||||||
|
string[] bits = line.Split(new char[] {' '});
|
||||||
|
if (bits.Length < 2) return 0;
|
||||||
|
return Int32.Parse(bits[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="addr">The target URI, including scheme, hostname and path.</param>
|
||||||
|
public static Stream doRPC(String method, Uri uri, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
Stream http = Transport.connect(tCLIprotocol, uri.Host, uri.Port);
|
||||||
|
String header = method + " " + uri.PathAndQuery + " HTTP/1.0\r\n\r\n";
|
||||||
|
writeLine(http, header);
|
||||||
|
String response = readLine(http);
|
||||||
|
int code = getResultCode(response);
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 200:
|
||||||
|
break;
|
||||||
|
case 302:
|
||||||
|
string url = "";
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
response = readLine(http);
|
||||||
|
if (response.StartsWith("Location: "))
|
||||||
|
url = response.Substring(10);
|
||||||
|
if (response.Equals("\r\n") || response.Equals("")) break;
|
||||||
|
}
|
||||||
|
Uri redirect = new Uri(url.Trim());
|
||||||
|
tCLIprotocol.conf.hostname = redirect.Host;
|
||||||
|
http.Close();
|
||||||
|
return doRPC(method, redirect, tCLIprotocol);
|
||||||
|
default:
|
||||||
|
tCLIprotocol.dGlobalError("Received an error message from the server doing an HTTP " + method + " " + uri.PathAndQuery + " : " + response);
|
||||||
|
http.Close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
response = readLine(http);
|
||||||
|
if (response.Equals("\r\n") || response.Equals("")) break;
|
||||||
|
}
|
||||||
|
// Stream should be positioned after the headers
|
||||||
|
return http;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Types{
|
||||||
|
public static uint unmarshal_int32(Stream stream){
|
||||||
|
uint a = (uint)stream.ReadByte();
|
||||||
|
uint b = (uint)stream.ReadByte();
|
||||||
|
uint c = (uint)stream.ReadByte();
|
||||||
|
uint d = (uint)stream.ReadByte();
|
||||||
|
//Console.WriteLine("a = " + a + " b = " + b + " c = " + c + " d = " + d);
|
||||||
|
return (a << 0) | (b << 8) | (c << 16) | (d << 24);
|
||||||
|
}
|
||||||
|
public static void marshal_int32(Stream stream, uint x){
|
||||||
|
uint mask = 0xff;
|
||||||
|
stream.WriteByte((byte) ((x >> 0) & mask));
|
||||||
|
stream.WriteByte((byte) ((x >> 8) & mask));
|
||||||
|
stream.WriteByte((byte) ((x >> 16) & mask));
|
||||||
|
stream.WriteByte((byte) ((x >> 24) & mask));
|
||||||
|
}
|
||||||
|
public static int unmarshal_int(Stream stream){
|
||||||
|
return (int)unmarshal_int32(stream);
|
||||||
|
}
|
||||||
|
public static void marshal_int(Stream stream, int x){
|
||||||
|
marshal_int32(stream, (uint)x);
|
||||||
|
}
|
||||||
|
public static byte[] unmarshal_n(Stream stream, uint n){
|
||||||
|
byte[] buffer = new byte[n];
|
||||||
|
int toread = (int)n;
|
||||||
|
int offset = 0;
|
||||||
|
while (toread > 0){
|
||||||
|
int nread = stream.Read(buffer, offset, toread);
|
||||||
|
offset= nread; toread -= nread;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
public static string unmarshal_string(Stream stream){
|
||||||
|
uint length = unmarshal_int32(stream);
|
||||||
|
byte[] buffer = unmarshal_n(stream, length);
|
||||||
|
Decoder decoder = Encoding.UTF8.GetDecoder();
|
||||||
|
char[] chars = new char[decoder.GetCharCount(buffer, 0, (int)length)];
|
||||||
|
decoder.GetChars(buffer, 0, (int)length, chars, 0);
|
||||||
|
return new string(chars);
|
||||||
|
}
|
||||||
|
public static void marshal_string(Stream stream, string x){
|
||||||
|
marshal_int(stream, x.Length);
|
||||||
|
char[] c = x.ToCharArray();
|
||||||
|
Encoder encoder = Encoding.UTF8.GetEncoder();
|
||||||
|
byte[] bytes = new byte[encoder.GetByteCount(c, 0, c.Length, true)];
|
||||||
|
encoder.GetBytes(c, 0, c.Length, bytes, 0, true);
|
||||||
|
stream.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Messages
|
||||||
|
{
|
||||||
|
public enum tag
|
||||||
|
{
|
||||||
|
Print = 0, Load = 1, HttpGet = 12, HttpPut = 13, Prompt = 3, Exit = 4,
|
||||||
|
Error = 14, OK = 5, Failed = 6, Chunk = 7, End = 8, Command = 9, Response = 10,
|
||||||
|
Blob = 11, Debug = 15, PrintStderr = 16
|
||||||
|
};
|
||||||
|
public static tag unmarshal_tag(Stream stream)
|
||||||
|
{
|
||||||
|
int x = Types.unmarshal_int(stream);
|
||||||
|
return (tag)x;
|
||||||
|
}
|
||||||
|
public static void marshal_tag(Stream stream, tag tag)
|
||||||
|
{
|
||||||
|
Types.marshal_int(stream, (int)tag);
|
||||||
|
}
|
||||||
|
public static void marshal_response(Stream stream, tag t)
|
||||||
|
{
|
||||||
|
Types.marshal_int(stream, 4 + 4);
|
||||||
|
marshal_tag(stream, tag.Response);
|
||||||
|
marshal_tag(stream, t);
|
||||||
|
}
|
||||||
|
public static void protocol_failure(string msg, tag t, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Protocol failure: Reading " + msg + ": unexpected tag: " + t);
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void load(Stream stream, string filename, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
FileInfo fi = new FileInfo(filename);
|
||||||
|
// Immediately report our success in opening the file
|
||||||
|
marshal_response(stream, tag.OK);
|
||||||
|
|
||||||
|
// The server doesn't like multiple chunks but this is fine for
|
||||||
|
// Zurich/Geneva imports
|
||||||
|
Types.marshal_int(stream, 4 + 4 + 4);
|
||||||
|
marshal_tag(stream, tag.Blob);
|
||||||
|
marshal_tag(stream, tag.Chunk);
|
||||||
|
Types.marshal_int32(stream, (uint)fi.Length);
|
||||||
|
|
||||||
|
byte[] block = new byte[tCLIprotocol.conf.block_size];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int n = fs.Read(block, 0, block.Length);
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
Types.marshal_int(stream, 4 + 4);
|
||||||
|
marshal_tag(stream, tag.Blob);
|
||||||
|
marshal_tag(stream, tag.End);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream.Write(block, 0, n);
|
||||||
|
tCLIprotocol.dProgress(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException)
|
||||||
|
{
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void http_put(Stream stream, string filename, Uri uri, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
|
||||||
|
{
|
||||||
|
using (Stream http = HTTP.doRPC("PUT", uri, tCLIprotocol))
|
||||||
|
{
|
||||||
|
if (http == null)
|
||||||
|
{
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] block = new byte[tCLIprotocol.conf.block_size];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int n = fs.Read(block, 0, block.Length);
|
||||||
|
if (n == 0) break;
|
||||||
|
http.Write(block, 0, n);
|
||||||
|
}
|
||||||
|
marshal_response(stream, tag.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("File not found");
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError(string.Format("Received exception: {0}", e.Message));
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void http_get(Stream stream, string filename, Uri uri, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(filename))
|
||||||
|
throw new Exception(string.Format("The file '{0}' already exists", filename));
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
using (Stream http = HTTP.doRPC("GET", uri, tCLIprotocol))
|
||||||
|
{
|
||||||
|
if (http == null)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Server rejected request");
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] block = new byte[tCLIprotocol.conf.block_size];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int n = http.Read(block, 0, block.Length);
|
||||||
|
if (n == 0) break;
|
||||||
|
fs.Write(block, 0, n);
|
||||||
|
}
|
||||||
|
marshal_response(stream, tag.OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Received exception: " + e.Message);
|
||||||
|
tCLIprotocol.dGlobalError("Unable to write output file: " + filename);
|
||||||
|
marshal_response(stream, tag.Failed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void version_handshake(Stream stream, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
/* Check for the initial magic string */
|
||||||
|
byte[] magic = Types.unmarshal_n(stream, (uint)tCLIprotocol.magic_string.Length);
|
||||||
|
for (int i = 0; i < tCLIprotocol.magic_string.Length; i++)
|
||||||
|
{
|
||||||
|
if (magic[i] != tCLIprotocol.magic_string[i])
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Failed to find a server on " + tCLIprotocol.conf.hostname + ":" + tCLIprotocol.conf.port);
|
||||||
|
tCLIprotocol.dGlobalUsage();
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Read the remote version numbers */
|
||||||
|
int remote_major = Types.unmarshal_int(stream);
|
||||||
|
int remote_minor = Types.unmarshal_int(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Remote host has version " + remote_major + "." + remote_minor, tCLIprotocol);
|
||||||
|
tCLIprotocol.dGlobalDebug("Client has version " + tCLIprotocol.major + "." + tCLIprotocol.minor, tCLIprotocol);
|
||||||
|
if (tCLIprotocol.major != remote_major)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Protocol version mismatch talking to server on " + tCLIprotocol.conf.hostname + ":" + tCLIprotocol.conf.port);
|
||||||
|
tCLIprotocol.dGlobalUsage();
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
/* Tell the server our version numbers */
|
||||||
|
for (int i = 0; i < tCLIprotocol.magic_string.Length; i++)
|
||||||
|
{
|
||||||
|
stream.WriteByte((byte)tCLIprotocol.magic_string[i]);
|
||||||
|
}
|
||||||
|
Types.marshal_int(stream, tCLIprotocol.major);
|
||||||
|
Types.marshal_int(stream, tCLIprotocol.minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void performCommand(string Body, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
string body = Body;
|
||||||
|
body += "username=" + tCLIprotocol.conf.username + "\n";
|
||||||
|
body += "password=" + tCLIprotocol.conf.password + "\n";
|
||||||
|
if (body.Length != 0)
|
||||||
|
{
|
||||||
|
body = body.Substring(0, body.Length - 1); // strip last "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
string header = "POST /cli HTTP/1.0\r\n";
|
||||||
|
string content_length = "content-length: " + Encoding.UTF8.GetBytes(body).Length + "\r\n";
|
||||||
|
string tosend = header + content_length + "\r\n" + body;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stream stream = Transport.connect(tCLIprotocol, tCLIprotocol.conf.hostname, tCLIprotocol.conf.port);
|
||||||
|
if (stream == null)
|
||||||
|
{
|
||||||
|
// The SSL functions already tell us what happened
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
byte[] message = Encoding.UTF8.GetBytes(tosend);
|
||||||
|
stream.Write(message, 0, message.Length);
|
||||||
|
stream.Flush();
|
||||||
|
Messages.version_handshake(stream, tCLIprotocol);
|
||||||
|
interpreter(stream, tCLIprotocol);
|
||||||
|
}
|
||||||
|
catch (SocketException)
|
||||||
|
{
|
||||||
|
tCLIprotocol.dGlobalError("Connection to " + tCLIprotocol.conf.hostname + ":" + tCLIprotocol.conf.port + " refused.");
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (tCLIprotocol.conf.debug) throw e;
|
||||||
|
tCLIprotocol.dGlobalError("Caught exception: " + e.Message);
|
||||||
|
tCLIprotocol.dExit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void interpreter(Stream stream, thinCLIProtocol tCLIprotocol)
|
||||||
|
{
|
||||||
|
string filename = "";
|
||||||
|
string path = "";
|
||||||
|
string msg = "";
|
||||||
|
while (!tCLIprotocol.dropOut)
|
||||||
|
{
|
||||||
|
Types.unmarshal_int32(stream); // total message length (unused here)
|
||||||
|
Messages.tag t = Messages.unmarshal_tag(stream);
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case Messages.tag.Command:
|
||||||
|
t = Messages.unmarshal_tag(stream);
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case Messages.tag.Print:
|
||||||
|
msg = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Print: " + msg, tCLIprotocol);
|
||||||
|
tCLIprotocol.dConsoleWriteLine(msg);
|
||||||
|
break;
|
||||||
|
case Messages.tag.PrintStderr:
|
||||||
|
msg = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: PrintStderr: " + msg, tCLIprotocol);
|
||||||
|
tCLIprotocol.dConsoleWriteLine(msg);
|
||||||
|
break;
|
||||||
|
case Messages.tag.Debug:
|
||||||
|
msg = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Debug: " + msg, tCLIprotocol);
|
||||||
|
tCLIprotocol.dConsoleWriteLine(msg);
|
||||||
|
break;
|
||||||
|
case Messages.tag.Exit:
|
||||||
|
int code = Types.unmarshal_int(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Command Exit " + code, tCLIprotocol);
|
||||||
|
tCLIprotocol.dExit(code);
|
||||||
|
break;
|
||||||
|
case Messages.tag.Error:
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Command Error", tCLIprotocol);
|
||||||
|
string err_code = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dConsoleWriteLine("Error code: " + err_code);
|
||||||
|
tCLIprotocol.dConsoleWrite("Error params: ");
|
||||||
|
int length = Types.unmarshal_int(stream);
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
string param = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dConsoleWrite(param);
|
||||||
|
if (i != (length - 1)) tCLIprotocol.dConsoleWrite(", ");
|
||||||
|
}
|
||||||
|
tCLIprotocol.dConsoleWriteLine("");
|
||||||
|
break;
|
||||||
|
case Messages.tag.Prompt:
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Command Prompt", tCLIprotocol);
|
||||||
|
string response = tCLIprotocol.dConsoleReadLine();
|
||||||
|
tCLIprotocol.dConsoleWriteLine("Read "+response);
|
||||||
|
/* NB, 4+4+4 here for the blob, chunk and string length, put in by the marshal_string
|
||||||
|
function. A franken-marshal. */
|
||||||
|
Types.marshal_int(stream, 4 + 4 + 4); // length
|
||||||
|
Messages.marshal_tag(stream, Messages.tag.Blob);
|
||||||
|
Messages.marshal_tag(stream, Messages.tag.Chunk);
|
||||||
|
Types.marshal_string(stream, response);
|
||||||
|
Types.marshal_int(stream, 4 + 4); // length
|
||||||
|
Messages.marshal_tag(stream, Messages.tag.Blob);
|
||||||
|
Messages.marshal_tag(stream, Messages.tag.End);
|
||||||
|
break;
|
||||||
|
case Messages.tag.Load:
|
||||||
|
filename = Types.unmarshal_string(stream);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: Load " + filename, tCLIprotocol);
|
||||||
|
Messages.load(stream, filename, tCLIprotocol);
|
||||||
|
break;
|
||||||
|
case Messages.tag.HttpPut:
|
||||||
|
filename = Types.unmarshal_string(stream);
|
||||||
|
path = Types.unmarshal_string(stream);
|
||||||
|
Uri uri = ParseUri(path, tCLIprotocol);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: HttpPut " + filename + " -> " + uri, tCLIprotocol);
|
||||||
|
Messages.http_put(stream, filename, uri, tCLIprotocol);
|
||||||
|
break;
|
||||||
|
case Messages.tag.HttpGet:
|
||||||
|
filename = Types.unmarshal_string(stream);
|
||||||
|
path = Types.unmarshal_string(stream);
|
||||||
|
uri = ParseUri(path, tCLIprotocol);
|
||||||
|
tCLIprotocol.dGlobalDebug("Read: HttpGet " + filename + " -> " + uri, tCLIprotocol);
|
||||||
|
Messages.http_get(stream, filename, uri, tCLIprotocol);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Messages.protocol_failure("Command", t, tCLIprotocol);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Messages.protocol_failure("Message", t, tCLIprotocol);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Uri ParseUri(string path, thinCLIProtocol tcli)
|
||||||
|
{
|
||||||
|
// The server sometimes sends us a relative path (e.g. for VM import)
|
||||||
|
// and sometimes an absolute URI (https://host/path). Construct the absolute URI
|
||||||
|
// based on what we're given. The same hack exists in the server code...
|
||||||
|
// See CA-10942.
|
||||||
|
if (path.StartsWith("/"))
|
||||||
|
{
|
||||||
|
string[] bits = path.Split('?');
|
||||||
|
UriBuilder uriBuilder = new UriBuilder();
|
||||||
|
uriBuilder.Scheme = "https";
|
||||||
|
uriBuilder.Host = tcli.conf.hostname;
|
||||||
|
uriBuilder.Port = tcli.conf.port;
|
||||||
|
uriBuilder.Path = bits[0];
|
||||||
|
if (bits.Length > 1)
|
||||||
|
uriBuilder.Query = bits[1];
|
||||||
|
return uriBuilder.Uri;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new Uri(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
LICENSE
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Copyright (c) Citrix Systems Inc.
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
10
MAINTAINERS
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
List of maintainers
|
||||||
|
===================
|
||||||
|
* Stephen Turner <Stephen.Turner@citrix.com>
|
||||||
|
* Mihaela Stoica <mihaela.stoica@citrix.com>
|
||||||
|
* Konstantina Chremmou <konstantina.chremmou@citrix.com>
|
||||||
|
* Adrian Jachacy <adrian.jachacy@citrix.com>
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For information on how to contribute to the project, please see CONTRIB file.
|
25
README
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
This repository contains the source code for XenCenter.
|
||||||
|
|
||||||
|
Citrix XenCenter is a Windows-based management tool for XenServer environments
|
||||||
|
which enables users to manage and monitor XenServer hosts and resource pools,
|
||||||
|
and to deploy, monitor, manage and migrate virtual machines.
|
||||||
|
|
||||||
|
XenCenter is written mostly in C#.
|
||||||
|
|
||||||
|
How to build XenCenter
|
||||||
|
======================
|
||||||
|
To build XenCenter, you not only need
|
||||||
|
* the source from xenadmin repository
|
||||||
|
|
||||||
|
but also some libraries which we do not store in the source tree:
|
||||||
|
* CookComputing.XmlRpcV2.dll
|
||||||
|
* DiscUtils.dll
|
||||||
|
* ICSharpCode.SharpZipLib.dll
|
||||||
|
* Ionic.Zip.dll
|
||||||
|
* log4net.dll
|
||||||
|
You can find the source code of these libraries (along with some patches) in dotnet-packages repository.
|
||||||
|
|
||||||
|
You also need NUnit libraries
|
||||||
|
* nunit.framework.dll
|
||||||
|
* Moq.dll
|
||||||
|
which can be obtained from http://www.nunit.org/
|
148
VNCControl/Program.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace XenAdmin
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static UserControl MainWindow = null;
|
||||||
|
|
||||||
|
private static log4net.ILog log = null;
|
||||||
|
public static volatile bool Exiting = false;
|
||||||
|
|
||||||
|
static Program()
|
||||||
|
{
|
||||||
|
log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(Assembly.GetCallingAssembly().Location + ".config"));
|
||||||
|
log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AssertOffEventThread()
|
||||||
|
{
|
||||||
|
if (Program.MainWindow.Visible && !Program.MainWindow.InvokeRequired)
|
||||||
|
{
|
||||||
|
FatalError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AssertOnEventThread()
|
||||||
|
{
|
||||||
|
if (Program.MainWindow != null && Program.MainWindow.Visible && Program.MainWindow.InvokeRequired)
|
||||||
|
{
|
||||||
|
FatalError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FatalError()
|
||||||
|
{
|
||||||
|
string msg = String.Format(Messages.MESSAGEBOX_PROGRAM_UNEXPECTED,
|
||||||
|
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), GetLogFile_());
|
||||||
|
log.Fatal(msg + "\n" + Environment.StackTrace);
|
||||||
|
MessageBox.Show(msg, Messages.XENCENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetLogFile_()
|
||||||
|
{
|
||||||
|
foreach (log4net.Appender.IAppender appender in log.Logger.Repository.GetAppenders())
|
||||||
|
{
|
||||||
|
if (appender is log4net.Appender.FileAppender)
|
||||||
|
{
|
||||||
|
// Assume that the first FileAppender is the primary log file.
|
||||||
|
return ((log4net.Appender.FileAppender)appender).File;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Safely invoke the given delegate on the given control.
|
||||||
|
/// </summary>
|
||||||
|
public static void Invoke(Control c, MethodInvoker f)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!IsExiting(c))
|
||||||
|
{
|
||||||
|
if (c.InvokeRequired)
|
||||||
|
{
|
||||||
|
c.Invoke(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
if (!IsExiting(c)) throw;
|
||||||
|
}
|
||||||
|
catch (InvalidAsynchronousStateException)
|
||||||
|
{
|
||||||
|
if (!IsExiting(c)) throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsExiting(Control c)
|
||||||
|
{
|
||||||
|
return Exiting || c.Disposing || c.IsDisposed || !c.IsHandleCreated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Safely invoke the given delegate on the given control.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the function call, or null if c is being disposed.</returns>
|
||||||
|
public static object Invoke(Control c, Delegate f, params object[] p)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!IsExiting(c))
|
||||||
|
{
|
||||||
|
return c.InvokeRequired ? c.Invoke(f, p) : f.DynamicInvoke(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
if (!IsExiting(c)) throw;
|
||||||
|
}
|
||||||
|
catch (InvalidAsynchronousStateException)
|
||||||
|
{
|
||||||
|
if (!IsExiting(c)) throw;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
VNCControl/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("VNCControl")]
|
||||||
|
[assembly: AssemblyDescription("Active-X control to access XenServer VM administrative console")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Citrix")]
|
||||||
|
[assembly: AssemblyProduct("XenAdmin")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © @COMPANY_NAME_LEGAL@")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("7cd118ea-d8da-464d-8303-b189912a9878")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("0.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("0000")]
|
49
VNCControl/VNCControl.Designer.cs
generated
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
namespace XenAdmin
|
||||||
|
{
|
||||||
|
partial class VNCControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
if (m_vncClient != null)
|
||||||
|
{
|
||||||
|
m_vncClient.Disconnect();
|
||||||
|
m_vncClient.Dispose();
|
||||||
|
m_vncClient = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// VNCControl
|
||||||
|
//
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
|
||||||
|
this.Name = "VNCControl";
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
656
VNCControl/VNCControl.cs
Normal file
@ -0,0 +1,656 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using DotNetVnc;
|
||||||
|
using XenAdmin;
|
||||||
|
using XenAdmin.ConsoleView;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
namespace XenAdmin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// XenServer hosted VM console events interface
|
||||||
|
/// </summary>
|
||||||
|
[Guid("4CF54BB1-3A27-4fe6-9BEC-03BD404AF367")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||||
|
[ComVisible(true)]
|
||||||
|
public interface IVMConsoleEvents
|
||||||
|
{
|
||||||
|
[DispIdAttribute(0x60020000)]
|
||||||
|
void OnDisconnectedCallbackEvent(int EventID, string DisconnectReason);
|
||||||
|
[DispIdAttribute(0x60020001)]
|
||||||
|
void OnResolutionChangeCallbackEvent(string NewResolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// XenServer hosted VM console access interface
|
||||||
|
/// </summary>
|
||||||
|
[Guid("FFD87368-B188-4921-BE52-B3F75967FC89")]
|
||||||
|
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
|
||||||
|
[ComVisible(true)]
|
||||||
|
public interface IVMConsole
|
||||||
|
{
|
||||||
|
#region interface functions
|
||||||
|
bool Connect(string server, int port, string vm_uuid, string username, string password, int width, int height, bool show_border);
|
||||||
|
bool ConnectConsole(string consoleuri, int width, int height, bool show_border);
|
||||||
|
bool Disconnect();
|
||||||
|
bool CanConnect(); /* may not be necessary */
|
||||||
|
string GetVMResolution();
|
||||||
|
bool IsConnected();
|
||||||
|
void SendCtrlAltDel();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class that implements the Active-X interface and allows a COM client
|
||||||
|
/// to connect to the VNC console of a XenServer hosted VM.
|
||||||
|
/// </summary>
|
||||||
|
[Guid("D52D9588-AB6E-425b-9D8C-74FBDA46C4F8")]
|
||||||
|
[ProgId("XenAdmin.VNCControl")]
|
||||||
|
[ClassInterface(ClassInterfaceType.None)]
|
||||||
|
[ComVisible(true)]
|
||||||
|
[ComSourceInterfaces(typeof(IVMConsoleEvents))]
|
||||||
|
public partial class VNCControl : UserControl, IVMConsole
|
||||||
|
{
|
||||||
|
#region Properties and Events
|
||||||
|
// consts
|
||||||
|
private const string SESSION_INVALID = "SESSION_INVALID";
|
||||||
|
private const string HOST_IS_SLAVE = "HOST_IS_SLAVE";
|
||||||
|
private const string HANDLE_INVALID = "HANDLE_INVALID";
|
||||||
|
private const int SHORT_RETRY_COUNT = 10;
|
||||||
|
private const int SHORT_RETRY_SLEEP_TIME = 100;
|
||||||
|
private const int RETRY_SLEEP_TIME = 5000;
|
||||||
|
private const int VNC_PORT = 5900;
|
||||||
|
|
||||||
|
public MethodInvoker OnDetectVNC = null;
|
||||||
|
public String m_vncIP = null;
|
||||||
|
|
||||||
|
private VNCGraphicsClient m_vncClient = null;
|
||||||
|
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
// Xen API related properties
|
||||||
|
private XenAPI.Session m_session = null;
|
||||||
|
private char[] m_vncPassword = null;
|
||||||
|
private XenAPI.VM m_sourceVM = null;
|
||||||
|
private bool m_sourceIsPV = false;
|
||||||
|
//private bool UseSource = true; /* use VNC endpoint on host as opposed to guest */
|
||||||
|
|
||||||
|
// Event Handlers
|
||||||
|
private Dictionary<Set<int>, MethodInvoker> extraScans = new Dictionary<Set<int>, MethodInvoker>();
|
||||||
|
private Dictionary<Set<Keys>, MethodInvoker> extraCodes = new Dictionary<Set<Keys>, MethodInvoker>();
|
||||||
|
private Set<int> pressedScans = new Set<int>();
|
||||||
|
#endregion // Properties
|
||||||
|
|
||||||
|
#region Initializers and constructors
|
||||||
|
public VNCControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
initSubControl(0, 0, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the actual VNC client control.
|
||||||
|
/// </summary>
|
||||||
|
private void initSubControl(int width, int height, bool scaling, bool show_border)
|
||||||
|
{
|
||||||
|
Program.MainWindow = this;
|
||||||
|
bool wasFocused = m_vncClient != null && m_vncClient.Focused;
|
||||||
|
this.Controls.Clear();
|
||||||
|
|
||||||
|
Size newSize;
|
||||||
|
Size oldSize = new Size(1024, 768);
|
||||||
|
if (width == 0 || height == 0)
|
||||||
|
newSize = new Size(1024, 768);
|
||||||
|
else
|
||||||
|
newSize = new Size(width, height);
|
||||||
|
|
||||||
|
// Kill the old client.
|
||||||
|
if (m_vncClient != null)
|
||||||
|
{
|
||||||
|
oldSize = m_vncClient.DesktopSize;
|
||||||
|
m_vncClient.Disconnect();
|
||||||
|
m_vncClient.Dispose();
|
||||||
|
m_vncClient = null;
|
||||||
|
}
|
||||||
|
// Reset
|
||||||
|
this.AutoScroll = false;
|
||||||
|
this.AutoScrollMinSize = new Size(0, 0);
|
||||||
|
m_vncClient = new VNCGraphicsClient(this);
|
||||||
|
m_vncClient.Size = newSize;
|
||||||
|
this.Size = newSize;
|
||||||
|
m_vncClient.UseSource = true;
|
||||||
|
m_vncClient.SendScanCodes = !this.m_sourceIsPV;
|
||||||
|
m_vncClient.Dock = DockStyle.Fill;
|
||||||
|
this.m_vncClient.Scaling = scaling; // SCVMM requires a scaled image
|
||||||
|
m_vncClient.DisplayBorder = show_border;
|
||||||
|
m_vncClient.AutoScaleDimensions = newSize;
|
||||||
|
m_vncClient.AutoScaleMode = AutoScaleMode.Inherit;
|
||||||
|
|
||||||
|
this.m_vncClient.DesktopResized += ResolutionChangeHandler;
|
||||||
|
//this.m_vncClient.Resize += ResizeHandler;
|
||||||
|
//this.m_vncClient.ErrorOccurred += ErrorHandler;
|
||||||
|
//this.m_vncClient.ConnectionSuccess += ConnectionSuccess;
|
||||||
|
//this.m_vncClient.ErrorOccurred
|
||||||
|
//this.m_vncClient.MouseDown += new MouseEventHandler(vncClient_MouseDown);
|
||||||
|
//this.m_vncClient.KeyDown += new KeyEventHandler(vncClient_KeyDown);
|
||||||
|
|
||||||
|
m_vncClient.KeyHandler = new ConsoleKeyHandler();
|
||||||
|
this.m_vncClient.Unpause();
|
||||||
|
|
||||||
|
foreach (Set<Keys> keys in extraCodes.Keys)
|
||||||
|
{
|
||||||
|
m_vncClient.KeyHandler.AddKeyHandler(keys, extraCodes[keys]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Set<int> keys in extraScans.Keys)
|
||||||
|
{
|
||||||
|
m_vncClient.KeyHandler.AddKeyHandler(keys, extraScans[keys]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Active-X interface implementation
|
||||||
|
// externally subscribed events
|
||||||
|
public delegate void OnDisconnectedCallbackHandler(int EventID, string DisconnectReason);
|
||||||
|
public event OnDisconnectedCallbackHandler OnDisconnectedCallbackEvent;
|
||||||
|
|
||||||
|
public delegate void OnResolutionChangeCallbackHandler(string NewResolution);
|
||||||
|
public event OnResolutionChangeCallbackHandler OnResolutionChangeCallbackEvent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connect to a VM's console
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="server">XenServer to connect to</param>
|
||||||
|
/// <param name="port">Port that XenAPI is availabl on</param>
|
||||||
|
/// <param name="vm_uuid">The UUID of the VM whose console to connect to</param>
|
||||||
|
/// <param name="username">username for the xenapi AND the VM's console</param>
|
||||||
|
/// <param name="password">password for the xenapi AND the VM's console</param>
|
||||||
|
/// <param name="width">Width to initialize the VNC control to</param>
|
||||||
|
/// <param name="height">Height to initialize the VNC control to</param>
|
||||||
|
/// <param name="show_border">Bool to show border around the control when in focus</param>
|
||||||
|
/// <returns>true, if it succeeds and false if it doesnt</returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public bool Connect(string server, int port, string vm_uuid, string username, string password, int width, int height, bool show_border)
|
||||||
|
{
|
||||||
|
// reinitiailize the VNC Control
|
||||||
|
initSubControl(width, height, true, show_border);
|
||||||
|
m_vncClient.ErrorOccurred += ConnectionErrorHandler;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create a new XenAPI session
|
||||||
|
m_session = new Session(Session.STANDARD_TIMEOUT, server, port);
|
||||||
|
|
||||||
|
// Authenticate with username and password passed in.
|
||||||
|
// The third parameter tells the server which API version we support.
|
||||||
|
m_session.login_with_password(username, password, API_Version.LATEST);
|
||||||
|
m_vncPassword = password.ToCharArray();
|
||||||
|
|
||||||
|
// Find the VM in question
|
||||||
|
XenRef<VM> vmRef = VM.get_by_uuid(m_session, vm_uuid);
|
||||||
|
m_sourceVM = VM.get_record(m_session, vmRef);
|
||||||
|
|
||||||
|
// Check if this VM is PV or HVM
|
||||||
|
m_sourceIsPV = (m_sourceVM.PV_bootloader.Length != 0); /* No PV bootloader specified implies HVM */
|
||||||
|
|
||||||
|
// Get the console that uses the RFB (VNC) protocol
|
||||||
|
List<XenRef<XenAPI.Console>> consoleRefs = VM.get_consoles(m_session, vmRef);
|
||||||
|
XenAPI.Console console = null;
|
||||||
|
foreach (XenRef<XenAPI.Console> consoleRef in consoleRefs)
|
||||||
|
{
|
||||||
|
console = XenAPI.Console.get_record(m_session, consoleRef);
|
||||||
|
if (console.protocol == console_protocol.rfb)
|
||||||
|
break;
|
||||||
|
console = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (console != null)
|
||||||
|
//ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectToConsole), new KeyValuePair<VNCGraphicsClient, XenAPI.Console>(m_vncClient, console));
|
||||||
|
ConnectHostedConsole(m_vncClient, console, m_session.uuid);
|
||||||
|
|
||||||
|
// done with this session, log it out
|
||||||
|
m_session.logout();
|
||||||
|
}
|
||||||
|
catch (Exception exn)
|
||||||
|
{
|
||||||
|
// call the expcetion handler directly
|
||||||
|
this.ConnectionErrorHandler(this, exn);
|
||||||
|
}
|
||||||
|
return m_vncClient.Connected;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Connect to the VNC control via a URL
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if the connection worked</returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public bool ConnectConsole(string consoleuri, int width, int height, bool show_border)
|
||||||
|
{
|
||||||
|
|
||||||
|
//reinitialise the VNC Control
|
||||||
|
initSubControl(width, height, true, show_border);
|
||||||
|
m_vncClient.ErrorOccurred += ConnectionErrorHandler;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
XenAPI.Console console = new XenAPI.Console();
|
||||||
|
console.protocol = console_protocol.rfb;
|
||||||
|
console.location = consoleuri;
|
||||||
|
|
||||||
|
Uri uri = new Uri(consoleuri);
|
||||||
|
char[] delims = { '&', '=' , '?' };
|
||||||
|
string qargs = uri.Query;
|
||||||
|
string session_id = "";
|
||||||
|
string vm_Opref = "";
|
||||||
|
string console_ref = "";
|
||||||
|
|
||||||
|
string[] args = qargs.Split(delims);
|
||||||
|
int x = -1;
|
||||||
|
int y = -1;
|
||||||
|
int z = -1;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
foreach (string s in args)
|
||||||
|
{
|
||||||
|
if ( String.Equals(s, "session_id", StringComparison.Ordinal) ) {
|
||||||
|
//The session_id value must be one greater in array
|
||||||
|
x = count + 1;
|
||||||
|
} else if ( String.Equals(s, "ref", StringComparison.Ordinal) ) {
|
||||||
|
//The OpaqueRef for vnc console must be one greater in array
|
||||||
|
y = count + 1;
|
||||||
|
} else if (String.Equals(s, "uuid", StringComparison.Ordinal) ) {
|
||||||
|
//The uuid was passed for the vnc console - it must be one
|
||||||
|
//greater in the array.
|
||||||
|
z = count + 1;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Checks for incorrect parsing of the console URL
|
||||||
|
if( x == -1 || x == count)
|
||||||
|
this.ConnectionErrorHandler(this, new System.ApplicationException("Error: The session ID has been incorrectly parsed."));
|
||||||
|
else
|
||||||
|
session_id = args[x];
|
||||||
|
|
||||||
|
if (console != null){
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_session = new Session("http://" + uri.Host , session_id);
|
||||||
|
}
|
||||||
|
catch (XenAPI.Failure f) {
|
||||||
|
if (f.ErrorDescription[0] == HOST_IS_SLAVE)
|
||||||
|
{
|
||||||
|
string m_address = f.ErrorDescription[1];
|
||||||
|
m_session = new Session("http://" + m_address, session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( (y == -1 && z == -1) || (y == count && z == count)) {
|
||||||
|
//Check for the error case where neither uuid or vm_reference have been supplied.
|
||||||
|
this.ConnectionErrorHandler(this, new System.ApplicationException("Error: The console reference has been incorrectly parsed."));
|
||||||
|
}
|
||||||
|
else if( y != -1 && y != count) {
|
||||||
|
//The console reference has been provided.
|
||||||
|
console_ref = args[y];
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( z !=-1 && z != count){
|
||||||
|
//The console uuid has been supplied instead, we must get the VM reference.
|
||||||
|
console_ref = XenAPI.Console.get_by_uuid(m_session, args[z]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_Opref = XenAPI.Console.get_VM(m_session, console_ref);
|
||||||
|
m_sourceVM = VM.get_record(m_session, vm_Opref);
|
||||||
|
|
||||||
|
// Check if this VM is PV or HVM
|
||||||
|
m_sourceIsPV = (m_sourceVM.PV_bootloader.Length != 0);
|
||||||
|
ConnectHostedConsole(m_vncClient, console, session_id);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Exception exn) {
|
||||||
|
//call the exception handler directly
|
||||||
|
this.ConnectionErrorHandler(this, exn);
|
||||||
|
}
|
||||||
|
return m_vncClient.Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnect the VNC control from the VM's console it is presently connected to
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if the disconnect worked</returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public bool Disconnect()
|
||||||
|
{
|
||||||
|
m_vncClient.ErrorOccurred -= ConnectionErrorHandler;
|
||||||
|
if (m_vncClient != null)
|
||||||
|
{
|
||||||
|
m_vncClient.Disconnect();
|
||||||
|
return !m_vncClient.Connected;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check to see if the VNCControl can be connected to ????
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public bool CanConnect() /* may not be necessary */
|
||||||
|
{
|
||||||
|
return !m_vncClient.Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the current resolution of the connected VM
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>widthxheight in pixels</returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public string GetVMResolution()
|
||||||
|
{
|
||||||
|
Size DeskSize = m_vncClient.DesktopSize;
|
||||||
|
return DeskSize.Width + "x" + DeskSize.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check to see if the VNC Control is presently connected to a VM's console
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true or false</returns>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public bool IsConnected()
|
||||||
|
{
|
||||||
|
return m_vncClient.Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the CTRL+ALT+DEL key sequence to the VM's console.
|
||||||
|
/// If its a windows VM, it brings up the login dialog.
|
||||||
|
/// </summary>
|
||||||
|
[ComVisible(true)]
|
||||||
|
public void SendCtrlAltDel()
|
||||||
|
{
|
||||||
|
/* send ctrl alt del into the connection */
|
||||||
|
if (m_vncClient != null)
|
||||||
|
m_vncClient.SendCAD();
|
||||||
|
}
|
||||||
|
#endregion // Interface implementation
|
||||||
|
|
||||||
|
#region private helper APIs
|
||||||
|
private void ConnectHostedConsole(VNCGraphicsClient v, XenAPI.Console console, string session_uuid)
|
||||||
|
{
|
||||||
|
//Program.AssertOffEventThread();
|
||||||
|
Uri uri = new Uri(console.location);
|
||||||
|
Stream stream = HTTP.CONNECT(uri, null, session_uuid, 0);
|
||||||
|
InvokeConnection(v, stream, console, m_vncPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvokeConnection(VNCGraphicsClient v, Stream stream, XenAPI.Console console, char[] vncPassword)
|
||||||
|
{
|
||||||
|
Program.Invoke(this, delegate()
|
||||||
|
{
|
||||||
|
// This is the last chance that we have to make sure that we've not already
|
||||||
|
// connected this VNCGraphicsClient. Now that we are back on the event thread,
|
||||||
|
// we're guaranteed that no-one will beat us to the v.connect() call. We
|
||||||
|
// hand over responsibility for closing the stream at that point, so we have to
|
||||||
|
// close it ourselves if the client is already connected.
|
||||||
|
if (v.Connected || v.Terminated)
|
||||||
|
{
|
||||||
|
stream.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v.SendScanCodes = !m_sourceIsPV;
|
||||||
|
v.SourceVM = m_sourceVM;
|
||||||
|
v.Console = console;
|
||||||
|
v.Focus();
|
||||||
|
v.connect(stream, vncPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream connectGuest(string ip_address, int port)
|
||||||
|
{
|
||||||
|
return HTTP.ConnectStream(new Uri(String.Format("http://{0}:{1}/", ip_address, port)), null, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PollVNCPort(Object Sender)
|
||||||
|
{
|
||||||
|
m_vncIP = null;
|
||||||
|
String openIP = PollPort(VNC_PORT, true);
|
||||||
|
|
||||||
|
if (openIP != null)
|
||||||
|
{
|
||||||
|
if (OnDetectVNC != null)
|
||||||
|
{
|
||||||
|
Program.Invoke(this, OnDetectVNC);
|
||||||
|
}
|
||||||
|
m_vncIP = openIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// scan each ip address (from the guest agent) for an open port
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
private String PollPort(int port, bool vnc)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.Debug("PollPort called");
|
||||||
|
if (m_sourceVM == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
VM vm = m_sourceVM;
|
||||||
|
|
||||||
|
XenRef<VM_guest_metrics> guestMetricsRef = vm.guest_metrics;
|
||||||
|
if (guestMetricsRef == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
VM_guest_metrics metrics = XenAPI.VM_guest_metrics.get_record(m_session, vm.guest_metrics);
|
||||||
|
if (metrics == null)
|
||||||
|
return null;
|
||||||
|
Dictionary<string, string> networks = metrics.networks;
|
||||||
|
|
||||||
|
if (networks == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<String> ipAddresses = new List<String>();
|
||||||
|
foreach (String key in networks.Keys)
|
||||||
|
{
|
||||||
|
if (key.EndsWith("ip"))
|
||||||
|
ipAddresses.Add(networks[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (String ipAddress in ipAddresses)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Stream s = connectGuest(ipAddress, port);
|
||||||
|
if (vnc)
|
||||||
|
{
|
||||||
|
//SetPendingVNCConnection(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.Close();
|
||||||
|
}
|
||||||
|
return ipAddress;
|
||||||
|
}
|
||||||
|
catch (Exception exn)
|
||||||
|
{
|
||||||
|
Log.Debug(exn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (WebException)
|
||||||
|
{
|
||||||
|
// xapi has gone away.
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
// xapi has gone away.
|
||||||
|
}
|
||||||
|
catch (XenAPI.Failure exn)
|
||||||
|
{
|
||||||
|
if (exn.ErrorDescription[0] == HANDLE_INVALID)
|
||||||
|
{
|
||||||
|
// HANDLE_INVALID is fine -- the guest metrics are not there yet.
|
||||||
|
}
|
||||||
|
else if (exn.ErrorDescription[0] == SESSION_INVALID)
|
||||||
|
{
|
||||||
|
// SESSION_INVALID is fine -- these will expire from time to time.
|
||||||
|
// We need to invalidate the session though.
|
||||||
|
//lock (activeSessionLock)
|
||||||
|
//{
|
||||||
|
m_session = null;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Warn("Exception while polling VM for port " + port + ".", exn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Warn("Exception while polling VM for port " + port + ".", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
// Test API for the harness
|
||||||
|
public Dictionary<String, String> ListConsoles(String server, int port, String username, String password)
|
||||||
|
{
|
||||||
|
XenAPI.Session session = new Session(Session.STANDARD_TIMEOUT, server, port);
|
||||||
|
Dictionary<String, String> dict = new Dictionary<String, String>();
|
||||||
|
|
||||||
|
// Authenticate with username and password. The third parameter tells the server which API version we support.
|
||||||
|
session.login_with_password(username, password, API_Version.LATEST);
|
||||||
|
List<XenRef<XenAPI.Console>> consoleRefs = XenAPI.Console.get_all(session);
|
||||||
|
foreach (XenRef<XenAPI.Console> consoleRef in consoleRefs)
|
||||||
|
{
|
||||||
|
XenAPI.Console console = XenAPI.Console.get_record(session, consoleRef);
|
||||||
|
XenAPI.VM vm = XenAPI.VM.get_record(session, console.VM);
|
||||||
|
dict.Add(vm.uuid, vm.name_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
private void ConnectionErrorHandler(object sender, Exception exn)
|
||||||
|
{
|
||||||
|
Program.Invoke(this, delegate()
|
||||||
|
{
|
||||||
|
Log.Debug(exn, exn);
|
||||||
|
if(this.OnDisconnectedCallbackEvent != null)
|
||||||
|
this.OnDisconnectedCallbackEvent(0, exn.Message);
|
||||||
|
else
|
||||||
|
MessageBox.Show(exn.Message, "VNCControl Error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResolutionChangeHandler(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
Program.Invoke(this, delegate()
|
||||||
|
{
|
||||||
|
if (this.OnResolutionChangeCallbackEvent != null)
|
||||||
|
this.OnResolutionChangeCallbackEvent(GetVMResolution());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // private helpers
|
||||||
|
|
||||||
|
#region COM registration and unregistration helpers
|
||||||
|
[ComRegisterFunction()]
|
||||||
|
public static void RegisterClass ( string key )
|
||||||
|
{
|
||||||
|
// Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
|
||||||
|
StringBuilder sb = new StringBuilder ( key ) ;
|
||||||
|
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
|
||||||
|
|
||||||
|
// Open the CLSID\{guid} key for write access
|
||||||
|
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
|
||||||
|
// And create the 'Control' key - this allows it to show up in
|
||||||
|
|
||||||
|
// the ActiveX control container
|
||||||
|
RegistryKey ctrl = k.CreateSubKey ( "Control" ) ;
|
||||||
|
ctrl.Close ( ) ;
|
||||||
|
// Next create the CodeBase entry - needed if not string named and GACced.
|
||||||
|
|
||||||
|
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
|
||||||
|
inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ;
|
||||||
|
inprocServer32.Close ( ) ;
|
||||||
|
// Finally close the main key
|
||||||
|
k.Close ( ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ComUnregisterFunction()]
|
||||||
|
public static void UnregisterClass ( string key )
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder ( key ) ;
|
||||||
|
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
|
||||||
|
|
||||||
|
// Open HKCR\CLSID\{guid} for write access
|
||||||
|
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
|
||||||
|
|
||||||
|
// Delete the 'Control' key, but don't throw an exception if it does not exist
|
||||||
|
k.DeleteSubKey ( "Control" , false ) ;
|
||||||
|
|
||||||
|
// Next open up InprocServer32
|
||||||
|
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
|
||||||
|
|
||||||
|
// And delete the CodeBase key, again not throwing if missing
|
||||||
|
k.DeleteSubKey ( "CodeBase" , false ) ;
|
||||||
|
|
||||||
|
// Finally close the main key
|
||||||
|
k.Close ( ) ;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
152
VNCControl/VNCControl.csproj
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{8513A3E9-7048-4DDB-A787-EDA202E230BF}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>XenAdmin</RootNamespace>
|
||||||
|
<AssemblyName>VNCControl</AssemblyName>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
<OldToolsVersion>2.0</OldToolsVersion>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;DEBUG;VNCControl</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;VNCControl</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<RegisterForComInterop>true</RegisterForComInterop>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\XenAdmin\Properties\Resources.Designer.cs">
|
||||||
|
<Link>Properties\Resources.Designer.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\XenModel\Messages.Designer.cs">
|
||||||
|
<Link>Messages.Designer.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\XenModel\Utils\Util.cs">
|
||||||
|
<Link>Util.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Program.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="VNCControl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="VNCControl.Designer.cs">
|
||||||
|
<DependentUpon>VNCControl.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\XenAdmin\Core\Clip.cs" />
|
||||||
|
<Compile Include="..\XenAdmin\ConsoleView\VNCGraphicsClient.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\XenAdmin\ConsoleView\IRemoteConsole.cs" />
|
||||||
|
<Compile Include="..\XenAdmin\ConsoleView\ConsoleKeyHandler.cs" />
|
||||||
|
<EmbeddedResource Include="..\XenAdmin\Properties\Resources.resx">
|
||||||
|
<Link>Properties\Resources.resx</Link>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="..\XenModel\Messages.resx">
|
||||||
|
<Link>Messages.resx</Link>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="VNCControl.resx">
|
||||||
|
<DependentUpon>VNCControl.cs</DependentUpon>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="CookComputing.XmlRpcV2, Version=2.1.0.5, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\XenServer.NET\CookComputing.XmlRpcV2.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\log4net\build\bin\net\2.0\release\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Management" />
|
||||||
|
<Reference Include="System.Security" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.XML" />
|
||||||
|
<Reference Include="XenServer, Version=6.0.50.1, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\XenServer.NET\XenServer.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\XenCenterLib\XenCenterLib.csproj">
|
||||||
|
<Project>{9861DFA1-B41F-432D-A43F-226257DEBBB9}</Project>
|
||||||
|
<Name>XenCenterLib</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\XenCenterVNC\XenCenterVNC.csproj">
|
||||||
|
<Project>{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}</Project>
|
||||||
|
<Name>XenCenterVNC</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
17
VNCControl/VNCControl.csproj.user
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishUrlHistory>
|
||||||
|
</PublishUrlHistory>
|
||||||
|
<InstallUrlHistory>
|
||||||
|
</InstallUrlHistory>
|
||||||
|
<SupportUrlHistory>
|
||||||
|
</SupportUrlHistory>
|
||||||
|
<UpdateUrlHistory>
|
||||||
|
</UpdateUrlHistory>
|
||||||
|
<BootstrapperUrlHistory>
|
||||||
|
</BootstrapperUrlHistory>
|
||||||
|
<FallbackCulture>en-US</FallbackCulture>
|
||||||
|
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||||
|
<ProjectView>ProjectFiles</ProjectView>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
120
VNCControl/VNCControl.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
36
VNCControl/VNCControl.sln
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual Studio 2008
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VNCControl", "VNCControl.csproj", "{8513A3E9-7048-4DDB-A787-EDA202E230BF}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenCenterLib", "..\XenCenterLib\XenCenterLib.csproj", "{9861DFA1-B41F-432D-A43F-226257DEBBB9}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenCenterVNC", "..\XenCenterVNC\XenCenterVNC.csproj", "{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{8513A3E9-7048-4DDB-A787-EDA202E230BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8513A3E9-7048-4DDB-A787-EDA202E230BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8513A3E9-7048-4DDB-A787-EDA202E230BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8513A3E9-7048-4DDB-A787-EDA202E230BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
95
VNCControl/VNCTest.hta
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<html>
|
||||||
|
<body color=white>
|
||||||
|
<hr>
|
||||||
|
<form name="frm" id="frm">
|
||||||
|
Server IP: <input type="text" name="server" value="">
|
||||||
|
Port: <input type="text" name="port" value="80">
|
||||||
|
<br />
|
||||||
|
VM UUID: <input type="text" name="vmuuid" value="">
|
||||||
|
<br />
|
||||||
|
Credentials:
|
||||||
|
<input type="text" name="user" value="root">
|
||||||
|
<input type="password" name="pass" value="">
|
||||||
|
<br />
|
||||||
|
Width: <input type="text" name="wdth" value="1024">
|
||||||
|
Height: <input type="text" name="hgt" value="768">
|
||||||
|
<br />
|
||||||
|
Console URL: <input type="text" name="url" size="100">
|
||||||
|
<br />
|
||||||
|
Show Border: <select name="show_border"> <option value="true">true</option><option value="false">false</option></select>
|
||||||
|
<br />
|
||||||
|
Excercise Methods:
|
||||||
|
<input type=button value="Connect" onClick="doConnect();">
|
||||||
|
<input type=button value="CanConnect" onClick="doCanConnect();">
|
||||||
|
<input type=button value="IsConnected" onClick="doIsConnected();">
|
||||||
|
<input type=button value="Disconnect" onClick="doDisconnect();">
|
||||||
|
<input type=button value="Send Ctrl+Alt+Del" onClick="doSendCtrlAltDel();">
|
||||||
|
<input type=button value="Connect Via URL" onClick="doURLConnect();">
|
||||||
|
<input type=button value="Get VM Resolution" onClick="doGetVMResolution();">
|
||||||
|
</form>
|
||||||
|
<font face=arial size=1>
|
||||||
|
<OBJECT classid="clsid:D52D9588-AB6E-425b-9D8C-74FBDA46C4F8" id="myControl1" name="myControl1" width=300 height=100 OnDisconnectedCallback="myDisconnectedCallback(eventid, msg);">
|
||||||
|
</OBJECT>
|
||||||
|
</font>
|
||||||
|
|
||||||
|
<script for="myControl1" event="OnResolutionChangeCallbackEvent(msg)" language="javascript">
|
||||||
|
function myControl1::OnResolutionChangeCallbackEvent(msg)
|
||||||
|
{
|
||||||
|
alert("The VMs Resolution has been changed to " + msg);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script for="myControl1" event="OnDisconnectedCallbackEvent(id, msg)" language="javascript">
|
||||||
|
function myControl1::OnDisconnectedCallbackEvent(id, msg)
|
||||||
|
{
|
||||||
|
alert("Diconnect ID:" + id + " " + msg);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<hr>
|
||||||
|
</body>
|
||||||
|
<script language="javascript">
|
||||||
|
function doGetVMResolution()
|
||||||
|
{
|
||||||
|
fret = myControl1.GetVMResolution();
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
|
||||||
|
function myDisconnectedCallback(eventid, msg)
|
||||||
|
{
|
||||||
|
alert("error occured");
|
||||||
|
}
|
||||||
|
|
||||||
|
function doConnect()
|
||||||
|
{
|
||||||
|
//myControl1.add_OnDisconnectedCallbackEvent(myDisconnectedCallback);
|
||||||
|
fret = myControl1.Connect(frm.server.value, frm.port.value, frm.vmuuid.value, frm.user.value, frm.pass.value, frm.wdth.value, frm.hgt.value, frm.show_border.value);
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
function doURLConnect()
|
||||||
|
{
|
||||||
|
fret = myControl1.ConnectConsole(frm.url.value, frm.wdth.value , frm.hgt.value, frm.show_border.value);
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function doCanConnect()
|
||||||
|
{
|
||||||
|
fret = myControl1.CanConnect();
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
function doIsConnected()
|
||||||
|
{
|
||||||
|
fret = myControl1.IsConnected();
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
function doDisconnect()
|
||||||
|
{
|
||||||
|
fret = myControl1.Disconnect();
|
||||||
|
alert(fret);
|
||||||
|
}
|
||||||
|
function doSendCtrlAltDel()
|
||||||
|
{
|
||||||
|
myControl1.SendCtrlAltDel();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
BIN
WixInstaller/Bitmaps/BannrBmp.bmp
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
WixInstaller/Bitmaps/DlgBmp.bmp
Normal file
After Width: | Height: | Size: 451 KiB |
BIN
WixInstaller/Bitmaps/New.ico
Normal file
After Width: | Height: | Size: 318 B |
BIN
WixInstaller/Bitmaps/Up.ico
Normal file
After Width: | Height: | Size: 318 B |
BIN
WixInstaller/Bitmaps/exclamic.ico
Normal file
After Width: | Height: | Size: 766 B |
BIN
WixInstaller/Bitmaps/info.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
161
WixInstaller/License.rtf
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
|
||||||
|
{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f36\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}{\f128\froman\fcharset238\fprq2 Times New Roman CE;}{\f129\froman\fcharset204\fprq2 Times New Roman Cyr;}
|
||||||
|
{\f131\froman\fcharset161\fprq2 Times New Roman Greek;}{\f132\froman\fcharset162\fprq2 Times New Roman Tur;}{\f133\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f134\froman\fcharset178\fprq2 Times New Roman (Arabic);}
|
||||||
|
{\f135\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f136\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f148\fmodern\fcharset238\fprq1 Courier New CE;}{\f149\fmodern\fcharset204\fprq1 Courier New Cyr;}
|
||||||
|
{\f151\fmodern\fcharset161\fprq1 Courier New Greek;}{\f152\fmodern\fcharset162\fprq1 Courier New Tur;}{\f153\fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f154\fmodern\fcharset178\fprq1 Courier New (Arabic);}
|
||||||
|
{\f155\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f156\fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f488\fswiss\fcharset238\fprq2 Tahoma CE;}{\f489\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f491\fswiss\fcharset161\fprq2 Tahoma Greek;}
|
||||||
|
{\f492\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f493\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}{\f494\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f495\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f496\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}
|
||||||
|
{\f497\fswiss\fcharset222\fprq2 Tahoma (Thai);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;
|
||||||
|
\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{
|
||||||
|
\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
|
||||||
|
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
|
||||||
|
\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0
|
||||||
|
\f2\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \styrsid3112477 Plain Text;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\rsidtbl \rsid3112477\rsid7360708\rsid10307380\rsid12669558\rsid13774519\rsid14950620}
|
||||||
|
{\*\generator Microsoft Word 11.0.6502;}{\info{\title Common Public License Version 1}{\author Bob Arnson}{\operator Bob Arnson}{\creatim\yr2005\mo7\dy28\hr23\min4}{\revtim\yr2005\mo7\dy28\hr23\min12}{\version3}{\edmins1}{\nofpages4}{\nofwords1727}
|
||||||
|
{\nofchars9845}{\*\company None of Your Business, Inc.}{\nofcharsws11549}{\vern24579}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1800\dgvorigin1440
|
||||||
|
\dghshow1\dgvshow1\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nojkernpunct\rsidroot3112477 \fet0\sectd
|
||||||
|
\linex0\endnhere\sectlinegrid360\sectdefaultcl\sectrsid10307380\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}
|
||||||
|
{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang
|
||||||
|
{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain
|
||||||
|
\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7360708 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f36\fs20\insrsid3112477\charrsid7360708 Common Public License Version 1.0
|
||||||
|
\par
|
||||||
|
\par THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 1. DEFINITIONS
|
||||||
|
\par
|
||||||
|
\par "Contribution" means:
|
||||||
|
\par
|
||||||
|
\par a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
|
||||||
|
\par
|
||||||
|
\par b) in the case of each subsequent Contributor:
|
||||||
|
\par
|
||||||
|
\par i) changes to the Program, and
|
||||||
|
\par
|
||||||
|
\par ii) additions to the Program;
|
||||||
|
\par
|
||||||
|
\par where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A
|
||||||
|
Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distrib
|
||||||
|
uted in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
|
||||||
|
\par
|
||||||
|
\par "Contributor" means any person or entity that distributes the Program.
|
||||||
|
\par
|
||||||
|
\par "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
|
||||||
|
\par
|
||||||
|
\par "Program" means the Contributions distributed in accordance with this Agreement.
|
||||||
|
\par
|
||||||
|
\par "Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 2. GRANT OF RIGHTS
|
||||||
|
\par
|
||||||
|
\par a) Subject to the terms of this Agreem
|
||||||
|
ent, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any,
|
||||||
|
and such derivative works, in source code and object code form.
|
||||||
|
\par
|
||||||
|
\par b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to
|
||||||
|
sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the
|
||||||
|
Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
|
||||||
|
\par
|
||||||
|
\par c) Recipie
|
||||||
|
nt understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity.
|
||||||
|
|
||||||
|
Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby
|
||||||
|
a
|
||||||
|
ssumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license bef
|
||||||
|
ore distributing the Program.
|
||||||
|
\par
|
||||||
|
\par d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 3. REQUIREMENTS
|
||||||
|
\par
|
||||||
|
\par A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
|
||||||
|
\par
|
||||||
|
\par a) it complies with the terms and conditions of this Agreement; and
|
||||||
|
\par
|
||||||
|
\par b) its license agreement:
|
||||||
|
\par
|
||||||
|
\par i) effectively disclaims on behalf of all Contributors all warrantie
|
||||||
|
s and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
|
||||||
|
\par
|
||||||
|
\par ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
|
||||||
|
\par
|
||||||
|
\par iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
|
||||||
|
\par
|
||||||
|
\par iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
|
||||||
|
\par
|
||||||
|
\par When the Program is made available in source code form:
|
||||||
|
\par
|
||||||
|
\par a) it must be made available under this Agreement; and
|
||||||
|
\par
|
||||||
|
\par b) a copy of this Agreement must be included with each copy of the Program.
|
||||||
|
\par
|
||||||
|
\par Contributors may not remove or alter any copyright notices contained within the Program.
|
||||||
|
\par
|
||||||
|
\par Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 4. COMMERCIAL DISTRIBUTION
|
||||||
|
\par
|
||||||
|
\par Commercial distributors of softwar
|
||||||
|
e may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering shou
|
||||||
|
l
|
||||||
|
d do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify ever
|
||||||
|
y
|
||||||
|
other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the act
|
||||||
|
s
|
||||||
|
or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property
|
||||||
|
i
|
||||||
|
nfringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense an
|
||||||
|
d any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
|
||||||
|
\par
|
||||||
|
\par For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercia
|
||||||
|
l Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Cont
|
||||||
|
ributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 5. NO WARRANTY
|
||||||
|
\par
|
||||||
|
\par EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRIN
|
||||||
|
GEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement,
|
||||||
|
including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 6. DISCLAIMER OF LIABILITY
|
||||||
|
\par
|
||||||
|
\par EXCEPT AS EXPRESSLY SET
|
||||||
|
FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LI
|
||||||
|
A
|
||||||
|
BILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
|
||||||
|
.
|
||||||
|
\par
|
||||||
|
\par
|
||||||
|
\par 7. GENERAL
|
||||||
|
\par
|
||||||
|
\par If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such
|
||||||
|
provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
|
||||||
|
\par
|
||||||
|
\par If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterc
|
||||||
|
laim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a
|
||||||
|
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminat
|
||||||
|
e as of the date such litigation is filed.
|
||||||
|
\par
|
||||||
|
\par All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such fai
|
||||||
|
lure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's
|
||||||
|
obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
|
||||||
|
\par
|
||||||
|
\par Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrig
|
||||||
|
hted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreeme
|
||||||
|
n
|
||||||
|
t. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributio
|
||||||
|
n
|
||||||
|
s) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new v
|
||||||
|
e
|
||||||
|
rsion. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the P
|
||||||
|
rogram not expressly granted under this Agreement are reserved.
|
||||||
|
\par
|
||||||
|
\par This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under
|
||||||
|
this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.}{\f36\fs20\insrsid12669558\charrsid7360708
|
||||||
|
\par }}
|
101
WixInstaller/WiSubStg.vbs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
' Windows Installer utility to add a transform or nested database as a substorage
|
||||||
|
' For use with Windows Scripting Host, CScript.exe or WScript.exe
|
||||||
|
' Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
' Demonstrates the use of the database _Storages table
|
||||||
|
'
|
||||||
|
Option Explicit
|
||||||
|
|
||||||
|
Const msiOpenDatabaseModeReadOnly = 0
|
||||||
|
Const msiOpenDatabaseModeTransact = 1
|
||||||
|
Const msiOpenDatabaseModeCreate = 3
|
||||||
|
|
||||||
|
Const msiViewModifyInsert = 1
|
||||||
|
Const msiViewModifyUpdate = 2
|
||||||
|
Const msiViewModifyAssign = 3
|
||||||
|
Const msiViewModifyReplace = 4
|
||||||
|
Const msiViewModifyDelete = 6
|
||||||
|
|
||||||
|
Const ForAppending = 8
|
||||||
|
Const ForReading = 1
|
||||||
|
Const ForWriting = 2
|
||||||
|
Const TristateTrue = -1
|
||||||
|
|
||||||
|
' Check arg count, and display help if argument not present or contains ?
|
||||||
|
Dim argCount:argCount = Wscript.Arguments.Count
|
||||||
|
If argCount > 0 Then If InStr(1, Wscript.Arguments(0), "?", vbTextCompare) > 0 Then argCount = 0
|
||||||
|
If (argCount = 0) Then
|
||||||
|
Wscript.Echo "Windows Installer database substorage managment utility" &_
|
||||||
|
vbNewLine & " 1st argument is the path to MSI database (installer package)" &_
|
||||||
|
vbNewLine & " 2nd argument is the path to a transform or database to import" &_
|
||||||
|
vbNewLine & " If the 2nd argument is missing, substorages will be listed" &_
|
||||||
|
vbNewLine & " 3rd argument is optional, the name used for the substorage" &_
|
||||||
|
vbNewLine & " If the 3rd arugment is missing, the file name is used" &_
|
||||||
|
vbNewLine & " To remove a substorage, use /D or -D as the 2nd argument" &_
|
||||||
|
vbNewLine & " followed by the name of the substorage to remove" &_
|
||||||
|
vbNewLine &_
|
||||||
|
vbNewLine & "Copyright (C) Microsoft Corporation. All rights reserved."
|
||||||
|
Wscript.Quit 1
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Connect to Windows Installer object
|
||||||
|
On Error Resume Next
|
||||||
|
Dim installer : Set installer = Nothing
|
||||||
|
Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError
|
||||||
|
|
||||||
|
' Evaluate command-line arguments and set open and update modes
|
||||||
|
Dim databasePath:databasePath = Wscript.Arguments(0)
|
||||||
|
Dim openMode : If argCount = 1 Then openMode = msiOpenDatabaseModeReadOnly Else openMode = msiOpenDatabaseModeTransact
|
||||||
|
Dim updateMode : If argCount > 1 Then updateMode = msiViewModifyAssign 'Either insert or replace existing row
|
||||||
|
Dim importPath : If argCount > 1 Then importPath = Wscript.Arguments(1)
|
||||||
|
Dim storageName : If argCount > 2 Then storageName = Wscript.Arguments(2)
|
||||||
|
If storageName = Empty And importPath <> Empty Then storageName = Right(importPath, Len(importPath) - InStrRev(importPath, "\",-1,vbTextCompare))
|
||||||
|
If UCase(importPath) = "/D" Or UCase(importPath) = "-D" Then updateMode = msiViewModifyDelete : importPath = Empty 'substorage will be deleted if no input data
|
||||||
|
|
||||||
|
' Open database and create a view on the _Storages table
|
||||||
|
Dim sqlQuery : Select Case updateMode
|
||||||
|
Case msiOpenDatabaseModeReadOnly: sqlQuery = "SELECT `Name` FROM _Storages"
|
||||||
|
Case msiViewModifyAssign: sqlQuery = "SELECT `Name`,`Data` FROM _Storages"
|
||||||
|
Case msiViewModifyDelete: sqlQuery = "SELECT `Name` FROM _Storages WHERE `Name` = ?"
|
||||||
|
End Select
|
||||||
|
Dim database : Set database = installer.OpenDatabase(databasePath, openMode) : CheckError
|
||||||
|
Dim view : Set view = database.OpenView(sqlQuery)
|
||||||
|
Dim record
|
||||||
|
|
||||||
|
If openMode = msiOpenDatabaseModeReadOnly Then 'If listing storages, simply fetch all records
|
||||||
|
Dim message, name
|
||||||
|
view.Execute : CheckError
|
||||||
|
Do
|
||||||
|
Set record = view.Fetch
|
||||||
|
If record Is Nothing Then Exit Do
|
||||||
|
name = record.StringData(1)
|
||||||
|
If message = Empty Then message = name Else message = message & vbNewLine & name
|
||||||
|
Loop
|
||||||
|
Wscript.Echo message
|
||||||
|
Else 'If adding a storage, insert a row, else if removing a storage, delete the row
|
||||||
|
Set record = installer.CreateRecord(2)
|
||||||
|
record.StringData(1) = storageName
|
||||||
|
view.Execute record : CheckError
|
||||||
|
If importPath <> Empty Then 'Insert storage - copy data into stream
|
||||||
|
record.SetStream 2, importPath : CheckError
|
||||||
|
Else 'Delete storage, fetch first to provide better error message if missing
|
||||||
|
Set record = view.Fetch
|
||||||
|
If record Is Nothing Then Wscript.Echo "Storage not present:", storageName : Wscript.Quit 2
|
||||||
|
End If
|
||||||
|
view.Modify updateMode, record : CheckError
|
||||||
|
database.Commit : CheckError
|
||||||
|
Set view = Nothing
|
||||||
|
Set database = Nothing
|
||||||
|
CheckError
|
||||||
|
End If
|
||||||
|
|
||||||
|
Sub CheckError
|
||||||
|
Dim message, errRec
|
||||||
|
If Err = 0 Then Exit Sub
|
||||||
|
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
|
||||||
|
If Not installer Is Nothing Then
|
||||||
|
Set errRec = installer.LastErrorRecord
|
||||||
|
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
|
||||||
|
End If
|
||||||
|
Wscript.Echo message
|
||||||
|
Wscript.Quit 2
|
||||||
|
End Sub
|
178
WixInstaller/XenCenter.l10n.diff
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
# Copyright (c) Citrix Systems Inc.
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
--- XenCenter.wxs 2012-04-27 15:35:27.662068200 +0100
|
||||||
|
+++ XenCenter.l10n.wxs 2012-04-27 16:28:00.539817200 +0100
|
||||||
|
@@ -4,7 +4,7 @@
|
||||||
|
<?define UpgradeCode="{EA0EF50F-5CC6-452B-B09F-3F5EC564899D}"?>
|
||||||
|
<?define ProductCode="{65AE1345-A520-456D-8A19-2F52D43D3A09}"?>
|
||||||
|
<Product Id="$(var.ProductCode)" Name="Citrix XenCenter" Language="$(env.WixLangId)" Version="$(var.ProductVersion)" Manufacturer="Citrix Systems, Inc." UpgradeCode="$(var.UpgradeCode)">
|
||||||
|
- <Package Description="Citrix XenCenter" Comments="none." InstallerVersion="200" Compressed="yes" />
|
||||||
|
+ <Package Languages="1033,1041,2052,1028" Description="Citrix XenCenter" Comments="none." InstallerVersion="200" Compressed="yes" />
|
||||||
|
<Media Id="1" Cabinet="XenCenter.cab" EmbedCab="yes" />
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="ProgramFilesFolder">
|
||||||
|
@@ -54,64 +54,64 @@
|
||||||
|
<File Id="XslicIcon" Source="..\XenAdmin\Images\file_license.ico" />
|
||||||
|
<File Id="XkbIcon" Source="..\XenAdmin\Images\file_backup.ico" />
|
||||||
|
<File Id="XsupdateIcon" Source="..\XenAdmin\Images\file_updates.ico" />
|
||||||
|
- <!-- Define XVA extension -->
|
||||||
|
- <ProgId Id="XenCenter.xva" Description="XVA File" Icon="XvaIcon">
|
||||||
|
+ <!-- Define XVA extension -->
|
||||||
|
+ <ProgId Id="XenCenter.xva" Description="!(loc.XVA_File)" Icon="XvaIcon">
|
||||||
|
<Extension Id="xva" ContentType="application/xva">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define OVF extension -->
|
||||||
|
- <ProgId Id="XenCenter.ovf" Description="OVF File" Icon="XvaIcon">
|
||||||
|
+ <!-- Define OVF extension -->
|
||||||
|
+ <ProgId Id="XenCenter.ovf" Description="!(loc.OVF_File)" Icon="XvaIcon">
|
||||||
|
<Extension Id="ovf" ContentType="application/ovf">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define OVA extension -->
|
||||||
|
- <ProgId Id="XenCenter.ova" Description="OVA File" Icon="XvaIcon">
|
||||||
|
+ <!-- Define OVA extension -->
|
||||||
|
+ <ProgId Id="XenCenter.ova" Description="!(loc.OVA_File)" Icon="XvaIcon">
|
||||||
|
<Extension Id="ova" ContentType="application/ova">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define VHD extension -->
|
||||||
|
- <ProgId Id="XenCenter.vhd" Description="VHD File" Icon="XvaIcon">
|
||||||
|
+ <!-- Define VHD extension -->
|
||||||
|
+ <ProgId Id="XenCenter.vhd" Description="!(loc.VHD_File)" Icon="XvaIcon">
|
||||||
|
<Extension Id="vhd" ContentType="application/vhd">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define VMDK extension -->
|
||||||
|
- <ProgId Id="XenCenter.vmdk" Description="VMDK File" Icon="XvaIcon">
|
||||||
|
+ <!-- Define VMDK extension -->
|
||||||
|
+ <ProgId Id="XenCenter.vmdk" Description="!(loc.VMDK_File)" Icon="XvaIcon">
|
||||||
|
<Extension Id="vmdk" ContentType="application/vmdk">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define XSLIC extension -->
|
||||||
|
- <ProgId Id="XenCenter.xslic" Description="XenServer License File" Icon="XslicIcon">
|
||||||
|
+ <!-- Define XSLIC extension -->
|
||||||
|
+ <ProgId Id="XenCenter.xslic" Description="!(loc.XenServer_License_File)" Icon="XslicIcon">
|
||||||
|
<Extension Id="xslic" ContentType="application/xslic">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="license "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="license "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
- <!-- Define XBK extension -->
|
||||||
|
- <ProgId Id="XenCenter.xbk" Description="XenServer Backup File" Icon="XkbIcon">
|
||||||
|
+ <!-- Define XBK extension -->
|
||||||
|
+ <ProgId Id="XenCenter.xbk" Description="!(loc.XenServer_Backup_File)" Icon="XkbIcon">
|
||||||
|
<Extension Id="xbk" ContentType="application/xbk">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="restore "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="restore "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XSUPDATE extension -->
|
||||||
|
- <ProgId Id="XenCenter.xsupdate" Description="XenServer Update File" Icon="XsupdateIcon">
|
||||||
|
+ <ProgId Id="XenCenter.xsupdate" Description="!(loc.XenServer_Update_File)" Icon="XsupdateIcon">
|
||||||
|
<Extension Id="xsupdate" ContentType="application/xsupdate">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XSOEM extension -->
|
||||||
|
- <ProgId Id="XenCenter.xsoem" Description="XenServer OEM Update File" Icon="XsupdateIcon">
|
||||||
|
+ <ProgId Id="XenCenter.xsoem" Description="!(loc.XenServer_OEM_Update_File)" Icon="XsupdateIcon">
|
||||||
|
<Extension Id="xsoem" ContentType="application/xsoem">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XENSEARCH extension -->
|
||||||
|
- <ProgId Id="XenCenter.xensearch" Description="XenCenter Saved Search" Icon="XenCenterIcon">
|
||||||
|
+ <ProgId Id="XenCenter.xensearch" Description="!(loc.XenCenter_Saved_Search)" Icon="XenCenterIcon">
|
||||||
|
<Extension Id="xensearch" ContentType="application/xensearch">
|
||||||
|
- <Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="xensearch "%1"" />
|
||||||
|
+ <Verb Id="open" Command="!(loc.Open)" TargetFile="XenCenterEXE" Argument="xensearch "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
</Component>
|
||||||
|
@@ -130,6 +130,30 @@
|
||||||
|
<Component Id="HelpFiles" Guid="EA8D4F56-A94A-467c-9E6B-F3DC26F95B1E">
|
||||||
|
<File Id="XenCenterCHM" Source="..\XenAdmin\bin\Release\Help\XenCenter.chm" />
|
||||||
|
<File Id="WLBCHM" Source="..\XenAdmin\bin\Release\Help\WLB.chm" />
|
||||||
|
+ <File Id="XenCenterJaCHM" Source="..\XenAdmin\bin\Release\Help\XenCenter.ja.chm" />
|
||||||
|
+ <File Id="WLBJaCHM" Source="..\XenAdmin\bin\Release\Help\WLB.ja.chm" />
|
||||||
|
+ <File Id="XenCenterScCHM" Source="..\XenAdmin\bin\Release\Help\XenCenter.zh-CN.chm" />
|
||||||
|
+ <File Id="WLBScCHM" Source="..\XenAdmin\bin\Release\Help\WLB.zh-CN.chm" />
|
||||||
|
+ </Component>
|
||||||
|
+ </Directory>
|
||||||
|
+ <Directory Id="ja" Name="ja">
|
||||||
|
+ <Component Id="JaResources" Guid="D3ADD803-AF0B-4787-AC29-C6387FFF403B">
|
||||||
|
+ <File Id="JaResourcesDLL" Source="..\XenAdmin\bin\Release\ja\XenCenterMain.resources.dll" />
|
||||||
|
+ <File Id="JaXenModResourcesDLL" Source="..\XenAdmin\bin\Release\ja\XenModel.resources.dll" />
|
||||||
|
+ <File Id="JaMicRepVwrCmnResDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.Common.resources.dll" />
|
||||||
|
+ <File Id="JaMicRepVwrPrcObjResDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.WinForms.resources.dll" />
|
||||||
|
+ <File Id="JaXOResourcesDLL" Source="..\XenOvfApi\bin\Release\ja\XenOvf.resources.dll" />
|
||||||
|
+ <File Id="JaXOTResourcesDLL" Source="..\XenOvfTransport\bin\Release\ja\XenOvfTransport.resources.dll" />
|
||||||
|
+ </Component>
|
||||||
|
+ </Directory>
|
||||||
|
+ <Directory Id="sc" Name="zh-CN">
|
||||||
|
+ <Component Id="ScResources" Guid="381e9319-f0c4-4c69-a1c2-0a2fc725bd19">
|
||||||
|
+ <File Id="ScResourcesDLL" Source="..\XenAdmin\bin\Release\zh-CN\XenCenterMain.resources.dll" />
|
||||||
|
+ <File Id="ScXenModResourcesDLL" Source="..\XenAdmin\bin\Release\zh-CN\XenModel.resources.dll" />
|
||||||
|
+ <File Id="ScMicRepVwrCmnResDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.Common.resources.dll" />
|
||||||
|
+ <File Id="ScMicRepVwrPrcObjResDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.WinForms.resources.dll" />
|
||||||
|
+ <File Id="ScXOResourcesDLL" Source="..\XenOvfApi\bin\Release\zh-CN\XenOvf.resources.dll" />
|
||||||
|
+ <File Id="ScXOTResourcesDLL" Source="..\XenOvfTransport\bin\Release\zh-CN\XenOvfTransport.resources.dll" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="EXTERNALTOOLS" ShortName="External" Name="External Tools">
|
||||||
|
@@ -179,6 +203,8 @@
|
||||||
|
<Feature Id="MainProgram" Title="Citrix XenCenter" Description="The complete package" Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no" InstallDefault="local" Absent="disallow">
|
||||||
|
<ComponentRef Id="MainExecutable" />
|
||||||
|
<ComponentRef Id="HelpFiles" />
|
||||||
|
+ <ComponentRef Id="JaResources" />
|
||||||
|
+ <ComponentRef Id="ScResources" />
|
||||||
|
<ComponentRef Id="ReportViewer" />
|
||||||
|
<ComponentRef Id="TestResources" />
|
||||||
|
<ComponentRef Id="SchemasFilesComponent" />
|
||||||
|
@@ -195,7 +221,7 @@
|
||||||
|
</Property>
|
||||||
|
<Property Id="ARPPRODUCTICON" Value="XenCenterICO" />
|
||||||
|
<MajorUpgrade AllowDowngrades="no" AllowSameVersionUpgrades="yes" DowngradeErrorMessage="!(loc.ErrorNewerProduct)" Schedule="afterInstallInitialize"/>
|
||||||
|
- <Condition Message=".NET Framework 3.5 is required for this installation.">FRAMEWORK35 >= "#1"</Condition>
|
||||||
|
+ <Condition Message="!(loc.Required_For_Installation)">FRAMEWORK35 >= "#1"</Condition>
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<AppSearch Sequence="50" />
|
||||||
|
<FindRelatedProducts Before="LaunchConditions" />
|
263
WixInstaller/XenCenter.wxs
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright (c) Citrix Systems Inc.
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||||
|
<?define ProductVersion="1.0.0" ?>
|
||||||
|
<?define UpgradeCode="{EA0EF50F-5CC6-452B-B09F-3F5EC564899D}"?>
|
||||||
|
<?define ProductCode="{65AE1345-A520-456D-8A19-2F52D43D3A09}"?>
|
||||||
|
<Product Id="$(var.ProductCode)" Name="Citrix XenCenter" Language="$(env.WixLangId)" Version="$(var.ProductVersion)" Manufacturer="Citrix Systems, Inc." UpgradeCode="$(var.UpgradeCode)">
|
||||||
|
<Package Description="Citrix XenCenter" Comments="none." InstallerVersion="200" Compressed="yes" />
|
||||||
|
<Media Id="1" Cabinet="XenCenter.cab" EmbedCab="yes" />
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="ProgramFilesFolder">
|
||||||
|
<Directory Id="Citrix" Name="Citrix">
|
||||||
|
<Directory Id="INSTALLDIR" ShortName="XenCente" Name="XenCenter">
|
||||||
|
<Component Id="ReportViewer" Guid="D01090B9-1988-4ab4-B48A-D0B6161FAA48">
|
||||||
|
<File Id="MicRepVwrCmnDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.Common.dll" />
|
||||||
|
<File Id="MicRepVwrPrcObjDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.ProcessingObjectModel.dll" />
|
||||||
|
<File Id="MicRepVwrWFDLL" Source="..\XenAdmin\ReportViewer\Microsoft.ReportViewer.WinForms.dll" />
|
||||||
|
<File Id="HostHealthHistoryRDLC" Source="..\XenAdmin\ReportViewer\host_health_history.rdlc" />
|
||||||
|
<File Id="PoolHealthRDLC" Source="..\XenAdmin\ReportViewer\pool_health.rdlc" />
|
||||||
|
<File Id="opt_perf_histRDLC" Source="..\XenAdmin\ReportViewer\optimization_performance_history.rdlc" />
|
||||||
|
<File Id="vmMovementHistoryRDLC" Source="..\XenAdmin\ReportViewer\vm_movement_history.rdlc" />
|
||||||
|
<File Id="vmPerformanceHistoryRDLC" Source="..\XenAdmin\ReportViewer\vm_performance_history.rdlc" />
|
||||||
|
<File Id="PoolHealthHistoryRDLC" Source="..\XenAdmin\ReportViewer\pool_health_history.rdlc" />
|
||||||
|
<File Id="ReportConfigXML" Source="..\XenAdmin\ReportViewer\reports.xml" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="MainExecutable" Guid="64FEF765-7593-4612-8D4D-EE81CF704DEB">
|
||||||
|
<!-- XenCenter EXE -->
|
||||||
|
<File Id="XenCenterEXE" Source="..\XenAdmin\bin\Release\XenCenter.exe" KeyPath="yes" />
|
||||||
|
<!-- other EXEs -->
|
||||||
|
<File Id="XenCenterMainEXE" Source="..\XenAdmin\bin\Release\XenCenterMain.exe" />
|
||||||
|
<File Id="XeEXE" Source="..\xe\bin\Release\xe.exe" />
|
||||||
|
<File Id="xva_verifyEXE" Source="..\xva_verify\bin\Release\xva_verify.exe" />
|
||||||
|
<!-- config -->
|
||||||
|
<File Id="XenCenterMainCONFIG" Source="..\XenAdmin\bin\Release\XenCenterMain.exe.config" />
|
||||||
|
<!-- DLLs -->
|
||||||
|
<File Id="CommandLibDLL" Source="..\XenAdmin\bin\Release\CommandLib.dll" />
|
||||||
|
<File Id="CookComputingDLL" Source="..\XenAdmin\bin\Release\CookComputing.XmlRpcV2.dll" />
|
||||||
|
<File Id="log4netDLL" Source="..\XenAdmin\bin\Release\log4net.dll" />
|
||||||
|
<File Id="SharpZipLibDLL" Source="..\XenAdmin\bin\Release\ICSharpCode.SharpZipLib.dll" />
|
||||||
|
<File Id="IonicZipDLL" Source="..\XenAdmin\bin\Release\Ionic.Zip.dll" />
|
||||||
|
<File Id="MSTSCLibDLL" Source="..\XenAdmin\bin\Release\MSTSCLib.dll" />
|
||||||
|
<File Id="XenCenterLibDLL" Source="..\XenAdmin\bin\Release\XenCenterLib.dll" />
|
||||||
|
<File Id="XenCenterVNCDLL" Source="..\XenAdmin\bin\Release\XenCenterVNC.dll" />
|
||||||
|
<File Id="XenModelDLL" Source="..\XenAdmin\bin\Release\XenModel.dll" />
|
||||||
|
<File Id="DiscUtils" Source="..\XenAdmin\bin\Release\DiscUtils.dll" />
|
||||||
|
<File Id="XenOvf" Source="..\XenAdmin\bin\Release\XenOvf.dll" />
|
||||||
|
<File Id="XenOvfTransport" Source="..\XenAdmin\bin\Release\XenOvfTransport.dll" />
|
||||||
|
<!-- Icons -->
|
||||||
|
<File Id="XenCenterIcon" Source="..\XenAdmin\AppIcon.ico" />
|
||||||
|
<File Id="hotfixCowley" Source="..\XenAdmin\XS56EFP1002.xsupdate" />
|
||||||
|
<File Id="hotfixMNR" Source="..\XenAdmin\XS56E008.xsupdate" />
|
||||||
|
<File Id="hotfixBoston" Source="..\XenAdmin\XS60E001.xsupdate" />
|
||||||
|
<File Id="hotfixBostonSanibel" Source="..\XenAdmin\XS60E009.xsupdate" />
|
||||||
|
<File Id="XvaIcon" Source="..\XenAdmin\Images\file_vm.ico" />
|
||||||
|
<File Id="XslicIcon" Source="..\XenAdmin\Images\file_license.ico" />
|
||||||
|
<File Id="XkbIcon" Source="..\XenAdmin\Images\file_backup.ico" />
|
||||||
|
<File Id="XsupdateIcon" Source="..\XenAdmin\Images\file_updates.ico" />
|
||||||
|
<!-- Define XVA extension -->
|
||||||
|
<ProgId Id="XenCenter.xva" Description="XVA File" Icon="XvaIcon">
|
||||||
|
<Extension Id="xva" ContentType="application/xva">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define OVF extension -->
|
||||||
|
<ProgId Id="XenCenter.ovf" Description="OVF File" Icon="XvaIcon">
|
||||||
|
<Extension Id="ovf" ContentType="application/ovf">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define OVA extension -->
|
||||||
|
<ProgId Id="XenCenter.ova" Description="OVA File" Icon="XvaIcon">
|
||||||
|
<Extension Id="ova" ContentType="application/ova">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define VHD extension -->
|
||||||
|
<ProgId Id="XenCenter.vhd" Description="VHD File" Icon="XvaIcon">
|
||||||
|
<Extension Id="vhd" ContentType="application/vhd">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define VMDK extension -->
|
||||||
|
<ProgId Id="XenCenter.vmdk" Description="VMDK File" Icon="XvaIcon">
|
||||||
|
<Extension Id="vmdk" ContentType="application/vmdk">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="import "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XSLIC extension -->
|
||||||
|
<ProgId Id="XenCenter.xslic" Description="XenServer License File" Icon="XslicIcon">
|
||||||
|
<Extension Id="xslic" ContentType="application/xslic">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="license "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XBK extension -->
|
||||||
|
<ProgId Id="XenCenter.xbk" Description="XenServer Backup File" Icon="XkbIcon">
|
||||||
|
<Extension Id="xbk" ContentType="application/xbk">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="restore "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XSUPDATE extension -->
|
||||||
|
<ProgId Id="XenCenter.xsupdate" Description="XenServer Update File" Icon="XsupdateIcon">
|
||||||
|
<Extension Id="xsupdate" ContentType="application/xsupdate">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XSOEM extension -->
|
||||||
|
<ProgId Id="XenCenter.xsoem" Description="XenServer OEM Update File" Icon="XsupdateIcon">
|
||||||
|
<Extension Id="xsoem" ContentType="application/xsoem">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="update "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
<!-- Define XENSEARCH extension -->
|
||||||
|
<ProgId Id="XenCenter.xensearch" Description="XenCenter Saved Search" Icon="XenCenterIcon">
|
||||||
|
<Extension Id="xensearch" ContentType="application/xensearch">
|
||||||
|
<Verb Id="open" Command="Open" TargetFile="XenCenterEXE" Argument="xensearch "%1"" />
|
||||||
|
</Extension>
|
||||||
|
</ProgId>
|
||||||
|
</Component>
|
||||||
|
<!-- TestResources -->
|
||||||
|
<Directory Id="TestReso" ShortName="TestReso" Name="TestResources">
|
||||||
|
<Component Id="TestResources" Guid="FA8D4F56-A94A-467c-9E6B-F3DC26F95B1E">
|
||||||
|
<File Source="..\XenAdmin\bin\Release\TestResources\credits.xml" />
|
||||||
|
<File Id="george_1.xml" Source="..\XenAdmin\bin\Release\TestResources\george-xapi-db.xml" />
|
||||||
|
<File Id="george_2.xml" Source="..\XenAdmin\bin\Release\TestResources\george-xapi-db-2.xml" />
|
||||||
|
<File Id="interes1.xml" Source="..\XenAdmin\bin\Release\TestResources\interesting-development.xml" />
|
||||||
|
<File Id="interes2.xml" Source="..\XenAdmin\bin\Release\TestResources\interesting-production.xml" />
|
||||||
|
<File Id="interes3.xml" Source="..\XenAdmin\bin\Release\TestResources\interesting-xenapp.xml" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="Help" Name="Help">
|
||||||
|
<Component Id="HelpFiles" Guid="EA8D4F56-A94A-467c-9E6B-F3DC26F95B1E">
|
||||||
|
<File Id="XenCenterCHM" Source="..\XenAdmin\bin\Release\Help\XenCenter.chm" />
|
||||||
|
<File Id="WLBCHM" Source="..\XenAdmin\bin\Release\Help\WLB.chm" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="EXTERNALTOOLS" ShortName="External" Name="External Tools">
|
||||||
|
<Component Id="ExternalToolsComponent" Guid="D5FC0252-C97B-46e7-9633-A6B68EDB6654">
|
||||||
|
<File Id="XENSERVERLINUXFIXUP" Source="..\XenOvfApi\External Tools\xenserver-linuxfixup-disk.iso" />
|
||||||
|
<File Id="REFERENCEVHD" Source="..\XenOvfApi\External Tools\bootablereference.vhd.bz2" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="SCHEMAS" Name="Schemas">
|
||||||
|
<Component Id="SchemasFilesComponent" Guid="E2186CD8-5064-4414-8AD7-E4495B6A3204">
|
||||||
|
<File Id="CIMOSXML" Source="..\XenAdmin\bin\Release\Schemas\CIM_OperatingSystem.xml" />
|
||||||
|
<File Id="CIMRASDXML" Source="..\XenAdmin\bin\Release\Schemas\CIM_ResourceAllocationSettingData.xml" />
|
||||||
|
<File Id="CIMRASDXSD" Source="..\XenAdmin\bin\Release\Schemas\CIM_ResourceAllocationSettingData.xsd" />
|
||||||
|
<File Id="CIMVSSDXML" Source="..\XenAdmin\bin\Release\Schemas\CIM_VirtualSystemSettingData.xml" />
|
||||||
|
<File Id="CIMVSSDXSD" Source="..\XenAdmin\bin\Release\Schemas\CIM_VirtualSystemSettingData.xsd" />
|
||||||
|
<File Id="COMMONXSD" Source="..\XenAdmin\bin\Release\Schemas\common.xsd" />
|
||||||
|
<File Id="DSP8023XSD" Source="..\XenAdmin\bin\Release\Schemas\DSP8023.xsd" />
|
||||||
|
<File Id="DSP8027XSD" Source="..\XenAdmin\bin\Release\Schemas\DSP8027.xsd" />
|
||||||
|
<File Id="SECEXTXSD" Source="..\XenAdmin\bin\Release\Schemas\secext-1.0.xsd" />
|
||||||
|
<File Id="WSSUTILXSD" Source="..\XenAdmin\bin\Release\Schemas\wss-utility-1.0.xsd" />
|
||||||
|
<File Id="XENCXSD" Source="..\XenAdmin\bin\Release\Schemas\xenc-schema.xsd" />
|
||||||
|
<File Id="XMLXSD" Source="..\XenAdmin\bin\Release\Schemas\xml.xsd" />
|
||||||
|
<File Id="XMLDSIGXSD" Source="..\XenAdmin\bin\Release\Schemas\xmldsig-core-schema.xsd" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
<Directory Id="ProgramMenuFolder">
|
||||||
|
<Directory Id="ApplicationProgramsFolder" Name="Citrix" />
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
<DirectoryRef Id="TARGETDIR">
|
||||||
|
<Component Id="RegistryEntries" Guid="193BAE1F-F2AE-4451-94DC-4B105DB5179C">
|
||||||
|
<RegistryKey Root="HKMU" Key="Software\Citrix\XenCenter">
|
||||||
|
<RegistryValue Type="string" Name="InstallDir" Value="[INSTALLDIR]" />
|
||||||
|
</RegistryKey>
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||||
|
<Component Id="ApplicationShortcut" Guid="6B875059-26BC-4fa7-ACB7-0B9A4E4665CA">
|
||||||
|
<Shortcut Id="startmenuXenCenter" ShortName="XenCen50" Name="Citrix XenCenter" Description="XenCenter Shortcut" Target="[INSTALLDIR]XenCenter.exe" WorkingDirectory="INSTALLDIR" Icon="XenCenterICO" />
|
||||||
|
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall" />
|
||||||
|
<RegistryValue Root="HKCU" Key="Software\Microsoft\XenCenter" Name="installed" Type="integer" Value="1" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<Feature Id="MainProgram" Title="Citrix XenCenter" Description="The complete package" Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no" InstallDefault="local" Absent="disallow">
|
||||||
|
<ComponentRef Id="MainExecutable" />
|
||||||
|
<ComponentRef Id="HelpFiles" />
|
||||||
|
<ComponentRef Id="ReportViewer" />
|
||||||
|
<ComponentRef Id="TestResources" />
|
||||||
|
<ComponentRef Id="SchemasFilesComponent" />
|
||||||
|
<ComponentRef Id="ExternalToolsComponent" />
|
||||||
|
<ComponentRef Id="RegistryEntries" />
|
||||||
|
<ComponentRef Id="ApplicationShortcut" />
|
||||||
|
</Feature>
|
||||||
|
<UIRef Id="My_WixUI_InstallDir" />
|
||||||
|
<UIRef Id="WixUI_ErrorProgressText" />
|
||||||
|
<Property Id="Install_All" Value="0" />
|
||||||
|
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
|
||||||
|
<Property Id="FRAMEWORK35">
|
||||||
|
<RegistrySearch Id="Framework35Registry" Type="raw" Root="HKLM" Key="Software\Microsoft\NET Framework Setup\NDP\v3.5" Name="Install" />
|
||||||
|
</Property>
|
||||||
|
<Property Id="ARPPRODUCTICON" Value="XenCenterICO" />
|
||||||
|
<MajorUpgrade AllowDowngrades="no" AllowSameVersionUpgrades="yes" DowngradeErrorMessage="!(loc.ErrorNewerProduct)" Schedule="afterInstallInitialize"/>
|
||||||
|
<Condition Message=".NET Framework 3.5 is required for this installation.">FRAMEWORK35 >= "#1"</Condition>
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<AppSearch Sequence="50" />
|
||||||
|
<FindRelatedProducts Before="LaunchConditions" />
|
||||||
|
<LaunchConditions Sequence="100" />
|
||||||
|
<ValidateProductID Sequence="700" />
|
||||||
|
<CostInitialize Sequence="800" />
|
||||||
|
<FileCost Sequence="900" />
|
||||||
|
<CostFinalize Sequence="1000" />
|
||||||
|
<MigrateFeatureStates Sequence="1200" />
|
||||||
|
<InstallValidate Sequence="1400" />
|
||||||
|
<InstallInitialize Sequence="1500" />
|
||||||
|
<ProcessComponents Sequence="1600" />
|
||||||
|
<UnpublishFeatures Sequence="1800" />
|
||||||
|
<RemoveRegistryValues Sequence="2600" />
|
||||||
|
<RemoveShortcuts Sequence="3200" />
|
||||||
|
<RemoveFiles Sequence="3500" />
|
||||||
|
<InstallFiles Sequence="4000" />
|
||||||
|
<CreateShortcuts Sequence="4500" />
|
||||||
|
<WriteRegistryValues Sequence="5000" />
|
||||||
|
<RegisterUser Sequence="6000" />
|
||||||
|
<RegisterProduct Sequence="6100" />
|
||||||
|
<PublishFeatures Sequence="6300" />
|
||||||
|
<PublishProduct Sequence="6400" />
|
||||||
|
<InstallFinalize Sequence="6600" />
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
<InstallUISequence>
|
||||||
|
<FindRelatedProducts Before="LaunchConditions" />
|
||||||
|
<ExecuteAction Sequence="1102" />
|
||||||
|
</InstallUISequence>
|
||||||
|
<Icon Id="XenCenterICO" SourceFile="..\XenAdmin\AppIcon.ico" />
|
||||||
|
</Product>
|
||||||
|
</Wix>
|
195
WixInstaller/codepagechange.vbs
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
'
|
||||||
|
' CCCCC PPPPP MM MM Citrix
|
||||||
|
' CC PP P MMM MMM Password
|
||||||
|
' CC PPPPP MM M MM Manager
|
||||||
|
' CCCCC PP MM MM
|
||||||
|
'
|
||||||
|
' Copyright 1990-2009 Citrix Systems, Inc. All rights reserved.
|
||||||
|
'
|
||||||
|
' This file changes codepages; product code; package codes for appropriate languages.
|
||||||
|
' arguments <language> , <projectName>
|
||||||
|
|
||||||
|
Option Explicit
|
||||||
|
Dim language,packageType, projectName
|
||||||
|
language=wscript.Arguments(0)
|
||||||
|
projectName=wscript.Arguments(1)
|
||||||
|
Const ForReading = 1
|
||||||
|
Const ForWriting = 2
|
||||||
|
Const TristateFalse = 0
|
||||||
|
Const msiViewModifyAssign = 3
|
||||||
|
|
||||||
|
' source- compile.vbs IM tree
|
||||||
|
If language <> "" Then
|
||||||
|
Dim languageCode, codePage, packageCode
|
||||||
|
packageType = UCase(Right(projectName, 3))
|
||||||
|
language = UCase(language)
|
||||||
|
If language = "ENGLISH" Or language = "EN" Then
|
||||||
|
languageCode = 1033
|
||||||
|
packageCode = "1033"
|
||||||
|
codePage = 1252
|
||||||
|
ElseIf language = "GERMAN" Or language = "DE" Then
|
||||||
|
languageCode = 1031
|
||||||
|
packageCode= "1031"
|
||||||
|
codePage = 1252
|
||||||
|
ElseIf language = "FRENCH" Or language = "FR" Then
|
||||||
|
languageCode = 1036
|
||||||
|
packageCode = "1036"
|
||||||
|
codePage = 1252
|
||||||
|
ElseIf language = "SPANISH" Or language = "ES" Then
|
||||||
|
languageCode = 3082
|
||||||
|
packageCode = "3082"
|
||||||
|
codePage = 1252
|
||||||
|
ElseIf language = "JAPANESE" Or language = "JA" Then
|
||||||
|
languageCode = 1041
|
||||||
|
packageCode = "1041"
|
||||||
|
codePage = 932
|
||||||
|
ElseIf language = "KOREAN" Or language = "KO" Then
|
||||||
|
languageCode = 1042
|
||||||
|
packageCode = "1042"
|
||||||
|
codePage = 949
|
||||||
|
ElseIf language = "CHINESESIMPLIFIED" Or language = "ZH-CN" Then
|
||||||
|
languageCode = 2052
|
||||||
|
packageCode = "2052"
|
||||||
|
codePage = 936
|
||||||
|
ElseIf language = "CHINESETRADITIONAL" Or language = "ZH-TW" Then
|
||||||
|
languageCode = 1028
|
||||||
|
packageCode = "1028"
|
||||||
|
codePage = 950
|
||||||
|
Else
|
||||||
|
Wscript.Echo "ERROR: Unsupported language '" & language & "'"
|
||||||
|
Wscript.Quit 1
|
||||||
|
End If
|
||||||
|
FixLanguageInformation projectName, "Codepage", codePage
|
||||||
|
FixLanguageInformation projectName, "Package", packageCode
|
||||||
|
FixLanguageInformation projectName, "Product", languageCode
|
||||||
|
|
||||||
|
|
||||||
|
End If
|
||||||
|
|
||||||
|
Wscript.Echo "CodePageChange script complete"
|
||||||
|
Wscript.Quit 0
|
||||||
|
|
||||||
|
Sub FixLanguageInformation(package, key, code)
|
||||||
|
Dim installer : Set installer = Nothing
|
||||||
|
Set installer = Wscript.CreateObject("WindowsInstaller.Installer")
|
||||||
|
|
||||||
|
|
||||||
|
' Open database
|
||||||
|
Dim databasePath:databasePath = projectName
|
||||||
|
|
||||||
|
Dim database : Set database = installer.OpenDatabase(databasePath, 1): CheckError
|
||||||
|
|
||||||
|
' Update value if supplied
|
||||||
|
|
||||||
|
Dim value:value = code
|
||||||
|
Select Case UCase(key)
|
||||||
|
Case "PACKAGE" : SetPackageLanguage database, value
|
||||||
|
Case "PRODUCT" : SetProductLanguage installer, database, value
|
||||||
|
Case "CODEPAGE" : SetDatabaseCodepage database, value
|
||||||
|
Case Else : Fail "Invalid value keyword"
|
||||||
|
End Select
|
||||||
|
' Extract language info and compose report message
|
||||||
|
|
||||||
|
|
||||||
|
database.Commit ' no effect if opened ReadOnly
|
||||||
|
Set database = nothing
|
||||||
|
|
||||||
|
Set installer = nothing
|
||||||
|
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
' Get language list from summary information
|
||||||
|
Function PackageLanguage(database)
|
||||||
|
On Error Resume Next
|
||||||
|
Dim sumInfo : Set sumInfo = database.SummaryInformation(0) : CheckError
|
||||||
|
Dim template : template = sumInfo.Property(7) : CheckError
|
||||||
|
Dim iDelim:iDelim = InStr(1, template, ";", vbTextCompare)
|
||||||
|
If iDelim = 0 Then template = "Not specified!"
|
||||||
|
PackageLanguage = Right(template, Len(template) - iDelim)
|
||||||
|
If Len(PackageLanguage) = 0 Then PackageLanguage = "0"
|
||||||
|
End Function
|
||||||
|
|
||||||
|
' Get ProductLanguge property from Property table
|
||||||
|
Function ProductLanguage(database)
|
||||||
|
On Error Resume Next
|
||||||
|
Dim view : Set view = database.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductLanguage'")
|
||||||
|
view.Execute : CheckError
|
||||||
|
Dim record : Set record = view.Fetch : CheckError
|
||||||
|
If record Is Nothing Then ProductLanguage = "Not specified!" Else ProductLanguage = record.IntegerData(1)
|
||||||
|
End Function
|
||||||
|
|
||||||
|
' Get ANSI codepage of database text data
|
||||||
|
Function DatabaseCodepage(database)
|
||||||
|
On Error Resume Next
|
||||||
|
Dim WshShell : Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckError
|
||||||
|
Dim tempPath:tempPath = WshShell.ExpandEnvironmentStrings("%TEMP%") : CheckError
|
||||||
|
database.Export "_ForceCodepage", tempPath, "codepage.idt" : CheckError
|
||||||
|
Dim fileSys : Set fileSys = CreateObject("Scripting.FileSystemObject") : CheckError
|
||||||
|
Dim file : Set file = fileSys.OpenTextFile(tempPath & "\codepage.idt", ForReading, False, TristateFalse) : CheckError
|
||||||
|
file.ReadLine ' skip column name record
|
||||||
|
file.ReadLine ' skip column defn record
|
||||||
|
DatabaseCodepage = file.ReadLine
|
||||||
|
Dim iDelim:iDelim = InStr(1, DatabaseCodepage, vbTab, vbTextCompare)
|
||||||
|
If iDelim = 0 Then Fail "Failure in codepage export file"
|
||||||
|
DatabaseCodepage = Left(DatabaseCodepage, iDelim - 1)
|
||||||
|
End Function
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
' Set ProductLanguge property in Property table
|
||||||
|
Sub SetProductLanguage(installer, database, language)
|
||||||
|
On Error Resume Next
|
||||||
|
If Not IsNumeric(language) Then Fail "ProductLanguage must be numeric"
|
||||||
|
Dim view : Set view = database.OpenView("SELECT `Property`,`Value` FROM `Property`")
|
||||||
|
view.Execute : CheckError
|
||||||
|
Dim record : Set record = installer.CreateRecord(2)
|
||||||
|
record.StringData(1) = "ProductLanguage"
|
||||||
|
record.StringData(2) = CStr(language)
|
||||||
|
view.Modify msiViewModifyAssign, record : CheckError
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
' Set ANSI codepage of database text data
|
||||||
|
Sub SetDatabaseCodepage(database, codepage)
|
||||||
|
On Error Resume Next
|
||||||
|
If Not IsNumeric(codepage) Then Fail "Codepage must be numeric"
|
||||||
|
Dim WshShell : Set WshShell = Wscript.CreateObject("Wscript.Shell") : CheckError
|
||||||
|
Dim tempPath:tempPath = WshShell.ExpandEnvironmentStrings("%TEMP%") : CheckError
|
||||||
|
Dim fileSys : Set fileSys = CreateObject("Scripting.FileSystemObject") : CheckError
|
||||||
|
Dim file : Set file = fileSys.OpenTextFile(tempPath & "\codepage.idt", ForWriting, True, TristateFalse) : CheckError
|
||||||
|
file.WriteLine ' dummy column name record
|
||||||
|
file.WriteLine ' dummy column defn record
|
||||||
|
file.WriteLine codepage & vbTab & "_ForceCodepage"
|
||||||
|
file.Close : CheckError
|
||||||
|
database.Import tempPath, "codepage.idt" : CheckError
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
' Set language list in summary information
|
||||||
|
Sub SetPackageLanguage(database, language)
|
||||||
|
On Error Resume Next
|
||||||
|
Dim sumInfo : Set sumInfo = database.SummaryInformation(1)
|
||||||
|
Dim template : template = sumInfo.Property(7)
|
||||||
|
Dim iDelim:iDelim = InStr(1, template, ";", vbTextCompare)
|
||||||
|
Dim platform : If iDelim = 0 Then platform = ";" Else platform = Left(template, iDelim)
|
||||||
|
sumInfo.Property(7) = platform & language
|
||||||
|
sumInfo.Persist
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub CheckError
|
||||||
|
Dim message, errRec
|
||||||
|
If Err = 0 Then Exit Sub
|
||||||
|
message = Err.Source & " " & Hex(Err) & ": " & Err.Description
|
||||||
|
If Not installer Is Nothing Then
|
||||||
|
Set errRec = installer.LastErrorRecord
|
||||||
|
If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
|
||||||
|
End If
|
||||||
|
Fail message
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Sub Fail(message)
|
||||||
|
Wscript.Echo message
|
||||||
|
Wscript.Quit 2
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
15
WixInstaller/en-us.wxl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<WixLocalization Culture="en-US" Codepage="1252" xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||||
|
<String Id="Open">Open</String>
|
||||||
|
<String Id="XVA_File">XVA File</String>
|
||||||
|
<String Id="OVF_File">OVF File</String>
|
||||||
|
<String Id="OVA_File">OVA File</String>
|
||||||
|
<String Id="VHD_File">VHD File</String>
|
||||||
|
<String Id="VMDK_File">VMDK File</String>
|
||||||
|
<String Id="XenServer_License_File">XenServer License File</String>
|
||||||
|
<String Id="XenServer_Backup_File">XenServer Backup File</String>
|
||||||
|
<String Id="XenServer_Update_File">XenServer Update File</String>
|
||||||
|
<String Id="XenServer_OEM_Update_File">XenServer OEM Update File</String>
|
||||||
|
<String Id="XenCenter_Saved_Search">XenCenter Saved Search</String>
|
||||||
|
<String Id="Required_For_Installation">.NET Framework 3.5 is required for this installation.</String>
|
||||||
|
</WixLocalization>
|
15
WixInstaller/ja-jp.wxl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<WixLocalization Culture="ja-JP" Codepage="932" xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||||
|
<String Id="Open">開く</String>
|
||||||
|
<String Id="XVA_File">XenServer 仮想アプライアンス</String>
|
||||||
|
<String Id="OVF_File">OVF ファイル</String>
|
||||||
|
<String Id="OVA_File">OVA ファイル</String>
|
||||||
|
<String Id="VHD_File">VHD ファイル</String>
|
||||||
|
<String Id="VMDK_File">VMDK ファイル</String>
|
||||||
|
<String Id="XenServer_License_File">XenServer ライセンス ファイル</String>
|
||||||
|
<String Id="XenServer_Backup_File">XenServer バックアップ ファイル</String>
|
||||||
|
<String Id="XenServer_Update_File">XenServer アップデート ファイル</String>
|
||||||
|
<String Id="XenServer_OEM_Update_File">XenServer OEM アップデート ファイル</String>
|
||||||
|
<String Id="XenCenter_Saved_Search">XenCenter 保存された検索条件</String>
|
||||||
|
<String Id="Required_For_Installation">この製品をインストールするには、.NET Framework 3.5 以降が必要です。</String>
|
||||||
|
</WixLocalization>
|
17
WixInstaller/msidiff.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
if (WScript.Arguments.Length != 3) {
|
||||||
|
WScript.echo("// MsiDiff.js");
|
||||||
|
WScript.echo("// Usage: MsiDiff.js base.msi target.msi diff.mst");
|
||||||
|
WScript.quit(0);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var installerObj = new ActiveXObject("WindowsInstaller.Installer");
|
||||||
|
var baseDatabase = installerObj.OpenDatabase(WScript.Arguments.Item(0), 0);
|
||||||
|
var targetDatabase = installerObj.OpenDatabase(WScript.Arguments.Item(1), 0);
|
||||||
|
|
||||||
|
targetDatabase.GenerateTransform(baseDatabase, WScript.Arguments.Item(2));
|
||||||
|
targetDatabase.CreateTransformSummaryInfo(baseDatabase, WScript.Arguments.Item(2), 0, 0);
|
||||||
|
} catch (ex) {
|
||||||
|
try { // for cscript.exe only; not for wscript.exe
|
||||||
|
WScript.StdErr.WriteLine("Error : " + ex.number + " : " + ex.description);
|
||||||
|
} catch (ex2) { /* exception on wscript.exe; keep quiet to avoid pop up error dialogs */ }
|
||||||
|
}
|
130
WixInstaller/vnccontrol.wxs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Copyright (c) Citrix Systems Inc.
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||||
|
<?define ProductVersion="1.0.0" ?>
|
||||||
|
<?define UpgradeCode="{A77AF69F-14AF-4cd0-B978-236945C7AC97}"?>
|
||||||
|
<?define ProductCode="{0CE5C3E7-E786-467a-80CF-F3EC04D414E4}"?>
|
||||||
|
<?define VersionShort="5.5" ?>
|
||||||
|
<Product Id="$(var.ProductCode)" Name="Citrix VNCControl" Language="$(env.WiXLangId)" Version="$(var.ProductVersion)" Manufacturer="Citrix Systems, Inc." UpgradeCode="$(var.UpgradeCode)">
|
||||||
|
<Package Description="Citrix VNCControl" Languages="$(env.WiXLangId)" Comments="none." InstallerVersion="200" Compressed="yes" />
|
||||||
|
<Media Id="1" Cabinet="VNCControl.cab" EmbedCab="yes" />
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="ProgramFilesFolder">
|
||||||
|
<Directory Id="Citrix" Name="Citrix">
|
||||||
|
<Directory Id="INSTALLDIR" ShortName="VNCContr" Name="VNCControl">
|
||||||
|
<Component Id="MainControl" Guid="C2E335C1-3ADF-492d-BD03-27DA10A44232">
|
||||||
|
<!--Main VNC Control-->
|
||||||
|
<File Id="VNCControlDLL" Source="..\VNCControl\bin\Release\VNCControl.dll" />
|
||||||
|
<!-- DLLs -->
|
||||||
|
<File Id="CookComputingDLL" Source="..\VNCControl\bin\Release\CookComputing.XmlRpcV2.dll" />
|
||||||
|
<File Id="log4netDLL" Source="..\VNCControl\bin\Release\log4net.dll" />
|
||||||
|
<File Id="XenCenterLibDLL" Source="..\VNCControl\bin\Release\XenCenterLib.dll" />
|
||||||
|
<File Id="XenCenterVNCDLL" Source="..\VNCControl\bin\Release\XenCenterVNC.dll" />
|
||||||
|
<File Id="XenServerDLL" Source="..\VNCControl\bin\Release\XenServer.dll" />
|
||||||
|
<!-- VNCControl COM Type Library -->
|
||||||
|
<File Id="VNCControlTlb" KeyPath="yes" Source="..\VNCControl\bin\Release\VNCControl.tlb">
|
||||||
|
<TypeLib Id="{7CD118EA-D8DA-464D-8303-B189912A9878}" Description="Active-X control to access XenServer VM administrative console" HelpDirectory="INSTALLDIR" Language="0" MajorVersion="1" MinorVersion="0">
|
||||||
|
<Interface Id="{4CF54BB1-3A27-4FE6-9BEC-03BD404AF367}" Name="IVMConsoleEvents" ProxyStubClassId="{00020424-0000-0000-C000-000000000046}" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
|
||||||
|
<Interface Id="{9088E0E7-BF28-39D3-9BBA-A2258660AF42}" Name="_VNCControl" ProxyStubClassId="{00020424-0000-0000-C000-000000000046}" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
|
||||||
|
<Interface Id="{FFD87368-B188-4921-BE52-B3F75967FC89}" Name="IVMConsole" ProxyStubClassId="{00020424-0000-0000-C000-000000000046}" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
|
||||||
|
</TypeLib>
|
||||||
|
</File>
|
||||||
|
<!-- COM Registration -->
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Action="write" Type="string" Value="" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Value="mscoree.dll" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Name="Class" Value="XenAdmin.VNCControl" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Name="Assembly" Value="VNCControl, Version=1.0.1000.0, Culture=neutral, PublicKeyToken=null" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Name="RuntimeVersion" Value="v2.0.50727" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Name="CodeBase" Value="file:///[#VNCControlDLL]" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32" Name="ThreadingModel" Value="Both" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32\1.0.1000.0" Name="Class" Value="XenAdmin.VNCControl" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32\1.0.1000.0" Name="Assembly" Value="VNCControl, Version=1.0.1000.0, Culture=neutral, PublicKeyToken=null" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32\1.0.1000.0" Name="RuntimeVersion" Value="v2.0.50727" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\InprocServer32\1.0.1000.0" Name="CodeBase" Value="file:///[#VNCControlDLL]" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="CLSID\{D52D9588-AB6E-425B-9D8C-74FBDA46C4F8}\ProgId" Value="XenAdmin.VNCControl" Type="string" Action="write" />
|
||||||
|
<RegistryValue Root="HKCR" Key="Component Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Name="0" Value=".NET Category" Type="string" Action="write" />
|
||||||
|
</Component>
|
||||||
|
<!-- TestResources -->
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
<Feature Id="MainControl" Title="VNCControl $(var.VersionShort)" Description="Citrix VNCControl $(var.VersionShort) - for accessing XenServer VM Consoles " Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR" AllowAdvertise="no" InstallDefault="local" Absent="disallow">
|
||||||
|
<ComponentRef Id="MainControl" />
|
||||||
|
</Feature>
|
||||||
|
<Property Id="Install_All" Value="0" />
|
||||||
|
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
|
||||||
|
<Property Id="FRAMEWORK20">
|
||||||
|
<RegistrySearch Id="Framework20Registry" Type="raw" Root="HKLM" Key="Software\Microsoft\NET Framework Setup\NDP\v2.0.50727" Name="Install" />
|
||||||
|
</Property>
|
||||||
|
<Property Id="ARPPRODUCTICON" Value="XenCenterICO" />
|
||||||
|
<Upgrade Id="$(var.UpgradeCode)">
|
||||||
|
<UpgradeVersion Property="UPGRADEFOUND" ExcludeLanguages="yes" Minimum="0.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" />
|
||||||
|
<UpgradeVersion OnlyDetect="yes" ExcludeLanguages="yes" Property="NEWERPRODUCTFOUND" Minimum="$(var.ProductVersion)" IncludeMinimum="no" />
|
||||||
|
</Upgrade>
|
||||||
|
<Condition Message=".NET Framework 2.0 is not present on the computer.">FRAMEWORK20 = "#1"</Condition>
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<AppSearch Sequence="50" />
|
||||||
|
<FindRelatedProducts Before="LaunchConditions" />
|
||||||
|
<LaunchConditions Sequence="100" />
|
||||||
|
<ValidateProductID Sequence="700" />
|
||||||
|
<CostInitialize Sequence="800" />
|
||||||
|
<FileCost Sequence="900" />
|
||||||
|
<CostFinalize Sequence="1000" />
|
||||||
|
<MigrateFeatureStates Sequence="1200" />
|
||||||
|
<InstallValidate Sequence="1400" />
|
||||||
|
<InstallInitialize Sequence="1500" />
|
||||||
|
<RemoveExistingProducts Sequence="1501" />
|
||||||
|
<ProcessComponents Sequence="1600" />
|
||||||
|
<UnpublishFeatures Sequence="1800" />
|
||||||
|
<RemoveRegistryValues Sequence="2600" />
|
||||||
|
<RemoveShortcuts Sequence="3200" />
|
||||||
|
<RemoveFiles Sequence="3500" />
|
||||||
|
<InstallFiles Sequence="4000" />
|
||||||
|
<CreateShortcuts Sequence="4500" />
|
||||||
|
<WriteRegistryValues Sequence="5000" />
|
||||||
|
<RegisterUser Sequence="6000" />
|
||||||
|
<RegisterProduct Sequence="6100" />
|
||||||
|
<PublishFeatures Sequence="6300" />
|
||||||
|
<PublishProduct Sequence="6400" />
|
||||||
|
<InstallFinalize Sequence="6600" />
|
||||||
|
</InstallExecuteSequence>
|
||||||
|
<InstallUISequence>
|
||||||
|
<FindRelatedProducts Before="LaunchConditions" />
|
||||||
|
<ExecuteAction Sequence="1102" />
|
||||||
|
</InstallUISequence>
|
||||||
|
<Icon Id="XenCenterICO" SourceFile="..\XenAdmin\AppIcon.ico" />
|
||||||
|
</Product>
|
||||||
|
</Wix>
|
488
WixInstaller/vnccontrolui_1033.wxl
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
-->
|
||||||
|
<WixLocalization xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||||
|
<String Id="ProductLanguage">1033</String>
|
||||||
|
<String Id="PkgComment">"Copyright 2009 Citrix Systems, Inc. All rights reserved."</String>
|
||||||
|
<String Id="DiskPromptStr">"Installation "</String>
|
||||||
|
|
||||||
|
<String Id="WixUIBack">&Back</String>
|
||||||
|
<String Id="WixUINext">&Next</String>
|
||||||
|
<String Id="WixUICancel">Cancel</String>
|
||||||
|
<String Id="WixUIFinish">&Finish</String>
|
||||||
|
<String Id="WixUIRetry">&Retry</String>
|
||||||
|
<String Id="WixUIIgnore">&Ignore</String>
|
||||||
|
<String Id="WixUIYes">&Yes</String>
|
||||||
|
<String Id="WixUINo">&No</String>
|
||||||
|
<String Id="WixUIOK">OK</String>
|
||||||
|
<String Id="WixUIPrint">&Print</String>
|
||||||
|
|
||||||
|
<String Id="CancelDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="CancelDlgText">Are you sure you want to cancel [ProductName] installation?</String>
|
||||||
|
<String Id="CancelDlgIcon">WixUI_Ico_Info</String>
|
||||||
|
<String Id="CancelDlgIconTooltip">Information icon</String>
|
||||||
|
|
||||||
|
<String Id="ErrorDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="ErrorDlgErrorText">Information text</String>
|
||||||
|
<String Id="ErrorDlgErrorIcon">WixUI_Ico_Info</String>
|
||||||
|
<String Id="ErrorDlgErrorIconTooltip">Information icon</String>
|
||||||
|
|
||||||
|
<String Id="ExitDialog_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="ExitDialogBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="ExitDialogDescription">Click the Finish button to exit the Setup Wizard.</String>
|
||||||
|
<String Id="ExitDialogTitle">{\WixUI_Font_Bigger}Completed the [ProductName] Setup Wizard</String>
|
||||||
|
|
||||||
|
<String Id="FatalError_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="FatalErrorBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="FatalErrorTitle">{\WixUI_Font_Bigger}[ProductName] Setup Wizard ended prematurely</String>
|
||||||
|
<String Id="FatalErrorDescription1">[ProductName] Setup Wizard ended prematurely because of an error. Your system has not been modified. To install this program at a later time, run Setup Wizard again.</String>
|
||||||
|
<String Id="FatalErrorDescription2">Click the Finish button to exit the Setup Wizard.</String>
|
||||||
|
|
||||||
|
<String Id="FilesInUse_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="FilesInUseExit">E&xit</String>
|
||||||
|
<String Id="FilesInUseBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="FilesInUseText">The following applications are using files that need to be updated by this setup. Close these applications and then click &Retry to continue the installation or Exit to exit it.</String>
|
||||||
|
<String Id="FilesInUseDescription">Some files that need to be updated are currently in use.</String>
|
||||||
|
<String Id="FilesInUseTitle">{\WixUI_Font_Title}Files in Use</String>
|
||||||
|
|
||||||
|
<String Id="MaintenanceTypeDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="MaintenanceTypeDlgChangeButton">&Change</String>
|
||||||
|
<String Id="MaintenanceTypeDlgChangeButtonTooltip">Change Installation</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRepairButton">Re&pair</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRepairButtonTooltip">Repair Installation</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRemoveButton">&Remove</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRemoveButtonTooltip">Remove Installation</String>
|
||||||
|
<String Id="MaintenanceTypeDlgBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="MaintenanceTypeDlgDescription">Select the operation you wish to perform.</String>
|
||||||
|
<String Id="MaintenanceTypeDlgTitle">{\WixUI_Font_Title}Change, repair, or remove installation</String>
|
||||||
|
<String Id="MaintenanceTypeDlgChangeText">Lets you change the way features are installed.</String>
|
||||||
|
<String Id="MaintenanceTypeDlgChangeDisabledText">[ProductName] has no independently selectable features.</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRemoveText">Removes [ProductName] from your computer.</String>
|
||||||
|
<String Id="MaintenanceTypeDlgRepairText">Repairs errors in the most recent installation by fixing missing and corrupt files, shortcuts, and registry entries.</String>
|
||||||
|
|
||||||
|
<String Id="MaintenanceWelcomeDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="MaintenanceWelcomeDlgBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="MaintenanceWelcomeDlgDescription">The Setup Wizard allows you to change the way [ProductName] features are installed on your computer or to remove it from your computer. Click Next to continue or Cancel to exit the Setup Wizard.</String>
|
||||||
|
<String Id="MaintenanceWelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] Setup Wizard</String>
|
||||||
|
|
||||||
|
<String Id="MsiRMFilesInUse_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="MsiRMFilesInUseBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="MsiRMFilesInUseText">The following applications are using files that need to be updated by this setup. You can let Setup Wizard close them and attempt to restart them or reboot the machine later.</String>
|
||||||
|
<String Id="MsiRMFilesInUseDescription">Some files that need to be updated are currently in use.</String>
|
||||||
|
<String Id="MsiRMFilesInUseTitle">{\WixUI_Font_Title}Files in Use</String>
|
||||||
|
<String Id="MsiRMFilesInUseUseRM">&Close the applications and attempt to restart them.</String>
|
||||||
|
<String Id="MsiRMFilesInUseDontUseRM">&Do not close applications. A reboot will be required.</String>
|
||||||
|
|
||||||
|
<String Id="OutOfDiskDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="OutOfDiskDlgBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="OutOfDiskDlgText">The highlighted volumes do not have enough disk space available for the currently selected features. You can remove some files from the highlighted volumes, install fewer features, or select a different destination drive.</String>
|
||||||
|
<String Id="OutOfDiskDlgDescription">Disk space required for the installation exceeds available disk space.</String>
|
||||||
|
<String Id="OutOfDiskDlgTitle">{\WixUI_Font_Title}Out of Disk Space</String>
|
||||||
|
<String Id="OutOfDiskDlgVolumeList">{120}{70}{70}{70}{70}</String>
|
||||||
|
|
||||||
|
<String Id="OutOfRbDiskDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="OutOfRbDiskDlgBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="OutOfRbDiskDlgText">The highlighted volumes do not have enough disk space available for the currently selected features. You can remove some files from the highlighted volumes, install fewer features, or select a different destination drive.</String>
|
||||||
|
<String Id="OutOfRbDiskDlgDescription">Disk space required for the installation exceeds available disk space.</String>
|
||||||
|
<String Id="OutOfRbDiskDlgTitle">{\WixUI_Font_Title}Out of Disk Space</String>
|
||||||
|
<String Id="OutOfRbDiskDlgVolumeList">{120}{70}{70}{70}{70}</String>
|
||||||
|
<String Id="OutOfRbDiskDlgText2">Alternatively, you may choose to disable the installer's rollback functionality. Disabling rollback prevents the installer from restoring your computer's original state should the installation be interrupted in any way. Click Yes if you wish to take the risk of disabling rollback.</String>
|
||||||
|
|
||||||
|
<String Id="PrepareDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="PrepareDlgBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="PrepareDlgDescription">Please wait while the Setup Wizard prepares to guide you through the installation.</String>
|
||||||
|
<String Id="PrepareDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] Setup Wizard</String>
|
||||||
|
|
||||||
|
<String Id="ProgressDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="ProgressDlgBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="ProgressDlgTextInstalling">Please wait while the Setup Wizard installs [ProductName].</String>
|
||||||
|
<String Id="ProgressDlgTitleInstalling">{\WixUI_Font_Title}Installing [ProductName]</String>
|
||||||
|
<String Id="ProgressDlgTextChanging">Please wait while the Setup Wizard changes [ProductName].</String>
|
||||||
|
<String Id="ProgressDlgTitleChanging">{\WixUI_Font_Title}Changing [ProductName]</String>
|
||||||
|
<String Id="ProgressDlgTextRepairing">Please wait while the Setup Wizard repairs [ProductName].</String>
|
||||||
|
<String Id="ProgressDlgTitleRepairing">{\WixUI_Font_Title}Repairing [ProductName]</String>
|
||||||
|
<String Id="ProgressDlgTextRemoving">Please wait while the Setup Wizard removes [ProductName].</String>
|
||||||
|
<String Id="ProgressDlgTitleRemoving">{\WixUI_Font_Title}Removing [ProductName]</String>
|
||||||
|
<String Id="ProgressDlgProgressBar">Progress done</String>
|
||||||
|
<String Id="ProgressDlgStatusLabel">Status:</String>
|
||||||
|
|
||||||
|
<String Id="ResumeDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="ResumeDlgInstall">&Install</String>
|
||||||
|
<String Id="ResumeDlgBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="ResumeDlgDescription">The Setup Wizard will complete the installation of [ProductName] on your computer. Click Install to continue or Cancel to exit the Setup Wizard.</String>
|
||||||
|
<String Id="ResumeDlgTitle">{\WixUI_Font_Bigger}Resuming the [ProductName] Setup Wizard</String>
|
||||||
|
|
||||||
|
<String Id="UserExit_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="UserExitBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="UserExitTitle">{\WixUI_Font_Bigger}[ProductName] Setup Wizard was interrupted</String>
|
||||||
|
<String Id="UserExitDescription1">[ProductName] setup was interrupted. Your system has not been modified. To install this program at a later time, please run the installation again.</String>
|
||||||
|
<String Id="UserExitDescription2">Click the Finish button to exit the Setup Wizard.</String>
|
||||||
|
|
||||||
|
<String Id="VerifyReadyDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="VerifyReadyDlgBannerBitmap">WixUI_Bmp_Banner</String>
|
||||||
|
<String Id="VerifyReadyDlgInstall">&Install</String>
|
||||||
|
<String Id="VerifyReadyDlgInstallText">Click Install to begin the installation. Click Back to review or change any of your installation settings. Click Cancel to exit the wizard.</String>
|
||||||
|
<String Id="VerifyReadyDlgInstallTitle">{\WixUI_Font_Title}Ready to install [ProductName]</String>
|
||||||
|
<String Id="VerifyReadyDlgChange">&Change</String>
|
||||||
|
<String Id="VerifyReadyDlgChangeText">Click Change to begin the installation. Click Back to review or change any of your installation settings. Click Cancel to exit the wizard.</String>
|
||||||
|
<String Id="VerifyReadyDlgChangeTitle">{\WixUI_Font_Title}Ready to change [ProductName]</String>
|
||||||
|
<String Id="VerifyReadyDlgRepair">Re&pair</String>
|
||||||
|
<String Id="VerifyReadyDlgRepairText">Click Repair to repair the installation of [ProductName]. Click Back to review or change any of your installation settings. Click Cancel to exit the wizard.</String>
|
||||||
|
<String Id="VerifyReadyDlgRepairTitle">{\WixUI_Font_Title}Ready to repair [ProductName]</String>
|
||||||
|
<String Id="VerifyReadyDlgRemove">&Remove</String>
|
||||||
|
<String Id="VerifyReadyDlgRemoveText">Click Remove to remove [ProductName] from your computer. Click Back to review or change any of your installation settings. Click Cancel to exit the wizard.</String>
|
||||||
|
<String Id="VerifyReadyDlgRemoveTitle">{\WixUI_Font_Title}Ready to remove [ProductName]</String>
|
||||||
|
|
||||||
|
<String Id="WaitForCostingDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="WaitForCostingDlgReturn">&Return</String>
|
||||||
|
<String Id="WaitForCostingDlgText">Please wait while the installer finishes determining your disk space requirements.</String>
|
||||||
|
<String Id="WaitForCostingDlgIcon">WixUI_Ico_Exclam</String>
|
||||||
|
<String Id="WaitForCostingDlgIconTooltip">Exclamation icon</String>
|
||||||
|
|
||||||
|
<String Id="WelcomeEulaDlg_Title">[ProductName] Setup</String>
|
||||||
|
<String Id="WelcomeEulaDlgBitmap">WixUI_Bmp_Dialog</String>
|
||||||
|
<String Id="WelcomeEulaDlgLicenseAcceptedCheckBox">I &accept the terms in the License Agreement</String>
|
||||||
|
<String Id="WelcomeEulaDlgInstall">&Install</String>
|
||||||
|
<String Id="WelcomeEulaDlgTitle">{\WixUI_Font_Title}Please read the [ProductName] License Agreement</String>
|
||||||
|
<String Id="WelcomeEulaDlgAgreementText" />
|
||||||
|
|
||||||
|
<String Id="ProgressTextInstallValidate">Validating install</String>
|
||||||
|
<String Id="ProgressTextInstallFiles">Copying new files</String>
|
||||||
|
<String Id="ProgressTextInstallFilesTemplate">File: [1], Directory: [9], Size: [6]</String>
|
||||||
|
<String Id="ProgressTextInstallAdminPackage">Copying network install files</String>
|
||||||
|
<String Id="ProgressTextInstallAdminPackageTemplate">File: [1], Directory: [9], Size: [6]</String>
|
||||||
|
<String Id="ProgressTextFileCost">Computing space requirements</String>
|
||||||
|
<String Id="ProgressTextCostInitialize">Computing space requirements</String>
|
||||||
|
<String Id="ProgressTextCostFinalize">Computing space requirements</String>
|
||||||
|
<String Id="ProgressTextCreateShortcuts">Creating shortcuts</String>
|
||||||
|
<String Id="ProgressTextCreateShortcutsTemplate">Shortcut: [1]</String>
|
||||||
|
<String Id="ProgressTextPublishComponents">Publishing Qualified Components</String>
|
||||||
|
<String Id="ProgressTextPublishComponentsTemplate">Component ID: [1], Qualifier: [2]</String>
|
||||||
|
<String Id="ProgressTextPublishFeatures">Publishing Product Features</String>
|
||||||
|
<String Id="ProgressTextPublishFeaturesTemplate">Feature: [1]</String>
|
||||||
|
<String Id="ProgressTextPublishProduct">Publishing product information</String>
|
||||||
|
<String Id="ProgressTextRegisterClassInfo">Registering Class servers</String>
|
||||||
|
<String Id="ProgressTextRegisterClassInfoTemplate">Class Id: [1]</String>
|
||||||
|
<String Id="ProgressTextRegisterExtensionInfo">Registering extension servers</String>
|
||||||
|
<String Id="ProgressTextRegisterExtensionInfoTemplate">Extension: [1]</String>
|
||||||
|
<String Id="ProgressTextRegisterMIMEInfo">Registering MIME info</String>
|
||||||
|
<String Id="ProgressTextRegisterMIMEInfoTemplate">MIME Content Type: [1], Extension: [2]</String>
|
||||||
|
<String Id="ProgressTextRegisterProgIdInfo">Registering program identifiers</String>
|
||||||
|
<String Id="ProgressTextRegisterProgIdInfoTemplate">ProgId: [1]</String>
|
||||||
|
<String Id="ProgressTextAllocateRegistrySpace">Allocating registry space</String>
|
||||||
|
<String Id="ProgressTextAllocateRegistrySpaceTemplate">Free space: [1]</String>
|
||||||
|
<String Id="ProgressTextAppSearch">Searching for installed applications</String>
|
||||||
|
<String Id="ProgressTextAppSearchTemplate">Property: [1], Signature: [2]</String>
|
||||||
|
<String Id="ProgressTextBindImage">Binding executables</String>
|
||||||
|
<String Id="ProgressTextBindImageTemplate">File: [1]</String>
|
||||||
|
<String Id="ProgressTextCCPSearch">Searching for qualifying products</String>
|
||||||
|
<String Id="ProgressTextCreateFolders">Creating folders</String>
|
||||||
|
<String Id="ProgressTextCreateFoldersTemplate">Folder: [1]</String>
|
||||||
|
<String Id="ProgressTextDeleteServices">Deleting services</String>
|
||||||
|
<String Id="ProgressTextDeleteServicesTemplate">Service: [1]</String>
|
||||||
|
<String Id="ProgressTextDuplicateFiles">Creating duplicate files</String>
|
||||||
|
<String Id="ProgressTextDuplicateFilesTemplate">File: [1], Directory: [9], Size: [6]</String>
|
||||||
|
<String Id="ProgressTextFindRelatedProducts">Searching for related applications</String>
|
||||||
|
<String Id="ProgressTextFindRelatedProductsTemplate">Found application: [1]</String>
|
||||||
|
<String Id="ProgressTextInstallODBC">Installing ODBC components</String>
|
||||||
|
<String Id="ProgressTextInstallServices">Installing new services</String>
|
||||||
|
<String Id="ProgressTextInstallServicesTemplate">Service: [2]</String>
|
||||||
|
<String Id="ProgressTextLaunchConditions">Evaluating launch conditions</String>
|
||||||
|
<String Id="ProgressTextMigrateFeatureStates">Migrating feature states from related applications</String>
|
||||||
|
<String Id="ProgressTextMigrateFeatureStatesTemplate">Application: [1]</String>
|
||||||
|
<String Id="ProgressTextMoveFiles">Moving files</String>
|
||||||
|
<String Id="ProgressTextMoveFilesTemplate">File: [1], Directory: [9], Size: [6]</String>
|
||||||
|
<String Id="ProgressTextPatchFiles">Patching files</String>
|
||||||
|
<String Id="ProgressTextPatchFilesTemplate">File: [1], Directory: [2], Size: [3]</String>
|
||||||
|
<String Id="ProgressTextProcessComponents">Updating component registration</String>
|
||||||
|
<String Id="ProgressTextRegisterComPlus">Registering COM+ Applications and Components</String>
|
||||||
|
<String Id="ProgressTextRegisterComPlusTemplate">AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}</String>
|
||||||
|
<String Id="ProgressTextRegisterFonts">Registering fonts</String>
|
||||||
|
<String Id="ProgressTextRegisterFontsTemplate">Font: [1]</String>
|
||||||
|
<String Id="ProgressTextRegisterProduct">Registering product</String>
|
||||||
|
<String Id="ProgressTextRegisterProductTemplate">[1]</String>
|
||||||
|
<String Id="ProgressTextRegisterTypeLibraries">Registering type libraries</String>
|
||||||
|
<String Id="ProgressTextRegisterTypeLibrariesTemplate">LibID: [1]</String>
|
||||||
|
<String Id="ProgressTextRegisterUser">Registering user</String>
|
||||||
|
<String Id="ProgressTextRegisterUserTemplate">[1]</String>
|
||||||
|
<String Id="ProgressTextRemoveDuplicateFiles">Removing duplicated files</String>
|
||||||
|
<String Id="ProgressTextRemoveDuplicateFilesTemplate">File: [1], Directory: [9]</String>
|
||||||
|
<String Id="ProgressTextRemoveEnvironmentStrings">Updating environment strings</String>
|
||||||
|
<String Id="ProgressTextRemoveEnvironmentStringsTemplate">Name: [1], Value: [2], Action [3]</String>
|
||||||
|
<String Id="ProgressTextRemoveExistingProducts">Removing applications</String>
|
||||||
|
<String Id="ProgressTextRemoveExistingProductsTemplate">Application: [1], Command line: [2]</String>
|
||||||
|
<String Id="ProgressTextRemoveFiles">Removing files</String>
|
||||||
|
<String Id="ProgressTextRemoveFilesTemplate">File: [1], Directory: [9]</String>
|
||||||
|
<String Id="ProgressTextRemoveFolders">Removing folders</String>
|
||||||
|
<String Id="ProgressTextRemoveFoldersTemplate">Folder: [1]</String>
|
||||||
|
<String Id="ProgressTextRemoveIniValues">Removing INI files entries</String>
|
||||||
|
<String Id="ProgressTextRemoveIniValuesTemplate">File: [1], Section: [2], Key: [3], Value: [4]</String>
|
||||||
|
<String Id="ProgressTextRemoveODBC">Removing ODBC components</String>
|
||||||
|
<String Id="ProgressTextRemoveRegistryValues">Removing system registry values</String>
|
||||||
|
<String Id="ProgressTextRemoveRegistryValuesTemplate">Key: [1], Name: [2]</String>
|
||||||
|
<String Id="ProgressTextRemoveShortcuts">Removing shortcuts</String>
|
||||||
|
<String Id="ProgressTextRemoveShortcutsTemplate">Shortcut: [1]</String>
|
||||||
|
<String Id="ProgressTextRMCCPSearch">Searching for qualifying products</String>
|
||||||
|
<String Id="ProgressTextSelfRegModules">Registering modules</String>
|
||||||
|
<String Id="ProgressTextSelfRegModulesTemplate">File: [1], Folder: [2]</String>
|
||||||
|
<String Id="ProgressTextSelfUnregModules">Unregistering modules</String>
|
||||||
|
<String Id="ProgressTextSelfUnregModulesTemplate">File: [1], Folder: [2]</String>
|
||||||
|
<String Id="ProgressTextSetODBCFolders">Initializing ODBC directories</String>
|
||||||
|
<String Id="ProgressTextStartServices">Starting services</String>
|
||||||
|
<String Id="ProgressTextStartServicesTemplate">Service: [1]</String>
|
||||||
|
<String Id="ProgressTextStopServices">Stopping services</String>
|
||||||
|
<String Id="ProgressTextStopServicesTemplate">Service: [1]</String>
|
||||||
|
<String Id="ProgressTextUnpublishComponents">Unpublishing Qualified Components</String>
|
||||||
|
<String Id="ProgressTextUnpublishComponentsTemplate">Component ID: [1], Qualifier: [2]</String>
|
||||||
|
<String Id="ProgressTextUnpublishFeatures">Unpublishing Product Features</String>
|
||||||
|
<String Id="ProgressTextUnpublishFeaturesTemplate">Feature: [1]</String>
|
||||||
|
<String Id="ProgressTextUnregisterClassInfo">Unregister Class servers</String>
|
||||||
|
<String Id="ProgressTextUnregisterClassInfoTemplate">Class Id: [1]</String>
|
||||||
|
<String Id="ProgressTextUnregisterComPlus">Unregistering COM+ Applications and Components</String>
|
||||||
|
<String Id="ProgressTextUnregisterComPlusTemplate">AppId: [1]{{, AppType: [2]}}</String>
|
||||||
|
<String Id="ProgressTextUnregisterExtensionInfo">Unregistering extension servers</String>
|
||||||
|
<String Id="ProgressTextUnregisterExtensionInfoTemplate">Extension: [1]</String>
|
||||||
|
<String Id="ProgressTextUnregisterFonts">Unregistering fonts</String>
|
||||||
|
<String Id="ProgressTextUnregisterFontsTemplate">Font: [1]</String>
|
||||||
|
<String Id="ProgressTextUnregisterMIMEInfo">Unregistering MIME info</String>
|
||||||
|
<String Id="ProgressTextUnregisterMIMEInfoTemplate">MIME Content Type: [1], Extension: [2]</String>
|
||||||
|
<String Id="ProgressTextUnregisterProgIdInfo">Unregistering program identifiers</String>
|
||||||
|
<String Id="ProgressTextUnregisterProgIdInfoTemplate">ProgId: [1]</String>
|
||||||
|
<String Id="ProgressTextUnregisterTypeLibraries">Unregistering type libraries</String>
|
||||||
|
<String Id="ProgressTextUnregisterTypeLibrariesTemplate">LibID: [1]</String>
|
||||||
|
<String Id="ProgressTextWriteEnvironmentStrings">Updating environment strings</String>
|
||||||
|
<String Id="ProgressTextWriteEnvironmentStringsTemplate">Name: [1], Value: [2], Action [3]</String>
|
||||||
|
<String Id="ProgressTextWriteIniValues">Writing INI files values</String>
|
||||||
|
<String Id="ProgressTextWriteIniValuesTemplate">File: [1], Section: [2], Key: [3], Value: [4]</String>
|
||||||
|
<String Id="ProgressTextWriteRegistryValues">Writing system registry values</String>
|
||||||
|
<String Id="ProgressTextWriteRegistryValuesTemplate">Key: [1], Name: [2], Value: [3]</String>
|
||||||
|
<String Id="ProgressTextAdvertise">Advertising application</String>
|
||||||
|
<String Id="ProgressTextGenerateScript">Generating script operations for action:</String>
|
||||||
|
<String Id="ProgressTextGenerateScriptTemplate">[1]</String>
|
||||||
|
<String Id="ProgressTextInstallSFPCatalogFile">Installing system catalog</String>
|
||||||
|
<String Id="ProgressTextInstallSFPCatalogFileTemplate">File: [1], Dependencies: [2]</String>
|
||||||
|
<String Id="ProgressTextMsiPublishAssemblies">Publishing assembly information</String>
|
||||||
|
<String Id="ProgressTextMsiPublishAssembliesTemplate">Application Context:[1], Assembly Name:[2]</String>
|
||||||
|
<String Id="ProgressTextMsiUnpublishAssemblies">Unpublishing assembly information</String>
|
||||||
|
<String Id="ProgressTextMsiUnpublishAssembliesTemplate">Application Context:[1], Assembly Name:[2]</String>
|
||||||
|
<String Id="ProgressTextRollback">Rolling back action:</String>
|
||||||
|
<String Id="ProgressTextRollbackTemplate">[1]</String>
|
||||||
|
<String Id="ProgressTextRollbackCleanup">Removing backup files</String>
|
||||||
|
<String Id="ProgressTextRollbackCleanupTemplate">File: [1]</String>
|
||||||
|
<String Id="ProgressTextUnmoveFiles">Removing moved files</String>
|
||||||
|
<String Id="ProgressTextUnmoveFilesTemplate">File: [1], Directory: [9]</String>
|
||||||
|
<String Id="ProgressTextUnpublishProduct">Unpublishing product information</String>
|
||||||
|
|
||||||
|
<String Id="Error0">{{Fatal error: }}</String>
|
||||||
|
<String Id="Error1">{{Error [1]. }}</String>
|
||||||
|
<String Id="Error2">Warning [1]. </String>
|
||||||
|
<String Id="Error4">Info [1]. </String>
|
||||||
|
<String Id="Error5">The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is [1]. {{The arguments are: [2], [3], [4]}}</String>
|
||||||
|
<String Id="Error7">{{Disk full: }}</String>
|
||||||
|
<String Id="Error8">Action [Time]: [1]. [2]</String>
|
||||||
|
<String Id="Error9">[ProductName]</String>
|
||||||
|
<String Id="Error10">{[2]}{, [3]}{, [4]}</String>
|
||||||
|
<String Id="Error11">Message type: [1], Argument: [2]</String>
|
||||||
|
<String Id="Error12">=== Logging started: [Date] [Time] ===</String>
|
||||||
|
<String Id="Error13">=== Logging stopped: [Date] [Time] ===</String>
|
||||||
|
<String Id="Error14">Action start [Time]: [1].</String>
|
||||||
|
<String Id="Error15">Action ended [Time]: [1]. Return value [2].</String>
|
||||||
|
<String Id="Error16">Time remaining: {[1] minutes }{[2] seconds}</String>
|
||||||
|
<String Id="Error17">Out of memory. Shut down other applications before retrying.</String>
|
||||||
|
<String Id="Error18">Installer is no longer responding.</String>
|
||||||
|
<String Id="Error19">Installer stopped prematurely.</String>
|
||||||
|
<String Id="Error20">Please wait while Windows configures [ProductName]</String>
|
||||||
|
<String Id="Error21">Gathering required information...</String>
|
||||||
|
<String Id="Error22">Removing older versions of this application...</String>
|
||||||
|
<String Id="Error23">Preparing to remove older versions of this application...</String>
|
||||||
|
<String Id="Error32">{[ProductName] }Setup completed successfully.</String>
|
||||||
|
<String Id="Error33">{[ProductName] }Setup failed.</String>
|
||||||
|
<String Id="Error1101">Error reading from file: [2]. {{ System error [3].}} Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1301">Cannot create the file '[2]'. A directory with this name already exists. Cancel the install and try installing to a different location.</String>
|
||||||
|
<String Id="Error1302">Please insert the disk: [2]</String>
|
||||||
|
<String Id="Error1303">The installer has insufficient privileges to access this directory: [2]. The installation cannot continue. Log on as administrator or contact your system administrator.</String>
|
||||||
|
<String Id="Error1304">Error writing to file: [2]. Verify that you have access to that directory.</String>
|
||||||
|
<String Id="Error1305">Error reading from file [2]. {{ System error [3].}} Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1306">Another application has exclusive access to the file '[2]'. Please shut down all other applications, then click Retry.</String>
|
||||||
|
<String Id="Error1307">There is not enough disk space to install this file: [2]. Free some disk space and click Retry, or click Cancel to exit.</String>
|
||||||
|
<String Id="Error1308">Source file not found: [2]. Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1309">Error reading from file: [3]. {{ System error [2].}} Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1310">Error writing to file: [3]. {{ System error [2].}} Verify that you have access to that directory.</String>
|
||||||
|
<String Id="Error1311">Source file not found{{(cabinet)}}: [2]. Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1312">Cannot create the directory '[2]'. A file with this name already exists. Please rename or remove the file and click Retry, or click Cancel to exit.</String>
|
||||||
|
<String Id="Error1313">The volume [2] is currently unavailable. Please select another.</String>
|
||||||
|
<String Id="Error1314">The specified path '[2]' is unavailable.</String>
|
||||||
|
<String Id="Error1315">Unable to write to the specified folder: [2].</String>
|
||||||
|
<String Id="Error1316">A network error occurred while attempting to read from the file: [2]</String>
|
||||||
|
<String Id="Error1317">An error occurred while attempting to create the directory: [2]</String>
|
||||||
|
<String Id="Error1318">A network error occurred while attempting to create the directory: [2]</String>
|
||||||
|
<String Id="Error1319">A network error occurred while attempting to open the source file cabinet: [2]</String>
|
||||||
|
<String Id="Error1320">The specified path is too long: [2]</String>
|
||||||
|
<String Id="Error1321">The Installer has insufficient privileges to modify this file: [2].</String>
|
||||||
|
<String Id="Error1322">A portion of the folder path '[2]' is invalid. It is either empty or exceeds the length allowed by the system.</String>
|
||||||
|
<String Id="Error1323">The folder path '[2]' contains words that are not valid in folder paths.</String>
|
||||||
|
<String Id="Error1324">The folder path '[2]' contains an invalid character.</String>
|
||||||
|
<String Id="Error1325">'[2]' is not a valid short file name.</String>
|
||||||
|
<String Id="Error1326">Error getting file security: [3] GetLastError: [2]</String>
|
||||||
|
<String Id="Error1327">Invalid Drive: [2]</String>
|
||||||
|
<String Id="Error1328">Error applying patch to file [2]. It has probably been updated by other means, and can no longer be modified by this patch. For more information contact your patch vendor. {{System Error: [3]}}</String>
|
||||||
|
<String Id="Error1329">A file that is required cannot be installed because the cabinet file [2] is not digitally signed. This may indicate that the cabinet file is corrupt.</String>
|
||||||
|
<String Id="Error1330">A file that is required cannot be installed because the cabinet file [2] has an invalid digital signature. This may indicate that the cabinet file is corrupt.{{ Error [3] was returned by WinVerifyTrust.}}</String>
|
||||||
|
<String Id="Error1331">Failed to correctly copy [2] file: CRC error.</String>
|
||||||
|
<String Id="Error1332">Failed to correctly move [2] file: CRC error.</String>
|
||||||
|
<String Id="Error1333">Failed to correctly patch [2] file: CRC error.</String>
|
||||||
|
<String Id="Error1334">The file '[2]' cannot be installed because the file cannot be found in cabinet file '[3]'. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</String>
|
||||||
|
<String Id="Error1335">The cabinet file '[2]' required for this installation is corrupt and cannot be used. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</String>
|
||||||
|
<String Id="Error1336">There was an error creating a temporary file that is needed to complete this installation.{{ Folder: [3]. System error code: [2]}}</String>
|
||||||
|
<String Id="Error1401">Could not create key: [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </String>
|
||||||
|
<String Id="Error1402">Could not open key: [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </String>
|
||||||
|
<String Id="Error1403">Could not delete value [2] from key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel. </String>
|
||||||
|
<String Id="Error1404">Could not delete key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel. </String>
|
||||||
|
<String Id="Error1405">Could not read value [2] from key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel. </String>
|
||||||
|
<String Id="Error1406">Could not write value [2] to key [3]. {{ System error [4].}} Verify that you have sufficient access to that key, or contact your support personnel.</String>
|
||||||
|
<String Id="Error1407">Could not get value names for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</String>
|
||||||
|
<String Id="Error1408">Could not get sub key names for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</String>
|
||||||
|
<String Id="Error1409">Could not read security information for key [2]. {{ System error [3].}} Verify that you have sufficient access to that key, or contact your support personnel.</String>
|
||||||
|
<String Id="Error1410">Could not increase the available registry space. [2] KB of free registry space is required for the installation of this application.</String>
|
||||||
|
<String Id="Error1500">Another installation is in progress. You must complete that installation before continuing this one.</String>
|
||||||
|
<String Id="Error1501">Error accessing secured data. Please make sure the Windows Installer is configured properly and try the install again.</String>
|
||||||
|
<String Id="Error1502">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product. Your current install will now continue.</String>
|
||||||
|
<String Id="Error1503">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product.</String>
|
||||||
|
<String Id="Error1601">Out of disk space -- Volume: '[2]'; required space: [3] KB; available space: [4] KB. Free some disk space and retry.</String>
|
||||||
|
<String Id="Error1602">Are you sure you want to cancel?</String>
|
||||||
|
<String Id="Error1603">The file [2][3] is being held in use{ by the following process: Name: [4], Id: [5], Window Title: '[6]'}. Close that application and retry.</String>
|
||||||
|
<String Id="Error1604">The product '[2]' is already installed, preventing the installation of this product. The two products are incompatible.</String>
|
||||||
|
<String Id="Error1605">There is not enough disk space on the volume '[2]' to continue the install with recovery enabled. [3] KB are required, but only [4] KB are available. Click Ignore to continue the install without saving recovery information, click Retry to check for available space again, or click Cancel to quit the installation.</String>
|
||||||
|
<String Id="Error1606">Could not access network location [2].</String>
|
||||||
|
<String Id="Error1607">The following applications should be closed before continuing the install:</String>
|
||||||
|
<String Id="Error1608">Could not find any previously installed compliant products on the machine for installing this product.</String>
|
||||||
|
<String Id="Error1609">An error occurred while applying security settings. [2] is not a valid user or group. This could be a problem with the package, or a problem connecting to a domain controller on the network. Check your network connection and click Retry, or Cancel to end the install. {{Unable to locate the user's SID, system error [3]}}</String>
|
||||||
|
<String Id="Error1701">The key [2] is not valid. Verify that you entered the correct key.</String>
|
||||||
|
<String Id="Error1702">The installer must restart your system before configuration of [2] can continue. Click Yes to restart now or No if you plan to manually restart later.</String>
|
||||||
|
<String Id="Error1703">You must restart your system for the configuration changes made to [2] to take effect. Click Yes to restart now or No if you plan to manually restart later.</String>
|
||||||
|
<String Id="Error1704">An installation for [2] is currently suspended. You must undo the changes made by that installation to continue. Do you want to undo those changes?</String>
|
||||||
|
<String Id="Error1705">A previous installation for this product is in progress. You must undo the changes made by that installation to continue. Do you want to undo those changes?</String>
|
||||||
|
<String Id="Error1706">An installation package for the product [2] cannot be found. Try the installation again using a valid copy of the installation package '[3]'.</String>
|
||||||
|
<String Id="Error1707">Installation completed successfully.</String>
|
||||||
|
<String Id="Error1708">Installation failed.</String>
|
||||||
|
<String Id="Error1709">Product: [2] -- [3]</String>
|
||||||
|
<String Id="Error1710">You may either restore your computer to its previous state or continue the install later. Would you like to restore?</String>
|
||||||
|
<String Id="Error1711">An error occurred while writing installation information to disk. Check to make sure enough disk space is available, and click Retry, or Cancel to end the install.</String>
|
||||||
|
<String Id="Error1712">One or more of the files required to restore your computer to its previous state could not be found. Restoration will not be possible.</String>
|
||||||
|
<String Id="Error1713">[2] cannot install one of its required products. Contact your technical support group. {{System Error: [3].}}</String>
|
||||||
|
<String Id="Error1714">The older version of [2] cannot be removed. Contact your technical support group. {{System Error [3].}}</String>
|
||||||
|
<String Id="Error1715">Installed [2]</String>
|
||||||
|
<String Id="Error1716">Configured [2]</String>
|
||||||
|
<String Id="Error1717">Removed [2]</String>
|
||||||
|
<String Id="Error1718">File [2] was rejected by digital signature policy.</String>
|
||||||
|
<String Id="Error1719">The Windows Installer Service could not be accessed. This can occur if you are running Windows in safe mode, or if the Windows Installer is not correctly installed. Contact your support personnel for assistance.</String>
|
||||||
|
<String Id="Error1720">There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor. {{Custom action [2] script error [3], [4]: [5] Line [6], Column [7], [8] }}</String>
|
||||||
|
<String Id="Error1721">There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action: [2], location: [3], command: [4] }}</String>
|
||||||
|
<String Id="Error1722">There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. {{Action [2], location: [3], command: [4] }}</String>
|
||||||
|
<String Id="Error1723">There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action [2], entry: [3], library: [4] }}</String>
|
||||||
|
<String Id="Error1724">Removal completed successfully.</String>
|
||||||
|
<String Id="Error1725">Removal failed.</String>
|
||||||
|
<String Id="Error1726">Advertisement completed successfully.</String>
|
||||||
|
<String Id="Error1727">Advertisement failed.</String>
|
||||||
|
<String Id="Error1728">Configuration completed successfully.</String>
|
||||||
|
<String Id="Error1729">Configuration failed.</String>
|
||||||
|
<String Id="Error1730">You must be an Administrator to remove this application. To remove this application, you can log on as an Administrator, or contact your technical support group for assistance.</String>
|
||||||
|
<String Id="Error1731">The source installation package for the product [2] is out of sync with the client package. Try the installation again using a valid copy of the installation package '[3]'.</String>
|
||||||
|
<String Id="Error1732">In order to complete the installation of [2], you must restart the computer. Other users are currently logged on to this computer, and restarting may cause them to lose their work. Do you want to restart now?</String>
|
||||||
|
<String Id="Error1801">The path [2] is not valid. Please specify a valid path.</String>
|
||||||
|
<String Id="Error1802">Out of memory. Shut down other applications before retrying.</String>
|
||||||
|
<String Id="Error1803">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to go back to the previously selected volume.</String>
|
||||||
|
<String Id="Error1804">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to return to the browse dialog and select a different volume.</String>
|
||||||
|
<String Id="Error1805">The folder [2] does not exist. Please enter a path to an existing folder.</String>
|
||||||
|
<String Id="Error1806">You have insufficient privileges to read this folder.</String>
|
||||||
|
<String Id="Error1807">A valid destination folder for the install could not be determined.</String>
|
||||||
|
<String Id="Error1901">Error attempting to read from the source install database: [2].</String>
|
||||||
|
<String Id="Error1902">Scheduling reboot operation: Renaming file [2] to [3]. Must reboot to complete operation.</String>
|
||||||
|
<String Id="Error1903">Scheduling reboot operation: Deleting file [2]. Must reboot to complete operation.</String>
|
||||||
|
<String Id="Error1904">Module [2] failed to register. HRESULT [3]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1905">Module [2] failed to unregister. HRESULT [3]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1906">Failed to cache package [2]. Error: [3]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1907">Could not register font [2]. Verify that you have sufficient permissions to install fonts, and that the system supports this font.</String>
|
||||||
|
<String Id="Error1908">Could not unregister font [2]. Verify that you that you have sufficient permissions to remove fonts.</String>
|
||||||
|
<String Id="Error1909">Could not create Shortcut [2]. Verify that the destination folder exists and that you can access it.</String>
|
||||||
|
<String Id="Error1910">Could not remove Shortcut [2]. Verify that the shortcut file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1911">Could not register type library for file [2]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1912">Could not unregister type library for file [2]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1913">Could not update the ini file [2][3]. Verify that the file exists and that you can access it.</String>
|
||||||
|
<String Id="Error1914">Could not schedule file [2] to replace file [3] on reboot. Verify that you have write permissions to file [3].</String>
|
||||||
|
<String Id="Error1915">Error removing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1916">Error installing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</String>
|
||||||
|
<String Id="Error1917">Error removing ODBC driver: [4], ODBC error [2]: [3]. Verify that you have sufficient privileges to remove ODBC drivers.</String>
|
||||||
|
<String Id="Error1918">Error installing ODBC driver: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</String>
|
||||||
|
<String Id="Error1919">Error configuring ODBC data source: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</String>
|
||||||
|
<String Id="Error1920">Service '[2]' ([3]) failed to start. Verify that you have sufficient privileges to start system services.</String>
|
||||||
|
<String Id="Error1921">Service '[2]' ([3]) could not be stopped. Verify that you have sufficient privileges to stop system services.</String>
|
||||||
|
<String Id="Error1922">Service '[2]' ([3]) could not be deleted. Verify that you have sufficient privileges to remove system services.</String>
|
||||||
|
<String Id="Error1923">Service '[2]' ([3]) could not be installed. Verify that you have sufficient privileges to install system services.</String>
|
||||||
|
<String Id="Error1924">Could not update environment variable '[2]'. Verify that you have sufficient privileges to modify environment variables.</String>
|
||||||
|
<String Id="Error1925">You do not have sufficient privileges to complete this installation for all users of the machine. Log on as administrator and then retry this installation.</String>
|
||||||
|
<String Id="Error1926">Could not set file security for file '[3]'. Error: [2]. Verify that you have sufficient privileges to modify the security permissions for this file.</String>
|
||||||
|
<String Id="Error1927">Component Services (COM+ 1.0) are not installed on this computer. This installation requires Component Services in order to complete successfully. Component Services are available on Windows 2000.</String>
|
||||||
|
<String Id="Error1928">Error registering COM+ Application. Contact your support personnel for more information.</String>
|
||||||
|
<String Id="Error1929">Error unregistering COM+ Application. Contact your support personnel for more information.</String>
|
||||||
|
<String Id="Error1930">The description for service '[2]' ([3]) could not be changed.</String>
|
||||||
|
<String Id="Error1931">The Windows Installer service cannot update the system file [2] because the file is protected by Windows. You may need to update your operating system for this program to work correctly. {{Package version: [3], OS Protected version: [4]}}</String>
|
||||||
|
<String Id="Error1932">The Windows Installer service cannot update the protected Windows file [2]. {{Package version: [3], OS Protected version: [4], SFP Error: [5]}}</String>
|
||||||
|
<String Id="Error1933">The Windows Installer service cannot update one or more protected Windows files. {{SFP Error: [2]. List of protected files:\r\n[3]}}</String>
|
||||||
|
<String Id="Error1934">User installations are disabled via policy on the machine.</String>
|
||||||
|
<String Id="Error1935">An error occurred during the installation of assembly '[6]'. Please refer to Help and Support for more information. HRESULT: [3]. {{assembly interface: [4], function: [5], component: [2]}}</String>
|
||||||
|
<String Id="Error1936">An error occurred during the installation of assembly '[6]'. The assembly is not strongly named or is not signed with the minimal key length. HRESULT: [3]. {{assembly interface: [4], function: [5], component: [2]}}</String>
|
||||||
|
<String Id="Error1937">An error occurred during the installation of assembly '[6]'. The signature or catalog could not be verified or is not valid. HRESULT: [3]. {{assembly interface: [4], function: [5], component: [2]}}</String>
|
||||||
|
<String Id="Error1938">An error occurred during the installation of assembly '[6]'. One or more modules of the assembly could not be found. HRESULT: [3]. {{assembly interface: [4], function: [5], component: [2]}}</String>
|
||||||
|
|
||||||
|
<String Id="UITextbytes">bytes</String>
|
||||||
|
<String Id="UITextGB">GB</String>
|
||||||
|
<String Id="UITextKB">KB</String>
|
||||||
|
<String Id="UITextMB">MB</String>
|
||||||
|
<String Id="UITextMenuAbsent">Entire feature will be unavailable</String>
|
||||||
|
<String Id="UITextMenuAdvertise">Feature will be installed when required</String>
|
||||||
|
<String Id="UITextMenuAllCD">Entire feature will be installed to run from CD</String>
|
||||||
|
<String Id="UITextMenuAllLocal">Entire feature will be installed on local hard drive</String>
|
||||||
|
<String Id="UITextMenuAllNetwork">Entire feature will be installed to run from network</String>
|
||||||
|
<String Id="UITextMenuCD">Will be installed to run from CD</String>
|
||||||
|
<String Id="UITextMenuLocal">Will be installed on local hard drive</String>
|
||||||
|
<String Id="UITextMenuNetwork">Will be installed to run from network</String>
|
||||||
|
<String Id="UITextScriptInProgress">Gathering required information...</String>
|
||||||
|
<String Id="UITextSelAbsentAbsent">This feature will remain uninstalled</String>
|
||||||
|
<String Id="UITextSelAbsentAdvertise">This feature will be set to be installed when required</String>
|
||||||
|
<String Id="UITextSelAbsentCD">This feature will be installed to run from CD</String>
|
||||||
|
<String Id="UITextSelAbsentLocal">This feature will be installed on the local hard drive</String>
|
||||||
|
<String Id="UITextSelAbsentNetwork">This feature will be installed to run from the network</String>
|
||||||
|
<String Id="UITextSelAdvertiseAbsent">This feature will become unavailable</String>
|
||||||
|
<String Id="UITextSelAdvertiseAdvertise">Will be installed when required</String>
|
||||||
|
<String Id="UITextSelAdvertiseCD">This feature will be available to run from CD</String>
|
||||||
|
<String Id="UITextSelAdvertiseLocal">This feature will be installed on your local hard drive</String>
|
||||||
|
<String Id="UITextSelAdvertiseNetwork">This feature will be available to run from the network</String>
|
||||||
|
<String Id="UITextSelCDAbsent">This feature will be uninstalled completely, you won't be able to run it from CD</String>
|
||||||
|
<String Id="UITextSelCDAdvertise">This feature will change from run from CD state to set to be installed when required</String>
|
||||||
|
<String Id="UITextSelCDCD">This feature will remain to be run from CD</String>
|
||||||
|
<String Id="UITextSelCDLocal">This feature will change from run from CD state to be installed on the local hard drive</String>
|
||||||
|
<String Id="UITextSelChildCostNeg">This feature frees up [1] on your hard drive.</String>
|
||||||
|
<String Id="UITextSelChildCostPos">This feature requires [1] on your hard drive.</String>
|
||||||
|
<String Id="UITextSelCostPending">Compiling cost for this feature...</String>
|
||||||
|
<String Id="UITextSelLocalAbsent">This feature will be completely removed</String>
|
||||||
|
<String Id="UITextSelLocalAdvertise">This feature will be removed from your local hard drive, but will be set to be installed when required</String>
|
||||||
|
<String Id="UITextSelLocalCD">This feature will be removed from your local hard drive, but will be still available to run from CD</String>
|
||||||
|
<String Id="UITextSelLocalLocal">This feature will remain on you local hard drive</String>
|
||||||
|
<String Id="UITextSelLocalNetwork">This feature will be removed from your local hard drive, but will be still available to run from the network</String>
|
||||||
|
<String Id="UITextSelNetworkAbsent">This feature will be uninstalled completely, you won't be able to run it from the network</String>
|
||||||
|
<String Id="UITextSelNetworkAdvertise">This feature will change from run from network state to set to be installed when required</String>
|
||||||
|
<String Id="UITextSelNetworkLocal">This feature will change from run from network state to be installed on the local hard drive</String>
|
||||||
|
<String Id="UITextSelNetworkNetwork">This feature will remain to be run from the network</String>
|
||||||
|
<String Id="UITextSelParentCostNegNeg">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</String>
|
||||||
|
<String Id="UITextSelParentCostNegPos">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</String>
|
||||||
|
<String Id="UITextSelParentCostPosNeg">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</String>
|
||||||
|
<String Id="UITextSelParentCostPosPos">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</String>
|
||||||
|
<String Id="UITextTimeRemaining">Time remaining: {[1] minutes }{[2] seconds}</String>
|
||||||
|
<String Id="UITextVolumeCostAvailable">Available</String>
|
||||||
|
<String Id="UITextVolumeCostDifference">Difference</String>
|
||||||
|
<String Id="UITextVolumeCostRequired">Required</String>
|
||||||
|
<String Id="UITextVolumeCostSize">Disk Size</String>
|
||||||
|
<String Id="UITextVolumeCostVolume">Volume</String>
|
||||||
|
</WixLocalization>
|
15
WixInstaller/zh-cn.wxl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<WixLocalization Culture="zh-CN" Codepage="950" xmlns="http://schemas.microsoft.com/wix/2006/localization">
|
||||||
|
<String Id="Open">打开</String>
|
||||||
|
<String Id="XVA_File">XVA 文件</String>
|
||||||
|
<String Id="OVF_File">OVF 文件</String>
|
||||||
|
<String Id="OVA_File">OVA 文件</String>
|
||||||
|
<String Id="VHD_File">VHD 文件</String>
|
||||||
|
<String Id="VMDK_File">VMDK 文件</String>
|
||||||
|
<String Id="XenServer_License_File">XenServer 许可文件</String>
|
||||||
|
<String Id="XenServer_Backup_File">XenServer 备份文件</String>
|
||||||
|
<String Id="XenServer_Update_File">XenServer 更新文件</String>
|
||||||
|
<String Id="XenServer_OEM_Update_File">XenServer OEM 更新文件</String>
|
||||||
|
<String Id="XenCenter_Saved_Search">XenCenter 保存的搜索</String>
|
||||||
|
<String Id="Required_For_Installation">此安装。NET Framework 3.5中是必需的。</String>
|
||||||
|
</WixLocalization>
|
160
XenAdmin.sln
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual Studio 2008
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenAdmin", "XenAdmin\XenAdmin.csproj", "{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7} = {6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommandLib", "CommandLib\CommandLib.csproj", "{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xva_verify", "xva_verify\xva_verify.csproj", "{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Splash", "splash\splash.vcproj", "{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65} = {70BDA4BC-F062-4302-8ACD-A15D8BF31D65}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenAdminTests", "XenAdminTests\XenAdminTests.csproj", "{21B9482C-D255-40D5-ABA7-C8F00F99547C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenCenterLib", "XenCenterLib\XenCenterLib.csproj", "{9861DFA1-B41F-432D-A43F-226257DEBBB9}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenCenterVNC", "XenCenterVNC\XenCenterVNC.csproj", "{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenModel", "XenModel\XenModel.csproj", "{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenOvfApi", "XenOvfApi\XenOvfApi.csproj", "{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenOvfTransport", "XenOvfTransport\XenOvfTransport.csproj", "{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CFUValidator", "CFUValidator\CFUValidator.csproj", "{39308480-78C3-40B4-924D-06914F343ACD}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|Mixed Platforms = Release|Mixed Platforms
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{70BDA4BC-F062-4302-8ACD-A15D8BF31D65}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{6CE6A8FF-CF49-46B6-BEA4-6464A2F0A4D7}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{2A70D7E7-EAB2-4C36-B3F4-85B79D2384B5}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Debug|Mixed Platforms.Build.0 = Debug|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Release|Mixed Platforms.ActiveCfg = Release|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Release|Mixed Platforms.Build.0 = Release|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{AFB19C9D-DD63-478B-A4A3-8452CBD0B9AB}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{21B9482C-D255-40D5-ABA7-C8F00F99547C}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{9861DFA1-B41F-432D-A43F-226257DEBBB9}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{BD345C89-E8F4-4767-9BE0-1F0EAB7FA927}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{B306FC59-4441-4A5F-9F54-D3F68D4EE38D}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{2D78AC6C-B867-484A-A447-3C6FC8B8EAF7}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{9F7E6285-5CBF-41B4-8CB9-AB06DFF90DC0}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{39308480-78C3-40B4-924D-06914F343ACD}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
101
XenAdmin/Actions/GUIActions/DeleteAllAlertsAction.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Alerts;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class DeleteAllAlertsAction : AsyncAction
|
||||||
|
{
|
||||||
|
private readonly List<Alert> Alerts;
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <param name="connection">May be null, in which case this is expected to be for client-side alerts.</param>
|
||||||
|
public DeleteAllAlertsAction(IXenConnection connection, List<Alert> alerts)
|
||||||
|
: base(connection,
|
||||||
|
connection == null ? Messages.ACTION_REMOVE_ALERTS_ON_CLIENT_TITLE : string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CONNECTION_TITLE, Helpers.GetName(connection)),
|
||||||
|
Messages.ACTION_REMOVE_ALERTS_DESCRIPTION)
|
||||||
|
{
|
||||||
|
this.Alerts = alerts;
|
||||||
|
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
Pool = Helpers.GetPoolOfOne(connection);
|
||||||
|
Host = Helpers.GetMaster(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int max = Alerts.Count;
|
||||||
|
Exception e = null;
|
||||||
|
LogDescriptionChanges = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (Alert a in Alerts)
|
||||||
|
{
|
||||||
|
PercentComplete = (i * 100) / max;
|
||||||
|
i++;
|
||||||
|
Description = string.Format(Messages.ACTION_REMOVE_ALERTS_PROGRESS_DESCRIPTION, i, max);
|
||||||
|
BestEffort(ref e, delegate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
a.DismissSingle(Session);
|
||||||
|
}
|
||||||
|
catch (Failure exn)
|
||||||
|
{
|
||||||
|
if (exn.ErrorDescription[0] != Failure.HANDLE_INVALID)
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
LogDescriptionChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Description = max == 1 ? Messages.ACTION_REMOVE_ALERTS_DONE_ONE : string.Format(Messages.ACTION_REMOVE_ALERTS_DONE, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
381
XenAdmin/Actions/GUIActions/ExternalPluginAction.cs
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Plugins;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
internal class ExternalPluginAction : AsyncAction
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private const string EmptyParameter = "null";
|
||||||
|
private const string BlankParamter = "blank";
|
||||||
|
|
||||||
|
private static readonly string SnapInTrustedCertXml =
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
"Citrix\\XenServerPSSnapIn\\XenServer_Known_Certificates.xml");
|
||||||
|
|
||||||
|
private static readonly string SnapInTrustedCertXmlDir =
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||||
|
"Citrix\\XenServerPSSnapIn");
|
||||||
|
|
||||||
|
private readonly ReadOnlyCollection<IXenObject> _targets = new ReadOnlyCollection<IXenObject>(new List<IXenObject>());
|
||||||
|
private readonly bool XenCenterNodeTarget = false;
|
||||||
|
private readonly MenuItemFeature _menuItemFeature;
|
||||||
|
private Process _extAppProcess;
|
||||||
|
|
||||||
|
public ExternalPluginAction(MenuItemFeature menuItemFeature, IEnumerable<IXenObject> targets, bool XenCenterNodeSelected)
|
||||||
|
: base(null,
|
||||||
|
string.Format(Messages.EXTERNAL_PLUGIN_TITLE, menuItemFeature.ToString(), menuItemFeature.PluginName),
|
||||||
|
string.Format(Messages.EXTERNAL_PLUGIN_RUNNING, menuItemFeature.ToString()), false)
|
||||||
|
{
|
||||||
|
if (targets != null)
|
||||||
|
{
|
||||||
|
_targets = new ReadOnlyCollection<IXenObject>(new List<IXenObject>(targets));
|
||||||
|
if (_targets.Count == 1)
|
||||||
|
{
|
||||||
|
Connection = this._targets[0].Connection;
|
||||||
|
SetAppliesTo(this._targets[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XenCenterNodeTarget = XenCenterNodeSelected;
|
||||||
|
ShowProgress = false;
|
||||||
|
_menuItemFeature = menuItemFeature;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// build up a list of params to pass to the process, checking each connection for permissions as we go
|
||||||
|
Dictionary<IXenConnection, bool> connectionsChecked = new Dictionary<IXenConnection, bool>();
|
||||||
|
List<string> procParams = new List<string>();
|
||||||
|
if (XenCenterNodeTarget)
|
||||||
|
{
|
||||||
|
foreach (IXenConnection c in ConnectionsManager.XenConnectionsCopy)
|
||||||
|
{
|
||||||
|
if (c.IsConnected)
|
||||||
|
{
|
||||||
|
if (!connectionsChecked.ContainsKey(c))
|
||||||
|
{
|
||||||
|
CheckPermission(c);
|
||||||
|
connectionsChecked.Add(c, true);
|
||||||
|
}
|
||||||
|
procParams.AddRange(RetrieveParams(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_targets != null)
|
||||||
|
{
|
||||||
|
foreach (IXenObject o in _targets)
|
||||||
|
{
|
||||||
|
if (!connectionsChecked.ContainsKey(o.Connection))
|
||||||
|
{
|
||||||
|
CheckPermission(o.Connection);
|
||||||
|
connectionsChecked.Add(o.Connection, true);
|
||||||
|
}
|
||||||
|
procParams.AddRange(RetrieveParams(o));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_extAppProcess = _menuItemFeature.ShellCmd.CreateProcess(procParams, _targets);
|
||||||
|
|
||||||
|
_extAppProcess.OutputDataReceived += new DataReceivedEventHandler(_extAppProcess_OutputDataReceived);
|
||||||
|
|
||||||
|
log.InfoFormat("Plugin process for {0} running with parameters {1}", _extAppProcess.StartInfo.FileName, _extAppProcess.StartInfo.Arguments);
|
||||||
|
_extAppProcess.Start();
|
||||||
|
|
||||||
|
if (_extAppProcess.StartInfo.RedirectStandardError)
|
||||||
|
_extAppProcess.BeginOutputReadLine();
|
||||||
|
|
||||||
|
RecomputeCanCancel();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!_extAppProcess.HasExited)
|
||||||
|
{
|
||||||
|
if (Cancelling || Cancelled)
|
||||||
|
throw new CancelledException();
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecomputeCanCancel();
|
||||||
|
|
||||||
|
if (_extAppProcess.HasExited && _extAppProcess.ExitCode != 0)
|
||||||
|
{
|
||||||
|
log.ErrorFormat("Plugin process for {0} running with parameters {1} exited with Exit Code: {2}", _extAppProcess.StartInfo.FileName, _extAppProcess.StartInfo.Arguments, _extAppProcess.ExitCode);
|
||||||
|
throw new Exception(String.Format(Messages.EXTERNAL_PLUGIN_BAD_EXIT, _extAppProcess.ExitCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
if (Cancelling || Cancelled)
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Description = Messages.EXTERNAL_PLUGIN_FINISHED;
|
||||||
|
}
|
||||||
|
catch (Win32Exception ex)
|
||||||
|
{
|
||||||
|
log.Error("Error running plugin executable", ex);
|
||||||
|
throw new Win32Exception(Messages.EXTERNAL_PLUGIN_WIN32, ex);
|
||||||
|
}
|
||||||
|
catch (CancelledException)
|
||||||
|
{
|
||||||
|
Description = Messages.CANCELING;
|
||||||
|
log.Error("User pressed cancel, sending close request and waiting");
|
||||||
|
if (_extAppProcess != null && !_extAppProcess.HasExited)
|
||||||
|
{
|
||||||
|
_extAppProcess.CloseMainWindow();
|
||||||
|
WatchForClose(_extAppProcess);
|
||||||
|
}
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_extAppProcess != null)
|
||||||
|
{
|
||||||
|
_extAppProcess.Close();
|
||||||
|
_extAppProcess.Dispose();
|
||||||
|
_extAppProcess = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckPermission(IXenConnection xenConnection)
|
||||||
|
{
|
||||||
|
ShellCmd cmd = _menuItemFeature.ShellCmd;
|
||||||
|
RbacMethodList methodsToCheck = cmd.RequiredMethods.Count == 0 ? _menuItemFeature.GetMethodList(cmd.RequiredMethodList) : cmd.RequiredMethods;
|
||||||
|
if (methodsToCheck == null || xenConnection.Session == null || xenConnection.Session.IsLocalSuperuser || !Helpers.MidnightRideOrGreater(xenConnection))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.DebugFormat("Checking Plugin can run against connection {0}", xenConnection.Name);
|
||||||
|
List<Role> rolesAbleToCompleteAction;
|
||||||
|
bool ableToCompleteAction = Role.CanPerform(methodsToCheck, xenConnection, out rolesAbleToCompleteAction);
|
||||||
|
|
||||||
|
log.DebugFormat("Roles able to complete action: {0}", Role.FriendlyCSVRoleList(rolesAbleToCompleteAction));
|
||||||
|
log.DebugFormat("Subject {0} has roles: {1}", xenConnection.Session.UserLogName, Role.FriendlyCSVRoleList(xenConnection.Session.Roles));
|
||||||
|
|
||||||
|
if (ableToCompleteAction)
|
||||||
|
{
|
||||||
|
log.Debug("Subject authorized to complete action");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't run on this connection, bail out
|
||||||
|
string desc = string.Format(FriendlyErrorNames.RBAC_PERMISSION_DENIED_FRIENDLY_CONNECTION,
|
||||||
|
xenConnection.Session.FriendlyRoleDescription,
|
||||||
|
Role.FriendlyCSVRoleList(rolesAbleToCompleteAction),
|
||||||
|
xenConnection.Name);
|
||||||
|
throw new Exception(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WatchForClose(Process _extAppProcess)
|
||||||
|
{
|
||||||
|
TimeSpan gracePeriod = new TimeSpan(0, 0, (int)_menuItemFeature.ShellCmd.DisposeTime);
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
while (DateTime.Now - start < gracePeriod)
|
||||||
|
{
|
||||||
|
if (_extAppProcess.HasExited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
if (!_extAppProcess.HasExited)
|
||||||
|
{
|
||||||
|
Program.Invoke(Program.MainWindow, delegate
|
||||||
|
{
|
||||||
|
ThreeButtonDialog d = new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(System.Drawing.SystemIcons.Warning, string.Format(Messages.FORCE_CLOSE_PLUGIN_PROMPT, _menuItemFeature.ToString())),
|
||||||
|
"ProcessForceClosePrompt",
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.FORCE_CLOSE, DialogResult.Yes),
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.ALLOW_TO_CONTINUE, DialogResult.No));
|
||||||
|
|
||||||
|
if (d.ShowDialog(Program.MainWindow) == DialogResult.Yes && !_extAppProcess.HasExited)
|
||||||
|
_extAppProcess.Kill();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _extAppProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
log.Debug(e.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a set of params which relate to the object you have selected in the treeview
|
||||||
|
private List<string> RetrieveParams(IXenObject obj)
|
||||||
|
{
|
||||||
|
IXenConnection connection = obj.Connection;
|
||||||
|
Host master = connection != null ? Helpers.GetMaster(connection) : null; // get master asserts connection is not null
|
||||||
|
string masterAddress = EmptyParameter;
|
||||||
|
|
||||||
|
if (master != null)
|
||||||
|
{
|
||||||
|
masterAddress = Helpers.GetUrl(master.Connection);
|
||||||
|
WriteTrustedCertificates(master.Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
string sessionRef = connection.Session != null ? connection.Session.uuid : EmptyParameter;
|
||||||
|
string objCls = obj != null ? obj.GetType().Name : EmptyParameter;
|
||||||
|
string objUuid = obj != null && connection.Session != null ? Helpers.GetUuid(obj) : EmptyParameter;
|
||||||
|
return new List<string>(new string[] { masterAddress, sessionRef, objCls, objUuid });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a set of params which relate to the connection in general, with no obj information
|
||||||
|
private List<string> RetrieveParams(IXenConnection connection)
|
||||||
|
{
|
||||||
|
Host master = connection != null ? Helpers.GetMaster(connection) : null; // get master asserts connection is not null
|
||||||
|
string masterAddress = EmptyParameter;
|
||||||
|
|
||||||
|
if (master != null)
|
||||||
|
{
|
||||||
|
masterAddress = Helpers.GetUrl(master.Connection);
|
||||||
|
WriteTrustedCertificates(master.Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
string sessionRef = connection.Session != null ? connection.Session.uuid : EmptyParameter;
|
||||||
|
string objCls = BlankParamter;
|
||||||
|
string objUuid = BlankParamter;
|
||||||
|
return new List<string>(new string[] { masterAddress, sessionRef, objCls, objUuid });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteTrustedCertificates(IXenConnection connection)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(SnapInTrustedCertXmlDir))
|
||||||
|
Directory.CreateDirectory(SnapInTrustedCertXmlDir); // CA-42052
|
||||||
|
|
||||||
|
Dictionary<string, string> trusted = Settings.KnownServers;
|
||||||
|
|
||||||
|
if (!trusted.ContainsKey(connection.Hostname))
|
||||||
|
return;
|
||||||
|
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
XmlNode cert = doc.CreateElement("certificate");
|
||||||
|
XmlAttribute hostname = doc.CreateAttribute("hostname");
|
||||||
|
XmlAttribute fingerprint = doc.CreateAttribute("fingerprint");
|
||||||
|
|
||||||
|
hostname.Value = connection.Hostname;
|
||||||
|
fingerprint.Value = Helpers.PrettyFingerprint(trusted[connection.Hostname]);
|
||||||
|
|
||||||
|
cert.Attributes.Append(hostname);
|
||||||
|
cert.Attributes.Append(fingerprint);
|
||||||
|
|
||||||
|
XmlNode certs;
|
||||||
|
|
||||||
|
if (File.Exists(SnapInTrustedCertXml))
|
||||||
|
{
|
||||||
|
doc.Load(SnapInTrustedCertXml);
|
||||||
|
|
||||||
|
certs = doc.SelectSingleNode("certificates");
|
||||||
|
|
||||||
|
foreach (XmlNode node in certs.ChildNodes)
|
||||||
|
{
|
||||||
|
if (node.Name == "certificate" && node.Attributes["hostname"] != null && node.Attributes["hostname"].Value == hostname.Value)
|
||||||
|
certs.RemoveChild(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlNode decl = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
|
||||||
|
certs = doc.CreateElement("certificates");
|
||||||
|
|
||||||
|
doc.AppendChild(decl);
|
||||||
|
doc.AppendChild(certs);
|
||||||
|
}
|
||||||
|
|
||||||
|
certs.AppendChild(cert);
|
||||||
|
|
||||||
|
doc.Save(SnapInTrustedCertXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RecomputeCanCancel()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CanCancel = _extAppProcess != null && !_extAppProcess.HasExited;
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
CanCancel = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string AuditDescription()
|
||||||
|
{
|
||||||
|
return string.Format("{0}: {1} {2} {3}", this.GetType().Name, DescribeTargets(), _menuItemFeature.ShellCmd.Filename, Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string DescribeTargets()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (IXenObject o in _targets)
|
||||||
|
{
|
||||||
|
if (o is VM)
|
||||||
|
{
|
||||||
|
sb.Append(DescribeVM(o as VM));
|
||||||
|
}
|
||||||
|
else if (o is Pool)
|
||||||
|
{
|
||||||
|
sb.Append(DescribePool(o as Pool));
|
||||||
|
}
|
||||||
|
else if (o is Host)
|
||||||
|
{
|
||||||
|
sb.Append(DescribeHost(o as Host));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(o.GetType().Name);
|
||||||
|
sb.Append(" ");
|
||||||
|
sb.Append(o.opaque_ref);
|
||||||
|
sb.Append(" : ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
109
XenAdmin/Actions/GUIActions/GeneralEditPageAction.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Model;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
// Save folders and tags from the GeneralEditPage
|
||||||
|
class GeneralEditPageAction : AsyncAction
|
||||||
|
{
|
||||||
|
private readonly IXenObject xenObjectOrig;
|
||||||
|
private readonly IXenObject xenObjectCopy;
|
||||||
|
private readonly string newFolder;
|
||||||
|
private readonly List<string> oldTags, newTags;
|
||||||
|
|
||||||
|
public GeneralEditPageAction(IXenObject xenObjectOrig, IXenObject xenObjectCopy, string newFolder, List<string> newTags)
|
||||||
|
: base(xenObjectCopy.Connection, Messages.ACTION_SAVE_FOLDER_TAGS, string.Format(Messages.ACTION_SAVING_FOLDER_TAGS_FOR, xenObjectCopy))
|
||||||
|
{
|
||||||
|
this.xenObjectOrig = xenObjectOrig;
|
||||||
|
this.xenObjectCopy = xenObjectCopy;
|
||||||
|
this.newFolder = newFolder;
|
||||||
|
this.oldTags = new List<string>(Tags.GetTags(xenObjectCopy));
|
||||||
|
this.newTags = newTags;
|
||||||
|
oldTags.Sort();
|
||||||
|
newTags.Sort();
|
||||||
|
|
||||||
|
string type = xenObjectCopy.GetType().Name.ToLowerInvariant();
|
||||||
|
|
||||||
|
if (newFolder != xenObjectCopy.Path)
|
||||||
|
{
|
||||||
|
ApiMethodsToRoleCheck.Add(type + ".remove_from_other_config", Folders.FOLDER);
|
||||||
|
if (!String.IsNullOrEmpty(newFolder))
|
||||||
|
ApiMethodsToRoleCheck.Add(type + ".add_to_other_config", Folders.FOLDER);
|
||||||
|
// TODO: Full RBAC for folders
|
||||||
|
}
|
||||||
|
foreach (string tag in oldTags)
|
||||||
|
{
|
||||||
|
if (newTags.BinarySearch(tag) < 0)
|
||||||
|
{
|
||||||
|
ApiMethodsToRoleCheck.Add(type + ".remove_tags");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (string tag in newTags)
|
||||||
|
{
|
||||||
|
if (oldTags.BinarySearch(tag) < 0)
|
||||||
|
{
|
||||||
|
ApiMethodsToRoleCheck.Add(type + ".add_tags");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
if (newFolder != xenObjectCopy.Path)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(newFolder))
|
||||||
|
Folders.Move(Session, xenObjectOrig, newFolder);
|
||||||
|
else
|
||||||
|
Folders.Unfolder(Session, xenObjectOrig);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string tag in oldTags)
|
||||||
|
{
|
||||||
|
if (newTags.BinarySearch(tag) < 0)
|
||||||
|
Tags.RemoveTag(Session, xenObjectOrig, tag);
|
||||||
|
}
|
||||||
|
foreach (string tag in newTags)
|
||||||
|
{
|
||||||
|
if (oldTags.BinarySearch(tag) < 0)
|
||||||
|
Tags.AddTag(Session, xenObjectOrig, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
XenAdmin/Actions/GUIActions/IgnorePatchAction.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class IgnorePatchAction : AsyncAction
|
||||||
|
{
|
||||||
|
public const string IgnorePatchKey = "XenCenter.IgnorePatches";
|
||||||
|
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private XenServerPatch Patch;
|
||||||
|
|
||||||
|
public IgnorePatchAction(IXenConnection connection, XenServerPatch patch)
|
||||||
|
: base(connection, "ignore_patch", "ignore_patch", true)
|
||||||
|
{
|
||||||
|
Patch = patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
XenAPI.Pool pool = Helpers.GetPoolOfOne(Connection);
|
||||||
|
if (pool == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dictionary<string, string> other_config = pool.other_config;
|
||||||
|
|
||||||
|
if (other_config.ContainsKey(IgnorePatchKey))
|
||||||
|
{
|
||||||
|
List<string> current = new List<string>(other_config[IgnorePatchKey].Split(','));
|
||||||
|
if (current.Contains(Patch.Uuid))
|
||||||
|
return;
|
||||||
|
current.Add(Patch.Uuid);
|
||||||
|
other_config[IgnorePatchKey] = string.Join(",", current.ToArray());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
other_config.Add(IgnorePatchKey, Patch.Uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
XenAPI.Pool.set_other_config(Session, pool.opaque_ref, other_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
XenAdmin/Actions/GUIActions/IgnoreServerAction.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class IgnoreServerAction : AsyncAction
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private XenServerVersion Version;
|
||||||
|
|
||||||
|
public IgnoreServerAction(IXenConnection connection, XenServerVersion version)
|
||||||
|
: base(connection, "ignore_patch", "ignore_patch", true)
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
Pool pool = Helpers.GetPoolOfOne(Connection);
|
||||||
|
if (pool == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dictionary<string, string> other_config = pool.other_config;
|
||||||
|
|
||||||
|
if (other_config.ContainsKey(Updates.LastSeenServerVersionKey))
|
||||||
|
{
|
||||||
|
List<string> current = new List<string>(other_config[Updates.LastSeenServerVersionKey].Split(','));
|
||||||
|
if (current.Contains(Version.VersionAndOEM))
|
||||||
|
return;
|
||||||
|
current.Add(Version.VersionAndOEM);
|
||||||
|
other_config[Updates.LastSeenServerVersionKey] = string.Join(",", current.ToArray());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
other_config.Add(Updates.LastSeenServerVersionKey, Version.VersionAndOEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
XenAPI.Pool.set_other_config(Session, pool.opaque_ref, other_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
XenAdmin/Actions/GUIActions/MeddlingAction.cs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.GUIActions
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A "meddling" Action is one being performed by someone else -- in other words, they are ones that we've inferred by the
|
||||||
|
/// presence of task instances on the pool.
|
||||||
|
/// </summary>
|
||||||
|
public class MeddlingAction : CancellingAction
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public MeddlingAction(Task task)
|
||||||
|
: base(ActionType.Meddling, task.MeddlingActionTitle ?? task.Title, task.Description, false, false)
|
||||||
|
{
|
||||||
|
RelatedTask = new XenRef<Task>(task.opaque_ref);
|
||||||
|
Started = (task.created + task.Connection.ServerTimeOffset).ToLocalTime();
|
||||||
|
SetAppliesToData(task);
|
||||||
|
VM = VMFromAppliesTo(task);
|
||||||
|
Connection = task.Connection;
|
||||||
|
Update(task, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(Task task, bool deleting)
|
||||||
|
{
|
||||||
|
ThreadPool.QueueUserWorkItem(delegate
|
||||||
|
{
|
||||||
|
if (!deleting)
|
||||||
|
{
|
||||||
|
RecomputeCanCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task == null || IsCompleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log.DebugFormat("Updating task {0} : {1} - {2}", task.opaque_ref,
|
||||||
|
task.created, task.finished);
|
||||||
|
|
||||||
|
int percentComplete = task.progress < 0 ? 0 : (int) (100.0*task.progress);
|
||||||
|
if (PercentComplete < percentComplete)
|
||||||
|
PercentComplete = percentComplete;
|
||||||
|
|
||||||
|
SetFatalErrorData(task);
|
||||||
|
|
||||||
|
DetermineIfTaskIsComplete(task, deleting);
|
||||||
|
|
||||||
|
if (IsCompleted)
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
|
||||||
|
DestroyUnwantedOperations(task);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DetermineIfTaskIsComplete(Task task, bool deleting)
|
||||||
|
{
|
||||||
|
if (task.finished.Year > 1970)
|
||||||
|
{
|
||||||
|
DateTime t = task.finished + task.Connection.ServerTimeOffset;
|
||||||
|
Finished = t.ToLocalTime();
|
||||||
|
IsCompleted = true;
|
||||||
|
}
|
||||||
|
else if (deleting)
|
||||||
|
{
|
||||||
|
Finished = DateTime.Now;
|
||||||
|
IsCompleted = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartedRunning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFatalErrorData(Task task)
|
||||||
|
{
|
||||||
|
string[] err = task.error_info;
|
||||||
|
if (err != null && err.Length > 0)
|
||||||
|
Exception = new Failure(err);
|
||||||
|
else if (task.status == task_status_type.cancelled)
|
||||||
|
Exception = new CancelledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAppliesToData(Task task)
|
||||||
|
{
|
||||||
|
List<string> applies_to = task.AppliesTo;
|
||||||
|
if (applies_to != null)
|
||||||
|
{
|
||||||
|
AppliesTo.AddRange(applies_to);
|
||||||
|
Description = task.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A non-aware client has created this task. We'll create a new action for this, and place it under
|
||||||
|
// the task.resident_on host, or if that doesn't resolve, the pool master.
|
||||||
|
Host host = task.Connection.Resolve(task.resident_on) ?? Helpers.GetMaster(task.Connection);
|
||||||
|
if (host != null)
|
||||||
|
AppliesTo.Add(host.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VM VMFromAppliesTo(Task task)
|
||||||
|
{
|
||||||
|
foreach (string r in AppliesTo)
|
||||||
|
{
|
||||||
|
VM vm = task.Connection.Resolve(new XenRef<VM>(r));
|
||||||
|
if (vm != null)
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DestroyUnwantedOperations(Task task)
|
||||||
|
{
|
||||||
|
string[] err = task.error_info;
|
||||||
|
if (task.Name == "SR.create" && err != null && err.Length > 0 && err[0] == Failure.SR_BACKEND_FAILURE_107)
|
||||||
|
{
|
||||||
|
// This isn't an SR create at all, it is a scan for LUNs. Hide it, since the 'error' info contains loads of XML,
|
||||||
|
// and is not useful. We don't know this until the error occurs though. Destroy the MeddlingAction.
|
||||||
|
task.PropertyChanged -= MeddlingActionManager.Task_PropertyChanged;
|
||||||
|
ConnectionsManager.History.Remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
185
XenAdmin/Actions/GUIActions/MeddlingActionManager.cs
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.GUIActions
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MeddlingActionManager handles task events, categorises tasks depending upon whether they
|
||||||
|
/// are ours or not, and creates MeddlingAction instances when necessary
|
||||||
|
/// </summary>
|
||||||
|
public class MeddlingActionManager
|
||||||
|
{
|
||||||
|
#region Predicates
|
||||||
|
private static readonly ITaskSpecification taskFinishedSuccessfully =
|
||||||
|
new TaskHasFinishedSuccessfullySpecification();
|
||||||
|
|
||||||
|
private static readonly ITaskSpecification taskIsSuitableForMeddlingAction =
|
||||||
|
new TaskIsSuitableForMeddlingActionSpecification();
|
||||||
|
|
||||||
|
private static readonly ITaskSpecification taskIsUnwanted =
|
||||||
|
new TaskIsUnwantedSpecification();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tasks that we've seen, but haven't categorised yet. May only be acccesed under the DictionaryLock.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly List<string> UnmatchedTasks = new List<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tasks that we've categorised as not being ours, and the corresponding MeddlingAction that we created. May
|
||||||
|
/// only be accessed under the DictionaryLock.
|
||||||
|
/// </summary>
|
||||||
|
private static readonly Dictionary<string, MeddlingAction> MatchedTasks = new Dictionary<string, MeddlingAction>();
|
||||||
|
|
||||||
|
private static readonly object DictionaryLock = new object();
|
||||||
|
|
||||||
|
public static void TaskCollectionChanged(object sender, CollectionChangeEventArgs e)
|
||||||
|
{
|
||||||
|
lock (DictionaryLock)
|
||||||
|
{
|
||||||
|
Task task = (Task)e.Element;
|
||||||
|
if (e.Action == CollectionChangeAction.Add)
|
||||||
|
{
|
||||||
|
if (!UnmatchedTasks.Contains(task.opaque_ref))
|
||||||
|
AddTaskToUnmatchedList(task);
|
||||||
|
}
|
||||||
|
else if (e.Action == CollectionChangeAction.Remove)
|
||||||
|
{
|
||||||
|
CompletelyForgetTask(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.DebugFormat(String.Format("Unmatched action from sender -- Action: {0}; Task: {1}", e.Action, task.opaque_ref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddTaskToUnmatchedList(Task task)
|
||||||
|
{
|
||||||
|
task.PropertyChanged += Task_PropertyChanged;
|
||||||
|
UnmatchedTasks.Add(task.opaque_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompletelyForgetTask(Task task)
|
||||||
|
{
|
||||||
|
task.PropertyChanged -= Task_PropertyChanged;
|
||||||
|
if (MatchedTasks.ContainsKey(task.opaque_ref))
|
||||||
|
{
|
||||||
|
MatchedTasks[task.opaque_ref].Update(task, true);
|
||||||
|
}
|
||||||
|
UnmatchedTasks.Remove(task.opaque_ref);
|
||||||
|
MatchedTasks.Remove(task.opaque_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ForceAddTask(Task task)
|
||||||
|
{
|
||||||
|
TaskCollectionChanged(task, new CollectionChangeEventArgs(CollectionChangeAction.Add, task));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Task_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
Task task = (Task)sender;
|
||||||
|
lock (DictionaryLock)
|
||||||
|
{
|
||||||
|
if (UnmatchedTasks.Contains(task.opaque_ref))
|
||||||
|
{
|
||||||
|
if (taskIsUnwanted.IsSatisfiedBy(task))
|
||||||
|
{
|
||||||
|
RemoveUnmatchedTask(task);
|
||||||
|
}
|
||||||
|
else if (taskIsSuitableForMeddlingAction.IsSatisfiedBy(task))
|
||||||
|
{
|
||||||
|
CreateMeddlingActionForTask(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.DebugFormat("Unmatched meddling task skipped -- " + task.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (MatchedTasks.ContainsKey(task.opaque_ref))
|
||||||
|
{
|
||||||
|
if (taskFinishedSuccessfully.IsSatisfiedBy(task))
|
||||||
|
{
|
||||||
|
UpdateAndDeleteTask(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
UpdateTask(task);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// else - it is a hidden (etc..) task that has called already and been removed from unmatched
|
||||||
|
//(and not put into matched) - so ignore it
|
||||||
|
log.DebugFormat("Uncategorised meddling task skipped -- " + task.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateTask(Task task)
|
||||||
|
{
|
||||||
|
MatchedTasks[task.opaque_ref].Update(task, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateAndDeleteTask(Task task)
|
||||||
|
{
|
||||||
|
task.PropertyChanged -= Task_PropertyChanged;
|
||||||
|
MatchedTasks[task.opaque_ref].Update(task, true);
|
||||||
|
MatchedTasks.Remove(task.opaque_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateMeddlingActionForTask(Task task)
|
||||||
|
{
|
||||||
|
// If AppliesTo is set, then the client that created this task knows about our scheme for passing
|
||||||
|
// info between clients. We give the client a window (AwareClientHeuristic) to set this field
|
||||||
|
// before deciding that it's a non-aware client. Having decided that it's one of those two cases,
|
||||||
|
// we make a MeddlingAction.
|
||||||
|
|
||||||
|
MeddlingAction a = new MeddlingAction(task);
|
||||||
|
UnmatchedTasks.Remove(task.opaque_ref);
|
||||||
|
MatchedTasks[task.opaque_ref] = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RemoveUnmatchedTask(Task task)
|
||||||
|
{
|
||||||
|
// This is one of our tasks, or it's a subtask of something else, or it's one that we
|
||||||
|
// just don't care about. We're going to do no more with it.
|
||||||
|
task.PropertyChanged -= Task_PropertyChanged;
|
||||||
|
UnmatchedTasks.Remove(task.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 XenAPI;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.GUIActions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifcation for a task
|
||||||
|
/// </summary>
|
||||||
|
public interface ITaskSpecification
|
||||||
|
{
|
||||||
|
bool IsSatisfiedBy(Task task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the task unwanted by XenCenter?
|
||||||
|
/// </summary>
|
||||||
|
public class TaskIsUnwantedSpecification : ITaskSpecification
|
||||||
|
{
|
||||||
|
public bool IsSatisfiedBy(Task task)
|
||||||
|
{
|
||||||
|
return (task.XenCenterUUID == Program.XenCenterUUID ||
|
||||||
|
task.Connection.Resolve(task.subtask_of) != null ||
|
||||||
|
task.Hidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Is the task suitable to create a meddling action from?
|
||||||
|
/// </summary>
|
||||||
|
public class TaskIsSuitableForMeddlingActionSpecification : ITaskSpecification
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Heuristic to determine whether a new task was created by a client aware of our task.AppliesTo scheme, or by some other client.
|
||||||
|
/// </summary>
|
||||||
|
private readonly TimeSpan awareClientHeuristic = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
|
public bool IsSatisfiedBy(Task task)
|
||||||
|
{
|
||||||
|
return (task.AppliesTo != null ||
|
||||||
|
task.created + task.Connection.ServerTimeOffset < DateTime.UtcNow - awareClientHeuristic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Has the task successfully finished?
|
||||||
|
/// </summary>
|
||||||
|
public class TaskHasFinishedSuccessfullySpecification : ITaskSpecification
|
||||||
|
{
|
||||||
|
public bool IsSatisfiedBy(Task task)
|
||||||
|
{
|
||||||
|
return task.status == task_status_type.success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
XenAdmin/Actions/GUIActions/SaveCustomFieldsAction.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.CustomFields;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.XenSearch;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class SaveCustomFieldsAction : PureAsyncAction
|
||||||
|
{
|
||||||
|
private readonly IXenObject xenObject;
|
||||||
|
private readonly List<CustomField> customFields;
|
||||||
|
|
||||||
|
public SaveCustomFieldsAction(IXenObject xenObject, List<CustomField> customFields)
|
||||||
|
: base(xenObject.Connection, Messages.ACTION_SAVE_CUSTOM_FIELDS, string.Format(Messages.ACTION_SAVING_CUSTOM_FIELDS_FOR, xenObject))
|
||||||
|
{
|
||||||
|
this.xenObject = xenObject;
|
||||||
|
this.customFields = customFields;
|
||||||
|
|
||||||
|
string type = xenObject.GetType().Name.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
foreach (CustomField customField in customFields)
|
||||||
|
{
|
||||||
|
string key = CustomFieldsManager.GetCustomFieldKey(customField.Definition);
|
||||||
|
string value = customField.ValueAsInvariantString;
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(value))
|
||||||
|
Helpers.RemoveFromOtherConfig(Session, xenObject, key);
|
||||||
|
else
|
||||||
|
Helpers.SetOtherConfig(Session, xenObject, key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
149
XenAdmin/Actions/GUIActions/SaveDataSourceStateAction.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Controls.CustomDataGraph;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class SaveDataSourceStateAction : PureAsyncAction
|
||||||
|
{
|
||||||
|
List<DataSourceItem> DataSourceItems;
|
||||||
|
List<DesignedGraph> Graphs;
|
||||||
|
IXenObject XenObject;
|
||||||
|
|
||||||
|
private Pool GetPool()
|
||||||
|
{
|
||||||
|
return Helpers.GetPoolOfOne(Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, string> GetGuiConfig()
|
||||||
|
{
|
||||||
|
Pool pool = GetPool();
|
||||||
|
return pool != null ? Helpers.GetGuiConfig(pool) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaveDataSourceStateAction(IXenConnection connection, IXenObject xmo, List<DataSourceItem> items, List<DesignedGraph> graphs)
|
||||||
|
: base(connection, "Saving DataSources", "Saving DataSources", true)
|
||||||
|
{
|
||||||
|
DataSourceItems = items;
|
||||||
|
XenObject = xmo;
|
||||||
|
Graphs = graphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> gui_config = GetGuiConfig();
|
||||||
|
|
||||||
|
if (DataSourceItems != null)
|
||||||
|
{
|
||||||
|
foreach (DataSourceItem ds in DataSourceItems)
|
||||||
|
{
|
||||||
|
if (ds.DataSource.enabled != ds.Enabled)
|
||||||
|
{
|
||||||
|
Host host = XenObject as Host;
|
||||||
|
VM vm = XenObject as VM;
|
||||||
|
if (host != null)
|
||||||
|
{
|
||||||
|
if (ds.Enabled)
|
||||||
|
XenAPI.Host.record_data_source(Session, host.opaque_ref, ds.DataSource.name_label);
|
||||||
|
else
|
||||||
|
XenAPI.Host.forget_data_source_archives(Session, host.opaque_ref, ds.DataSource.name_label);
|
||||||
|
}
|
||||||
|
else if (vm != null)
|
||||||
|
{
|
||||||
|
if (ds.Enabled)
|
||||||
|
XenAPI.VM.record_data_source(Session, vm.opaque_ref, ds.DataSource.name_label);
|
||||||
|
else
|
||||||
|
XenAPI.VM.forget_data_source_archives(Session, vm.opaque_ref, ds.DataSource.name_label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.ColorChanged)
|
||||||
|
{
|
||||||
|
if (gui_config != null)
|
||||||
|
{
|
||||||
|
string key = Palette.GetColorKey(ds.DataSource.name_label, XenObject);
|
||||||
|
string value = ds.Color.ToArgb().ToString();
|
||||||
|
|
||||||
|
if (!gui_config.ContainsKey(key))
|
||||||
|
gui_config.Add(key, value);
|
||||||
|
else
|
||||||
|
gui_config[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, string> new_gui_config = new Dictionary<string, string>();
|
||||||
|
string uuid = Helpers.GetUuid(XenObject);
|
||||||
|
|
||||||
|
// build new gui config dictionary:
|
||||||
|
// add keys not related to current XenObject
|
||||||
|
if (gui_config != null)
|
||||||
|
{
|
||||||
|
foreach (string key in gui_config.Keys)
|
||||||
|
{
|
||||||
|
bool isMatch = (Palette.LayoutKey.IsMatch(key) || Palette.GraphNameKey.IsMatch(key));
|
||||||
|
if (isMatch && key.Contains(uuid))
|
||||||
|
continue;
|
||||||
|
new_gui_config.Add(key, gui_config[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Graphs != null)
|
||||||
|
{
|
||||||
|
// add current XenObject keys
|
||||||
|
for (int i = 0; i < Graphs.Count; i++)
|
||||||
|
{
|
||||||
|
string key = Palette.GetLayoutKey(i, XenObject);
|
||||||
|
string value = Graphs[i].ToString();
|
||||||
|
|
||||||
|
// 'key' should not exist in the new gui config dictionary
|
||||||
|
new_gui_config.Add(key, value);
|
||||||
|
|
||||||
|
key = Palette.GetGraphNameKey(i, XenObject);
|
||||||
|
value = Graphs[i].DisplayName;
|
||||||
|
if (value != String.Empty)
|
||||||
|
{
|
||||||
|
new_gui_config.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XenAPI.Pool.set_gui_config(Session, GetPool().opaque_ref, new_gui_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
98
XenAdmin/Actions/GUIActions/SearchAction.cs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.XenSearch;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
class SearchAction : AsyncAction
|
||||||
|
{
|
||||||
|
public enum Operation { save, delete };
|
||||||
|
|
||||||
|
private readonly Operation operation;
|
||||||
|
private readonly Search search;
|
||||||
|
|
||||||
|
public SearchAction(Search search, Operation operation)
|
||||||
|
: base(null, GetTitle(search, operation), GetDescription(search, operation))
|
||||||
|
{
|
||||||
|
this.operation = operation;
|
||||||
|
this.search = search;
|
||||||
|
Connection = search.Connection;
|
||||||
|
Pool = XenAdmin.Core.Helpers.GetPoolOfOne(Connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String GetTitle(Search search, Operation operation)
|
||||||
|
{
|
||||||
|
switch(operation)
|
||||||
|
{
|
||||||
|
case Operation.save:
|
||||||
|
return String.Format(Messages.SAVE_SEARCH, search.Name);
|
||||||
|
|
||||||
|
case Operation.delete:
|
||||||
|
return String.Format(Messages.DELETE_SEARCH, search.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String GetDescription(Search search, Operation operation)
|
||||||
|
{
|
||||||
|
switch(operation)
|
||||||
|
{
|
||||||
|
case Operation.save:
|
||||||
|
return String.Format(Messages.SAVING_SEARCH, search.Name);
|
||||||
|
|
||||||
|
case Operation.delete:
|
||||||
|
return String.Format(Messages.DELETING_SEARCH, search.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
switch(operation)
|
||||||
|
{
|
||||||
|
case Operation.save:
|
||||||
|
search.Save();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Operation.delete:
|
||||||
|
search.Delete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
XenAdmin/Actions/GUIActions/Wlb/ExportReportAction.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Reporting.WinForms;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.Wlb
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class exports the reports and stores the result into a byte array
|
||||||
|
/// </summary>
|
||||||
|
class ExportReportAction : AsyncAction
|
||||||
|
{
|
||||||
|
private byte[] _reportData;
|
||||||
|
private string _format;
|
||||||
|
private ReportViewer _reportViewer;
|
||||||
|
|
||||||
|
public byte[] ReportData
|
||||||
|
{
|
||||||
|
get { return _reportData; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExportReportAction(string format, ref ReportViewer reportViewer)
|
||||||
|
: base(null, String.Format(Messages.WLB_REPORT_EXPORTING, format + "..."))
|
||||||
|
{
|
||||||
|
this._format = format;
|
||||||
|
this._reportViewer = reportViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
SafeToExit = false;
|
||||||
|
Warning[] warnings;
|
||||||
|
string[] streamids;
|
||||||
|
string mimeType;
|
||||||
|
string encoding;
|
||||||
|
string extension;
|
||||||
|
|
||||||
|
this._reportData = _reportViewer.LocalReport.Render(
|
||||||
|
this._format, null, out mimeType, out encoding, out extension,
|
||||||
|
out streamids, out warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
458
XenAdmin/Actions/GUIActions/Wlb/WlbOptimizePoolAction.cs
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Commands;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Wlb;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAPI;
|
||||||
|
using System.Drawing;
|
||||||
|
using XenAdmin.Actions.VMActions;
|
||||||
|
|
||||||
|
using XenAdmin.Actions.HostActions;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.Wlb
|
||||||
|
{
|
||||||
|
class WlbOptimizePoolAction : AsyncAction
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private string optId = String.Empty;
|
||||||
|
private readonly Dictionary<VM, WlbOptimizationRecommendation> vmOptList = new Dictionary<VM, WlbOptimizationRecommendation>();
|
||||||
|
|
||||||
|
private bool moveToNext = false;
|
||||||
|
private string hostActionError = String.Empty;
|
||||||
|
|
||||||
|
public WlbOptimizePoolAction(Pool pool, Dictionary<VM, WlbOptimizationRecommendation> vmOptLst, string optId)
|
||||||
|
: base(pool.Connection, string.Format(Messages.WLB_OPTIMIZING_POOL, Helpers.GetName(pool).Ellipsise(50)))
|
||||||
|
{
|
||||||
|
if (pool == null)
|
||||||
|
throw new ArgumentNullException("pool");
|
||||||
|
if (vmOptLst == null)
|
||||||
|
throw new ArgumentNullException("vmOptLst");
|
||||||
|
|
||||||
|
this.Pool = pool;
|
||||||
|
this.vmOptList = vmOptLst;
|
||||||
|
this.optId = optId;
|
||||||
|
|
||||||
|
#region RBAC Dependencies
|
||||||
|
// HA adjustments
|
||||||
|
ApiMethodsToRoleCheck.Add("pool.sync_database");
|
||||||
|
ApiMethodsToRoleCheck.Add("pool.set_ha_host_failures_to_tolerate");
|
||||||
|
ApiMethodsToRoleCheck.Add("vm.set_ha_restart_priority");
|
||||||
|
ApiMethodsToRoleCheck.Add("vm.set_ha_always_run");
|
||||||
|
|
||||||
|
ApiMethodsToRoleCheck.Add("vm.assert_can_boot_here");
|
||||||
|
ApiMethodsToRoleCheck.Add("vm.assert_agile");
|
||||||
|
ApiMethodsToRoleCheck.AddRange(Role.CommonTaskApiList);
|
||||||
|
ApiMethodsToRoleCheck.AddRange(Role.CommonSessionApiList);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
if (vmOptList.Count == 0)
|
||||||
|
{
|
||||||
|
log.ErrorFormat("{0} has no VMs need to be optimized", Helpers.GetName(Pool));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Description = Messages.ACTION_WLB_POOL_OPTIMIZING;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
log.Debug("Optimizing " + Pool.Name);
|
||||||
|
|
||||||
|
// for checking whether to display recommendations on optimize pool listview
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool,WlbOptimizationRecommendation.OPTIMIZINGPOOL, Messages.IN_PROGRESS);
|
||||||
|
int start = 0;
|
||||||
|
int each = 90 / vmOptList.Count;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<VM, WlbOptimizationRecommendation> vmItem in vmOptList)
|
||||||
|
{
|
||||||
|
VM vm = vmItem.Key;
|
||||||
|
Host fromHost = null;
|
||||||
|
Host toHost = null;
|
||||||
|
|
||||||
|
if (vmItem.Key.is_control_domain)
|
||||||
|
{
|
||||||
|
log.Debug(vmItem.Value.powerOperation + " " + Helpers.GetName(vmItem.Value.toHost));
|
||||||
|
fromHost = vmItem.Value.fromHost;
|
||||||
|
Helpers.SetOtherConfig(fromHost.Connection.Session, fromHost,WlbOptimizationRecommendation.OPTIMIZINGPOOL, vmItem.Value.recId.ToString());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AsyncAction hostAction = null;
|
||||||
|
int waitingInterval = 10 * 1000; // default to 10s
|
||||||
|
|
||||||
|
if (vmItem.Value.fromHost.IsLive)
|
||||||
|
{
|
||||||
|
hostAction = new ShutdownHostAction(fromHost,AddHostToPoolCommand.NtolDialog);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hostAction = new HostPowerOnAction(fromHost);
|
||||||
|
waitingInterval = 30 * 1000; // wait for 30s
|
||||||
|
}
|
||||||
|
|
||||||
|
hostAction.Completed += HostAction_Completed;
|
||||||
|
hostAction.RunAsync();
|
||||||
|
|
||||||
|
while (!moveToNext)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(hostActionError))
|
||||||
|
{
|
||||||
|
throw new Exception(hostActionError);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//wait
|
||||||
|
System.Threading.Thread.Sleep(waitingInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.Debug("Migrating VM " + vm.Name);
|
||||||
|
fromHost = this.Pool.Connection.Resolve(vm.resident_on);
|
||||||
|
toHost = vmItem.Value.toHost;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// check if there is a conflict with HA, start optimize if we can
|
||||||
|
RelocateVmWithHa(this, vm, toHost, start, start + each, vmItem.Value.recId);
|
||||||
|
}
|
||||||
|
catch (Failure f)
|
||||||
|
{
|
||||||
|
// prompt to user if ha notl can be raised, if yes, continue
|
||||||
|
long newNtol = 0;
|
||||||
|
if (RaiseHANotl(vm, f, out newNtol))
|
||||||
|
{
|
||||||
|
DelegatedAsyncAction action = new DelegatedAsyncAction(vm.Connection, Messages.HA_LOWERING_NTOL, null, null,
|
||||||
|
delegate(Session session)
|
||||||
|
{
|
||||||
|
// Set new ntol, then retry action
|
||||||
|
XenAPI.Pool.set_ha_host_failures_to_tolerate(session, this.Pool.opaque_ref, newNtol);
|
||||||
|
// ntol set succeeded, start new action
|
||||||
|
Program.MainWindow.closeActiveWizards(vm);
|
||||||
|
new VMMigrateAction(vm,toHost).RunAsync();
|
||||||
|
});
|
||||||
|
action.RunAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool, WlbOptimizationRecommendation.OPTIMIZINGPOOL, Messages.WLB_OPT_FAILED);
|
||||||
|
this.Description = Messages.WLB_OPT_FAILED;
|
||||||
|
throw f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start += each;
|
||||||
|
|
||||||
|
// stop if user cancels optimize pool
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
this.Description = Messages.WLB_OPT_OK_NOTICE_TEXT;
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool, WlbOptimizationRecommendation.OPTIMIZINGPOOL, optId);
|
||||||
|
log.Debug("Completed optimizing " + Pool.Name);
|
||||||
|
}
|
||||||
|
catch (Failure ex)
|
||||||
|
{
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool, WlbOptimizationRecommendation.OPTIMIZINGPOOL, optId);
|
||||||
|
WlbServerState.SetState(Pool, WlbServerState.ServerState.ConnectionError, (Failure)ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (CancelledException)
|
||||||
|
{
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool, WlbOptimizationRecommendation.OPTIMIZINGPOOL, optId);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.Error(ex, ex);
|
||||||
|
this.Description = Messages.WLB_OPT_FAILED;
|
||||||
|
Helpers.SetOtherConfig(this.Session, this.Pool, WlbOptimizationRecommendation.OPTIMIZINGPOOL, optId);
|
||||||
|
log.Debug("Optimizing " + Pool.Name + " is failed");
|
||||||
|
}
|
||||||
|
this.PercentComplete = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void HostAction_Completed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
AsyncAction action = (AsyncAction)sender;
|
||||||
|
if (action.IsCompleted)
|
||||||
|
{
|
||||||
|
action.Completed -= HostAction_Completed;
|
||||||
|
|
||||||
|
if (action is ShutdownHostAction || action is HostPowerOnAction)
|
||||||
|
{
|
||||||
|
if (action.Description == Messages.ACTION_HOST_STARTED || action.Description == String.Format(Messages.ACTION_HOST_SHUTDOWN, Helpers.GetName(action.Host)))
|
||||||
|
{
|
||||||
|
moveToNext = true;
|
||||||
|
}
|
||||||
|
if ((action.Exception != null && !String.IsNullOrEmpty(action.Exception.Message)) || action.Description == String.Format(Messages.ACTION_HOST_START_FAILED, Helpers.GetName(action.Host)))
|
||||||
|
{
|
||||||
|
hostActionError = action.Exception == null ? action.Description : action.Exception.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void RelocateVmWithHa(AsyncAction action, VM vm, Host host, int start, int end, int recommendationId)
|
||||||
|
{
|
||||||
|
bool setDoNotRestart = false;
|
||||||
|
|
||||||
|
if (vm.HaPriorityIsRestart())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XenAPI.VM.assert_agile(action.Session, vm.opaque_ref);
|
||||||
|
}
|
||||||
|
catch (Failure)
|
||||||
|
{
|
||||||
|
// VM is not agile, but it is 'Protected' by HA. This is an inconsistent state (see CA-20820).
|
||||||
|
// Tell the user the VM will be started without HA protection.
|
||||||
|
Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
{
|
||||||
|
new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(
|
||||||
|
SystemIcons.Warning,
|
||||||
|
String.Format(Messages.HA_INVALID_CONFIG_RESUME, Helpers.GetName(vm).Ellipsise(500)),
|
||||||
|
Messages.HIGH_AVAILABILITY)).ShowDialog(Program.MainWindow);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the VM to 'Do not restart'.
|
||||||
|
XenAPI.VM.set_ha_restart_priority(action.Session, vm.opaque_ref, XenAPI.VM.RESTART_PRIORITY_DO_NOT_RESTART);
|
||||||
|
setDoNotRestart = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setDoNotRestart && vm.HasSavedRestartPriority)
|
||||||
|
{
|
||||||
|
// If HA is turned on, setting ha_always_run will cause the VM to be started by itself
|
||||||
|
// but when the VM fails to start we want to know why, so we do a VM.start here too.
|
||||||
|
// This will fail with a power state exception if HA has already started the VM - but in
|
||||||
|
// that case we don't care, since the VM successfully started already.
|
||||||
|
SetHaProtection(true, action, vm, start, end);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DoAction(action, vm, host, start, end, recommendationId);
|
||||||
|
}
|
||||||
|
catch (Failure f)
|
||||||
|
{
|
||||||
|
if (f.ErrorDescription.Count == 4 && f.ErrorDescription[0] == Failure.VM_BAD_POWER_STATE && f.ErrorDescription[3] == "running")
|
||||||
|
{
|
||||||
|
// The VM started successfully via HA
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// HA off: just do a regular start
|
||||||
|
DoAction(action, vm, host, start, end, recommendationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// In the case there was nowhere to start/resume the VM (NO_HOSTS_AVAILABLE), shows the reason why the VM could not be started
|
||||||
|
/// on each host. If the start failed due to HA_OPERATION_WOULD_BREAK_FAILOVER_PLAN, offers to decrement ntol and try the operation
|
||||||
|
/// again.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vm">vm</param>
|
||||||
|
/// <param name="failure">failure, xapi exception</param>
|
||||||
|
//private static bool StartDiagnosisForm(XenObject<VM> vm, Failure failure, string recommendationId)
|
||||||
|
private bool RaiseHANotl(VM vm, Failure failure, out long newNtol)
|
||||||
|
{
|
||||||
|
bool error = false;
|
||||||
|
newNtol = 0;
|
||||||
|
|
||||||
|
if (failure.ErrorDescription[0] == Failure.NO_HOSTS_AVAILABLE)
|
||||||
|
{
|
||||||
|
VMOperationCommand.StartDiagnosisForm(vm);
|
||||||
|
}
|
||||||
|
else if (failure.ErrorDescription[0] == Failure.HA_OPERATION_WOULD_BREAK_FAILOVER_PLAN)
|
||||||
|
{
|
||||||
|
// The action was blocked by HA because it would reduce the number of tolerable server failures.
|
||||||
|
// With the user's consent, we'll reduce the number of configured failures to tolerate and try again.
|
||||||
|
if (this.Pool == null)
|
||||||
|
{
|
||||||
|
log.ErrorFormat("Could not get pool for VM {0} in StartDiagnosisForm()", Helpers.GetName(vm));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
long ntol = this.Pool.ha_host_failures_to_tolerate;
|
||||||
|
newNtol = Math.Min(this.Pool.ha_plan_exists_for - 1, ntol - 1);
|
||||||
|
if (newNtol <= 0)
|
||||||
|
{
|
||||||
|
// We would need to basically turn HA off to start this VM
|
||||||
|
string msg = String.Format(Messages.HA_OPT_VM_RELOCATE_NTOL_ZERO,
|
||||||
|
Helpers.GetName(this.Pool).Ellipsise(100),
|
||||||
|
Helpers.GetName(vm).Ellipsise(100));
|
||||||
|
Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
{
|
||||||
|
new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(
|
||||||
|
SystemIcons.Warning,
|
||||||
|
msg,
|
||||||
|
Messages.HIGH_AVAILABILITY)).ShowDialog(Program.MainWindow);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show 'reduce ntol?' dialog
|
||||||
|
string msg = String.Format(Messages.HA_OPT_DISABLE_NTOL_DROP,
|
||||||
|
Helpers.GetName(this.Pool).Ellipsise(100), ntol,
|
||||||
|
Helpers.GetName(vm).Ellipsise(100), newNtol);
|
||||||
|
|
||||||
|
Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
{
|
||||||
|
DialogResult r = new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(
|
||||||
|
SystemIcons.Warning,
|
||||||
|
msg,
|
||||||
|
Messages.HIGH_AVAILABILITY),
|
||||||
|
ThreeButtonDialog.ButtonYes,
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)).ShowDialog(Program.MainWindow);
|
||||||
|
|
||||||
|
if (r != DialogResult.Yes)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Migrate vm and log recommendation id for reporting purpose
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="action">AsyncAction</param>
|
||||||
|
/// <param name="vm">VM that needs to be migrated</param>
|
||||||
|
/// <param name="host">Host that vm will migrate to</param>
|
||||||
|
/// <param name="start">progress bar start point</param>
|
||||||
|
/// <param name="end">progress bar end point</param>
|
||||||
|
/// <param name="recommendationId">recommendation id</param>
|
||||||
|
private static void DoAction(AsyncAction action, VM vm, Host host, int start, int end, int recommendationId)
|
||||||
|
{
|
||||||
|
action.RelatedTask = XenAPI.VM.async_live_migrate(action.Session, vm.opaque_ref, host.opaque_ref);
|
||||||
|
|
||||||
|
if (recommendationId != 0)
|
||||||
|
{
|
||||||
|
// set vm migrate task key values for wlb reporting purpose
|
||||||
|
Task.add_to_other_config(action.Session, action.RelatedTask.opaque_ref, "wlb_advised", recommendationId.ToString());
|
||||||
|
Task.add_to_other_config(action.Session, action.RelatedTask.opaque_ref, "wlb_action", "vm_migrate");
|
||||||
|
Task.add_to_other_config(action.Session, action.RelatedTask.opaque_ref, "wlb_action_obj_ref", vm.opaque_ref);
|
||||||
|
Task.add_to_other_config(action.Session, action.RelatedTask.opaque_ref, "wlb_action_obj_type", "vm");
|
||||||
|
}
|
||||||
|
action.PollToCompletion(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables or disables HA protection for a VM (VM.ha_always_run). Also does a pool.sync_database afterwards.
|
||||||
|
/// Does nothing if the server is a build before ha_always_run was introduced.
|
||||||
|
/// May throw a XenAPI.Failure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="protect">true if vm is protected</param>
|
||||||
|
/// <param name="action">AsyncAction</param>
|
||||||
|
/// <param name="vm">vm</param>
|
||||||
|
/// <param name="start">progress bar start point</param>
|
||||||
|
/// <param name="end">progress bar end point</param>
|
||||||
|
private static void SetHaProtection(bool protect, AsyncAction action, VM vm, int start, int end)
|
||||||
|
{
|
||||||
|
if (!Helpers.BostonOrGreater(vm.Connection))
|
||||||
|
{
|
||||||
|
// Enable or disable HA protection for the VM.
|
||||||
|
XenAPI.VM.set_ha_always_run(action.Session, vm.opaque_ref, protect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do database sync. Helps to ensure that the change persists over master failover.
|
||||||
|
action.RelatedTask = XenAPI.Pool.async_sync_database(action.Session);
|
||||||
|
action.PollToCompletion(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// offer to bump ntol back up, if we can
|
||||||
|
/// Asks the user if they want to increase ntol (since hypothetical_max might have gone up).
|
||||||
|
/// </summary>
|
||||||
|
// not in use at the moment, keep it for now
|
||||||
|
//private void BumpNtol()
|
||||||
|
//{
|
||||||
|
// if (this.Pool!= null && this.Pool.ha_enabled)
|
||||||
|
// {
|
||||||
|
// Dictionary<XenRef<VM>, string> config = Helpers.GetVmHaRestartPrioritiesForApi(Helpers.GetVmHaRestartPriorities(this.Pool.Connection));
|
||||||
|
// long max = XenAPI.Pool.ha_compute_hypothetical_max_host_failures_to_tolerate(this.Session, config);
|
||||||
|
// long currentNtol = this.Pool.ha_host_failures_to_tolerate;
|
||||||
|
|
||||||
|
// if (currentNtol < max)
|
||||||
|
// {
|
||||||
|
// bool doit = false;
|
||||||
|
|
||||||
|
// Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
// {
|
||||||
|
// string poolName = Helpers.TrimStringIfRequired(Helpers.GetName(this.Pool), 500);
|
||||||
|
// string msg = String.Format(Messages.HA_OPT_ENABLE_NTOL_RAISE_QUERY, poolName, currentNtol, max);
|
||||||
|
|
||||||
|
// if (new ThreeButtonDialog(
|
||||||
|
// new ThreeButtonDialog.Details(null, msg, Messages.HIGH_AVAILABILITY),
|
||||||
|
// ThreeButtonDialog.ButtonYes,
|
||||||
|
// new ThreeButtonDialog.TBDButton(Messages.NO, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)).ShowDialog(Program.MainWindow) == DialogResult.Yes)
|
||||||
|
// {
|
||||||
|
// doit = true;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (doit)
|
||||||
|
// {
|
||||||
|
// XenAPI.Pool.set_ha_host_failures_to_tolerate(this.Session, this.Pool.opaque_ref, max);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
101
XenAdmin/Actions/OVFActions/ApplianceAction.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 XenAdmin.Core;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAPI;
|
||||||
|
using XenOvfTransport;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.OVFActions
|
||||||
|
{
|
||||||
|
public abstract class ApplianceAction : AsyncAction
|
||||||
|
{
|
||||||
|
protected string m_networkUuid;
|
||||||
|
protected bool m_isTvmIpStatic;
|
||||||
|
protected string m_tvmIpAddress;
|
||||||
|
protected string m_tvmSubnetMask;
|
||||||
|
protected string m_tvmGateway;
|
||||||
|
protected XenOvfTransportBase m_transportAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RBAC dependencies needed to import appliance/export an appliance/import disk image.
|
||||||
|
/// </summary>
|
||||||
|
public static RbacMethodList StaticRBACDependencies = new RbacMethodList("VM.add_to_other_config",
|
||||||
|
"VM.create",
|
||||||
|
"VM.destroy",
|
||||||
|
"VM.hard_shutdown",
|
||||||
|
"VM.remove_from_other_config",
|
||||||
|
"VM.set_HVM_boot_params",
|
||||||
|
"VM.start",
|
||||||
|
"VDI.create",
|
||||||
|
"VDI.destroy",
|
||||||
|
"VBD.create",
|
||||||
|
"VBD.eject",
|
||||||
|
"VIF.create",
|
||||||
|
"Host.call_plugin");
|
||||||
|
|
||||||
|
protected ApplianceAction(IXenConnection connection, string title,
|
||||||
|
string networkUuid, bool isTvmIpStatic, string tvmIpAddress, string tvmSubnetMask, string tvmGateway)
|
||||||
|
: base(connection, title)
|
||||||
|
{
|
||||||
|
m_networkUuid = networkUuid;
|
||||||
|
m_isTvmIpStatic = isTvmIpStatic;
|
||||||
|
m_tvmIpAddress = tvmIpAddress;
|
||||||
|
m_tvmSubnetMask = tvmSubnetMask;
|
||||||
|
m_tvmGateway = tvmGateway;
|
||||||
|
|
||||||
|
Pool pool = Helpers.GetPool(connection);
|
||||||
|
if (pool != null)
|
||||||
|
Pool = pool;
|
||||||
|
else
|
||||||
|
Host = Helpers.GetMaster(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateHandler(XenOvfTranportEventArgs e)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(e.Message))
|
||||||
|
Description = e.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RecomputeCanCancel()
|
||||||
|
{
|
||||||
|
CanCancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CancelRelatedTask()
|
||||||
|
{
|
||||||
|
Description = Messages.CANCELING;
|
||||||
|
|
||||||
|
if (m_transportAction != null)
|
||||||
|
m_transportAction.Cancel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
188
XenAdmin/Actions/OVFActions/ExportApplianceAction.cs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
using XenOvf;
|
||||||
|
using XenOvf.Definitions;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.OVFActions
|
||||||
|
{
|
||||||
|
public class ExportApplianceAction : ApplianceAction
|
||||||
|
{
|
||||||
|
#region Private fields
|
||||||
|
|
||||||
|
private readonly string m_applianceDirectory;
|
||||||
|
private readonly string m_applianceFileName;
|
||||||
|
private readonly List<VM> m_vmsToExport;
|
||||||
|
private readonly IEnumerable<string> m_eulas;
|
||||||
|
private readonly bool m_signAppliance;
|
||||||
|
private readonly bool m_createManifest;
|
||||||
|
private readonly X509Certificate2 m_certificate;
|
||||||
|
private readonly bool m_encryptFiles;
|
||||||
|
private readonly string m_encryptPassword;
|
||||||
|
private readonly bool m_createOVA;
|
||||||
|
private readonly bool m_compressOVFfiles;
|
||||||
|
private readonly bool m_shouldVerify;
|
||||||
|
private OvfCompressor m_compressor;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public ExportApplianceAction(IXenConnection connection, string applianceDirectory, string applianceFileName, List<VM> vmsToExport,
|
||||||
|
IEnumerable<string> eulas, bool signAppliance, bool createManifest, X509Certificate2 certificate,
|
||||||
|
bool encryptFiles, string encryptPassword, bool createOVA, bool compressOVFfiles,
|
||||||
|
string networkUuid, bool isTvmIpStatic, string tvmIpAddress, string tvmSubnetMask, string tvmGateway, bool shouldVerify)
|
||||||
|
: base(connection, Messages.EXPORT_APPLIANCE, networkUuid, isTvmIpStatic, tvmIpAddress, tvmSubnetMask, tvmGateway)
|
||||||
|
{
|
||||||
|
m_applianceDirectory = applianceDirectory;
|
||||||
|
m_applianceFileName = applianceFileName;
|
||||||
|
m_vmsToExport = vmsToExport;
|
||||||
|
m_eulas = eulas;
|
||||||
|
m_signAppliance = signAppliance;
|
||||||
|
m_createManifest = createManifest;
|
||||||
|
m_certificate = certificate;
|
||||||
|
m_encryptFiles = encryptFiles;
|
||||||
|
m_encryptPassword = encryptPassword;
|
||||||
|
m_createOVA = createOVA;
|
||||||
|
m_compressOVFfiles = compressOVFfiles;
|
||||||
|
m_shouldVerify = shouldVerify;
|
||||||
|
|
||||||
|
if (m_vmsToExport.Count == 1)
|
||||||
|
VM = m_vmsToExport.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
SafeToExit = false;
|
||||||
|
var session = Connection.Session;
|
||||||
|
var url = session.Url;
|
||||||
|
Uri uri = new Uri(url);
|
||||||
|
|
||||||
|
var appFolder = Path.Combine(m_applianceDirectory, m_applianceFileName);
|
||||||
|
var appFile = string.Format("{0}.ovf", m_applianceFileName);
|
||||||
|
|
||||||
|
if (!Directory.Exists(appFolder))
|
||||||
|
Directory.CreateDirectory(appFolder);
|
||||||
|
PercentComplete = 5;
|
||||||
|
|
||||||
|
Description = Messages.EXPORTING_VMS;
|
||||||
|
EnvelopeType env;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_transportAction = new XenOvfTransport.Export(uri, session)
|
||||||
|
{
|
||||||
|
UpdateHandler = UpdateHandler,
|
||||||
|
ShouldVerifyDisks = m_shouldVerify,
|
||||||
|
Cancel = Cancelling //in case the Cancel button has already been pressed
|
||||||
|
};
|
||||||
|
m_transportAction.SetTvmNetwork(m_networkUuid, m_isTvmIpStatic, m_tvmIpAddress, m_tvmSubnetMask, m_tvmGateway);
|
||||||
|
env = (m_transportAction as XenOvfTransport.Export).Process(appFolder, m_applianceFileName, (from VM vm in m_vmsToExport select vm.uuid).ToArray());
|
||||||
|
PercentComplete = 60;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var eula in m_eulas)
|
||||||
|
{
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
Description = Messages.ADDING_EULAS;
|
||||||
|
OVF.AddEula(env, eula);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
|
||||||
|
var ovfPath = Path.Combine(appFolder, appFile);
|
||||||
|
Description = String.Format(Messages.CREATING_FILE, appFile);
|
||||||
|
OVF.SaveAs(env, ovfPath);
|
||||||
|
PercentComplete = 70;
|
||||||
|
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
|
||||||
|
if (m_signAppliance)
|
||||||
|
{
|
||||||
|
Description = Messages.SIGNING_APPLIANCE;
|
||||||
|
OVF.Sign(m_certificate, appFolder, appFile);
|
||||||
|
}
|
||||||
|
else if (m_createManifest)
|
||||||
|
{
|
||||||
|
Description = Messages.CREATING_MANIFEST;
|
||||||
|
OVF.Manifest(appFolder, appFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
PercentComplete = 90;
|
||||||
|
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
|
||||||
|
if (m_createOVA)
|
||||||
|
{
|
||||||
|
Description = String.Format(Messages.CREATING_FILE, String.Format("{0}.ova", m_applianceFileName));
|
||||||
|
OVF.ConvertOVFtoOVA(appFolder, appFile, m_compressOVFfiles);
|
||||||
|
}
|
||||||
|
else if (m_compressOVFfiles)
|
||||||
|
{
|
||||||
|
Description = Messages.COMPRESSING_FILES;
|
||||||
|
m_compressor = new OvfCompressor { CancelCompression = Cancelling }; //in case the Cancel button has already been pressed}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_compressor.CompressOvfFiles(ovfPath, "GZip");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PercentComplete = 100;
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CancelRelatedTask()
|
||||||
|
{
|
||||||
|
base.CancelRelatedTask();
|
||||||
|
|
||||||
|
if (m_compressor != null)
|
||||||
|
m_compressor.CancelCompression = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
180
XenAdmin/Actions/OVFActions/ImportApplianceAction.cs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using XenAdmin.Mappings;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
|
||||||
|
using XenAPI;
|
||||||
|
using XenOvf;
|
||||||
|
using XenOvf.Definitions;
|
||||||
|
using XenOvfTransport;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.OVFActions
|
||||||
|
{
|
||||||
|
public class ImportApplianceAction : ApplianceAction
|
||||||
|
{
|
||||||
|
#region Private fields
|
||||||
|
|
||||||
|
private readonly EnvelopeType m_ovfEnvelope;
|
||||||
|
private readonly Package m_package;
|
||||||
|
private readonly Dictionary<string, VmMapping> m_vmMappings;
|
||||||
|
private readonly bool m_verifyManifest;
|
||||||
|
private readonly bool m_verifySignature;
|
||||||
|
private readonly string m_password;
|
||||||
|
private readonly bool m_runfixups;
|
||||||
|
private readonly SR m_selectedIsoSr;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public ImportApplianceAction(IXenConnection connection, EnvelopeType ovfEnv, Package package, Dictionary<string, VmMapping> vmMappings,
|
||||||
|
bool verifyManifest, bool verifySignature, string password, bool runfixups, SR selectedIsoSr,
|
||||||
|
string networkUuid, bool isTvmIpStatic, string tvmIpAddress, string tvmSubnetMask, string tvmGateway)
|
||||||
|
: base(connection, Messages.IMPORT_APPLIANCE, networkUuid, isTvmIpStatic, tvmIpAddress, tvmSubnetMask, tvmGateway)
|
||||||
|
{
|
||||||
|
m_ovfEnvelope = ovfEnv;
|
||||||
|
m_package = package;
|
||||||
|
m_vmMappings = vmMappings;
|
||||||
|
m_verifyManifest = verifyManifest;
|
||||||
|
m_verifySignature = verifySignature;
|
||||||
|
m_password = password;
|
||||||
|
m_runfixups = runfixups;
|
||||||
|
m_selectedIsoSr = selectedIsoSr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
SafeToExit = false;
|
||||||
|
if (m_verifySignature)
|
||||||
|
{
|
||||||
|
Description = Messages.VERIFYING_SIGNATURE;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// The appliance is known to have a signature and the user asked to verify it.
|
||||||
|
m_package.VerifySignature();
|
||||||
|
|
||||||
|
// If the appliance has a signature, then it has a manifest.
|
||||||
|
// Always verify the manifest after verifying the signature.
|
||||||
|
m_package.VerifyManifest();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception(String.Format(Messages.VERIFYING_SIGNATURE_ERROR, e.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_verifyManifest)
|
||||||
|
{
|
||||||
|
Description = Messages.VERIFYING_MANIFEST;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// The appliance had a manifest without a signature and the user asked to verify it.
|
||||||
|
// VerifyManifest() throws an exception when verification fails for any reason.
|
||||||
|
m_package.VerifyManifest();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception(String.Format(Messages.VERIFYING_MANIFEST_ERROR, e.Message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> validationErrors;
|
||||||
|
OVF.Validate(m_package.PackageSourceFile, out validationErrors);
|
||||||
|
|
||||||
|
PercentComplete = 20;
|
||||||
|
Description = Messages.IMPORTING_VMS;
|
||||||
|
|
||||||
|
var session = Connection.Session;
|
||||||
|
var url = session.Url;
|
||||||
|
Uri uri = new Uri(url);
|
||||||
|
|
||||||
|
//create a copy of the OVF
|
||||||
|
var envelopes = new List<EnvelopeType>();
|
||||||
|
|
||||||
|
foreach (var vmMapping in m_vmMappings)
|
||||||
|
{
|
||||||
|
if (Cancelling)
|
||||||
|
throw new CancelledException();
|
||||||
|
|
||||||
|
string systemid = vmMapping.Key;
|
||||||
|
var mapping = vmMapping.Value;
|
||||||
|
EnvelopeType[] envs = OVF.Split(m_ovfEnvelope, "system", new object[] {new[] {systemid}});
|
||||||
|
|
||||||
|
//storage
|
||||||
|
foreach (var kvp in mapping.Storage)
|
||||||
|
OVF.SetTargetSRInRASD(envs[0], systemid, kvp.Key, kvp.Value.uuid);
|
||||||
|
|
||||||
|
foreach (var kvp in mapping.StorageToAttach)
|
||||||
|
OVF.SetTargetVDIInRASD(envs[0], systemid, kvp.Key, kvp.Value.uuid);
|
||||||
|
|
||||||
|
//network
|
||||||
|
foreach (var kvp in mapping.Networks)
|
||||||
|
OVF.SetTargetNetworkInRASD(envs[0], systemid, kvp.Key, kvp.Value.uuid);
|
||||||
|
|
||||||
|
if (m_runfixups)
|
||||||
|
{
|
||||||
|
string cdId = OVF.SetRunOnceBootCDROMOSFixup(envs[0], systemid, Path.GetDirectoryName(m_package.PackageSourceFile));
|
||||||
|
OVF.SetTargetISOSRInRASD(envs[0], systemid, cdId, m_selectedIsoSr.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
envelopes.Add(envs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var appName = m_ovfEnvelope.Name;
|
||||||
|
if (string.IsNullOrEmpty(appName))
|
||||||
|
appName = Path.GetFileNameWithoutExtension(m_package.PackageSourceFile);
|
||||||
|
|
||||||
|
EnvelopeType env = OVF.Merge(envelopes, appName);
|
||||||
|
|
||||||
|
try //importVM
|
||||||
|
{
|
||||||
|
m_transportAction = new Import(uri, session)
|
||||||
|
{
|
||||||
|
ApplianceName = appName,
|
||||||
|
UpdateHandler = UpdateHandler,
|
||||||
|
Cancel = Cancelling //in case the Cancel button has already been pressed
|
||||||
|
};
|
||||||
|
m_transportAction.SetTvmNetwork(m_networkUuid, m_isTvmIpStatic, m_tvmIpAddress, m_tvmSubnetMask, m_tvmGateway);
|
||||||
|
(m_transportAction as Import).Process(env, Path.GetDirectoryName(m_package.PackageSourceFile), m_password);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PercentComplete = 100;
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
XenAdmin/Actions/OVFActions/ImportImageAction.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using XenAdmin.Mappings;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
|
||||||
|
using XenAPI;
|
||||||
|
using XenOvf;
|
||||||
|
using XenOvf.Definitions;
|
||||||
|
using XenOvfTransport;
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions.OVFActions
|
||||||
|
{
|
||||||
|
public class ImportImageAction : ApplianceAction
|
||||||
|
{
|
||||||
|
#region Private fields
|
||||||
|
|
||||||
|
private readonly EnvelopeType m_ovfEnvelope;
|
||||||
|
private readonly Dictionary<string, VmMapping> m_vmMappings;
|
||||||
|
private readonly bool m_runfixups;
|
||||||
|
private readonly SR m_selectedIsoSr;
|
||||||
|
private readonly string m_directory;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public ImportImageAction(IXenConnection connection, EnvelopeType ovfEnv, string directory, Dictionary<string, VmMapping> vmMappings, bool runfixups, SR selectedIsoSr,
|
||||||
|
string networkUuid, bool isTvmIpStatic, string tvmIpAddress, string tvmSubnetMask, string tvmGateway)
|
||||||
|
: base(connection, Messages.IMPORT_DISK_IMAGE, networkUuid, isTvmIpStatic, tvmIpAddress, tvmSubnetMask, tvmGateway)
|
||||||
|
{
|
||||||
|
m_ovfEnvelope = ovfEnv;
|
||||||
|
m_directory = directory;
|
||||||
|
m_vmMappings = vmMappings;
|
||||||
|
m_runfixups = runfixups;
|
||||||
|
m_selectedIsoSr = selectedIsoSr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
SafeToExit = false;
|
||||||
|
Debug.Assert(m_vmMappings.Count == 1, "There is one VM mapping");
|
||||||
|
|
||||||
|
string systemid = m_vmMappings.Keys.ElementAt(0);
|
||||||
|
var mapping = m_vmMappings.Values.ElementAt(0);
|
||||||
|
|
||||||
|
var session = Connection.Session;
|
||||||
|
var url = session.Url;
|
||||||
|
Uri uri = new Uri(url);
|
||||||
|
|
||||||
|
PercentComplete = 20;
|
||||||
|
Description = Messages.IMPORTING_DISK_IMAGE;
|
||||||
|
|
||||||
|
//create a copy of the ovf envelope
|
||||||
|
EnvelopeType[] envs = OVF.Split(m_ovfEnvelope, "system", new object[] {new[] {systemid}});
|
||||||
|
EnvelopeType curEnv = envs[0];
|
||||||
|
|
||||||
|
//storage
|
||||||
|
foreach (var kvp in mapping.Storage)
|
||||||
|
OVF.SetTargetSRInRASD(curEnv, systemid, kvp.Key, kvp.Value.uuid);
|
||||||
|
|
||||||
|
//network
|
||||||
|
foreach (var kvp in mapping.Networks)
|
||||||
|
OVF.SetTargetNetworkInRASD(curEnv, systemid, kvp.Key, kvp.Value.uuid);
|
||||||
|
|
||||||
|
if (m_runfixups)
|
||||||
|
{
|
||||||
|
string cdId = OVF.SetRunOnceBootCDROMOSFixup(curEnv, systemid, m_directory);
|
||||||
|
OVF.SetTargetISOSRInRASD(curEnv, systemid, cdId, m_selectedIsoSr.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
try //importVM
|
||||||
|
{
|
||||||
|
m_transportAction = new Import(uri, session)
|
||||||
|
{
|
||||||
|
UpdateHandler = UpdateHandler,
|
||||||
|
Cancel = Cancelling //in case the Cancel button has already been pressed
|
||||||
|
};
|
||||||
|
m_transportAction.SetTvmNetwork(m_networkUuid, m_isTvmIpStatic, m_tvmIpAddress, m_tvmSubnetMask, m_tvmGateway);
|
||||||
|
(m_transportAction as Import).Process(curEnv, m_directory, null);
|
||||||
|
|
||||||
|
PercentComplete = 100;
|
||||||
|
Description = Messages.COMPLETED;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw new CancelledException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
XenAdmin/Actions/SetCslgCredentialsAction.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Network.StorageLink;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
class SetCslgCredentialsAction : AsyncAction
|
||||||
|
{
|
||||||
|
private readonly string _host;
|
||||||
|
private readonly string _username;
|
||||||
|
private readonly string _password;
|
||||||
|
private readonly List<IXenConnection> _connections;
|
||||||
|
|
||||||
|
public SetCslgCredentialsAction(IEnumerable<IXenConnection> connections, string host, string username, string password)
|
||||||
|
: base(null, Messages.SET_STORAGELINK_CREDS_ACTION_TITLE, Messages.SET_STORAGELINK_CREDS_ACTION_DESCRIPTION)
|
||||||
|
{
|
||||||
|
Util.ThrowIfEnumerableParameterNullOrEmpty(connections, "connections");
|
||||||
|
|
||||||
|
_connections = Util.GetList(connections).FindAll(c => c.IsConnected && Helpers.GetPoolOfOne(c) != null && Helpers.MidnightRideOrGreater(c) && !Helpers.FeatureForbidden(c, XenAPI.Host.RestrictStorageChoices));
|
||||||
|
_host = host;
|
||||||
|
_username = username;
|
||||||
|
_password = password;
|
||||||
|
|
||||||
|
foreach (IXenConnection c in connections)
|
||||||
|
{
|
||||||
|
XenAPI.Pool pool = Helpers.GetPool(c);
|
||||||
|
|
||||||
|
if (pool != null)
|
||||||
|
{
|
||||||
|
AppliesTo.Add(pool.opaque_ref);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XenAPI.Host master = Helpers.GetMaster(c);
|
||||||
|
|
||||||
|
if (master != null)
|
||||||
|
{
|
||||||
|
AppliesTo.Add(master.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
var actions = new List<AsyncAction>();
|
||||||
|
foreach (IXenConnection c in _connections)
|
||||||
|
{
|
||||||
|
actions.Add(new SetCslgCredentialsToPoolAction(c, _host, _username, _password));
|
||||||
|
}
|
||||||
|
|
||||||
|
new MultipleAction(null, Messages.SET_STORAGELINK_CREDS_ACTION_TITLE, Messages.SET_STORAGELINK_CREDS_ACTION_DESCRIPTION, Messages.SET_STORAGELINK_CREDS_ACTION_TITLE, actions).RunExternal(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
XenAdmin/Actions/SetCslgCredentialsToPoolAction.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Network.StorageLink;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Actions
|
||||||
|
{
|
||||||
|
public class SetCslgCredentialsToPoolAction : AsyncAction
|
||||||
|
{
|
||||||
|
private readonly string _host;
|
||||||
|
private readonly string _username;
|
||||||
|
private readonly string _password;
|
||||||
|
|
||||||
|
public SetCslgCredentialsToPoolAction(IXenConnection connection, string host, string username, string password)
|
||||||
|
: base(connection,
|
||||||
|
string.Format(Messages.SET_STORAGELINK_CREDS_TO_POOL_ACTION_TITLE, Helpers.GetPoolOfOne(connection)),
|
||||||
|
string.Format(Messages.SET_STORAGELINK_CREDS_TO_POOL_ACTION_DESCRIPTION, Helpers.GetPoolOfOne(connection)))
|
||||||
|
{
|
||||||
|
Util.ThrowIfParameterNull(connection, "connection");
|
||||||
|
|
||||||
|
_host = host;
|
||||||
|
_username = username;
|
||||||
|
_password = password;
|
||||||
|
|
||||||
|
if (Helpers.FeatureForbidden(connection, Host.RestrictStorageChoices))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Pool not licensed.", "host");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Helpers.MidnightRideOrGreater(connection))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Pool must by Midnight Ride or later.", "host");
|
||||||
|
}
|
||||||
|
|
||||||
|
XenAPI.Pool pool = Helpers.GetPool(Connection);
|
||||||
|
|
||||||
|
if (pool != null)
|
||||||
|
{
|
||||||
|
AppliesTo.Add(pool.opaque_ref);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XenAPI.Host master = Helpers.GetMaster(Connection);
|
||||||
|
|
||||||
|
if (master != null)
|
||||||
|
{
|
||||||
|
AppliesTo.Add(master.opaque_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Run()
|
||||||
|
{
|
||||||
|
if (Connection.IsConnected)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Program.Invoke(Program.MainWindow, () =>
|
||||||
|
{
|
||||||
|
// check that local SL creds have been moved to pool.other_config by StorageLinkConnectionManager.
|
||||||
|
Settings.CslgCredentials localCrds = Settings.GetCslgCredentials(Connection);
|
||||||
|
Debug.Assert(localCrds == null || string.IsNullOrEmpty(localCrds.Host));
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Pool pool = Helpers.GetPoolOfOne(Connection);
|
||||||
|
pool.SetStorageLinkCredentials(_host, _username, _password);
|
||||||
|
|
||||||
|
// other-config gets set on event thread.
|
||||||
|
// so wait until other-config has been updated.
|
||||||
|
|
||||||
|
WaitForUpdate(pool);
|
||||||
|
|
||||||
|
// force an other-config change event. In case only the value of the secret has changed.
|
||||||
|
Program.BeginInvoke(Program.MainWindow, () => pool.NotifyPropertyChanged("other_config"));
|
||||||
|
|
||||||
|
foreach (PBD pbd in Connection.Cache.PBDs)
|
||||||
|
{
|
||||||
|
StorageLinkCredentials creds = pbd.GetStorageLinkCredentials();
|
||||||
|
|
||||||
|
if (creds != null && creds.Host == _host && creds.Username == _username)
|
||||||
|
{
|
||||||
|
creds.SetPassword(_password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WaitForUpdate(Pool pool)
|
||||||
|
{
|
||||||
|
StorageLinkCredentials creds = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
Program.Invoke(Program.MainWindow, () => creds = pool.GetStorageLinkCredentials());
|
||||||
|
|
||||||
|
if (creds != null && creds.Host == _host && creds.Username == _username)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
296
XenAdmin/Alerts/Types/AlarmMessageAlert.cs
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.TabPages;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class AlarmMessageAlert : MessageAlert
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private AlarmType AlarmType;
|
||||||
|
private double CurrentValue;
|
||||||
|
private double TriggerLevel;
|
||||||
|
private int TriggerPeriod;
|
||||||
|
private SR sr;
|
||||||
|
|
||||||
|
public AlarmMessageAlert(Message m)
|
||||||
|
: base(m)
|
||||||
|
{
|
||||||
|
ParseAlarmMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseAlarmMessage(Message m)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* message.body will look similar to this:
|
||||||
|
* value: 1234
|
||||||
|
* config:
|
||||||
|
* <variable>
|
||||||
|
* <name value="network_usage"/>
|
||||||
|
* <alarm_trigger_level value="1"/>
|
||||||
|
* <alarm_trigger_period value="60"/>
|
||||||
|
* </variable>
|
||||||
|
*/
|
||||||
|
List<string> lines = new List<string>(m.body.Split('\n'));
|
||||||
|
if (lines.Count < 2)
|
||||||
|
return;
|
||||||
|
string value = lines[0].Replace("value: ", "");
|
||||||
|
double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out CurrentValue);
|
||||||
|
|
||||||
|
string variableName = "";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string xml = string.Join("", lines.GetRange(1, lines.Count - 1).ToArray()).Replace("config:", "");
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xml);
|
||||||
|
|
||||||
|
XmlNodeList name = doc.GetElementsByTagName("name");
|
||||||
|
if (name.Count > 0)
|
||||||
|
variableName = name[0].Attributes["value"].Value;
|
||||||
|
// if this doesn't get set the alarm will appear as "unrecognised"
|
||||||
|
//in the dialog and will show the message body instead
|
||||||
|
|
||||||
|
XmlNodeList level = doc.GetElementsByTagName("alarm_trigger_level");
|
||||||
|
if (level.Count > 0)
|
||||||
|
double.TryParse(level[0].Attributes["value"].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out TriggerLevel);
|
||||||
|
|
||||||
|
XmlNodeList period = doc.GetElementsByTagName("alarm_trigger_period");
|
||||||
|
if (period.Count > 0)
|
||||||
|
int.TryParse(period[0].Attributes["value"].Value, NumberStyles.Any, CultureInfo.InvariantCulture, out TriggerPeriod);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.Debug("Error Parsing Message Description", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (variableName)
|
||||||
|
{
|
||||||
|
case PerfmonDefinition.ALARM_TYPE_CPU:
|
||||||
|
AlarmType = AlarmType.Cpu;
|
||||||
|
break;
|
||||||
|
case PerfmonDefinition.ALARM_TYPE_NETWORK:
|
||||||
|
AlarmType = AlarmType.Net;
|
||||||
|
break;
|
||||||
|
case PerfmonDefinition.ALARM_TYPE_DISK:
|
||||||
|
AlarmType = AlarmType.Disk;
|
||||||
|
break;
|
||||||
|
case PerfmonDefinition.ALARM_TYPE_FILESYSTEM:
|
||||||
|
AlarmType = AlarmType.FileSystem;
|
||||||
|
break;
|
||||||
|
case PerfmonDefinition.ALARM_TYPE_MEMORY:
|
||||||
|
AlarmType = AlarmType.Memory;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
var match = PerfmonDefinition.SrRegex.Match(variableName);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
AlarmType = AlarmType.Storage;
|
||||||
|
sr = GetStorage(match.Groups[1].Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AlarmType = AlarmType.None;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (AlarmType)
|
||||||
|
{
|
||||||
|
case AlarmType.FileSystem:
|
||||||
|
return AlertPriority.Priority2;
|
||||||
|
default:
|
||||||
|
return base.Priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (AlarmType)
|
||||||
|
{
|
||||||
|
case AlarmType.Cpu:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_CPU_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
Util.PercentageString(CurrentValue),
|
||||||
|
Util.TimeString(TriggerPeriod),
|
||||||
|
Util.PercentageString(TriggerLevel));
|
||||||
|
case AlarmType.Net:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_NETWORK_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
Util.DataRateString(CurrentValue),
|
||||||
|
Util.TimeString(TriggerPeriod),
|
||||||
|
Util.DataRateString(TriggerLevel));
|
||||||
|
case AlarmType.Disk:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_DISK_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
Util.DataRateString(CurrentValue),
|
||||||
|
Util.TimeString(TriggerPeriod),
|
||||||
|
Util.DataRateString(TriggerLevel));
|
||||||
|
case AlarmType.FileSystem:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_FILESYSTEM_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
Util.PercentageString(CurrentValue));
|
||||||
|
case AlarmType.Memory:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_MEMORY_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
Util.MemorySizeString(CurrentValue * Util.BINARY_KILO),//xapi unit is in kib
|
||||||
|
Util.TimeString(TriggerPeriod),
|
||||||
|
Util.MemorySizeString(TriggerLevel * Util.BINARY_KILO));
|
||||||
|
case AlarmType.Storage:
|
||||||
|
return string.Format(Messages.ALERT_ALARM_STORAGE_DESCRIPTION,
|
||||||
|
Helpers.GetNameAndObject(XenObject),
|
||||||
|
sr == null ? "" : sr.Name,
|
||||||
|
Util.DataRateString(CurrentValue * Util.BINARY_MEGA), //xapi unit is in Mib
|
||||||
|
Util.TimeString(TriggerPeriod),
|
||||||
|
Util.DataRateString(TriggerLevel * Util.BINARY_MEGA));
|
||||||
|
default:
|
||||||
|
return base.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (AlarmType)
|
||||||
|
{
|
||||||
|
case AlarmType.Cpu:
|
||||||
|
return Messages.ALERT_ALARM_CPU;
|
||||||
|
case AlarmType.Net:
|
||||||
|
return Messages.ALERT_ALARM_NETWORK;
|
||||||
|
case AlarmType.Disk:
|
||||||
|
return Messages.ALERT_ALARM_DISK;
|
||||||
|
case AlarmType.FileSystem:
|
||||||
|
return Messages.ALERT_ALARM_FILESYSTEM;
|
||||||
|
case AlarmType.Memory:
|
||||||
|
return Messages.ALERT_ALARM_MEMORY;
|
||||||
|
case AlarmType.Storage:
|
||||||
|
return Messages.ALERT_ALARM_STORAGE;
|
||||||
|
default:
|
||||||
|
return base.Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
IXenObject xenObject = null;
|
||||||
|
int tabIndex = 0;
|
||||||
|
|
||||||
|
if (this.XenObject is Host)
|
||||||
|
{
|
||||||
|
//sr is only set when it's AlarmType.Storage
|
||||||
|
xenObject = sr ?? this.XenObject;
|
||||||
|
tabIndex = 2;
|
||||||
|
}
|
||||||
|
else if (this.XenObject is VM)
|
||||||
|
{
|
||||||
|
xenObject = this.XenObject;
|
||||||
|
tabIndex = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xenObject == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (var dialog = new PropertiesDialog(xenObject) { TopMost = true })
|
||||||
|
{
|
||||||
|
dialog.SelectTab(tabIndex);
|
||||||
|
dialog.ShowDialog(Program.MainWindow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_ALARM_ACTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format("{0}UsageMessageAlert", AlarmType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_GENERIC_HELP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SR GetStorage(string srUuid)
|
||||||
|
{
|
||||||
|
var connection = XenObject.Connection;
|
||||||
|
|
||||||
|
for (int i = 0; i < connection.Cache.PBDs.Length; i++)
|
||||||
|
{
|
||||||
|
var sr = connection.Resolve(connection.Cache.PBDs[i].SR);
|
||||||
|
if (sr != null && sr.uuid.StartsWith(srUuid))
|
||||||
|
return sr;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AlarmType { None, Cpu, Net, Disk, FileSystem, Memory, Storage }
|
||||||
|
}
|
82
XenAdmin/Alerts/Types/DuplicateIqnAlert.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class DuplicateIqnAlert : IqnAlert
|
||||||
|
{
|
||||||
|
private Dictionary<Host, Host> RepeatedIQNs;
|
||||||
|
|
||||||
|
public DuplicateIqnAlert(Host host, Dictionary<Host, Host> repeatedIQNs)
|
||||||
|
: base(host)
|
||||||
|
{
|
||||||
|
RepeatedIQNs = repeatedIQNs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.IQN_CHECK_EXISTS_TITLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.IQN_CHECK_EXISTS_TEXT, Helpers.GetName(Host), Host.iscsi_iqn, Helpers.GetName(RepeatedIQNs[Host]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "DuplicateIqnAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Alert other)
|
||||||
|
{
|
||||||
|
if (other is DuplicateIqnAlert)
|
||||||
|
{
|
||||||
|
return Host.opaque_ref == ((DuplicateIqnAlert)other).Host.opaque_ref;
|
||||||
|
}
|
||||||
|
return base.Equals(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
XenAdmin/Alerts/Types/GuiOldAlert.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class GuiOldAlert : Alert
|
||||||
|
{
|
||||||
|
public GuiOldAlert()
|
||||||
|
{
|
||||||
|
_timestamp = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority { get { return AlertPriority.Priority5; } }
|
||||||
|
|
||||||
|
public override string AppliesTo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.XENCENTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.NEWER_GUI_AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get { return () => Program.OpenURL(InvisibleMessages.OUT_OF_DATE_WEBSITE); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_NEW_VERSION_DOWNLOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "GuiOldAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.XENCENTER_NEWER_AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
XenAdmin/Alerts/Types/IqnAlert.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public abstract class IqnAlert : Alert
|
||||||
|
{
|
||||||
|
protected readonly Host Host;
|
||||||
|
|
||||||
|
protected IqnAlert(Host host)
|
||||||
|
{
|
||||||
|
Host = host;
|
||||||
|
HostUuid = host.uuid;
|
||||||
|
_timestamp = DateTime.UtcNow;
|
||||||
|
Connection = host.Connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority { get { return AlertPriority.Priority3; } }
|
||||||
|
|
||||||
|
public override string AppliesTo { get { return Helpers.GetName(Host); } }
|
||||||
|
|
||||||
|
public override string FixLinkText { get { return Messages.IQN_CHECK_EDIT; } }
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return delegate
|
||||||
|
{
|
||||||
|
using (PropertiesDialog dialog = new PropertiesDialog(Host))
|
||||||
|
{
|
||||||
|
dialog.SelectPage(dialog.GeneralEditPage);
|
||||||
|
dialog.GeneralEditPage.txtIQN.Focus();
|
||||||
|
dialog.GeneralEditPage.txtIQN.SelectAll();
|
||||||
|
dialog.ShowDialog(Program.MainWindow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
474
XenAdmin/Alerts/Types/MessageAlert.cs
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Model;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Help;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using XenAdmin.Commands;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class MessageAlert : Alert
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public XenAPI.Message Message;
|
||||||
|
public IXenObject XenObject;
|
||||||
|
|
||||||
|
private const int DEFAULT_PRIORITY = 0;
|
||||||
|
|
||||||
|
public MessageAlert(XenAPI.Message m)
|
||||||
|
{
|
||||||
|
Message = m;
|
||||||
|
uuid = m.uuid;
|
||||||
|
_timestamp = m.timestamp;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_priority = (int)m.priority;
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
_priority = DEFAULT_PRIORITY;
|
||||||
|
}
|
||||||
|
Connection = m.Connection;
|
||||||
|
XenObject = Helpers.XenObjectFromMessage(m);
|
||||||
|
|
||||||
|
// TODO: This would be better if there was some way of getting the actual host that the XenObject belongs to
|
||||||
|
// Currently if the applies to object is not a host or pool and belongs to a slave it is filtered under the master.
|
||||||
|
|
||||||
|
Host h = XenObject as Host;
|
||||||
|
if (h == null)
|
||||||
|
h = Helpers.GetMaster(m.Connection);
|
||||||
|
|
||||||
|
if (h != null)
|
||||||
|
HostUuid = h.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Helpers.ClearwaterOrGreater(Connection) && Enum.IsDefined(typeof(AlertPriority), _priority))
|
||||||
|
return (AlertPriority)_priority;
|
||||||
|
|
||||||
|
return AlertPriority.Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string AppliesTo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string name = Helpers.GetName(Helpers.GetPoolOfOne(Connection));
|
||||||
|
return !string.IsNullOrEmpty(name) ? name : Message.obj_uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// If you add something to this switch statement, be sure to add a corresponding entry to FriendlyNames.
|
||||||
|
switch (Message.Type)
|
||||||
|
{
|
||||||
|
case XenAPI.Message.MessageType.HA_POOL_DROP_IN_PLAN_EXISTS_FOR:
|
||||||
|
case XenAPI.Message.MessageType.HA_POOL_OVERCOMMITTED:
|
||||||
|
int pef;
|
||||||
|
if (XenObject != null && int.TryParse(Message.body, out pef))
|
||||||
|
{
|
||||||
|
string f = Message.FriendlyBody("ha_pool_drop_in_plan_exists_for-" + (pef == 0 ? "0" : pef == 1 ? "1" : "n"));
|
||||||
|
return string.Format(f, Helpers.GetName(XenObject), pef);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// applies to is hosts, vms and pools where only the name is required
|
||||||
|
case XenAPI.Message.MessageType.HA_HEARTBEAT_APPROACHING_TIMEOUT:
|
||||||
|
case XenAPI.Message.MessageType.HA_HOST_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.HA_HOST_WAS_FENCED:
|
||||||
|
case XenAPI.Message.MessageType.HA_PROTECTED_VM_RESTART_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.HA_STATEFILE_APPROACHING_TIMEOUT:
|
||||||
|
case XenAPI.Message.MessageType.HA_STATEFILE_LOST:
|
||||||
|
case XenAPI.Message.MessageType.HA_XAPI_HEALTHCHECK_APPROACHING_TIMEOUT:
|
||||||
|
//case XenAPI.Message.MessageType.HOST_SYNC_DATA_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_DOES_NOT_SUPPORT_POOLING:
|
||||||
|
case XenAPI.Message.MessageType.PBD_PLUG_FAILED_ON_SERVER_START:
|
||||||
|
case XenAPI.Message.MessageType.VM_CLONED:
|
||||||
|
case XenAPI.Message.MessageType.VM_CRASHED:
|
||||||
|
case XenAPI.Message.MessageType.VM_REBOOTED:
|
||||||
|
case XenAPI.Message.MessageType.VM_RESUMED:
|
||||||
|
case XenAPI.Message.MessageType.VM_SHUTDOWN:
|
||||||
|
case XenAPI.Message.MessageType.VM_STARTED:
|
||||||
|
case XenAPI.Message.MessageType.VM_SUSPENDED:
|
||||||
|
case XenAPI.Message.MessageType.METADATA_LUN_BROKEN:
|
||||||
|
case XenAPI.Message.MessageType.METADATA_LUN_HEALTHY:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_SERVER_UNREACHABLE:
|
||||||
|
case XenAPI.Message.MessageType.GRACE_LICENSE:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_NOT_AVAILABLE:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_EXPIRED:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_SERVER_CONNECTED:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_SERVER_UNAVAILABLE:
|
||||||
|
case XenAPI.Message.MessageType.HOST_CLOCK_WENT_BACKWARDS:
|
||||||
|
if (XenObject != null)
|
||||||
|
return string.Format(FriendlyFormat(), Helpers.GetName(XenObject));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// object then pool
|
||||||
|
case XenAPI.Message.MessageType.HOST_CLOCK_SKEW_DETECTED:
|
||||||
|
case XenAPI.Message.MessageType.POOL_MASTER_TRANSITION:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
Pool pool = Helpers.GetPoolOfOne(XenObject.Connection);
|
||||||
|
if (pool != null)
|
||||||
|
return string.Format(FriendlyFormat(), Helpers.GetName(XenObject), pool.Name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.HA_NETWORK_BONDING_ERROR:
|
||||||
|
if (XenObject != null)
|
||||||
|
return string.Format(FriendlyFormat(), GetManagementBondName(), Helpers.GetName(XenObject));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_EXPIRES_SOON:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
Host host = XenObject as Host ?? Helpers.GetMaster(Connection);
|
||||||
|
return string.Format(FriendlyFormat(), Helpers.GetName(XenObject), host == null ? Messages.UNKNOWN : HelpersGUI.HostLicenseExpiryString(host, true, DateTime.UtcNow));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.VBD_QOS_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.VCPU_QOS_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.VIF_QOS_FAILED:
|
||||||
|
if (XenObject != null)
|
||||||
|
return string.Format(FriendlyFormat(), "", Helpers.GetName(XenObject));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.EXTAUTH_INIT_IN_HOST_FAILED:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
Match m = extAuthRegex.Match(Message.body);
|
||||||
|
return m.Success ? string.Format(FriendlyFormat(), Helpers.GetName(XenObject), m.Groups[1].Value) : "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.EXTAUTH_IN_POOL_IS_NON_HOMOGENEOUS:
|
||||||
|
if (XenObject != null)
|
||||||
|
return string.Format(FriendlyFormat(), Helpers.GetName(Helpers.GetPoolOfOne(XenObject.Connection)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.MULTIPATH_PERIODIC_ALERT:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
log.InfoFormat("{0} - {1}", Title, Message.body);
|
||||||
|
return extractMultipathCurrentState(Message.body, FriendlyFormat());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.WLB_CONSULTATION_FAILED:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
Pool p = Helpers.GetPoolOfOne(XenObject.Connection);
|
||||||
|
return string.Format(FriendlyFormat(), Helpers.GetName(p), Helpers.GetName(XenObject));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.WLB_OPTIMIZATION_ALERT:
|
||||||
|
if (XenObject != null)
|
||||||
|
{
|
||||||
|
Match match = wlbOptAlertRegex.Match(Message.body);
|
||||||
|
return match.Success
|
||||||
|
? string.Format(FriendlyFormat(), Helpers.GetName(Helpers.GetPoolOfOne(XenObject.Connection)),
|
||||||
|
match.Groups[2], match.Groups[1])
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//these here do not need the object
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_FAILED_0:
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_LOCK_FAILED:
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_MISSED_EVENT:
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_SUCCEEDED:
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_TARGET_MOUNT_FAILED:
|
||||||
|
case Message.MessageType.VMPP_ARCHIVE_TARGET_UNMOUNT_FAILED:
|
||||||
|
case Message.MessageType.VMPP_SNAPSHOT_ARCHIVE_ALREADY_EXISTS:
|
||||||
|
case Message.MessageType.VMPP_SNAPSHOT_FAILED:
|
||||||
|
case Message.MessageType.VMPP_SNAPSHOT_LOCK_FAILED:
|
||||||
|
case Message.MessageType.VMPP_SNAPSHOT_MISSED_EVENT:
|
||||||
|
case Message.MessageType.VMPP_SNAPSHOT_SUCCEEDED:
|
||||||
|
case Message.MessageType.VMPP_LICENSE_ERROR:
|
||||||
|
case Message.MessageType.VMPP_XAPI_LOGON_FAILURE:
|
||||||
|
var policyAlert = new PolicyAlert(Message.Connection, Message.body);
|
||||||
|
return policyAlert.Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Message.body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FriendlyFormat()
|
||||||
|
{
|
||||||
|
return XenAPI.Message.FriendlyBody(Message.MessageTypeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Regex extAuthRegex = new Regex(@"error=(.*)");
|
||||||
|
private static readonly Regex multipathRegex = new Regex(@"^.*host=(.*); host-name=.*; current=(\d+); max=(\d+)$");
|
||||||
|
private static readonly Regex wlbOptAlertRegex = new Regex(@"severity:(.*) mode:(.*)");
|
||||||
|
|
||||||
|
private string extractMultipathCurrentState(string body, string format)
|
||||||
|
{
|
||||||
|
/* message body format - if this changes you need to alter this method
|
||||||
|
*
|
||||||
|
* Unhealthy paths:
|
||||||
|
* [20090511T16:29:22Z] host=foo; host-name=bar; pbd=whiz; scsi_id=pop; current=1; max=2
|
||||||
|
* [20090511T16:29:22Z] host=foo; host-name=bar; pbd=whiz; scsi_id=pop; current=1; max=2
|
||||||
|
* ....
|
||||||
|
* Events received during the last 120 seconds:
|
||||||
|
* [20090511T16:29:22Z] host=foo; host-name=bar; pbd=whiz; scsi_id=pop; current=1; max=2
|
||||||
|
* [20090511T16:29:22Z] host=foo; host-name=bar; pbd=whiz; scsi_id=pop; current=1; max=2
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
string[] lines = Message.body.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
List<string> currentState = new List<string>();
|
||||||
|
if (lines[0] == "Events received during the last 120 seconds:")
|
||||||
|
{
|
||||||
|
// current state is healthy, past errors have been resolved.
|
||||||
|
if (Helpers.IsPool(Message.Connection))
|
||||||
|
{
|
||||||
|
return string.Format(XenAdmin.Core.PropertyManager.GetFriendlyName("Message.body-multipath_periodic_alert_healthy"),
|
||||||
|
Helpers.GetName(XenObject));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return string.Format(XenAdmin.Core.PropertyManager.GetFriendlyName("Message.body-multipath_periodic_alert_healthy_standalone"),
|
||||||
|
Helpers.GetName(XenObject));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip "unhealthy paths" line
|
||||||
|
int lineIndex = 1;
|
||||||
|
while (lineIndex < lines.Length && lines[lineIndex].StartsWith("["))
|
||||||
|
{
|
||||||
|
//record all lines that describe the current state
|
||||||
|
currentState.Add(lines[lineIndex]);
|
||||||
|
lineIndex++;
|
||||||
|
}
|
||||||
|
if (currentState.Count == 1)
|
||||||
|
{
|
||||||
|
// Only one host currently unhealthy, describe it's specific min/max paths
|
||||||
|
Match m = multipathRegex.Match(currentState[0]);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
return string.Format(format, Message.Connection.Cache.Find_By_Uuid<Host>(m.Groups[1].Value),
|
||||||
|
m.Groups[2].Value,
|
||||||
|
m.Groups[3].Value);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Several hosts in pool unhealthy, list their names as a summary
|
||||||
|
string output = "";
|
||||||
|
foreach (string s in currentState)
|
||||||
|
{
|
||||||
|
Match m = multipathRegex.Match(s);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
output = string.Format("{0}, '{1}'", output, Message.Connection.Cache.Find_By_Uuid<Host>(m.Groups[1].Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string.Format(XenAdmin.Core.PropertyManager.GetFriendlyName("Message.body-multipath_periodic_alert_summary"),
|
||||||
|
Helpers.GetName(XenObject),
|
||||||
|
output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetManagementBondName()
|
||||||
|
{
|
||||||
|
Bond bond = NetworkingHelper.GetMasterManagementBond(Connection);
|
||||||
|
return bond == null ? Messages.UNKNOWN : bond.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (XenObject == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
switch (Message.Type)
|
||||||
|
{
|
||||||
|
case XenAPI.Message.MessageType.HA_HEARTBEAT_APPROACHING_TIMEOUT:
|
||||||
|
case XenAPI.Message.MessageType.HA_HOST_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.HA_HOST_WAS_FENCED:
|
||||||
|
case XenAPI.Message.MessageType.HA_NETWORK_BONDING_ERROR:
|
||||||
|
case XenAPI.Message.MessageType.HA_POOL_DROP_IN_PLAN_EXISTS_FOR:
|
||||||
|
case XenAPI.Message.MessageType.HA_POOL_OVERCOMMITTED:
|
||||||
|
case XenAPI.Message.MessageType.HA_PROTECTED_VM_RESTART_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.HA_STATEFILE_APPROACHING_TIMEOUT:
|
||||||
|
case XenAPI.Message.MessageType.HA_STATEFILE_LOST:
|
||||||
|
case XenAPI.Message.MessageType.HA_XAPI_HEALTHCHECK_APPROACHING_TIMEOUT:
|
||||||
|
return () => new HACommand(Program.MainWindow.CommandInterface, XenObject.Connection).Execute();
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_EXPIRES_SOON:
|
||||||
|
case XenAPI.Message.MessageType.LICENSE_DOES_NOT_SUPPORT_POOLING:
|
||||||
|
return () => Program.OpenURL(InvisibleMessages.LICENSE_EXPIRY_WEBPAGE);
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.VBD_QOS_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.VCPU_QOS_FAILED:
|
||||||
|
case XenAPI.Message.MessageType.VIF_QOS_FAILED:
|
||||||
|
return () => Program.MainWindow.LaunchLicensePicker("");
|
||||||
|
|
||||||
|
case XenAPI.Message.MessageType.MULTIPATH_PERIODIC_ALERT:
|
||||||
|
return Program.ViewLogFiles;
|
||||||
|
|
||||||
|
// CA-23823: XenCenter "Repair Storage" link broken
|
||||||
|
// PBD_PLUG_FAILED_ON_SERVER_START give us host not sr uuid.
|
||||||
|
// therefore nothing we can do.
|
||||||
|
//case XenAPI.Message.MessageType.PBD_PLUG_FAILED_ON_SERVER_START:
|
||||||
|
// Menus.RepairSR(XenObject as XenObject<SR>);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (XenObject == null)
|
||||||
|
return "";
|
||||||
|
if (FixLinkAction == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Message.FriendlyAction(Message.MessageTypeString) ?? Messages.DETAILS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string pageref = "MessageAlert_" + Message.Type.ToString();
|
||||||
|
return HelpManager.GetID(pageref) == null ? null : pageref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return XenAPI.Message.FriendlyHelp(Message.MessageTypeString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string title = XenAPI.Message.FriendlyName(Message.MessageTypeString);
|
||||||
|
if (string.IsNullOrEmpty(title))
|
||||||
|
title = Message.name;
|
||||||
|
|
||||||
|
if (Message.cls != cls.Pool)
|
||||||
|
{
|
||||||
|
Host host = XenObject as Host;
|
||||||
|
if (host == null || Helpers.IsPool(host.Connection))
|
||||||
|
{
|
||||||
|
string name = Helpers.GetName(XenObject);
|
||||||
|
if (!string.IsNullOrEmpty(name))
|
||||||
|
title = string.Format(Messages.MESSAGE_ALERT_TITLE, name, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dismiss()
|
||||||
|
{
|
||||||
|
new DestroyMessageAction(Message.Connection, Message.opaque_ref).RunAsync();
|
||||||
|
base.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DismissSingle(Session s)
|
||||||
|
{
|
||||||
|
XenAPI.Message.destroy(s, Message.opaque_ref);
|
||||||
|
base.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the MessageAlert corresponding to the given Message, or null if none exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="m"></param>
|
||||||
|
public static Alert FindAlert(XenAPI.Message m)
|
||||||
|
{
|
||||||
|
lock (XenCenterAlertsLock)
|
||||||
|
{
|
||||||
|
foreach (Alert a in XenCenterAlerts)
|
||||||
|
{
|
||||||
|
if (a is MessageAlert && ((MessageAlert)a).Message.opaque_ref == m.opaque_ref && m.Connection == a.Connection)
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveAlert(XenAPI.Message m)
|
||||||
|
{
|
||||||
|
Alert a = FindAlert(m);
|
||||||
|
if (a != null)
|
||||||
|
RemoveAlert(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses a XenAPI.Message into an Alert object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Alert ParseMessage(XenAPI.Message msg)
|
||||||
|
{
|
||||||
|
if (msg.IsPerfmonAlarm)
|
||||||
|
{
|
||||||
|
return new AlarmMessageAlert(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all other kinds of alert
|
||||||
|
return new MessageAlert(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
XenAdmin/Alerts/Types/MissingIqnAlert.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class MissingIqnAlert : IqnAlert
|
||||||
|
{
|
||||||
|
public MissingIqnAlert(Host host)
|
||||||
|
: base(host)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.IQN_CHECK_MISSING_TITLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.IQN_CHECK_MISSING_TEXT, Helpers.GetName(Host));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "MissingIqnAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Alert other)
|
||||||
|
{
|
||||||
|
if (other is MissingIqnAlert)
|
||||||
|
{
|
||||||
|
return Host.opaque_ref == ((MissingIqnAlert)other).Host.opaque_ref;
|
||||||
|
}
|
||||||
|
return base.Equals(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
XenAdmin/Alerts/Types/XenCenterUpdateAlert.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class XenCenterUpdateAlert : Alert
|
||||||
|
{
|
||||||
|
public readonly XenCenterVersion NewVersion;
|
||||||
|
|
||||||
|
public XenCenterUpdateAlert(XenCenterVersion version)
|
||||||
|
{
|
||||||
|
NewVersion = version;
|
||||||
|
_timestamp = NewVersion.TimeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority { get { return AlertPriority.Priority5; } }
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_NEW_VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.ALERT_NEW_VERSION_DETAILS, NewVersion.Name, HelpersGUI.DateTimeToString(NewVersion.TimeStamp, Messages.DATEFORMAT_DMY_LONG, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string DescriptionInvariant
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.ALERT_NEW_VERSION_DETAILS, NewVersion.Name, HelpersGUI.DateTimeToString(NewVersion.TimeStamp, Messages.DATEFORMAT_DMY_LONG, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get { return () => Program.OpenURL(NewVersion.Url); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_NEW_VERSION_DOWNLOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string AppliesTo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.XENCENTER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "XenCenterUpdateAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dismiss()
|
||||||
|
{
|
||||||
|
Properties.Settings.Default.LatestXenCenterSeen = NewVersion.VersionAndLang;
|
||||||
|
base.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Alert other)
|
||||||
|
{
|
||||||
|
if (other is XenCenterUpdateAlert)
|
||||||
|
{
|
||||||
|
return NewVersion.VersionAndLang == ((XenCenterUpdateAlert)other).NewVersion.VersionAndLang;
|
||||||
|
}
|
||||||
|
return base.Equals(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
225
XenAdmin/Alerts/Types/XenServerPatchAlert.cs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class XenServerPatchAlert : Alert
|
||||||
|
{
|
||||||
|
private readonly List<IXenConnection> connections = new List<IXenConnection>();
|
||||||
|
private readonly List<Host> hosts = new List<Host>();
|
||||||
|
public List<Host> Hosts
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<Host> result = new List<Host>();
|
||||||
|
|
||||||
|
foreach (Host host in hosts)
|
||||||
|
result.Add(host);
|
||||||
|
|
||||||
|
foreach (IXenConnection connection in connections)
|
||||||
|
result.AddRange(connection.Cache.Hosts);
|
||||||
|
|
||||||
|
return result.Distinct().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool canIgnore;
|
||||||
|
public bool CanIgnore
|
||||||
|
{ get { return canIgnore; } }
|
||||||
|
|
||||||
|
public XenServerPatch Patch;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Can we apply this alert. Calling this sets the CannotApplyReason where applicable
|
||||||
|
/// </summary>
|
||||||
|
public override bool CanApply
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(Hosts != null)
|
||||||
|
{
|
||||||
|
if(Hosts.All(IsHostLicenseRestricted))
|
||||||
|
{
|
||||||
|
CannotApplyReason = Messages.MANUAL_CHECK_FOR_UPDATES_UNLICENSED_INFO;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Hosts.Any(IsHostLicenseRestricted))
|
||||||
|
{
|
||||||
|
CannotApplyReason = Messages.MANUAL_CHECK_FOR_UPDATES_PARTIAL_UNLICENSED_INFO;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CannotApplyReason = string.Empty;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsHostLicenseRestricted(Host host)
|
||||||
|
{
|
||||||
|
if(host == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !host.CanApplyHotfixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XenServerPatchAlert(XenServerPatch patch)
|
||||||
|
{
|
||||||
|
Patch = patch;
|
||||||
|
_priority = patch.Priority;
|
||||||
|
_timestamp = Patch.TimeStamp;
|
||||||
|
canIgnore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncludeConnection(IXenConnection newConnection)
|
||||||
|
{
|
||||||
|
connections.Add(newConnection);
|
||||||
|
if (connections.Count > 0)
|
||||||
|
canIgnore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncludeHosts(List<Host> newHosts)
|
||||||
|
{
|
||||||
|
hosts.AddRange(newHosts);
|
||||||
|
if (hosts.Count > 0)
|
||||||
|
canIgnore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyConnectionsAndHosts(XenServerPatchAlert alert)
|
||||||
|
{
|
||||||
|
connections.Clear();
|
||||||
|
connections.AddRange(alert.connections);
|
||||||
|
hosts.Clear();
|
||||||
|
hosts.AddRange(alert.hosts);
|
||||||
|
canIgnore = connections.Count == 0 && hosts.Count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Enum.IsDefined(typeof(AlertPriority), _priority))
|
||||||
|
return (AlertPriority)_priority;
|
||||||
|
|
||||||
|
return AlertPriority.Priority2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string AppliesTo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<string> names = new List<string>();
|
||||||
|
|
||||||
|
foreach (Host host in hosts)
|
||||||
|
names.Add(host.Name);
|
||||||
|
|
||||||
|
foreach (IXenConnection connection in connections)
|
||||||
|
names.Add(Helpers.GetName(connection));
|
||||||
|
|
||||||
|
return string.Join(", ", names.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format("{0} ({1})", Patch.Description, HelpersGUI.DateTimeToString(Patch.TimeStamp, Messages.DATEFORMAT_DMY_LONG, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string DescriptionInvariant
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format("{0} ({1})", Patch.Description, HelpersGUI.DateTimeToString(Patch.TimeStamp, Messages.DATEFORMAT_DMY_LONG, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get { return () => Program.OpenURL(Patch.Url); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_NEW_PATCH_DOWNLOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "XenServerPatchAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.NEW_UPDATE_AVAILABLE,Patch.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dismiss()
|
||||||
|
{
|
||||||
|
base.Dismiss();
|
||||||
|
foreach (IXenConnection connection in connections)
|
||||||
|
{
|
||||||
|
new IgnorePatchAction(connection, Patch).RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Alert other)
|
||||||
|
{
|
||||||
|
if (other is XenServerPatchAlert)
|
||||||
|
{
|
||||||
|
return Patch.Uuid == ((XenServerPatchAlert)other).Patch.Uuid;
|
||||||
|
}
|
||||||
|
return base.Equals(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
166
XenAdmin/Alerts/Types/XenServerUpdateAlert.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Alerts
|
||||||
|
{
|
||||||
|
public class XenServerUpdateAlert : Alert
|
||||||
|
{
|
||||||
|
private readonly List<IXenConnection> connections = new List<IXenConnection>();
|
||||||
|
private readonly List<Host> hosts = new List<Host>();
|
||||||
|
|
||||||
|
private bool canIgnore;
|
||||||
|
public bool CanIgnore
|
||||||
|
{ get { return canIgnore; } }
|
||||||
|
|
||||||
|
public XenServerVersion Version;
|
||||||
|
|
||||||
|
public XenServerUpdateAlert(XenServerVersion version)
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
_timestamp = version.TimeStamp;
|
||||||
|
canIgnore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncludeConnection(IXenConnection newConnection)
|
||||||
|
{
|
||||||
|
connections.Add(newConnection);
|
||||||
|
if (connections.Count > 0)
|
||||||
|
canIgnore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncludeHosts(List<Host> newHosts)
|
||||||
|
{
|
||||||
|
hosts.AddRange(newHosts);
|
||||||
|
if (hosts.Count > 0)
|
||||||
|
canIgnore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyConnectionsAndHosts(XenServerUpdateAlert alert)
|
||||||
|
{
|
||||||
|
connections.Clear();
|
||||||
|
connections.AddRange(alert.connections);
|
||||||
|
hosts.Clear();
|
||||||
|
hosts.AddRange(alert.hosts);
|
||||||
|
canIgnore = connections.Count == 0 && hosts.Count == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Title
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.DOWLOAD_LATEST_XS_TITLE,Version.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.DOWNLOAD_LATEST_XS_BODY, Version.Name, HelpersGUI.DateTimeToString(Version.TimeStamp, Messages.DATEFORMAT_DMY_LONG, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string DescriptionInvariant
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return string.Format(Messages.DOWNLOAD_LATEST_XS_BODY, Version.Name, HelpersGUI.DateTimeToString(Version.TimeStamp, Messages.DATEFORMAT_DMY_LONG, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string AppliesTo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<string> names = new List<string>();
|
||||||
|
|
||||||
|
foreach (Host host in hosts)
|
||||||
|
names.Add(host.Name);
|
||||||
|
|
||||||
|
foreach (IXenConnection connection in connections)
|
||||||
|
names.Add(Helpers.GetName(connection));
|
||||||
|
|
||||||
|
return string.Join(", ", names.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string FixLinkText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ALERT_NEW_VERSION_DOWNLOAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override AlertPriority Priority
|
||||||
|
{
|
||||||
|
get { return AlertPriority.Priority5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override FixLinkDelegate FixLinkAction
|
||||||
|
{
|
||||||
|
get { return () => Program.OpenURL(Version.Url); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string HelpID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "XenServerUpdateAlert";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dismiss()
|
||||||
|
{
|
||||||
|
foreach (IXenConnection connection in ConnectionsManager.XenConnectionsCopy)
|
||||||
|
new IgnoreServerAction(connection, Version).RunAsync();
|
||||||
|
base.Dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Alert other)
|
||||||
|
{
|
||||||
|
if (other is XenServerUpdateAlert)
|
||||||
|
{
|
||||||
|
return Version.VersionAndOEM == ((XenServerUpdateAlert)other).Version.VersionAndOEM;
|
||||||
|
}
|
||||||
|
return base.Equals(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
XenAdmin/AppIcon.ico
Normal file
After Width: | Height: | Size: 25 KiB |
46
XenAdmin/Branding.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
// Values taken from branding.hg
|
||||||
|
|
||||||
|
namespace XenAdmin
|
||||||
|
{
|
||||||
|
static public class Branding
|
||||||
|
{
|
||||||
|
public const string PRODUCT_VERSION_TEXT = "@PRODUCT_VERSION_TEXT@";
|
||||||
|
public const string COPYRIGHT_YEARS = "@COPYRIGHT_YEARS@";
|
||||||
|
public const string COMPANY_NAME_LEGAL = "@COMPANY_NAME_LEGAL@";
|
||||||
|
}
|
||||||
|
}
|
170
XenAdmin/Commands/ActivateVBDCommand.cs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
class ActivateVBDCommand : Command
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deactivates a selection of VBDs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow"></param>
|
||||||
|
/// <param name="selection"></param>
|
||||||
|
public ActivateVBDCommand(IMainWindow mainWindow, IEnumerable<SelectedItem> selection)
|
||||||
|
: base(mainWindow, selection)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deactivates a single VBD
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow"></param>
|
||||||
|
/// <param name="vbd"></param>
|
||||||
|
public ActivateVBDCommand(IMainWindow mainWindow, VBD vbd)
|
||||||
|
: base(mainWindow, vbd)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ContextMenuText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.MESSAGEBOX_ACTIVATE_VD_TITLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
return selection.AllItemsAre<VBD>() && selection.AtLeastOneXenObjectCan<VBD>(CanExecute);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanExecute(VBD vbd)
|
||||||
|
{
|
||||||
|
VM vm = vbd.Connection.Resolve<VM>(vbd.VM);
|
||||||
|
VDI vdi = vbd.Connection.Resolve<VDI>(vbd.VDI);
|
||||||
|
if (vm == null || vm.not_a_real_vm || vdi == null)
|
||||||
|
return false;
|
||||||
|
if (vm.power_state != vm_power_state.Running)
|
||||||
|
return false;
|
||||||
|
if (vdi.type == vdi_type.system)
|
||||||
|
return false;
|
||||||
|
if (vm.virtualisation_status != VM.VirtualisationStatus.OPTIMIZED)
|
||||||
|
return false;
|
||||||
|
if (vbd.currently_attached)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return vbd.allowed_operations.Contains(vbd_operations.plug);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetCantExecuteReasonCore(SelectedItem item)
|
||||||
|
{
|
||||||
|
VBD vbd = item.XenObject as VBD;
|
||||||
|
if (vbd == null)
|
||||||
|
return base.GetCantExecuteReasonCore(item);
|
||||||
|
|
||||||
|
VM vm = vbd.Connection.Resolve<VM>(vbd.VM);
|
||||||
|
VDI vdi = vbd.Connection.Resolve<VDI>(vbd.VDI);
|
||||||
|
if (vm == null || vm.not_a_real_vm || vdi == null)
|
||||||
|
return base.GetCantExecuteReasonCore(item);
|
||||||
|
|
||||||
|
SR sr = vdi.Connection.Resolve<SR>(vdi.SR);
|
||||||
|
if (sr == null)
|
||||||
|
return Messages.SR_COULD_NOT_BE_CONTACTED;
|
||||||
|
|
||||||
|
if (vdi.Locked)
|
||||||
|
return vdi.VDIType == VDI.FriendlyType.SNAPSHOT ? Messages.CANNOT_ACTIVATE_SNAPSHOT_IN_USE
|
||||||
|
: vdi.VDIType == VDI.FriendlyType.ISO ? Messages.CANNOT_ACTIVATE_ISO_IN_USE
|
||||||
|
: Messages.CANNOT_ACTIVATE_VD_IN_USE;
|
||||||
|
|
||||||
|
if (vm.power_state != vm_power_state.Running)
|
||||||
|
return string.Format(
|
||||||
|
Messages.CANNOT_ACTIVATE_VD_VM_HALTED,
|
||||||
|
Helpers.GetName(vm).Ellipsise(50));
|
||||||
|
|
||||||
|
if (vdi.type == vdi_type.system)
|
||||||
|
return Messages.TOOLTIP_DEACTIVATE_SYSVDI;
|
||||||
|
|
||||||
|
if (vm.virtualisation_status != VM.VirtualisationStatus.OPTIMIZED)
|
||||||
|
return string.Format(
|
||||||
|
Messages.CANNOT_ACTIVATE_VD_VM_NEEDS_TOOLS,
|
||||||
|
Helpers.GetName(vm).Ellipsise(50));
|
||||||
|
|
||||||
|
if (vbd.currently_attached)
|
||||||
|
return string.Format(Messages.CANNOT_ACTIVATE_VD_ALREADY_ACTIVE, Helpers.GetName(vm).Ellipsise(50));
|
||||||
|
|
||||||
|
return base.GetCantExecuteReasonCore(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override CommandErrorDialog GetErrorDialogCore(IDictionary<SelectedItem, string> cantExecuteReasons)
|
||||||
|
{
|
||||||
|
return new CommandErrorDialog(Messages.ERROR_ACTIVATING_VDIS_TITLE, Messages.ERROR_ACTIVATING_VDIS_MESSAGE, cantExecuteReasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
List<AsyncAction> actionsToComplete = new List<AsyncAction>();
|
||||||
|
foreach (VBD vbd in selection.AsXenObjects<VBD>())
|
||||||
|
{
|
||||||
|
if (vbd.Locked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
actionsToComplete.Add(getActivateVBDAction(vbd));
|
||||||
|
}
|
||||||
|
if (actionsToComplete.Count > 1)
|
||||||
|
RunMultipleActions(actionsToComplete, Messages.ACTION_ACTIVATING_MULTIPLE_VDIS_TITLE, Messages.ACTION_ACTIVATING_MULTIPLE_VDIS_STATUS, Messages.COMPLETED, true);
|
||||||
|
else
|
||||||
|
actionsToComplete[0].RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AsyncAction getActivateVBDAction(VBD vbd)
|
||||||
|
{
|
||||||
|
VDI vdi = vbd.Connection.Resolve<VDI>(vbd.VDI);
|
||||||
|
VM vm = vbd.Connection.Resolve<VM>(vbd.VM);
|
||||||
|
String title = String.Format(Messages.ACTION_DISK_ACTIVATING_TITLE, vdi.Name, vm.Name);
|
||||||
|
String startDesc = Messages.ACTION_DISK_ACTIVATING;
|
||||||
|
String endDesc = Messages.ACTION_DISK_ACTIVATED;
|
||||||
|
|
||||||
|
AsyncAction action = new DelegatedAsyncAction(vbd.Connection,
|
||||||
|
title, startDesc, endDesc,session => VBD.plug(session, vbd.opaque_ref),"vbd.plug");
|
||||||
|
action.VM = vm;
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
XenAdmin/Commands/ActivationRequestCommand.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
class ActivationRequestCommand : Command
|
||||||
|
{
|
||||||
|
private string _request;
|
||||||
|
|
||||||
|
public ActivationRequestCommand(IMainWindow mainWindow,string request)
|
||||||
|
{
|
||||||
|
_request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
ActivationRequestAction action = new ActivationRequestAction(_request);
|
||||||
|
action.Completed += action_Completed;
|
||||||
|
action.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void action_Completed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ActivationRequestAction action = (ActivationRequestAction)sender;
|
||||||
|
if (action.Succeeded)
|
||||||
|
Program.OpenURL(string.Format(InvisibleMessages.ACTIVATION_FORM_URL, InvisibleMessages.ACTIVATION_SERVER, action.Result));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (DialogResult.Cancel == ShowSaveDialog())
|
||||||
|
throw action.Exception;
|
||||||
|
|
||||||
|
SaveFileDialog fd = new SaveFileDialog();
|
||||||
|
Program.Invoke(Program.MainWindow,
|
||||||
|
delegate()
|
||||||
|
{
|
||||||
|
fd.AddExtension = true;
|
||||||
|
fd.DefaultExt = "txt";
|
||||||
|
fd.Filter = string.Format("{0} (*.*)|*.*", Messages.ALL_FILES);
|
||||||
|
fd.FilterIndex = 0;
|
||||||
|
fd.RestoreDirectory = true;
|
||||||
|
if (DialogResult.Cancel == fd.ShowDialog(Program.MainWindow))
|
||||||
|
throw action.Exception;
|
||||||
|
|
||||||
|
using (FileStream fs = File.Open(fd.FileName, FileMode.Create))
|
||||||
|
{
|
||||||
|
byte[] bytes = Encoding.UTF8.GetBytes(_request);
|
||||||
|
fs.Write(bytes, 0, bytes.Length);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Description = string.Format(Messages.ACTIVATION_REQUEST_SAVED, fd.FileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate DialogResult DialogInvoker();
|
||||||
|
|
||||||
|
private DialogResult ShowSaveDialog()
|
||||||
|
{
|
||||||
|
return (DialogResult)Program.Invoke(Program.MainWindow,
|
||||||
|
(DialogInvoker)delegate()
|
||||||
|
{
|
||||||
|
return new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(SystemIcons.Error, string.Format(Messages.ACTIVATION_FAILED_MESSAGE, InvisibleMessages.ACTIVATION_SERVER)),
|
||||||
|
"ActivationServerUnavailable",
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.ACTIVATION_SAVE, DialogResult.Yes),
|
||||||
|
ThreeButtonDialog.ButtonCancel).ShowDialog(Program.MainWindow);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
118
XenAdmin/Commands/AddHostCommand.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Windows.Forms;
|
||||||
|
using XenAdmin.Properties;
|
||||||
|
using System.Drawing;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pops up the dialog for adding a new Host to XenCenter.
|
||||||
|
/// </summary>
|
||||||
|
internal class AddHostCommand : Command
|
||||||
|
{
|
||||||
|
private AddServerDialog _dialog;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of this Command. The parameter-less constructor is required in the derived
|
||||||
|
/// class if it is to be attached to a ToolStrip menu item or button. It should not be used in any other scenario.
|
||||||
|
/// </summary>
|
||||||
|
public AddHostCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AddHostCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow">The main window interface. It can be found at MainWindow.CommandInterface.</param>
|
||||||
|
public AddHostCommand(IMainWindow mainWindow)
|
||||||
|
: base(mainWindow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AddHostCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow">The main window interface. It can be found at MainWindow.CommandInterface.</param>
|
||||||
|
/// <param name="parent">The parent for the Add Server dialog.</param>
|
||||||
|
public AddHostCommand(IMainWindow mainWindow, Control parent)
|
||||||
|
: base(mainWindow)
|
||||||
|
{
|
||||||
|
SetParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
_dialog = new AddServerDialog(null, false);
|
||||||
|
_dialog.CachePopulated += dialog_CachePopulated;
|
||||||
|
_dialog.Show(Parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dialog_CachePopulated(object sender, CachePopulatedEventArgs e)
|
||||||
|
{
|
||||||
|
_dialog.CachePopulated -= dialog_CachePopulated;
|
||||||
|
|
||||||
|
// first select the disconnected host in the tree
|
||||||
|
// before the tree is populated, the opaque_ref of the disconnected host is the hostname
|
||||||
|
// so use this to select the object.
|
||||||
|
MainWindowCommandInterface.Invoke(() => MainWindowCommandInterface.SelectObjectInTree(new Host { opaque_ref = e.Connection.Hostname }, false));
|
||||||
|
MainWindowCommandInterface.TrySelectNewObjectInTree(e.Connection, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Image MenuImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Resources._000_AddApplicationServer_h32bit_16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Image ToolBarImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Resources._000_AddApplicationServer_h32bit_24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string MenuText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.MAINWINDOW_ADD_HOST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
296
XenAdmin/Commands/AddHostToPoolCommand.cs
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A Command for adding a host to a pool. This Command does not use the current selection for specifying the host and pool.
|
||||||
|
/// The host and pool are set in the constructor for this class.
|
||||||
|
/// </summary>
|
||||||
|
internal class AddHostToPoolCommand : Command
|
||||||
|
{
|
||||||
|
private readonly List<Host> _hosts;
|
||||||
|
private readonly Pool _pool;
|
||||||
|
private readonly bool _confirm;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AddHostToPoolCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow">The main window interface. It can be found at Program.MainWindow.CommandInterface.</param>
|
||||||
|
/// <param name="hosts">The hosts which are to be added to the pool.</param>
|
||||||
|
/// <param name="pool">The pool the host should be added to.</param>
|
||||||
|
/// <param name="confirm">if set to <c>true</c> a confirmation dialog is shown.</param>
|
||||||
|
public AddHostToPoolCommand(IMainWindow mainWindow, IEnumerable<Host> hosts, Pool pool, bool confirm)
|
||||||
|
: base(mainWindow)
|
||||||
|
{
|
||||||
|
Util.ThrowIfParameterNull(hosts, "hosts");
|
||||||
|
Util.ThrowIfParameterNull(pool, "pool");
|
||||||
|
_hosts = new List<Host>(hosts);
|
||||||
|
_confirm = confirm;
|
||||||
|
_pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
Dictionary<SelectedItem, string> reasons = new Dictionary<SelectedItem, string>();
|
||||||
|
foreach (Host host in _hosts)
|
||||||
|
{
|
||||||
|
PoolJoinRules.Reason reason = PoolJoinRules.CanJoinPool(host.Connection, _pool.Connection, true, true, true);
|
||||||
|
if (reason != PoolJoinRules.Reason.Allowed)
|
||||||
|
reasons[new SelectedItem(host)] = PoolJoinRules.ReasonMessage(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasons.Count > 0)
|
||||||
|
{
|
||||||
|
string title = Messages.ERROR_DIALOG_ADD_TO_POOL_TITLE;
|
||||||
|
string text = string.Format(Messages.ERROR_DIALOG_ADD_TO_POOL_TEXT, Helpers.GetName(_pool).Ellipsise(500));
|
||||||
|
|
||||||
|
new CommandErrorDialog(title, text, reasons).ShowDialog(Parent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_confirm && !ShowConfirmationDialog())
|
||||||
|
{
|
||||||
|
// Bail out if the user doesn't want to continue.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Helpers.IsConnected(_pool))
|
||||||
|
{
|
||||||
|
string message = _hosts.Count == 1
|
||||||
|
? string.Format(Messages.ADD_HOST_TO_POOL_DISCONNECTED_POOL,
|
||||||
|
Helpers.GetName(_hosts[0]).Ellipsise(500), Helpers.GetName(_pool).Ellipsise(500))
|
||||||
|
: string.Format(Messages.ADD_HOST_TO_POOL_DISCONNECTED_POOL_MULTIPLE,
|
||||||
|
Helpers.GetName(_pool).Ellipsise(500));
|
||||||
|
|
||||||
|
new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(SystemIcons.Error, message, Messages.XENCENTER)).ShowDialog(Parent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check supp packs and warn
|
||||||
|
List<string> badSuppPacks = PoolJoinRules.HomogeneousSuppPacksDiffering(_hosts, _pool);
|
||||||
|
if (!HelpersGUI.GetPermissionFor(badSuppPacks, sp => true,
|
||||||
|
Messages.ADD_HOST_TO_POOL_SUPP_PACK, Messages.ADD_HOST_TO_POOL_SUPP_PACKS, false, "PoolJoinSuppPacks"))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Are there any hosts which are forbidden from masking their CPUs for licensing reasons?
|
||||||
|
// If so, we need to show upsell.
|
||||||
|
Host master = Helpers.GetMaster(_pool);
|
||||||
|
if (null != _hosts.Find(host =>
|
||||||
|
!PoolJoinRules.CompatibleCPUs(host, master, false) &&
|
||||||
|
Helpers.FeatureForbidden(host, Host.RestrictCpuMasking) &&
|
||||||
|
!PoolJoinRules.FreeHostPaidMaster(host, master, false))) // in this case we can upgrade the license and then mask the CPU
|
||||||
|
{
|
||||||
|
UpsellDialog dlg = new UpsellDialog(Messages.UPSELL_BLURB_CPUMASKING, InvisibleMessages.UPSELL_LEARNMOREURL_CPUMASKING);
|
||||||
|
dlg.ShowDialog(Parent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get permission for any fix-ups: 1) Licensing free hosts; 2) CPU masking 3) Ad configuration
|
||||||
|
// (We already know that these things are fixable because we have been through CanJoinPool() above).
|
||||||
|
if (!HelpersGUI.GetPermissionFor(_hosts, host => PoolJoinRules.FreeHostPaidMaster(host, master, false),
|
||||||
|
Messages.ADD_HOST_TO_POOL_LICENSE_MESSAGE, Messages.ADD_HOST_TO_POOL_LICENSE_MESSAGE_MULTIPLE, true, "PoolJoinRelicensing")
|
||||||
|
||
|
||||||
|
!HelpersGUI.GetPermissionFor(_hosts, host => !PoolJoinRules.CompatibleCPUs(host, master, false),
|
||||||
|
Messages.ADD_HOST_TO_POOL_CPU_MASKING_MESSAGE, Messages.ADD_HOST_TO_POOL_CPU_MASKING_MESSAGE_MULTIPLE, true, "PoolJoinCpuMasking")
|
||||||
|
||
|
||||||
|
!HelpersGUI.GetPermissionFor(_hosts, host => !PoolJoinRules.CompatibleAdConfig(host, master, false),
|
||||||
|
Messages.ADD_HOST_TO_POOL_AD_MESSAGE, Messages.ADD_HOST_TO_POOL_AD_MESSAGE_MULTIPLE, true, "PoolJoinAdConfiguring")
|
||||||
|
)
|
||||||
|
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowCommandInterface.SelectObjectInTree(_pool, false);
|
||||||
|
MainWindowCommandInterface.AllowHistorySwitch();
|
||||||
|
|
||||||
|
List<AsyncAction> actions = new List<AsyncAction>();
|
||||||
|
foreach (Host host in _hosts)
|
||||||
|
{
|
||||||
|
string opaque_ref = host.opaque_ref;
|
||||||
|
AddHostToPoolAction action = new AddHostToPoolAction(_pool, host, GetAdPrompt, NtolDialog, ApplyLicenseEditionCommand.ShowLicensingFailureDialog);
|
||||||
|
action.Completed += (s, e) => Program.ShowObject(opaque_ref);
|
||||||
|
actions.Add(action);
|
||||||
|
|
||||||
|
// hide connection. If the action fails, re-show it.
|
||||||
|
Program.HideObject(opaque_ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunMultipleActions(actions, string.Format(Messages.ADDING_SERVERS_TO_POOL, _pool.Name), Messages.POOLCREATE_ADDING, Messages.POOLCREATE_ADDED, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
if (_hosts.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (Host host in _hosts)
|
||||||
|
{
|
||||||
|
// only allowed to add standalone hosts.
|
||||||
|
if (Helpers.GetPool(host.Connection) != null || host.RestrictPooling)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ConfirmationDialogText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_hosts.Count == 1)
|
||||||
|
{
|
||||||
|
return string.Format(Messages.MAINWINDOW_CONFIRM_MOVE_TO_POOL, _hosts[0].Name.Ellipsise(500), _pool.Name.Ellipsise(500));
|
||||||
|
}
|
||||||
|
else if (_hosts.Count > 1)
|
||||||
|
{
|
||||||
|
return string.Format(Messages.MAINWINDOW_CONFIRM_MOVE_TO_POOL_MULTIPLE, _pool.Name.Ellipsise(500));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ConfirmationDialogTitle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.POOLCREATE_ADDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PoolAbstractAction.AdUserAndPassword GetAdPrompt(Host poolMaster)
|
||||||
|
{
|
||||||
|
AdPasswordPrompt adPrompt = new AdPasswordPrompt(true, poolMaster.external_auth_service_name);
|
||||||
|
|
||||||
|
Program.Invoke(Program.MainWindow, delegate
|
||||||
|
{
|
||||||
|
if (adPrompt.ShowDialog(Program.MainWindow) == DialogResult.Cancel)
|
||||||
|
throw new CancelledException();
|
||||||
|
});
|
||||||
|
return new PoolAbstractAction.AdUserAndPassword(adPrompt.Username, adPrompt.Password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool EnableNtolDialog(Pool pool, Host host, long currentNtol, long max)
|
||||||
|
{
|
||||||
|
bool doit = false;
|
||||||
|
Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
{
|
||||||
|
string poolName = Helpers.GetName(pool).Ellipsise(500);
|
||||||
|
string hostName = Helpers.GetName(host).Ellipsise(500);
|
||||||
|
string msg = string.Format(Messages.HA_HOST_ENABLE_NTOL_RAISE_QUERY, poolName, hostName, currentNtol, max);
|
||||||
|
if (new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(null, msg, Messages.HIGH_AVAILABILITY),
|
||||||
|
ThreeButtonDialog.ButtonYes,
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)).ShowDialog(Program.MainWindow)
|
||||||
|
== DialogResult.Yes)
|
||||||
|
{
|
||||||
|
doit = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return doit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool NtolDialog(HostAbstractAction action, Pool pool, long currentNtol, long targetNtol)
|
||||||
|
{
|
||||||
|
bool cancel = false;
|
||||||
|
Program.Invoke(Program.MainWindow, delegate()
|
||||||
|
{
|
||||||
|
string poolName = Helpers.GetName(pool).Ellipsise(500);
|
||||||
|
string hostName = Helpers.GetName(action.Host).Ellipsise(500);
|
||||||
|
|
||||||
|
string msg;
|
||||||
|
if (targetNtol == 0)
|
||||||
|
{
|
||||||
|
string f;
|
||||||
|
if (action is EvacuateHostAction)
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_DISABLE_NTOL_ZERO;
|
||||||
|
}
|
||||||
|
else if (action is RebootHostAction)
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_REBOOT_NTOL_ZERO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_SHUTDOWN_NTOL_ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = string.Format(f, poolName, hostName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string f;
|
||||||
|
if (action is EvacuateHostAction)
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_DISABLE_NTOL_DROP;
|
||||||
|
}
|
||||||
|
else if (action is RebootHostAction)
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_REBOOT_NTOL_DROP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f = Messages.HA_HOST_SHUTDOWN_NTOL_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = string.Format(f, poolName, currentNtol, hostName, targetNtol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(SystemIcons.Warning, msg, Messages.HIGH_AVAILABILITY),
|
||||||
|
ThreeButtonDialog.ButtonYes,
|
||||||
|
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)
|
||||||
|
).ShowDialog(Program.MainWindow) == DialogResult.No)
|
||||||
|
{
|
||||||
|
cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
118
XenAdmin/Commands/AddNewHostToPoolCommand.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 XenAdmin.Properties;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAdmin.Core;
|
||||||
|
using System.Drawing;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
internal class AddNewHostToPoolCommand : Command
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
private readonly Pool _pool;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AddNewHostToPoolCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mainWindow">The main window.</param>
|
||||||
|
/// <param name="pool">The pool that the new host is to be added to.</param>
|
||||||
|
public AddNewHostToPoolCommand(IMainWindow mainWindow, Pool pool)
|
||||||
|
: base(mainWindow)
|
||||||
|
{
|
||||||
|
Util.ThrowIfParameterNull(pool, "pool");
|
||||||
|
_pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
AddServerDialog dialog = new AddServerDialog(null, false);
|
||||||
|
dialog.CachePopulated += dialog_CachePopulated;
|
||||||
|
dialog.Show(Parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Image MenuImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Resources._000_AddApplicationServer_h32bit_16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string MenuText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ADD_NEW_SERVER_MENU_ITEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called in the 'connect new server and add to pool' action after the server has connected
|
||||||
|
/// and its cache has been populated. Adds the new server to the pool.
|
||||||
|
/// </summary>
|
||||||
|
private void dialog_CachePopulated(object sender, CachePopulatedEventArgs e)
|
||||||
|
{
|
||||||
|
IXenConnection newConnection = e.Connection;
|
||||||
|
|
||||||
|
// A new connection was successfully made: add the new server to its destination pool.
|
||||||
|
Host hostToAdd = Helpers.GetMaster(newConnection);
|
||||||
|
if (hostToAdd == null)
|
||||||
|
{
|
||||||
|
log.Debug("hostToAdd is null while joining host to pool in AddNewHostToPoolCommand: this should never happen!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check newly-connected host is not in pool
|
||||||
|
Pool hostPool = Helpers.GetPool(newConnection);
|
||||||
|
|
||||||
|
MainWindowCommandInterface.Invoke(delegate
|
||||||
|
{
|
||||||
|
if (hostPool != null)
|
||||||
|
{
|
||||||
|
string text = String.Format(Messages.HOST_ALREADY_IN_POOL, hostToAdd.Name, _pool.Name, hostPool.Name);
|
||||||
|
string caption = Messages.POOL_JOIN_IMPOSSIBLE;
|
||||||
|
|
||||||
|
new ThreeButtonDialog(new ThreeButtonDialog.Details(SystemIcons.Exclamation, text, caption)).ShowDialog(Program.MainWindow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new AddHostToPoolCommand(MainWindowCommandInterface, new Host[] { hostToAdd }, _pool, false).Execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
209
XenAdmin/Commands/AddStorageLinkSystemCommand.cs
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using XenAPI;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using XenAdmin.Properties;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Network.StorageLink;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
internal class AddStorageLinkSystemCommand : Command
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
public event EventHandler<CompletedEventArgs> Completed;
|
||||||
|
|
||||||
|
public AddStorageLinkSystemCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddStorageLinkSystemCommand(IMainWindow mainWindow, IEnumerable<SelectedItem> selection)
|
||||||
|
: base(mainWindow, selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddStorageLinkSystemCommand(IMainWindow mainWindow, StorageLinkServer server)
|
||||||
|
: base(mainWindow, server)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddStorageLinkSystemCommand(IMainWindow mainWindow, StorageLinkServer server, Control parent)
|
||||||
|
: base(mainWindow, server)
|
||||||
|
{
|
||||||
|
SetParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
if (selection.AllItemsAre<IStorageLinkObject>())
|
||||||
|
{
|
||||||
|
StorageLinkConnection con = ((IStorageLinkObject)selection.First).StorageLinkConnection;
|
||||||
|
|
||||||
|
// check all selected SL items are on the same SL connection.
|
||||||
|
if (con != null && con.ConnectionState == StorageLinkConnectionState.Connected && selection.AllItemsAre<IStorageLinkObject>(s => s.StorageLinkConnection.Equals(con)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
IXenObject selected = selection.FirstAsXenObject;
|
||||||
|
var server = GetStorageLinkServer(selected);
|
||||||
|
if (server == null)
|
||||||
|
return;
|
||||||
|
var dialog = new AddStorageLinkSystemDialog(server.StorageLinkConnection);
|
||||||
|
var parent = Parent ?? (Control)Program.MainWindow;
|
||||||
|
|
||||||
|
dialog.FormClosing += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dialog.DialogResult == DialogResult.OK)
|
||||||
|
{
|
||||||
|
var adapter = dialog.StorageAdapter;
|
||||||
|
var port = dialog.StorageSystemPort;
|
||||||
|
var address = dialog.StorageSystemAddress;
|
||||||
|
var username = dialog.StorageSystemUsername;
|
||||||
|
var password = dialog.StorageSystemPassword;
|
||||||
|
var ns = dialog.StorageSystemNamespace;
|
||||||
|
|
||||||
|
// There are no RBAC complexities here since only pool-operator and above can access the password for the storagelink service.
|
||||||
|
// Therefore only pool-operator and above can get here. These roles are permitted to add and remove storage systems.
|
||||||
|
|
||||||
|
var action = new StorageLinkDelegatedAsyncAction(
|
||||||
|
() => server.StorageLinkConnection.AddStorageSystem(adapter, port, address, username, password, ns),
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_TITLE, address),
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_START_DESCRIPTION, address),
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_END_DESCRIPTION, address));
|
||||||
|
|
||||||
|
var actionWithWait = new DelegatedAsyncAction(null,
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_TITLE, address),
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_START_DESCRIPTION, address),
|
||||||
|
string.Format(Messages.ADD_STORAGE_LINK_SYSTEM_ACTION_END_DESCRIPTION, address), ss =>
|
||||||
|
{
|
||||||
|
int storageSystemCountBefore = server.StorageLinkConnection.Cache.StorageSystems.Count;
|
||||||
|
action.RunExternal(ss);
|
||||||
|
|
||||||
|
for (int i = 0; i < 60 && action.Succeeded && server.StorageLinkConnection.Cache.StorageSystems.Count == storageSystemCountBefore; i++)
|
||||||
|
{
|
||||||
|
if((i%5)==0)
|
||||||
|
{
|
||||||
|
log.Info("Waiting for StorageLink storage-system to be added to cache.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
actionWithWait.AppliesTo.Add(server.opaque_ref);
|
||||||
|
actionWithWait.Completed += (ss, ee) => OnCompleted(new CompletedEventArgs(actionWithWait.Succeeded));
|
||||||
|
|
||||||
|
new ActionProgressDialog(actionWithWait, ProgressBarStyle.Continuous) { ShowCancel = true }.ShowDialog(dialog);
|
||||||
|
|
||||||
|
// keep creds dialog open if it failed.
|
||||||
|
e.Cancel = !actionWithWait.Succeeded;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog.Show(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StorageLinkServer GetStorageLinkServer(IXenObject xo)
|
||||||
|
{
|
||||||
|
if (xo is StorageLinkServer)
|
||||||
|
{
|
||||||
|
return (StorageLinkServer)xo;
|
||||||
|
}
|
||||||
|
else if (xo is StorageLinkSystem)
|
||||||
|
{
|
||||||
|
StorageLinkSystem system = (StorageLinkSystem)xo;
|
||||||
|
return system.StorageLinkServer;
|
||||||
|
}
|
||||||
|
else if (xo is StorageLinkPool)
|
||||||
|
{
|
||||||
|
StorageLinkPool pool = (StorageLinkPool)xo;
|
||||||
|
if (pool.Parent == null)
|
||||||
|
{
|
||||||
|
return pool.StorageLinkSystem.StorageLinkServer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GetStorageLinkServer(pool.Parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Image MenuImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Resources.sl_add_storage_system_16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string MenuText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Messages.ADD_STORAGE_LINK_SYSTEM_MENU;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnCompleted(CompletedEventArgs e)
|
||||||
|
{
|
||||||
|
var handler = Completed;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CompletedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public bool Success { get; private set; }
|
||||||
|
|
||||||
|
public CompletedEventArgs(bool success)
|
||||||
|
{
|
||||||
|
Success = success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
114
XenAdmin/Commands/AddVirtualDiskCommand.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAPI;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the add-virtual-disk dialog for the selected VM or SR.
|
||||||
|
/// </summary>
|
||||||
|
internal class AddVirtualDiskCommand : Command
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of this Command. The parameter-less constructor is required in the derived
|
||||||
|
/// class if it is to be attached to a ToolStrip menu item or button. It should not be used in any other scenario.
|
||||||
|
/// </summary>
|
||||||
|
public AddVirtualDiskCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddVirtualDiskCommand(IMainWindow mainWindow, IEnumerable<SelectedItem> selection)
|
||||||
|
: base(mainWindow, selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddVirtualDiskCommand(IMainWindow mainWindow, VM vm)
|
||||||
|
: base(mainWindow, vm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddVirtualDiskCommand(IMainWindow mainWindow, SR sr)
|
||||||
|
: base(mainWindow, sr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
VM vm = selection[0].XenObject as VM;
|
||||||
|
|
||||||
|
if (vm != null)
|
||||||
|
{
|
||||||
|
if (vm.VBDs.Count < vm.MaxVBDsAllowed)
|
||||||
|
{
|
||||||
|
MainWindowCommandInterface.ShowPerXenModelObjectWizard(vm, new NewDiskDialog(vm.Connection, vm));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(
|
||||||
|
SystemIcons.Error,
|
||||||
|
FriendlyErrorNames.VBDS_MAX_ALLOWED,
|
||||||
|
Messages.DISK_ADD)).ShowDialog(Program.MainWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SR sr = (SR)selection[0].XenObject;
|
||||||
|
MainWindowCommandInterface.ShowPerConnectionWizard(sr.Connection, new NewDiskDialog(sr.Connection, sr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
if (selection.Count == 1)
|
||||||
|
{
|
||||||
|
VM vm = selection[0].XenObject as VM;
|
||||||
|
SR sr = selection[0].XenObject as SR;
|
||||||
|
|
||||||
|
if (vm != null)
|
||||||
|
{
|
||||||
|
return !vm.is_a_snapshot && !vm.Locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sr != null && !sr.Locked;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
XenAdmin/Commands/ApplyLicenseEditionCommand.cs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using XenAPI;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
class ApplyLicenseEditionCommand : Command
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<IXenObject> xos;
|
||||||
|
private readonly Host.Edition _edition;
|
||||||
|
private readonly string _licenseServerAddress;
|
||||||
|
private readonly string _licenseServerPort;
|
||||||
|
|
||||||
|
public event EventHandler<EventArgs> Succedded;
|
||||||
|
|
||||||
|
public void InvokeSuccedded(EventArgs e)
|
||||||
|
{
|
||||||
|
EventHandler<EventArgs> handler = Succedded;
|
||||||
|
if (handler != null) handler(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ApplyLicenseEditionCommand(IMainWindow mainWindow, IEnumerable<IXenObject> xos,
|
||||||
|
Host.Edition edition, string licenseServerAddress, string licenseServerPort,
|
||||||
|
Control parent)
|
||||||
|
: base(mainWindow)
|
||||||
|
{
|
||||||
|
_edition = edition;
|
||||||
|
this.xos = xos;
|
||||||
|
_licenseServerAddress = licenseServerAddress;
|
||||||
|
_licenseServerPort = licenseServerPort;
|
||||||
|
SetParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
ApplyLicenseEditionAction action = new ApplyLicenseEditionAction(xos, _edition, _licenseServerAddress, _licenseServerPort, ShowLicensingFailureDialog);
|
||||||
|
ActionProgressDialog actionProgress = new ActionProgressDialog(action, ProgressBarStyle.Marquee);
|
||||||
|
|
||||||
|
// close dialog even when there's an error as this action shows its own error dialog box.
|
||||||
|
action.Completed += (s, ee) => Program.Invoke(Program.MainWindow, () =>
|
||||||
|
{
|
||||||
|
Failure f = action.Exception as Failure;
|
||||||
|
if (f != null && f.ErrorDescription[0] == Failure.RBAC_PERMISSION_DENIED_FRIENDLY)
|
||||||
|
return;
|
||||||
|
actionProgress.Close();
|
||||||
|
});
|
||||||
|
|
||||||
|
actionProgress.ShowDialog(Parent);
|
||||||
|
|
||||||
|
if (actionProgress.action.Succeeded)
|
||||||
|
{
|
||||||
|
InvokeSuccedded(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowLicensingFailureDialog(List<LicenseFailure> licenseFailures, string exceptionMessage)
|
||||||
|
{
|
||||||
|
Debug.Assert(licenseFailures.Count > 0);
|
||||||
|
|
||||||
|
|
||||||
|
if (licenseFailures.Count == 1)
|
||||||
|
{
|
||||||
|
Program.Invoke(Program.MainWindow, () => new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(SystemIcons.Error, licenseFailures[0].AlertText,
|
||||||
|
Messages.LICENSE_ERROR_TITLE),
|
||||||
|
ThreeButtonDialog.ButtonOK).ShowDialog(Program.MainWindow));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var failureDic = new Dictionary<SelectedItem, string>();
|
||||||
|
|
||||||
|
foreach (var f in licenseFailures)
|
||||||
|
{
|
||||||
|
failureDic.Add(new SelectedItem(f.Host), f.AlertText);
|
||||||
|
}
|
||||||
|
|
||||||
|
Program.Invoke(Program.MainWindow, () => new CommandErrorDialog(
|
||||||
|
Messages.LICENSE_ERROR_TITLE, exceptionMessage,
|
||||||
|
failureDic).ShowDialog(Program.MainWindow));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
XenAdmin/Commands/AttachVirtualDiskCommand.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAPI;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Dialogs;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the attach virtual disk dialog for the specified VM.
|
||||||
|
/// </summary>
|
||||||
|
internal class AttachVirtualDiskCommand : Command
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of this Command. The parameter-less constructor is required in the derived
|
||||||
|
/// class if it is to be attached to a ToolStrip menu item or button. It should not be used in any other scenario.
|
||||||
|
/// </summary>
|
||||||
|
public AttachVirtualDiskCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttachVirtualDiskCommand(IMainWindow mainWindow, IEnumerable<SelectedItem> selection)
|
||||||
|
: base(mainWindow, selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttachVirtualDiskCommand(IMainWindow mainWindow, VM vm)
|
||||||
|
: base(mainWindow, vm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
VM vm = (VM)selection[0].XenObject;
|
||||||
|
|
||||||
|
if (vm.VBDs.Count >= vm.MaxVBDsAllowed)
|
||||||
|
{
|
||||||
|
new ThreeButtonDialog(
|
||||||
|
new ThreeButtonDialog.Details(
|
||||||
|
SystemIcons.Error,
|
||||||
|
FriendlyErrorNames.VBDS_MAX_ALLOWED,
|
||||||
|
Messages.DISK_ATTACH)).ShowDialog(Program.MainWindow);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainWindowCommandInterface.ShowPerXenModelObjectWizard(vm, new AttachDiskDialog(vm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
if (selection.Count == 1)
|
||||||
|
{
|
||||||
|
VM vm = selection[0].XenObject as VM;
|
||||||
|
|
||||||
|
return vm != null && !vm.is_a_snapshot && !vm.Locked;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
XenAdmin/Commands/BackupHostCommand.cs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* Copyright (c) Citrix Systems Inc.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using XenAdmin.Network;
|
||||||
|
using XenAPI;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using XenAdmin.Actions;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
|
||||||
|
namespace XenAdmin.Commands
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Shows a SaveFileDialog for backing up the selected host and then runs the backup.
|
||||||
|
/// </summary>
|
||||||
|
internal class BackupHostCommand : Command
|
||||||
|
{
|
||||||
|
private readonly string _filename;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of this Command. The parameter-less constructor is required in the derived
|
||||||
|
/// class if it is to be attached to a ToolStrip menu item or button. It should not be used in any other scenario.
|
||||||
|
/// </summary>
|
||||||
|
public BackupHostCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupHostCommand(IMainWindow mainWindow, IEnumerable<SelectedItem> selection)
|
||||||
|
: base(mainWindow, selection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupHostCommand(IMainWindow mainWindow, Host host)
|
||||||
|
: base(mainWindow, host)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupHostCommand(IMainWindow mainWindow, Host host, string filename)
|
||||||
|
: base(mainWindow, host)
|
||||||
|
{
|
||||||
|
_filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
Host host = (Host)selection[0].XenObject;
|
||||||
|
|
||||||
|
if (_filename == null)
|
||||||
|
{
|
||||||
|
SaveFileDialog dialog = new SaveFileDialog();
|
||||||
|
dialog.AddExtension = true;
|
||||||
|
dialog.Filter = string.Format("{0} (*.xbk)|*.xbk|{1} (*.*)|*.*", Messages.XS_BACKUP_FILES, Messages.ALL_FILES);
|
||||||
|
dialog.FilterIndex = 0;
|
||||||
|
dialog.RestoreDirectory = true;
|
||||||
|
dialog.DefaultExt = "xbk";
|
||||||
|
|
||||||
|
if (dialog.ShowDialog(Parent) != DialogResult.Cancel)
|
||||||
|
{
|
||||||
|
MainWindowCommandInterface.AllowHistorySwitch();
|
||||||
|
new HostBackupRestoreAction(host, HostBackupRestoreAction.HostBackupRestoreType.backup, dialog.FileName).RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new HostBackupRestoreAction(host, HostBackupRestoreAction.HostBackupRestoreType.backup, _filename).RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanExecute(Host host)
|
||||||
|
{
|
||||||
|
return host != null && host.IsLive ;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CanExecuteCore(SelectedItemCollection selection)
|
||||||
|
{
|
||||||
|
return selection.ContainsOneItemOfType<Host>() && selection.AtLeastOneXenObjectCan<Host>(CanExecute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|