Merge branch 'master' of https://github.com/xenserver/xenadmin into development

# Conflicts:
#	Branding/Branding.resx
#	Branding/HomePage.mht
#	Branding/HomePage.zh-CN.mht
#	Branding/Images/000_XenCenterAlerts_h32bit_24.png
#	Branding/Images/DlgBmp.bmp
#	Branding/Images/XS.png
#	Branding/Images/about_box_graphic_423x79.png
#	Branding/Images/alerts_32.png
#	Branding/Images/splash.bmp
#	Branding/Images/upsell_16.png
#	Branding/Images/wizard_background.png
#	CFUValidator/CFUValidator.csproj
#	Jenkinsfile
#	LICENSE
#	MAINTAINERS
#	README.md
#	WixInstaller/XenCenter.wxs
#	WixInstaller/branding.wxi
#	WixInstaller/codepagechange.vbs
#	WixInstaller/en-us.wxl
#	WixInstaller/ja-jp.wxl
#	WixInstaller/wix_src.patch
#	WixInstaller/zh-cn.wxl
#	XenAdmin.sln
#	XenAdmin/Commands/Controls/ContextMenuBuilder.cs
#	XenAdmin/Commands/Controls/MigrateVMToolStripMenuItem.cs
#	XenAdmin/Commands/Controls/VMLifeCycleToolStripMenuItem.cs
#	XenAdmin/Commands/CopyTemplateCommand.cs
#	XenAdmin/Commands/CopyVMCommand.cs
#	XenAdmin/Commands/CrossPoolCopyVMCommand.cs
#	XenAdmin/Commands/CrossPoolMigrateCommand.cs
#	XenAdmin/Commands/CrossPoolMoveVMCommand.cs
#	XenAdmin/Commands/DragDropCrossPoolMoveHaltedVMCommand.cs
#	XenAdmin/Commands/DragDropMigrateVMCommand.cs
#	XenAdmin/Commands/MoveVMCommand.cs
#	XenAdmin/ConsoleView/VNCTabView.cs
#	XenAdmin/Core/Updates.cs
#	XenAdmin/Dialogs/AboutDialog.resx
#	XenAdmin/Dialogs/LegalNoticesDialog.cs
#	XenAdmin/Dialogs/WarningDialogs/LicenseWarningDialog.ja.resx
#	XenAdmin/Dialogs/WarningDialogs/LicenseWarningDialog.resx
#	XenAdmin/Dialogs/WarningDialogs/LicenseWarningDialog.zh-CN.resx
#	XenAdmin/Help/HelpManager.cs
#	XenAdmin/Images.cs
#	XenAdmin/MainWindow.Designer.cs
#	XenAdmin/MainWindow.cs
#	XenAdmin/MainWindow.ja.resx
#	XenAdmin/MainWindow.resx
#	XenAdmin/MainWindow.zh-CN.resx
#	XenAdmin/Properties/Resources.Designer.cs
#	XenAdmin/Properties/Settings.Designer.cs
#	XenAdmin/Properties/Settings.settings
#	XenAdmin/SettingsPanels/BootOptionsEditPage.cs
#	XenAdmin/TabPages/GeneralTabPage.Designer.cs
#	XenAdmin/TabPages/GeneralTabPage.cs
#	XenAdmin/TabPages/GeneralTabPage.resx
#	XenAdmin/VNC/VNCException.cs
#	XenAdmin/Wizards/CrossPoolMigrateWizard/CrossPoolMigrateDestinationPage.cs
#	XenAdmin/Wizards/CrossPoolMigrateWizard/CrossPoolMigrateWizard.cs
#	XenAdmin/Wizards/CrossPoolMigrateWizard/Filters/CrossPoolMigrateCanMigrateFilter.cs
#	XenAdmin/Wizards/NewNetworkWizard_Pages/NetWTypeSelect.cs
#	XenAdmin/Wizards/NewSRWizard.cs
#	XenAdmin/Wizards/NewSRWizard_Pages/Frontends/LVMoISCSI.cs
#	XenAdmin/XenAdmin.csproj
#	XenAdmin/app.config
#	XenAdminTests/ArchiveTests/ArchiveFactoryTests.cs
#	XenAdminTests/ArchiveTests/ArchiveIteratorTests.cs
#	XenAdminTests/ArchiveTests/ArchiveWriterTests.cs
#	XenAdminTests/ArchiveTests/ThirdPartyArchiveWriterTests.cs
#	XenAdminTests/CompressionTests/CompressionFactoryTests.cs
#	XenAdminTests/CompressionTests/ThirdPartyCompressionStreamTests.cs
#	XenAdminTests/HealthCheckTests/RequestUploadTaskTests.cs
#	XenAdminTests/UnitTests/CPUMaskingTest.cs
#	XenAdminTests/UnitTests/TimeUtilTests.cs
#	XenAdminTests/UnitTests/WlbTests/WlbPoolConfigurationTests.cs
#	XenAdminTests/UnitTests/WlbTests/WlbScheduledTaskTests.cs
#	XenAdminTests/UnitTests/WlbTests/WlbScheduledTasksTests.cs
#	XenAdminTests/XenAdminTests.csproj
#	XenModel/Actions/HealthCheck/GetHealthCheckAnalysisResultAction.cs
#	XenModel/Actions/HealthCheck/HealthCheckAuthenticationAction.cs
#	XenModel/Actions/HealthCheck/UploadServerStatusReportAction.cs
#	XenModel/Actions/HealthCheck/XenServerHealthCheckUpload.cs
#	XenModel/Actions/VM/ImportVmAction.cs
#	XenModel/Actions/VM/VMCrossPoolMigrateAction.cs
#	XenModel/Actions/VM/VMPauseAction.cs
#	XenModel/FriendlyNames.Designer.cs
#	XenModel/FriendlyNames.ja.resx
#	XenModel/FriendlyNames.resx
#	XenModel/FriendlyNames.zh-CN.resx
#	XenModel/HealthCheckSettings.cs
#	XenModel/InvisibleMessages.Designer.cs
#	XenModel/InvisibleMessages.ja.resx
#	XenModel/InvisibleMessages.resx
#	XenModel/InvisibleMessages.zh-CN.resx
#	XenModel/Messages.Designer.cs
#	XenModel/Messages.ja.resx
#	XenModel/Messages.resx
#	XenModel/Messages.zh-CN.resx
#	XenModel/SshConsole.cs
#	XenModel/Utils/Helpers.cs
#	XenModel/XenAPI-Extensions/SR.cs
#	XenModel/XenAPI/ApiVersion.cs
#	XenModel/XenModel.csproj
#	XenServerHealthCheck/Registry.cs
#	scripts/check_copyright.ps1
#	scripts/check_i18n.ps1
#	scripts/check_spelling.ps1
#	scripts/deps-map.json
#	scripts/dictionary.txt
#	scripts/download_hotfixes.ps1
#	scripts/download_packages.ps1
#	scripts/hotfix-map.json
#	splash/util.h
#	xe/Xe.csproj
#	xe/app.manifest
This commit is contained in:
Alexander Schulz 2023-12-30 16:42:53 +01:00
commit cd477a4e18
2637 changed files with 116215 additions and 220515 deletions

3
.gitignore vendored
View File

@ -27,6 +27,7 @@ Thumbs.db
packages/*
!packages/DOTNET_BUILD_LOCATION
Branding/Hotfixes/*
_ReSharper.*/
*.opensdf
@ -40,3 +41,5 @@ ServiceFabricBackup/
.vs
.vscode
vim.exe.stackdump

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +0,0 @@
/* -----------------------------------------------------------------------
File encoded as ISO-8859-1
Blueprint CSS Framework 1.0.1
http://blueprintcss.org
* Copyright (c) 2007-Present. See src/LICENSE for more info.
number of columns:24
column width:30
gutter width:10
total width:950
row height:18 px
----------------------------------------------------------------------- */
/* ie.css */
html {
overflow: auto;
}
body {
text-align: center;
}
.container {
text-align: left;
}
* html .column,
* html [class^="span-"],
* html [class*=" span- "] {
display: inline;
overflow-x: hidden;
}
img {
-ms-interpolation-mode: bicubic;
}
.clearfix, .container {
display: inline-block;
}
* html .clearfix, * html .container {
height: 1%;
}
/* fix opacity for tagline fonts */
p.cx-tagline span{
display: inline-block;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=69)"; /* IE 8 */
filter: alpha(opacity=69); /* IE 5-7 */
}

View File

@ -1,43 +0,0 @@
/* -----------------------------------------------------------------------
File encoded as ISO-8859-1
Blueprint CSS Framework 1.0.1
http://blueprintcss.org
* Copyright (c) 2007-Present. See src/LICENSE for more info.
number of columns:24
column width:30
gutter width:10
total width:950
row height:18 px
----------------------------------------------------------------------- */
/* print.css */
body {
line-height: 1.5;
font-family: citrixsans-regular, "Helvetica Neue", Arial, Helvetica, sans-serif;
color: #000;
background: none;
font-size: 10pt;
}
.container {
background: none;
}
a img {
border: none;
}
p img.top {
margin-top: 0;
}
.hide {
display: none;
}
a:link, a:visited {
background: transparent;
font-weight: 700;
text-decoration: underline;
}
a:link:after, a:visited:after {
content: " (" attr(href) ")";
font-size: 90%;
}

View File

@ -1,519 +0,0 @@
/* -----------------------------------------------------------------------
File encoded as ISO-8859-1
Blueprint CSS Framework 1.0.1
http://blueprintcss.org
* Copyright (c) 2007-Present. See src/LICENSE for more info.
number of columns:24
column width:30
gutter width:10
total width:950
row height:18 px
----------------------------------------------------------------------- */
/* reset.css */
html {
margin: 0;
padding: 0;
border: 0;
}
body, div, span, object, p, a, abbr, em, img, q, ol, ul, li {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
body {
line-height: 1.5;
background: #fff;
}
a img {
border: none;
}
:focus {
outline: 0;
}
/* typography.css */
html {
font-size: 100.01%;
}
body {
font-size: 75%;
color: #fff;
background: #fff;
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.left {
float: left !important;
}
p .left {
margin: 1.5em 1.5em 1.5em 0;
padding: 0;
}
.right {
float: right !important;
}
p .right {
margin: 1.5em 0 1.5em 1.5em;
padding: 0;
}
a:focus, a:hover {
color: #5F67B5;
}
a {
color: #5F67B5;
text-decoration: underline;
}
li ul, li ol {
margin: 0;
}
ul, ol {
margin: 0 1.5em 1.5em 0;
padding-left: 1.5em;
}
ul {
list-style-type: disc;
}
ol {
list-style-type: decimal;
}
.hide {
display: none;
}
.first {
margin-left: 0;
padding-left: 0;
}
.last {
margin-right: 0;
padding-right: 0;
}
.top {
margin-top: 0;
padding-top: 0;
}
.bottom {
margin-bottom: 0;
padding-bottom: 0;
}
/* grid.css */
.container {
width: 750px;
margin: 0 auto;
}
.showgrid {
background: url(../media/grid.png);
}
.column, [class^="span-"],
.column, [class*=" span- "] {
float: left;
margin-right: 10px;
}
.last {
margin-right: 0;
}
.span-1 {
width: 30px;
}
.span-2 {
width: 70px;
}
.span-3 {
width: 110px;
}
.span-4 {
width: 150px;
}
.span-5 {
width: 190px;
}
.span-6 {
width: 230px;
}
.span-7 {
width: 270px;
}
.span-8 {
width: 310px;
}
.span-9 {
width: 350px;
}
.span-10 {
width: 390px;
}
.span-11 {
width: 430px;
}
.span-12 {
width: 470px;
}
.span-13 {
width: 510px;
}
.span-14 {
width: 550px;
}
.span-15 {
width: 590px;
}
.span-16 {
width: 630px;
}
.span-17 {
width: 670px;
}
.span-18 {
width: 710px;
}
.span-19 {
width: 750px;
}
.span-20 {
width: 790px;
}
.span-21 {
width: 830px;
}
.span-22 {
width: 870px;
}
.span-23 {
width: 910px;
}
.span-24 {
width: 950px;
margin-right: 0;
}
.append-1 {
padding-right: 20px;
}
.append-2 {
padding-right: 80px;
}
.append-3 {
padding-right: 120px;
}
.append-4 {
padding-right: 160px;
}
.append-5 {
padding-right: 200px;
}
.append-6 {
padding-right: 240px;
}
.append-7 {
padding-right: 280px;
}
.append-8 {
padding-right: 320px;
}
.append-9 {
padding-right: 360px;
}
.append-10 {
padding-right: 400px;
}
.append-11 {
padding-right: 440px;
}
.append-12 {
padding-right: 480px;
}
.append-13 {
padding-right: 520px;
}
.append-14 {
padding-right: 560px;
}
.append-15 {
padding-right: 600px;
}
.append-16 {
padding-right: 640px;
}
.append-17 {
padding-right: 680px;
}
.append-18 {
padding-right: 720px;
}
.append-19 {
padding-right: 760px;
}
.append-20 {
padding-right: 800px;
}
.append-21 {
padding-right: 840px;
}
.append-22 {
padding-right: 880px;
}
.append-23 {
padding-right: 920px;
}
.prepend-1 {
padding-left: 40px;
}
.prepend-2 {
padding-left: 80px;
}
.prepend-3 {
padding-left: 120px;
}
.prepend-4 {
padding-left: 160px;
}
.prepend-5 {
padding-left: 200px;
}
.prepend-6 {
padding-left: 240px;
}
.prepend-7 {
padding-left: 280px;
}
.prepend-8 {
padding-left: 320px;
}
.prepend-9 {
padding-left: 360px;
}
.prepend-10 {
padding-left: 400px;
}
.prepend-11 {
padding-left: 440px;
}
.prepend-12 {
padding-left: 480px;
}
.prepend-13 {
padding-left: 520px;
}
.prepend-14 {
padding-left: 560px;
}
.prepend-15 {
padding-left: 600px;
}
.prepend-16 {
padding-left: 640px;
}
.prepend-17 {
padding-left: 680px;
}
.prepend-18 {
padding-left: 720px;
}
.prepend-19 {
padding-left: 760px;
}
.prepend-20 {
padding-left: 800px;
}
.prepend-21 {
padding-left: 840px;
}
.prepend-22 {
padding-left: 880px;
}
.prepend-23 {
padding-left: 920px;
}
.border {
padding-right: 4px;
margin-right: 5px;
border-right: 1px solid #ddd;
}
.colborder {
padding-right: 24px;
margin-right: 25px;
border-right: 1px solid #ddd;
}
.pull-1 {
margin-left: -40px;
}
.pull-2 {
margin-left: -80px;
}
.pull-3 {
margin-left: -120px;
}
.pull-4 {
margin-left: -160px;
}
.pull-5 {
margin-left: -200px;
}
.pull-6 {
margin-left: -240px;
}
.pull-7 {
margin-left: -280px;
}
.pull-8 {
margin-left: -320px;
}
.pull-9 {
margin-left: -360px;
}
.pull-10 {
margin-left: -400px;
}
.pull-11 {
margin-left: -440px;
}
.pull-12 {
margin-left: -480px;
}
.pull-13 {
margin-left: -520px;
}
.pull-14 {
margin-left: -560px;
}
.pull-15 {
margin-left: -600px;
}
.pull-16 {
margin-left: -640px;
}
.pull-17 {
margin-left: -680px;
}
.pull-18 {
margin-left: -720px;
}
.pull-19 {
margin-left: -760px;
}
.pull-20 {
margin-left: -800px;
}
.pull-21 {
margin-left: -840px;
}
.pull-22 {
margin-left: -880px;
}
.pull-23 {
margin-left: -920px;
}
.pull-24 {
margin-left: -960px;
}
[class^="pull-"],
[class*=" pull- "] {
float: left;
position: relative;
}
.push-1 {
margin: 0 -40px 1.5em 40px;
}
.push-2 {
margin: 0 -80px 1.5em 80px;
}
.push-3 {
margin: 0 -120px 1.5em 120px;
}
.push-4 {
margin: 0 -160px 1.5em 160px;
}
.push-5 {
margin: 0 -200px 1.5em 200px;
}
.push-6 {
margin: 0 -240px 1.5em 240px;
}
.push-7 {
margin: 0 -280px 1.5em 280px;
}
.push-8 {
margin: 0 -320px 1.5em 320px;
}
.push-9 {
margin: 0 -360px 1.5em 360px;
}
.push-10 {
margin: 0 -400px 1.5em 400px;
}
.push-11 {
margin: 0 -440px 1.5em 440px;
}
.push-12 {
margin: 0 -480px 1.5em 480px;
}
.push-13 {
margin: 0 -520px 1.5em 520px;
}
.push-14 {
margin: 0 -560px 1.5em 560px;
}
.push-15 {
margin: 0 -600px 1.5em 600px;
}
.push-16 {
margin: 0 -640px 1.5em 640px;
}
.push-17 {
margin: 0 -680px 1.5em 680px;
}
.push-18 {
margin: 0 -720px 1.5em 720px;
}
.push-19 {
margin: 0 -760px 1.5em 760px;
}
.push-20 {
margin: 0 -800px 1.5em 800px;
}
.push-21 {
margin: 0 -840px 1.5em 840px;
}
.push-22 {
margin: 0 -880px 1.5em 880px;
}
.push-23 {
margin: 0 -920px 1.5em 920px;
}
.push-24 {
margin: 0 -960px 1.5em 960px;
}
[class^="push-"],
[class*=" push- "] {
float: left;
position: relative;
}
div.prepend-top, .prepend-top {
margin-top: 1.5em;
}
div.append-bottom, .append-bottom {
margin-bottom: 1.5em;
}
.box {
padding: 1.5em;
margin-bottom: 1.5em;
background: #e5eCf9;
}
.clearfix:after, .container:after {
content: "\0020";
display: block;
height: 0;
clear: both;
visibility: hidden;
overflow: hidden;
}
.clearfix, .container {
display: block;
}
.clear {
clear: both;
}

View File

@ -1,134 +0,0 @@
/* Top Hero Section */
.cx-hero-top,
.cx-hero-top-bg {
background: #5F67B5;
height: 310px;
}
.cx-hero-top-bg {
position: absolute;
left: 0;
right: 0;
z-index: -1;
}
.cx-hero-top {
color: #fff;
}
/* top hero columns */
.cx-hero-top .inner .column {
height: 165px;
}
.cx-hero-top .inner .column.left {
padding-top: 36px;
padding-bottom: 42px;
}
.cx-hero-top .inner .column.right {
width: 127px;
height: 165px;
line-height: 165px;
text-align: center;
margin-top: 65px;
}
.cx-hero-top .inner .column.right img#cloudServerGraphic {
width: 129px;
height: 165px;
}
.cx-hero-top .inner .column.left img#logo-citrixHypervisor {
display: block;
width: 216px;
height: 31px;
margin-bottom: 10px;
}
p.cx-tagline {
font: 16px/1.3 "Helvetica Neue", Arial, Helvetica, sans-serif;
color: rgba(256, 256, 256, 0.69);
letter-spacing: 0.02em;
margin-bottom: 32px!important;
font-weight: 300;
}
/* call out list */
ul.cx-callouts-list {
font: 14px/1.3 "Helvetica Neue", Arial, Helvetica, sans-serif;
font-weight:300;
letter-spacing: 0.02em;
margin: 0;
list-style: none;
}
ul.cx-callouts-list li.cx-doc-icon{
display: block;
height: 21px;
line-height: 21px;
margin-bottom: 10px;
margin-left: -17px;
padding-left: 32px;
background: transparent url(../media/icons/cx-icon-generic-doc.png) no-repeat 0 50%;
}
ul.cx-callouts-list li.cx-doc-icon.last{
margin-bottom: 0;
}
/* start callout links */
ul.cx-callouts-list li.cx-doc-icon a.cx-link {
color: #fff;
text-decoration: none;
}
ul.cx-callouts-list li.cx-doc-icon a.cx-link:hover {
text-decoration: underline;
}
ul.cx-callouts-list li.cx-doc-icon ul.cx-link-list{
list-style-type: square;
list-style-position: inside;
padding: 0 0 0 0;
margin: 5px 0 0 0;
line-height: 1.5;
}
/* end callout links */
/* Bottom Hero Section */
.cx-hero-bottom {
margin:34px 0 0 0;
padding-bottom: 0px;
text-align: center;
}
/* cards */
.cx-hero-bottom .cx-cards {
height: 198px;
width: 200px;
margin-right: 20px;
}
.cx-hero-bottom .cx-cards:hover {
background-color: #f2f2f2;
cursor: pointer;
border-radius: 4px;
}
.cx-hero-bottom .cx-cards.last {
margin-right: 0;
}
.cx-hero-bottom .cx-cards p {
padding-top: 35px;
color: #5F67B5;
font: 14px/1.3 "Helvetica Neue", Arial, Helvetica, sans-serif;
font-weight: 500;
letter-spacing: 0.02em;
}
/* card icons */
.cx-cards img {
margin-top: 37px;
margin-left: auto;
margin-right: auto;
display: block;
}
img#addServer {
width: 55px;
height: 66px;
}
img#purchaseSupport {
width: 57px;
height: 65px;
}
img#deskTopVirt {
width: 86px;
height: 66px;
}

View File

@ -1,69 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Citrix Hypervisor</title>
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/theme.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/print.css" type="text/css" media="print">
</head>
<body>
<div class="cx-hero-top-bg">
</div>
<div class="container">
<div class="span-18 top cx-hero-top">
<div class="span-16 prepend-1 append-0 inner last">
<div class="column left span-12 first">
<img id="logo-citrixHypervisor" src="media/logos/cx-logo-citrixHypervisor.png" alt="Citrix Hypervisor Logo"/>
<p class="cx-tagline" title="Industry leading open source platform for cloud server and desktop virtualization">
<span>Industry leading open source platform for cloud server<br> and desktop virtualization</span>
</p>
<ul class="cx-callouts-list">
<li class="cx-doc-icon" title="Learn about using XenCenter">
<a href="xencenter://HelpContents" class="cx-link">Learn about using XenCenter</a>
</li>
<li class="cx-doc-icon" title="Network with other Citrix Hypervisor users">
<a href="https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver/" class="cx-link">Network with other Citrix Hypervisor users</a>
</li>
<li class="cx-doc-icon last" title="Community Support Partners">
<a href="https://www.citrix.com/support" class="cx-link">Visit the Citrix Knowledge Center</a>
</li>
</ul>
</div>
<div class="column right span-6 last">
<img id="cloudServerGraphic" src="media/icons/cx-cloudServerGraphic.png" alt="Cloud Server Graphic">
</div>
</div>
</div>
<div class="span-18 cx-hero-bottom clearfix">
<div class="column prepend-1 clearfix">
<div class="span-6 cx-cards" title="Add a Server">
<a class="cx-link" href="xencenter://AddServer">
<img id="addServer" src="media/icons/cx-icon-addServer.png" alt="Add a Server">
<p>Add a Server</p>
</a>
</div>
<div class="span-6 cx-cards" title="Purchase Support">
<a class="cx-link" href="http://www.citrix.com/xenserver/le/features">
<img id="purchaseSupport" src="media/icons/cx-icon-purchaseSupport.png" alt="Purchase Support">
<p>Purchase Support</p>
</a>
</div>
<div class="span-6 cx-cards last" title="Try Desktop Virtualization">
<a class="cx-link" href="http://www.citrix.com/TryXenDesktop">
<img id="deskTopVirt" src="media/icons/cx-icon-tryVirtualization.png" alt="Try Desktop Virtualization">
<p>Try Desktop Virtualization</p>
</a>
</div>
</div>
</div>
</div>
<img src="media/icons/cx-icon-generic-doc.png" height="0" width="0">
</body>
</html>

View File

@ -1,69 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Citrix Hypervisor</title>
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/theme.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/print.css" type="text/css" media="print">
</head>
<body>
<div class="cx-hero-top-bg">
</div>
<div class="container">
<div class="span-18 top cx-hero-top">
<div class="span-16 prepend-1 append-0 inner last">
<div class="column left span-12 first">
<img id="logo-citrixHypervisor" src="media/logos/cx-logo-citrixHypervisor.png" alt="Citrix Hypervisor Logo">
<p class="cx-tagline" title="業界で高く評価されているクラウド、サーバー、デスクトップの仮想化プラットフォームです。">
<span>業界で高く評価されているクラウド サーバー<br>およびデスクトップの仮想化プラットフォームです。</span>
</p>
<ul class="cx-callouts-list">
<li class="cx-doc-icon" title="XenCenter の使用について">
<a href="xencenter://HelpContents" class="cx-link">XenCenter の使用について</a>
</li>
<li class="cx-doc-icon" title="Citrix Hypervisor ユーザー ネットワーク">
<a href="https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver/" class="cx-link">Citrix Hypervisor ユーザー ネットワーク</a>
</li>
<li class="cx-doc-icon last" title="製品情報、コミュニティ、サポート、対応製品">
<a href="https://www.citrix.com/support" class="cx-link">Citrix Knowledge Center の参照</a>
</li>
</ul>
</div>
<div class="column right span-6 last">
<img id="cloudServerGraphic" src="media/icons/cx-cloudServerGraphic.png" alt="クラウド サーバーのグラフィック">
</div>
</div>
</div>
<div class="span-18 cx-hero-bottom clearfix">
<div class="column prepend-1 clearfix">
<div class="span-6 cx-cards" title="サーバーの追加">
<a class="cx-link" href="xencenter://AddServer">
<img id="addServer" src="media/icons/cx-icon-addServer.png" alt="サーバーの追加">
<p>サーバーの追加</p>
</a>
</div>
<div title="購入サポート" class="span-6 cx-cards">
<a class="cx-link" href="http://www.citrix.com/xenserver/le/features">
<img id="purchaseSupport" src="media/icons/cx-icon-purchaseSupport.png" alt="購入サポート">
<p>購入サポート</p>
</a>
</div>
<div class="span-6 cx-cards last" title="デスクトップの仮想化の試行">
<a class="cx-link" href="http://www.citrix.com/TryXenDesktop">
<img id="deskTopVirt" src="media/icons/cx-icon-tryVirtualization.png" alt="デスクトップの仮想化の試行">
<p>デスクトップの仮想化の試行</p>
</a>
</div>
</div>
</div>
</div>
<img src="media/icons/cx-icon-generic-doc.png" height="0" width="0">
</body>
</html>

View File

@ -1,69 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Citrix Hypervisor</title>
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/theme.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/print.css" type="text/css" media="print">
</head>
<body>
<div class="cx-hero-top-bg">
</div>
<div class="container">
<div class="span-18 top cx-hero-top">
<div class="span-16 prepend-1 append-0 inner last">
<div class="column left span-12 first">
<img id="logo-citrixHypervisor" src="media/logos/cx-logo-citrixHypervisor.png" alt="Citrix Hypervisor Logo"/>
<p class="cx-tagline" title="业界领先的开源平台,用于实现云服务器和桌面虚拟化">
<span>业界领先的面向云服务器和桌面虚拟化的<br>开源平台</span>
</p>
<ul class="cx-callouts-list">
<li class="cx-doc-icon" title="了解如何使用 XenCenter">
<a href="xencenter://HelpContents" class="cx-link">了解如何使用 XenCenter</a>
</li>
<li class="cx-doc-icon" title="与其他 Citrix Hypervisor 用户联网">
<a href="https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver/" class="cx-link">与其他 Citrix Hypervisor 用户联网</a>
</li>
<li class="cx-doc-icon last" title="社区支持合作伙伴">
<a href="https://www.citrix.com/support" class="cx-link">访问 Citrix 知识中心</a>
</li>
</ul>
</div>
<div class="column right span-6 last">
<img id="cloudServerGraphic" src="media/icons/cx-cloudServerGraphic.png" alt="云服务器图形">
</div>
</div>
</div>
<div class="span-18 cx-hero-bottom clearfix">
<div class="column prepend-1 clearfix">
<div class="span-6 cx-cards" title="添加服务器">
<a class="cx-link" href="xencenter://AddServer">
<img id="addServer" alt="添加服务器" src="media/icons/cx-icon-addServer.png">
<p>添加服务器</p>
</a>
</div>
<div class="span-6 cx-cards" title="购买支持">
<a class="cx-link" href="http://www.citrix.com/xenserver/le/features">
<img id="purchaseSupport" src="media/icons/cx-icon-purchaseSupport.png" alt="购买支持">
<p>购买支持</p>
</a>
</div>
<div class="span-6 cx-cards last" title="试用桌面虚拟化">
<a class="cx-link" href="http://www.citrix.com/TryXenDesktop">
<img id="deskTopVirt" src="media/icons/cx-icon-tryVirtualization.png" alt="试用桌面虚拟化">
<p>试用桌面虚拟化</p>
</a>
</div>
</div>
</div>
</div>
<img src="media/icons/cx-icon-generic-doc.png" height="0" width="0">
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 B

0
Branding/Images/wizard_background.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,67 +0,0 @@
#!/bin/sh
# 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.
#==============================================================
#Micro version override - please keep at the top of the script
#==============================================================
#Set and uncomment this to override the 3rd value of the product number
#normally fetched from branding
#
#PRODUCT_MICRO_VERSION_OVERRIDE=<My override value here>
# bring versions from the server branding repo
ROOT="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
TOPLEVEL_VERSIONS=${ROOT}/branding.git/xenserver/toplevel-versions
TOPLEVEL_BRANDING=${ROOT}/branding.git/xenserver/toplevel-branding
BRANDING_COMPANY_NAME_LEGAL=$(cat ${TOPLEVEL_BRANDING} | grep -F "COMPANY_NAME_LEGAL := " | sed -e 's/COMPANY_NAME_LEGAL := //g')
BRANDING_COMPANY_NAME_SHORT=$(cat ${TOPLEVEL_BRANDING} | grep -F "COMPANY_NAME_SHORT := " | sed -e 's/COMPANY_NAME_SHORT := //g')
BRANDING_PRODUCT_BRAND=$(cat ${TOPLEVEL_BRANDING} | grep "^PRODUCT_BRAND := " | sed -e 's/PRODUCT_BRAND := //g')
BRANDING_COMPANY_URL=www.$(cat ${TOPLEVEL_BRANDING} | grep -F "COMPANY_DOMAIN := " | sed -e 's/COMPANY_DOMAIN := //g')
BRANDING_PRODUCT_VERSION_TEXT=$(cat ${TOPLEVEL_VERSIONS} | grep -F "PRODUCT_VERSION_TEXT := " | sed -e 's/PRODUCT_VERSION_TEXT := //g')
BRANDING_PRODUCT_MAJOR_VERSION=$(cat ${TOPLEVEL_VERSIONS} | grep -F "PRODUCT_MAJOR_VERSION := " | sed -e 's/PRODUCT_MAJOR_VERSION := //g')
BRANDING_PRODUCT_MINOR_VERSION=$(cat ${TOPLEVEL_VERSIONS} | grep -F "PRODUCT_MINOR_VERSION := " | sed -e 's/PRODUCT_MINOR_VERSION := //g')
BRANDING_SERVER=${BRANDING_PRODUCT_BRAND}
BRANDING_COMPANY_AND_PRODUCT=${BRANDING_PRODUCT_BRAND}
BRANDING_BRAND_CONSOLE=$(cat ${TOPLEVEL_BRANDING} | grep -F "BRAND_CONSOLE := " | sed -e 's/BRAND_CONSOLE := //g')
BRANDING_PV_TOOLS=${BRANDING_COMPANY_NAME_SHORT}\ VM\ Tools
# Check for the micro version override and use it if present otherwise use the one from branding
if [ -n "${PRODUCT_MICRO_VERSION_OVERRIDE+x}" ]; then
BRANDING_PRODUCT_MICRO_VERSION=${PRODUCT_MICRO_VERSION_OVERRIDE}
echo Using override for micro product number of: ${BRANDING_PRODUCT_MICRO_VERSION}
else
BRANDING_PRODUCT_MICRO_VERSION=$(cat ${TOPLEVEL_VERSIONS} | grep -F "PRODUCT_MICRO_VERSION := " | sed -e 's/PRODUCT_MICRO_VERSION := //g')
fi
BRANDING_XC_PRODUCT_VERSION=${BRANDING_PRODUCT_MAJOR_VERSION}.${BRANDING_PRODUCT_MINOR_VERSION}.${BRANDING_PRODUCT_MICRO_VERSION}

View File

@ -1,292 +0,0 @@
/* 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...";
var xcupdateAlerts = XenAdmin.Core.Updates.NewXenCenterUpdateAlerts(xenCenterVersions, new Version(ServerVersion));
Status = "Determining XenServer update required...";
var updateAlerts = XenAdmin.Core.Updates.NewXenServerVersionAlerts(xenServerVersions).Where(alert => !alert.CanIgnore).ToList();
HfxEligibilityValidator hfxEligibilityValidator = new HfxEligibilityValidator(xenServerVersions);
Status = "Running hotfix eligibility check...";
RunHfxEligibilityValidator(hfxEligibilityValidator);
Status = "Determining patches required...";
var patchAlerts = XenAdmin.Core.Updates.NewXenServerPatchAlerts(xenServerVersions, xenServerPatches).Where(alert => !alert.CanIgnore).ToList();
//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, hfxEligibilityValidator, updateAlerts, xcupdateAlerts);
}
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 RunHfxEligibilityValidator(HfxEligibilityValidator validator)
{
validator.Validate();
Status = "Hotfix Eligibility Validator check complete";
}
private void validator_StatusChanged(object sender, EventArgs e)
{
Status = sender as string;
}
private void GeneratePatchSummary(List<XenServerPatchAlert> alerts, List<AlertFeatureValidator> validators, HfxEligibilityValidator hfxEligibilityValidator,
List<XenServerVersionAlert> updateAlerts, List<XenCenterUpdateAlert> xcupdateAlerts)
{
OuputComponent oc = new OutputTextOuputComponent(XmlLocation, ServerVersion);
XenCenterUpdateDecorator xcud = new XenCenterUpdateDecorator(oc, xcupdateAlerts);
XenServerUpdateDecorator xsud = new XenServerUpdateDecorator(xcud, updateAlerts);
HfxEligibilityValidatorDecorator hevd = new HfxEligibilityValidatorDecorator(xsud, hfxEligibilityValidator, "Hotfix eligibility check:");
PatchAlertDecorator pad = new PatchAlertDecorator(hevd, 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);
pool.Setup(p => p.other_config).Returns(new Dictionary<string, string>());
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);
mom.MockConnectionFor(id).Setup(c => c.IsConnected).Returns(true);
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;
}
}
}

View File

@ -1,159 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" 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>v4.6</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>
<TargetFrameworkProfile />
</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>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Core.4.2.1\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.8.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.8.2\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<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\HfxEligibilityValidatorDecorator.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\HfxEligibilityValidator.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>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</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>

View File

@ -1,131 +0,0 @@
/* 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();
}
}
}
}

View File

@ -1,63 +0,0 @@
/* 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; }
}
}

View File

@ -1,72 +0,0 @@
/* 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;
}
}
}
}
}

View File

@ -1,85 +0,0 @@
/* 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){}
}
}
}

View File

@ -1,60 +0,0 @@
/* 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);
}
}
}

View File

@ -1,53 +0,0 @@
/* 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();
}
}
}

View File

@ -1,60 +0,0 @@
/* 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 HfxEligibilityValidatorDecorator : Decorator
{
private readonly string header;
private readonly HfxEligibilityValidator validator;
public HfxEligibilityValidatorDecorator(OuputComponent ouputComponent, HfxEligibilityValidator 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);
}
}
}

View File

@ -1,66 +0,0 @@
/* 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; }
}
}
}

View File

@ -1,80 +0,0 @@
/* 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));
}
}
}
}

View File

@ -1,62 +0,0 @@
/* 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;
namespace CFUValidator.OutputDecorators
{
class XenCenterUpdateDecorator: Decorator
{
private readonly List<XenCenterUpdateAlert> alerts;
private const string header = "XenCenter updates required:";
private const string updateNotFound = "XenCenter update could not be found";
public XenCenterUpdateDecorator(OuputComponent ouputComponent, List<XenCenterUpdateAlert> alerts)
{
SetComponent(ouputComponent);
this.alerts = alerts;
}
public override StringBuilder Generate()
{
StringBuilder sb = base.Generate();
sb.AppendLine(header);
foreach (XenCenterUpdateAlert alert in alerts)
{
sb.AppendLine(alert == null ? updateNotFound : alert.NewVersion.VersionAndLang);
}
return sb.AppendLine(String.Empty);
}
}
}

View File

@ -1,63 +0,0 @@
/* 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 List<XenServerVersionAlert> alerts;
private const string header = "XenServer updates required:";
private const string updateNotFound = "XenServer update could not be found";
public XenServerUpdateDecorator(OuputComponent ouputComponent, List<XenServerVersionAlert> alerts)
{
SetComponent(ouputComponent);
this.alerts = alerts;
}
public override StringBuilder Generate()
{
StringBuilder sb = base.Generate();
sb.AppendLine(header);
foreach (XenServerVersionAlert alert in alerts)
{
sb.AppendLine(alert == null ? updateNotFound : alert.Version.Name);
}
return sb.AppendLine(String.Empty);
}
}
}

View File

@ -1,88 +0,0 @@
/* 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);
}
}
}

View File

@ -1,67 +0,0 @@
/* 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("[Citrix]")]
[assembly: AssemblyProduct("[XenCenter]")]
[assembly: AssemblyCopyright("Copyright © [BRANDING_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("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")]

View File

@ -1,81 +0,0 @@
/* 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)
: base(true, true, true, "CFU", "1", 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; }
}
}

View File

@ -1,48 +0,0 @@
/* 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; }
}
}

View File

@ -1,74 +0,0 @@
/* 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();
}
}
}
}

View File

@ -1,72 +0,0 @@
/* 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"; }
}
}
}

View File

@ -1,72 +0,0 @@
/* 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;
using XenAdmin.Core;
namespace CFUValidator.Validators
{
class HfxEligibilityValidator
{
private List<XenServerVersion> xsversions;
public List<string> Results { get; set; }
public HfxEligibilityValidator(List<XenServerVersion> xsversions)
{
this.xsversions = xsversions;
Results = new List<string>();
}
public void Validate()
{
foreach (XenServerVersion version in xsversions)
{
DateSanityCheck(version);
}
}
private void DateSanityCheck(XenServerVersion version)
{
if (version.HotfixEligibility == hotfix_eligibility.none && version.EolDate == DateTime.MinValue)
Results.Add("Missing or wrong eol-date field on: " + version.Name);
if (version.HotfixEligibility == hotfix_eligibility.premium && version.HotfixEligibilityPremiumDate == DateTime.MinValue)
Results.Add("Missing or wrong hotfix-eligibility-premium-date field on: " + version.Name);
if (version.HotfixEligibility == hotfix_eligibility.cu && version.HotfixEligibilityNoneDate == DateTime.MinValue)
Results.Add("Missing or wrong hotfix-eligibility-none-date field on: " + version.Name);
if (version.HotfixEligibility == hotfix_eligibility.cu && version.HotfixEligibilityPremiumDate == DateTime.MinValue)
Results.Add("Missing or wrong hotfix-eligibility-premium-date field on: " + version.Name);
}
public bool ErrorsFound { get { return Results.Count > 0; } }
}
}

View File

@ -1,104 +0,0 @@
/* 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"; }
}
}
}

View File

@ -1,101 +0,0 @@
/* 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;
using XenAdmin.Actions;
using XenAdmin.Alerts;
using XenAdmin.Core;
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, false, BrandManager.ExtensionUpdate, InvisibleMessages.ISO_UPDATE);
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);
}
}
}
}

View File

@ -1,3 +0,0 @@
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>

View File

@ -36,4 +36,4 @@ If you are unsure about something written here, ask on the XCP-ng forum https://
----------------------------------------------------------------------------
For a list of maintainers, please see MAINTAINERS file.
For a list of maintainers, please see [MAINTAINERS](./MAINTAINERS.md) file.

39
CREDITS.md Normal file
View File

@ -0,0 +1,39 @@
XenCenter Alumni
================
* Aaron Robson
* Adrian Jachacy
* Barbara Li
* Brian Donegan
* Callum McIntyre
* Carmen Agimof
* Cheng Zhang
* Chris Harding
* Daniel Lamping
* Darren Matthews
* Deane Smith
* Ewan Mellor
* Frederico Mazzone
* Gabor Apati-Nagy
* Henry Hughes
* Hugh Warrington
* Hui Zhang
* Javier Alvarez-Valle
* Jisheng Xing
* John Naab
* Johnni Aguirre
* Julie Allen
* Katherine Shann
* Kun Ma
* Letsibogo Ramadi
* Michael Zhao
* Mihaela Stoica
* Milind Padhye
* Rabin Karki
* Sarah Vallieres
* Seren Corbett
* Stephen Rice
* Stephen Turner
* Tom Wilkie
* Usha Mandya
* Victor Rodriguez

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="17.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CommandLib</RootNamespace>
<AssemblyName>CommandLib</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -42,10 +42,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="export.cs" />
<Compile Include="io.cs" />
<Compile Include="tar.cs" />
<Compile Include="thinCLIProtocol.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XXHash.cs" />
</ItemGroup>

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,20 +29,15 @@
*/
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: AssemblyDescription("[XenCenter] library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("[Citrix]")]
[assembly: AssemblyProduct("[XenCenter]")]
[assembly: AssemblyCopyright("Copyright © [BRANDING_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
@ -52,13 +46,3 @@ using System.Runtime.InteropServices;
// 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")]

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -37,199 +36,225 @@ using System.Text;
using System.Security.Cryptography;
using YYProject.XXHash;
/* Thrown if we fail to verify a block (ie sha1) checksum */
public class BlockChecksumFailed : ApplicationException
namespace CommandLib
{
private string block;
private string recomputed;
private string original;
public BlockChecksumFailed(string block, string recomputed, string original)
/// <summary>
/// Thrown if we fail to verify a block (ie sha1) checksum
/// </summary>
public class BlockChecksumFailed : ApplicationException
{
this.block = block;
this.recomputed = recomputed;
this.original = original;
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 override string ToString()
public class Export
{
return "Failed to verify the block checksum: block = " + block + "; recomputed = " + recomputed + "; original = " + original;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("csharpsquid",
"S4790:Using weak hashing algorithms is security-sensitive",
Justification = "Used only for checksum verification for backwards compatibility.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("csharpsquid",
"S2070:SHA-1 and Message-Digest hash algorithms should not be used in secure contexts",
Justification = "Used only for checksum verification for backwards compatibility.")]
private readonly SHA1 _sha1 = new SHA1CryptoServiceProvider();
private readonly XXHash64 _xxHash = new XXHash64();
private readonly bool _quiet;
public Export(bool quiet = false)
{
_quiet = quiet;
}
private void Debug(string x)
{
if (_quiet)
return;
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 XXHash64 xxhash = new XXHash64();
private string checksum_sha1(byte[] data)
{
byte[] result = sha.ComputeHash(data);
return hex(result).ToLower();
}
private string hex(byte[] bytes)
{
char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] output = new char[bytes.Length * 2];
for(uint i = 0; i < bytes.Length; i++)
{
uint b = (uint) bytes[i];
output[i * 2] = chars[b >> 4];
output[i * 2 + 1] = chars[b & 0x0F];
}
return new string(output);
}
private string checksum_xxhash(byte[] data)
{
xxhash.Initialize();
return hex(xxhash.ComputeHash(data));
}
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)
private string checksum_sha1(byte[] data)
{
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);
}
private Header nextHeader(Stream input, Stream output, verifyCallback callback)
{ // Interperate the next bytes from the stream as a Tar header
byte[] bytes = nextData(input, output, callback, Header.length);
if (Header.all_zeroes(bytes)) // Tar headers are 512-byte blocks in size
{
bytes = nextData(input, output, callback, Header.length);
if (Header.all_zeroes(bytes))
{
// Tars end with an End-Of-Archive marker, which is two consecutive 512-byte blocks of zero bytes
throw new EndOfArchive();
}
byte[] result = _sha1.ComputeHash(data);
return hex(result).ToLower();
}
return new Header(bytes);
}
private byte[] nextData(Stream input, Stream output, verifyCallback callback, uint size)
{ // Returns the next given number of bytes from the input
byte[] bytes = IO.unmarshal_n(input, size);
callback?.Invoke(size);
if (output != null) output.Write(bytes, 0, bytes.Length);
return bytes;
}
public void verify(Stream input, Stream output, cancellingCallback cancelling, verifyCallback callback)
{
Hashtable recomputed_checksums = new Hashtable();
Hashtable original_checksums = null;
try
private string hex(byte[] bytes)
{
while (!cancelling())
char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] output = new char[bytes.Length * 2];
for (uint i = 0; i < bytes.Length; i++)
{
Header header_data = nextHeader(input, output, callback);
debug(header_data.ToString());
uint b = (uint)bytes[i];
output[i * 2] = chars[b >> 4];
output[i * 2 + 1] = chars[b & 0x0F];
}
byte[] bytes_data = nextData(input, output, callback, header_data.file_size);
return new string(output);
}
if (header_data.file_name.Equals("ova.xml"))
private string checksum_xxhash(byte[] data)
{
_xxHash.Initialize();
return hex(_xxHash.ComputeHash(data));
}
private 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)
{
debug("Skipping ova.xml");
XmlNode v = child.FirstChild;
if (child.Name.Equals("name"))
name = v.Value;
if (child.Name.Equals("value"))
value = v.Value;
}
else if (header_data.file_name.EndsWith("checksum.xml"))
Debug(String.Format("adding {0} = {1}", name, value));
table.Add(name, value);
}
return table;
}
private 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))
{
string xml = string_of_byte_array(bytes_data);
original_checksums = parse_checksum_table(xml);
throw new BlockChecksumFailed((string)x.Key, ours, theirs);
}
else
{ // The file has no extension (must be a data file) so will have a .checksum or .xxhash file right after it
Header header_checksum = nextHeader(input, output, callback);
byte[] bytes_checksum = nextData(input, output, callback, header_checksum.file_size);
string csum_compare = string_of_byte_array(bytes_checksum);
string csum = header_checksum.file_name.EndsWith(".xxhash") ? checksum_xxhash(bytes_data) : checksum_sha1(bytes_data);
if (!csum.Equals(csum_compare))
throw new BlockChecksumFailed(header_data.file_name, csum, csum_compare);
debug(String.Format(" has checksum: {0}", csum));
recomputed_checksums.Add(header_data.file_name, csum);
nextData(input, output, callback, header_checksum.paddingLength()); // Eat the padding for the checksum file
{
Debug(String.Format("{0} hash OK", (string)x.Key));
}
nextData(input, output, callback, header_data.paddingLength()); // Eat the padding for the data file
}
}
catch (EndOfArchive)
private static string string_of_byte_array(byte[] payload)
{
debug("EOF");
if (original_checksums != null)
compare_tables(recomputed_checksums, original_checksums);
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);
}
/// <summary>
/// 'input' is the source of the export data, if 'output' is not null then
/// a perfect copy should be echoed there.
/// </summary>
public void verify(Stream input, Stream output, Func<bool> cancelling)
{
verify(input, output, cancelling, null);
}
private Header nextHeader(Stream input, Stream output, Action<uint> callback)
{
// Interperate the next bytes from the stream as a Tar header
byte[] bytes = nextData(input, output, callback, Header.length);
if (Header.all_zeroes(bytes)) // Tar headers are 512-byte blocks in size
{
bytes = nextData(input, output, callback, Header.length);
if (Header.all_zeroes(bytes))
{
// Tars end with an End-Of-Archive marker, which is two consecutive 512-byte blocks of zero bytes
throw new EndOfArchive();
}
}
return new Header(bytes);
}
private byte[] nextData(Stream input, Stream output, Action<uint> callback, uint size)
{
// Returns the next given number of bytes from the input
byte[] bytes = IO.unmarshal_n(input, size);
callback?.Invoke(size);
if (output != null) output.Write(bytes, 0, bytes.Length);
return bytes;
}
public void verify(Stream input, Stream output, Func<bool> cancelling, Action<uint> callback)
{
Hashtable recomputed_checksums = new Hashtable();
Hashtable original_checksums = null;
try
{
while (!cancelling())
{
Header header_data = nextHeader(input, output, callback);
Debug(header_data.ToString());
byte[] bytes_data = nextData(input, output, callback, header_data.file_size);
if (header_data.file_name.Equals("ova.xml"))
{
Debug("Skipping ova.xml");
}
else if (header_data.file_name.EndsWith("checksum.xml"))
{
string xml = string_of_byte_array(bytes_data);
original_checksums = parse_checksum_table(xml);
}
else
{
// The file has no extension (must be a data file) so will have a .checksum or .xxhash file right after it
Header header_checksum = nextHeader(input, output, callback);
byte[] bytes_checksum = nextData(input, output, callback, header_checksum.file_size);
string csum_compare = string_of_byte_array(bytes_checksum);
string csum = header_checksum.file_name.EndsWith(".xxhash") ? checksum_xxhash(bytes_data) : checksum_sha1(bytes_data);
if (!csum.Equals(csum_compare))
throw new BlockChecksumFailed(header_data.file_name, csum, csum_compare);
Debug(String.Format(" has checksum: {0}", csum));
recomputed_checksums.Add(header_data.file_name, csum);
nextData(input, output, callback, header_checksum.paddingLength()); // Eat the padding for the checksum file
}
nextData(input, output, callback, header_data.paddingLength()); // Eat the padding for the data file
}
}
catch (EndOfArchive)
{
Debug("EOF");
if (original_checksums != null)
compare_tables(recomputed_checksums, original_checksums);
}
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,40 +29,33 @@
*/
using System;
using System.Collections.Generic;
using System.Collections;
using System.Net;
using System.IO;
public class IO{
namespace CommandLib
{
public class IO
{
private 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));
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;
}
}
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 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;
}
}
}

View File

@ -1,215 +1,232 @@
/* 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");
}
}
}
/* Copyright (c) Cloud Software Group, Inc.
*
* 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 CommandLib
{
/// <summary>
/// Thrown if we fail to verify a tar header checksum
/// </summary>
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;
}
}
/// <summary>
/// Thrown when we find the end of archive marker (two zero blocks)
/// </summary>
class EndOfArchive : ApplicationException
{
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;
/// <summary>
/// True if a buffer contains all zeroes
/// </summary>
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;
}
/// <summary>
/// Return a sub-array of bytes
/// </summary>
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;
}
/// <summary>
/// Remove NULLs and spaces from the end of a string
/// </summary>
private string trim_trailing_stuff(string x)
{
char[] trimmed = {'\0', ' '};
return x.TrimEnd(trimmed);
}
/// <summary>
/// Convert the byte array into a string (assume UTF8)
/// </summary>
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));
}
/// <summary>
/// Unmarshal an octal string into an int32
/// </summary>
private uint unmarshal_int32(byte[] buffer)
{
string octal = "0" + unmarshal_string(buffer);
return System.Convert.ToUInt32(octal, 8);
}
/// <summary>
/// Unmarshal an octal string into an int
/// </summary>
private int unmarshal_int(byte[] buffer)
{
string octal = "0" + unmarshal_string(buffer);
return System.Convert.ToInt32(octal, 8);
}
/// <summary>
/// Recompute the (weak) header checksum
/// </summary>
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;
}
/// <summary>
/// Compute the required length of padding data to follow the data payload
/// </summary>
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;
}
/// <summary>
/// pretty-print a header
/// </summary>
public override string ToString()
{
return String.Format("{0}/{1} {2:000000000000} {3:000000000000} {4}",
user_id, group_id, file_size, mod_time, file_name);
}
/// <summary>
/// Unmarshal a header from a buffer, throw an exception if the checksum doesn't validate
/// </summary>
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);
}
}
}

View File

@ -1,616 +0,0 @@
/* 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("", null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, true);
}
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(string.Format("{0}\r\n", 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]);
}
public static Stream doRPC(String method, Uri uri, thinCLIProtocol tCLIprotocol, params string[] headers)
{
Stream http = Transport.connect(tCLIprotocol, uri.Host, uri.Port);
String startLine = string.Format("{0} {1} HTTP/1.0", method, uri.PathAndQuery);
writeLine(http, startLine);
foreach (string h in headers)
writeLine(http, h);
writeLine(http, "");
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, headers);
default:
tCLIprotocol.dGlobalError(string.Format("Received error code {0} from the server doing an HTTP {1}", code, method));
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,
string.Format("Content-Length: {0}", fs.Length)))
{
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);
}
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,23 +29,17 @@
*/
using System.Reflection;
using NUnit.Framework;
namespace XenAdminTests.CodeTests
{
[TestFixture, Category(TestCategories.Unit)]
public class XenModelReferencesTest
{
[Test]
public void TestReferences()
{
Assembly a = Assembly.Load(new AssemblyName("XenModel"));
AssemblyName[] an = a.GetReferencedAssemblies();
[assembly: AssemblyCompany("[XenServerProduct]")]
[assembly: AssemblyCopyright("Copyright © [Vendor Legal]")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.0.0.0")]
[assembly: AssemblyFileVersion("0000")]
foreach (AssemblyName name in an)
{
Assert.False(name.ToString().StartsWith("System.Windows"), "Assembly referenced: " + name);
}
}
}
}
/*
* .NET Framework 4.8 docs: All components of the version must be integers greater
* than or equal to 0. Metadata restricts the major, minor, build, and revision
* components for an assembly to a maximum value of UInt16.MaxValue - 1.
* If a component exceeds this value, a compilation error occurs.
*/

66
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,66 @@
#!groovy
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.
*/
def XENADMIN_BRANDING_TAG = 'v5.4'
@Library(['PacmanSharedLibrary', "xencenter-pipeline@v4.12"])
import com.xenserver.pipeline.xencenter.*
properties([
[
$class : 'BuildDiscarderProperty',
strategy: [
$class: 'LogRotator',
numToKeepStr: '10',
artifactNumToKeepStr: '10'
]
]
])
def builder = null
def globals = globals()
node(globals.buildNodeLabel) {
try {
builder = new Build(globals)
builder.xenadminBrandingTag = XENADMIN_BRANDING_TAG
runPipeline(builder)
currentBuild.result = 'SUCCESS'
} catch (Throwable ex) {
currentBuild.result = 'FAILURE'
throw ex
} finally {
buildComplete(builder)
}
}

View File

@ -1,4 +1,7 @@
Copyright (c) 2020 XCP-ng Project
Copyright (c) Cloud Software Group, Inc.
Copyright (c) 2023 XCP-ng Project
The 2-Clause BSD License
@ -15,7 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Copyright for portions of XCP-ng Center are held by Citrix Systems, Inc.
as part of Citrix® XenServer® and Citrix® XenCenter®:
as part of Citrix® XenServer® and Citrix® XenCenter®:
Copyright (c) Citrix Systems, Inc.
All rights reserved.

View File

@ -1,8 +0,0 @@
List of maintainers
===================
* Alexander Schulz (https://github.com/borzel)
-----------------------------------------------------------------------------
For information on how to contribute to the project, please see CONTRIB file.

11
MAINTAINERS.md Normal file
View File

@ -0,0 +1,11 @@
List of maintainers
===================
* Konstantina Chremmou <konstantina.chremmou@cloud.com>
* Chris Lancaster <chris.lancaster@cloud.com>
* Danilo Del Busso <danilo.delbusso@cloud.com>
* Joey Jiang <joey.jiang@cloud.com>
-----------------------------------------------------------------------------
For information on how to contribute to the project, please see [CONTRIBUTING](./CONTRIBUTING.md) file.

View File

@ -7,8 +7,8 @@ XCP-ng Center
This repository contains the source code for XCP-ng Center.
XCP-ng Center is a Windows-based management tool for XCP-ng and Citrix® XenServer® environments
which enables users to manage and monitor XCP-ng and Citrix® XenServer® hosts and resource pools,
XCP-ng Center is a Windows-based management tool for XCP-ng and Citrix® XenServer® environments
which enables users to manage and monitor XCP-ng and Citrix® XenServer® hosts and resource pools,
and to deploy, monitor, manage and migrate virtual machines.
XCP-ng Center is written mostly in C#.

View File

@ -14,18 +14,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xva_verify", "xva_verify\xv
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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XenServerHealthCheck", "XenServerHealthCheck\XenServerHealthCheck.csproj", "{DEB3208D-1153-407C-8C99-0D8899BE25A5}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "installer-xcp-ng", "installer-xcp-ng\installer-xcp-ng.wixproj", "{E0BDD733-D6EB-4EAF-B020-ED0F1154CF80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xe", "xe\Xe.csproj", "{727E885D-14BE-40F0-9D0B-3853D44D3984}"

View File

@ -0,0 +1,117 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Linq;
using XenAdmin.Core;
using XenAdmin.Network;
using XenAPI;
namespace XenAdmin.Actions.GUIActions
{
internal class ConfigYumRepoAction : AsyncAction
{
private readonly RepoDescriptor _repoToEnable;
private readonly Repository _introducedRepo;
private readonly List<Repository> _oldEnabledRepos;
private readonly Pool _pool;
public ConfigYumRepoAction(IXenConnection connection, RepoDescriptor repoDescriptor)
: base(connection, string.Empty)
{
Title = Description = string.Format(Messages.YUM_REPO_ACTION_CONFIG_TITLE, connection.Name, repoDescriptor.FriendlyName);
_repoToEnable = repoDescriptor;
_introducedRepo = connection.Cache.Repositories.FirstOrDefault(r => _repoToEnable.MatchesRepository(r));
_pool = Helpers.GetPoolOfOne(Connection);
_oldEnabledRepos = (from XenRef<Repository> repoRef in _pool.repositories
let repo = Connection.Resolve(repoRef)
where !_repoToEnable.MatchesRepository(repo)
select repo).ToList();
#region RBAC
if (_oldEnabledRepos.Count > 0)
ApiMethodsToRoleCheck.Add("Pool.remove_repository");
if (_introducedRepo == null)
ApiMethodsToRoleCheck.Add("Repository.introduce");
ApiMethodsToRoleCheck.Add("Pool.add_repository");
#endregion
}
protected override void Run()
{
foreach (var repo in _oldEnabledRepos)
{
var repoName = RepoDescriptor.AllRepos.FirstOrDefault(r => r.MatchesRepository(repo))?.FriendlyName ?? string.Empty;
Description = string.Format(Messages.YUM_REPO_ACTION_CONFIG_DESCRIPTION_DISABLE, repoName);
Pool.remove_repository(Session, _pool.opaque_ref, repo.opaque_ref);
}
XenRef<Repository> repoRef;
if (_introducedRepo == null)
{
var baseRepo = RepoDescriptor.BaseRepo;
if (!Connection.Cache.Repositories.Any(r => baseRepo.MatchesRepository(r)))
{
Description = string.Format(Messages.YUM_REPO_ACTION_CONFIG_DESCRIPTION_INTRODUCE, baseRepo.FriendlyName);
Repository.introduce(Session, baseRepo.Key, baseRepo.FriendlyName, baseRepo.BinUrl, baseRepo.SourceUrl, false, "");
}
Description = string.Format(Messages.YUM_REPO_ACTION_CONFIG_DESCRIPTION_INTRODUCE, _repoToEnable.FriendlyName);
repoRef = Repository.introduce(Session, _repoToEnable.Key, _repoToEnable.FriendlyName,
_repoToEnable.BinUrl, _repoToEnable.SourceUrl, true, "");
}
else
{
repoRef = new XenRef<Repository>(_introducedRepo.opaque_ref);
}
Description = string.Format(Messages.YUM_REPO_ACTION_CONFIG_DESCRIPTION_ENABLE, _repoToEnable.FriendlyName);
Pool.add_repository(Session, _pool.opaque_ref, repoRef);
//wait until the cache has been updated so that the config panel can show
//the new value if the action was triggered by hitting the Apply button
Connection.WaitFor(() => _pool.repositories.Contains(repoRef), null);
}
}
}

View File

@ -1,130 +0,0 @@
/* 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.Alerts;
using XenAdmin.Network;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Actions
{
public class DeleteAllAlertsAction : AsyncAction
{
private readonly IEnumerable<Alert> Alerts;
/// <param name="connection">May be null; this is expected for client-side alerts.</param>
/// <param name="alerts"></param>
public DeleteAllAlertsAction(IXenConnection connection, IEnumerable<Alert> alerts)
: base(connection,
GetActionTitle(connection, alerts.Count()),
Messages.ACTION_REMOVE_ALERTS_DESCRIPTION)
{
this.Alerts = alerts;
if (connection != null)
{
Pool = Helpers.GetPoolOfOne(connection);
Host = Helpers.GetMaster(connection);
}
}
private static string GetActionTitle(IXenConnection connection, int alertCount)
{
return connection == null
? alertCount == 1
? Messages.ACTION_REMOVE_ALERTS_ON_CLIENT_TITLE_ONE
: string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CLIENT_TITLE, alertCount)
: alertCount == 1
? string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CONNECTION_TITLE_ONE, Helpers.GetName(connection))
: string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CONNECTION_TITLE, alertCount, Helpers.GetName(connection));
}
protected override void Run()
{
int i = 0;
int max = Alerts.Count();
Exception e = null;
LogDescriptionChanges = false;
List<Alert> toBeDismissed = new List<Alert>();
try
{
var myList = new List<Alert>(Alerts);
foreach (Alert a in myList)
{
PercentComplete = (i * 100) / max;
i++;
Description = string.Format(Messages.ACTION_REMOVE_ALERTS_PROGRESS_DESCRIPTION, i, max);
Alert a1 = a;
BestEffort(ref e, delegate
{
try
{
if (a1 is XenServerPatchAlert || a1 is XenServerVersionAlert)
{
toBeDismissed.Add(a1);
}
else if(a1 is XenCenterUpdateAlert)
{
a1.Dismiss();
}
else
{
a1.DismissSingle(Session);
}
}
catch (Failure exn)
{
if (exn.ErrorDescription[0] != Failure.HANDLE_INVALID)
throw;
//remove alert from XenCenterAlerts; this will trigger the CollectionChanged event, on which we update the alert count
if (Alert.FindAlert(a1) != null)
Alert.RemoveAlert(a1);
}
});
}
Updates.DismissUpdates(toBeDismissed);
}
finally
{
LogDescriptionChanges = true;
}
Description = max == 1 ? Messages.ACTION_REMOVE_ALERTS_DONE_ONE : string.Format(Messages.ACTION_REMOVE_ALERTS_DONE, max);
}
}
}

View File

@ -0,0 +1,132 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Linq;
using XenAdmin.Alerts;
using XenAdmin.Network;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Actions
{
public class DismissAlertsAction : AsyncAction
{
private readonly List<Alert> _alerts;
public DismissAlertsAction(List<Alert> alerts, IXenConnection connection = null)
: base(connection, GetActionTitle(connection, alerts.Count),
Messages.ACTION_REMOVE_ALERTS_DESCRIPTION)
{
_alerts = alerts;
if (connection != null)
{
Pool = Helpers.GetPoolOfOne(connection);
Host = Helpers.GetCoordinator(connection);
}
}
private static string GetActionTitle(IXenConnection connection, int alertCount)
{
if (connection == null)
return alertCount == 1
? Messages.ACTION_REMOVE_ALERTS_ON_CLIENT_TITLE_ONE
: string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CLIENT_TITLE, alertCount);
return alertCount == 1
? string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CONNECTION_TITLE_ONE, Helpers.GetName(connection))
: string.Format(Messages.ACTION_REMOVE_ALERTS_ON_CONNECTION_TITLE, alertCount, Helpers.GetName(connection));
}
protected override void Run()
{
LogDescriptionChanges = false;
try
{
if (Connection != null && Helpers.XapiEqualOrGreater_22_19_0(Connection))
{
var msgRefs = new List<XenRef<Message>>();
var msgAlerts = new List<MessageAlert>();
var otherAlerts = new List<Alert>();
foreach (var a in _alerts)
{
if (a is MessageAlert ma)
{
msgAlerts.Add(ma);
msgRefs.Add(new XenRef<Message>(ma.Message.opaque_ref));
}
else
{
otherAlerts.Add(a);
}
}
int midPoint = 0;
if (_alerts.Count > 0)
midPoint = 100 * msgAlerts.Count / _alerts.Count;
if (msgAlerts.Count > 0)
{
RelatedTask = Message.async_destroy_many(Session, msgRefs);
PollToCompletion(0, midPoint);
Alert.RemoveAlert(a => msgAlerts.Contains(a));
}
for (var i = 0; i < otherAlerts.Count; i++)
{
_alerts[i].Dismiss();
PercentComplete = midPoint + i * (100 - midPoint) / otherAlerts.Count;
}
}
else
{
for (var i = 0; i < _alerts.Count; i++)
{
Description = string.Format(Messages.ACTION_REMOVE_ALERTS_PROGRESS_DESCRIPTION, i, _alerts.Count);
_alerts[i].Dismiss();
PercentComplete = i * 100 / _alerts.Count;
}
}
}
finally
{
LogDescriptionChanges = true;
}
Description = _alerts.Count == 1
? Messages.ACTION_REMOVE_ALERTS_DONE_ONE
: string.Format(Messages.ACTION_REMOVE_ALERTS_DONE, _alerts.Count);
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -521,7 +520,7 @@ namespace XenAdmin.Actions
ParamLabelsStr += "LBL_HOSTNAME|";
ParamValuesStr += Messages.NAME + "|";
ParamLabelsStr += "LBL_POOLMASTER|";
ParamValuesStr += Messages.POOL_MASTER + "|";
ParamValuesStr += Messages.POOL_COORDINATOR + "|";
ParamLabelsStr += "LBL_ADDRESS|";
ParamValuesStr += Messages.ADDRESS + "|";
ParamLabelsStr += "LBL_UUID|";
@ -640,7 +639,7 @@ namespace XenAdmin.Actions
HostInfo buf = new HostInfo(host.name_label, host.address, host.uuid, cpu_usage,
host.IsMaster() ? Messages.YES : Messages.NO, network_usage, usage,
host.IsCoordinator() ? Messages.YES : Messages.NO, network_usage, usage,
Convert.ToString(host.Uptime()), srSizeString, host.Description());
m_Hosts.Add(buf);
PercentComplete = Convert.ToInt32((++itemIndex) * baseIndex / itemCount);
@ -776,7 +775,7 @@ namespace XenAdmin.Actions
if (Cancelling)
throw new CancelledException();
if (!vm.is_a_real_vm())
if (!vm.IsRealVm())
{
PercentComplete = Convert.ToInt32((++itemIndex) * baseIndex / itemCount);
continue;
@ -959,7 +958,7 @@ namespace XenAdmin.Actions
items.Add(Messages.NAME);
items.Add(Messages.UUID);
items.Add(Messages.POOL_MASTER);
items.Add(Messages.POOL_COORDINATOR);
items.Add(Messages.ADDRESS);
items.Add(Messages.OVERVIEW_CPU_USAGE);
items.Add(Messages.OVERVIEW_MEMORY_USAGE);

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -195,8 +194,8 @@ namespace XenAdmin.Actions
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));
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)
{
@ -207,7 +206,7 @@ namespace XenAdmin.Actions
// Can't run on this connection, bail out
string desc = string.Format(FriendlyErrorNames.RBAC_PERMISSION_DENIED_FRIENDLY_CONNECTION,
xenConnection.Session.FriendlyRoleDescription(),
Role.FriendlyCSVRoleList(rolesAbleToCompleteAction),
Role.FriendlyCsvRoleList(rolesAbleToCompleteAction),
xenConnection.Name);
throw new Exception(desc);
}
@ -227,11 +226,10 @@ namespace XenAdmin.Actions
{
Program.Invoke(Program.MainWindow, delegate
{
using (var d = new ThreeButtonDialog(
new ThreeButtonDialog.Details(System.Drawing.SystemIcons.Warning, string.Format(Messages.FORCE_CLOSE_PLUGIN_PROMPT, _menuItemFeature.ToString())),
"ProcessForceClosePrompt",
using (var d = new WarningDialog(string.Format(Messages.FORCE_CLOSE_PLUGIN_PROMPT, _menuItemFeature.ToString()),
new ThreeButtonDialog.TBDButton(Messages.FORCE_CLOSE, DialogResult.Yes),
new ThreeButtonDialog.TBDButton(Messages.ALLOW_TO_CONTINUE, DialogResult.No)))
new ThreeButtonDialog.TBDButton(Messages.ALLOW_TO_CONTINUE, DialogResult.No))
{HelpNameSetter = "ProcessForceClosePrompt"})
{
if (d.ShowDialog(Program.MainWindow) == DialogResult.Yes && !_extAppProcess.HasExited)
_extAppProcess.Kill();
@ -247,40 +245,40 @@ namespace XenAdmin.Actions
}
// Returns a set of params which relate to the object you have selected in the treeview
private List<string> RetrieveParams(IXenObject obj)
private IEnumerable<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;
var connection = obj?.Connection;
var coordinator = connection != null ? Helpers.GetCoordinator(connection) : null; // get coordinator asserts connection is not null
var coordinatorAddress = EmptyParameter;
if (master != null)
if (coordinator != null)
{
masterAddress = Helpers.GetUrl(master.Connection);
WriteTrustedCertificates(master.Connection);
coordinatorAddress = Helpers.GetUrl(coordinator.Connection);
WriteTrustedCertificates(coordinator.Connection);
}
string sessionRef = connection.Session != null ? connection.Session.opaque_ref : 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 });
var sessionRef = connection?.Session != null ? connection.Session.opaque_ref : EmptyParameter;
var objCls = obj != null ? obj.GetType().Name : EmptyParameter;
var objUuid = connection?.Session != null ? Helpers.GetUuid(obj) : EmptyParameter;
return new List<string>(new string[] { coordinatorAddress, 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;
Host coordinator = connection != null ? Helpers.GetCoordinator(connection) : null; // get coordinator asserts connection is not null
string coordinatorAddress = EmptyParameter;
if (master != null)
if (coordinator != null)
{
masterAddress = Helpers.GetUrl(master.Connection);
WriteTrustedCertificates(master.Connection);
coordinatorAddress = Helpers.GetUrl(coordinator.Connection);
WriteTrustedCertificates(coordinator.Connection);
}
string sessionRef = connection.Session != null ? connection.Session.opaque_ref : EmptyParameter;
string sessionRef = connection?.Session != null ? connection.Session.opaque_ref : EmptyParameter;
string objCls = BlankParamter;
string objUuid = BlankParamter;
return new List<string>(new string[] { masterAddress, sessionRef, objCls, objUuid });
return new List<string>(new string[] { coordinatorAddress, sessionRef, objCls, objUuid });
}
private void WriteTrustedCertificates(IXenConnection connection)

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -31,7 +30,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using XenAPI;
using XenAdmin.Model;
@ -61,9 +59,9 @@ namespace XenAdmin.Actions
if (newFolder != xenObjectCopy.Path)
{
ApiMethodsToRoleCheck.Add(type + ".remove_from_other_config", Folders.FOLDER);
ApiMethodsToRoleCheck.AddWithKey(type + ".remove_from_other_config", Folders.FOLDER);
if (!String.IsNullOrEmpty(newFolder))
ApiMethodsToRoleCheck.Add(type + ".add_to_other_config", Folders.FOLDER);
ApiMethodsToRoleCheck.AddWithKey(type + ".add_to_other_config", Folders.FOLDER);
// TODO: Full RBAC for folders
}
foreach (string tag in oldTags)

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -78,11 +77,11 @@ namespace XenAdmin.Actions.GUIActions
private vm_operations vmOperation;
public MeddlingAction(Task task)
: base(task.Name(), task.Description(), false, false)
: base(task.Name(), task.Description(), false)
{
RelatedTask = new XenRef<Task>(task.opaque_ref);
Host = task.Connection.Resolve(task.resident_on) ?? Helpers.GetMaster(task.Connection);
Host = task.Connection.Resolve(task.resident_on) ?? Helpers.GetCoordinator(task.Connection);
Started = (task.created + task.Connection.ServerTimeOffset).ToLocalTime();
SetAppliesToData(task);
@ -164,8 +163,8 @@ namespace XenAdmin.Actions.GUIActions
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);
// the task.resident_on host, or if that doesn't resolve, the pool coordinator.
Host host = task.Connection.Resolve(task.resident_on) ?? Helpers.GetCoordinator(task.Connection);
if (host != null)
AppliesTo.Add(host.opaque_ref);
}
@ -228,7 +227,7 @@ namespace XenAdmin.Actions.GUIActions
}
else
{
host1 = task.Connection.Resolve(task.resident_on) ?? Helpers.GetMaster(task.Connection);
host1 = task.Connection.Resolve(task.resident_on) ?? Helpers.GetCoordinator(task.Connection);
}
List<string> names = new List<string>();
@ -314,7 +313,7 @@ namespace XenAdmin.Actions.GUIActions
/// </summary>
public static bool IsTaskUnwanted(Task task)
{
return task.XenCenterUUID() == Program.XenCenterUUID ||
return task.GetXenCenterUUID() == Program.XenCenterUUID ||
task.Connection.Resolve(task.subtask_of) != null ||
GetVmOperation(task) == vm_operations.unknown;
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -29,7 +28,6 @@
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using XenAPI;

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -29,9 +28,8 @@
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using XenAdmin.Alerts;
using XenAdmin.Network;
using XenAdmin.Core;
using XenAPI;
@ -56,11 +54,11 @@ namespace XenAdmin.Actions
Dictionary<string, string> other_config = pool.other_config;
if (other_config.ContainsKey(Updates.IgnorePatchKey))
other_config.Remove(Updates.IgnorePatchKey);
if (other_config.ContainsKey(XenServerPatchAlert.IgnorePatchKey))
other_config.Remove(XenServerPatchAlert.IgnorePatchKey);
if (other_config.ContainsKey(Updates.LAST_SEEN_SERVER_VERSION_KEY))
other_config.Remove(Updates.LAST_SEEN_SERVER_VERSION_KEY);
if (other_config.ContainsKey(XenServerVersionAlert.LAST_SEEN_SERVER_VERSION_KEY))
other_config.Remove(XenServerVersionAlert.LAST_SEEN_SERVER_VERSION_KEY);
XenAPI.Pool.set_other_config(Connection.Session, pool.opaque_ref, other_config);

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -29,121 +28,114 @@
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using XenAdmin.Network;
using XenAdmin.Controls.CustomDataGraph;
using XenAPI;
using XenAdmin.Core;
using XenAdmin.Network;
using XenAPI;
namespace XenAdmin.Actions
{
public class SaveDataSourceStateAction : PureAsyncAction
public class SaveDataSourceStateAction : AsyncAction
{
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;
}
private readonly List<DataSourceItem> _dataSourceItems;
private readonly List<DesignedGraph> _graphs;
private readonly IXenObject _xenObject;
public SaveDataSourceStateAction(IXenConnection connection, IXenObject xmo, List<DataSourceItem> items, List<DesignedGraph> graphs)
: base(connection, Messages.ACTION_SAVE_DATASOURCES, Messages.ACTION_SAVING_DATASOURCES, true)
{
DataSourceItems = items;
XenObject = xmo;
Graphs = graphs;
_dataSourceItems = items;
_xenObject = xmo;
_graphs = graphs;
if (xmo is Host)
ApiMethodsToRoleCheck.AddRange("host.record_data_source", "host.forget_data_source_archives");
else if (xmo is VM)
ApiMethodsToRoleCheck.AddRange("VM.record_data_source", "VM.forget_data_source_archives");
ApiMethodsToRoleCheck.Add("pool.set_gui_config");
}
protected override void Run()
{
Dictionary<string, string> gui_config = GetGuiConfig();
Pool pool = Helpers.GetPoolOfOne(Connection);
var guiConfig = pool?.gui_config;
if (DataSourceItems != null)
if (_dataSourceItems != null)
{
foreach (DataSourceItem ds in DataSourceItems)
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 (_xenObject is Host host)
{
if (ds.Enabled)
XenAPI.Host.record_data_source(Session, host.opaque_ref, ds.DataSource.name_label);
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);
Host.forget_data_source_archives(Session, host.opaque_ref, ds.DataSource.name_label);
}
else if (vm != null)
else if (_xenObject is VM vm)
{
if (ds.Enabled)
XenAPI.VM.record_data_source(Session, vm.opaque_ref, ds.DataSource.name_label);
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);
VM.forget_data_source_archives(Session, vm.opaque_ref, ds.DataSource.name_label);
}
}
if (ds.ColorChanged)
if (ds.ColorChanged && guiConfig != null)
{
if (gui_config != null)
{
string key = Palette.GetColorKey(ds.DataSource.name_label, XenObject);
string value = ds.Color.ToArgb().ToString();
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;
}
if (!guiConfig.ContainsKey(key))
guiConfig.Add(key, value);
else
guiConfig[key] = value;
}
}
}
Dictionary<string, string> new_gui_config = new Dictionary<string, string>();
string uuid = Helpers.GetUuid(XenObject);
var newGuiConfig = 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)
if (guiConfig != null)
{
foreach (string key in gui_config.Keys)
foreach (string key in guiConfig.Keys)
{
bool isMatch = (Palette.LayoutKey.IsMatch(key) || Palette.GraphNameKey.IsMatch(key));
bool isMatch = Palette.LayoutKey.IsMatch(key) || Palette.GraphNameKey.IsMatch(key);
if (isMatch && key.Contains(uuid))
continue;
new_gui_config.Add(key, gui_config[key]);
newGuiConfig.Add(key, guiConfig[key]);
}
}
if (Graphs != null)
if (_graphs != null)
{
// add current XenObject keys
for (int i = 0; i < Graphs.Count; i++)
for (int i = 0; i < _graphs.Count; i++)
{
string key = Palette.GetLayoutKey(i, XenObject);
string value = Graphs[i].ToString();
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);
newGuiConfig.Add(key, value);
key = Palette.GetGraphNameKey(i, XenObject);
value = Graphs[i].DisplayName;
if (value != String.Empty)
key = Palette.GetGraphNameKey(i, _xenObject);
value = _graphs[i].DisplayName;
if (value != string.Empty)
{
new_gui_config.Add(key, value);
newGuiConfig.Add(key, value);
}
}
}
XenAPI.Pool.set_gui_config(Session, GetPool().opaque_ref, new_gui_config);
if (pool != null)
Pool.set_gui_config(Session, pool.opaque_ref, newGuiConfig);
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,8 +29,6 @@
*/
using System;
using System.Collections.Generic;
using System.Text;
using XenAdmin.XenSearch;

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,10 +29,7 @@
*/
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Reporting.WinForms;
using XenAPI;
namespace XenAdmin.Actions.Wlb

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -31,18 +30,14 @@
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;
using XenAdmin.Actions.VMActions;
namespace XenAdmin.Actions.Wlb
{
@ -58,13 +53,8 @@ namespace XenAdmin.Actions.Wlb
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;
Pool = pool;
vmOptList = vmOptLst ?? throw new ArgumentNullException("vmOptLst");
this.optId = optId;
#region RBAC Dependencies
@ -244,11 +234,8 @@ namespace XenAdmin.Actions.Wlb
// Tell the user the VM will be started without HA protection.
Program.Invoke(Program.MainWindow, delegate()
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(
SystemIcons.Warning,
String.Format(Messages.HA_INVALID_CONFIG_RESUME, Helpers.GetName(vm).Ellipsise(500)),
Messages.HIGH_AVAILABILITY)))
using (var dlg = new WarningDialog(String.Format(Messages.HA_INVALID_CONFIG_RESUME, Helpers.GetName(vm).Ellipsise(500)))
{WindowTitle = Messages.HIGH_AVAILABILITY})
{
dlg.ShowDialog(Program.MainWindow);
}
@ -328,11 +315,8 @@ namespace XenAdmin.Actions.Wlb
Helpers.GetName(vm).Ellipsise(100));
Program.Invoke(Program.MainWindow, delegate()
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(
SystemIcons.Warning,
msg,
Messages.HIGH_AVAILABILITY)))
using (var dlg = new WarningDialog(msg)
{WindowTitle = Messages.HIGH_AVAILABILITY})
{
dlg.ShowDialog(Program.MainWindow);
}
@ -347,13 +331,10 @@ namespace XenAdmin.Actions.Wlb
Program.Invoke(Program.MainWindow, delegate()
{
using (var dlg = new ThreeButtonDialog(
new ThreeButtonDialog.Details(
SystemIcons.Warning,
msg,
Messages.HIGH_AVAILABILITY),
using (var dlg = new WarningDialog(msg,
ThreeButtonDialog.ButtonYes,
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, ThreeButtonDialog.ButtonType.CANCEL, true)))
new ThreeButtonDialog.TBDButton(Messages.NO_BUTTON_CAPTION, DialogResult.No, selected: true))
{WindowTitle = Messages.HIGH_AVAILABILITY})
{
DialogResult r = dlg.ShowDialog(Program.MainWindow);
if (r != DialogResult.Yes)
@ -378,7 +359,7 @@ namespace XenAdmin.Actions.Wlb
/// <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);
action.RelatedTask = VM.async_pool_migrate(action.Session, vm.opaque_ref, host.opaque_ref, new Dictionary<string, string> { ["live"] = "true" });
if (recommendationId != 0)
{
@ -403,7 +384,7 @@ namespace XenAdmin.Actions.Wlb
/// <param name="end">progress bar end point</param>
private static void SetHaProtection(bool protect, AsyncAction action, VM vm, int start, int end)
{
// Do database sync. Helps to ensure that the change persists over master failover.
// Do database sync. Helps to ensure that the change persists over coordinator failover.
action.RelatedTask = XenAPI.Pool.async_sync_database(action.Session);
action.PollToCompletion(start, end);
}

View File

@ -1,197 +0,0 @@
/* 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.Core;
using XenAdmin.Network;
using XenAPI;
using XenOvf;
using XenOvf.Definitions;
using XenOvfTransport;
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;
private Export m_transportAction;
#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,
string.Format(createOVA ? Messages.EXPORT_OVA_PACKAGE : Messages.EXPORT_OVF_PACKAGE, applianceFileName, Helpers.GetName(connection)),
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 XenOvfTransportBase TransportAction => m_transportAction;
protected override void Run()
{
base.Run();
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 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.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;
}
}
}

View File

@ -1,182 +0,0 @@
/* 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.Core;
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 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;
private Import m_transportAction;
#endregion
public ImportApplianceAction(IXenConnection connection, 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, string.Format(Messages.IMPORT_APPLIANCE, package.Name, Helpers.GetName(connection)),
networkUuid, isTvmIpStatic, tvmIpAddress, tvmSubnetMask, tvmGateway)
{
m_package = package;
m_vmMappings = vmMappings;
m_verifyManifest = verifyManifest;
m_verifySignature = verifySignature;
m_password = password;
m_runfixups = runfixups;
m_selectedIsoSr = selectedIsoSr;
}
protected override XenOvfTransportBase TransportAction => m_transportAction;
protected override void Run()
{
base.Run();
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));
}
}
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_package.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]);
}
EnvelopeType env = OVF.Merge(envelopes, m_package.Name);
m_package.ExtractToWorkingDir();
try //importVM
{
m_transportAction = new Import(uri, session)
{
ApplianceName = m_package.Name,
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.Process(env, m_package.WorkingDir, m_password);
}
catch (OperationCanceledException)
{
throw new CancelledException();
}
finally
{
m_package.CleanUpWorkingDir();
}
PercentComplete = 100;
Description = Messages.COMPLETED;
}
}
}

View File

@ -1,127 +0,0 @@
/* 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.Core;
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;
private Import m_transportAction;
#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, string.Format(Messages.IMPORT_DISK_IMAGE, ovfEnv.Name, Helpers.GetName(connection)),
networkUuid, isTvmIpStatic, tvmIpAddress, tvmSubnetMask, tvmGateway)
{
m_ovfEnvelope = ovfEnv;
m_directory = directory;
m_vmMappings = vmMappings;
m_runfixups = runfixups;
m_selectedIsoSr = selectedIsoSr;
}
protected override XenOvfTransportBase TransportAction => m_transportAction;
protected override void Run()
{
base.Run();
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.Process(curEnv, m_directory, null);
PercentComplete = 100;
Description = Messages.COMPLETED;
}
catch (OperationCanceledException)
{
throw new CancelledException();
}
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -78,5 +77,19 @@ namespace XenAdmin.Alerts
date.EscapeQuotes(),
a.WebPageLabel.EscapeQuotes());
}
public static string GetGuiDate(DateTime? dateTime)
{
string date = string.Empty;
Program.Invoke(Program.MainWindow,
() =>
{
if (dateTime.HasValue)
date = HelpersGUI.DateTimeToString(dateTime.Value.ToLocalTime(), Messages.DATEFORMAT_DMY_HM, true);
});
return date;
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -29,11 +28,7 @@
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XenAdmin.Alerts
{
@ -44,25 +39,20 @@ namespace XenAdmin.Alerts
if (alert1 == null || alert2 == null)
return 0;
int sortResult = 0;
if (IsVersionOrVersionUpdateAlert(alert1) && !IsVersionOrVersionUpdateAlert(alert2))
sortResult = 1;
return -1;
if (!IsVersionOrVersionUpdateAlert(alert1) && IsVersionOrVersionUpdateAlert(alert2))
sortResult = -1;
return 1;
if (sortResult == 0)
sortResult = Alert.CompareOnDate(alert1, alert2);
return -sortResult;
return -Alert.CompareOnDate(alert1, alert2); //descending date
}
private bool IsVersionOrVersionUpdateAlert(Alert alert)
{
return alert is XenServerPatchAlert && (alert as XenServerPatchAlert).ShowAsNewVersion
return alert is XenServerPatchAlert xspAlert && xspAlert.ShowAsNewVersion
|| alert is XenServerVersionAlert
|| alert is XenCenterUpdateAlert;
|| alert is ClientUpdateAlert;
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -31,12 +30,9 @@
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;
@ -188,7 +184,7 @@ namespace XenAdmin.Alerts
case AlarmType.FileSystem:
return string.Format(Messages.ALERT_ALARM_FILESYSTEM_DESCRIPTION,
Helpers.GetNameAndObject(XenObject),
Util.PercentageString(CurrentValue));
Util.PercentageString(CurrentValue), BrandManager.ProductBrand);
case AlarmType.Memory:
return string.Format(Messages.ALERT_ALARM_MEMORY_DESCRIPTION,
Helpers.GetNameAndObject(XenObject),
@ -257,29 +253,23 @@ namespace XenAdmin.Alerts
get
{
return () =>
{
IXenObject xenObject = null;
if (XenObject is Host) //sr is only set when it's AlarmType.Storage
xenObject = sr ?? XenObject;
else if (XenObject is VM vm)
xenObject = vm.IsControlDomainZero(out Host host) ? host : XenObject;
if (xenObject == null)
return;
using (var dialog = new PropertiesDialog(xenObject) {TopMost = true})
{
IXenObject xenObject = null;
if (XenObject is Host)
{
//sr is only set when it's AlarmType.Storage
xenObject = sr ?? XenObject;
}
else if (XenObject is VM)
{
VM vm = (VM)XenObject;
xenObject = vm.IsControlDomainZero() ? XenObject.Connection.Resolve(vm.resident_on) : XenObject;
}
if (xenObject == null)
return;
using (var dialog = new PropertiesDialog(xenObject) { TopMost = true })
{
dialog.SelectPerfmonAlertEditPage();
dialog.ShowDialog(Program.MainWindow);
}
};
dialog.SelectPerfmonAlertEditPage();
dialog.ShowDialog(Program.MainWindow);
}
};
}
}

View File

@ -0,0 +1,244 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Xml;
using XenAdmin.Commands;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Alerts
{
public class CertificateAlert : MessageAlert
{
private readonly DateTime? _certificateExpiryDate;
public CertificateAlert(Message m)
: base(m)
{
try
{
var doc = new XmlDocument();
doc.LoadXml(m.body);
var nodes = doc.GetElementsByTagName("date");
if (nodes.Count > 0 && Util.TryParseIso8601DateTime(nodes[0].InnerText, out DateTime result))
_certificateExpiryDate = result;
}
catch
{
//ignore
}
}
public override string Title
{
get
{
var objectName = XenObject == null ? Messages.UNKNOWN_OBJECT : XenObject.Name();
switch (Message.Type)
{
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRED:
var pool1 = Helpers.GetPoolOfOne(Connection);
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRED_TITLE, objectName, pool1.Name());
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_07:
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_14:
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_30:
var pool2 = Helpers.GetPoolOfOne(Connection);
if (_certificateExpiryDate.HasValue && _certificateExpiryDate.Value > Timestamp)
{
var eta = _certificateExpiryDate.Value - Timestamp;
if (eta.TotalDays >= 1)
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRING_TITLE_DAYS, objectName,
pool2.Name(), Math.Round(eta.TotalDays, MidpointRounding.AwayFromZero));
if (eta.TotalHours >= 1)
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRING_TITLE_HOURS, objectName,
pool2.Name(), Math.Round(eta.TotalHours, MidpointRounding.AwayFromZero));
if (eta.TotalMinutes >= 1)
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRING_TITLE_MINUTES, objectName,
pool2.Name(), Math.Round(eta.TotalMinutes, MidpointRounding.AwayFromZero));
}
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRED_TITLE, objectName, pool2.Name());
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRED:
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRED_TITLE, objectName);
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_30:
if (_certificateExpiryDate.HasValue && _certificateExpiryDate.Value > Timestamp)
{
var eta = _certificateExpiryDate.Value - Timestamp;
if (eta.TotalDays >= 1)
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRING_TITLE_DAYS, objectName,
Math.Round(eta.TotalDays, MidpointRounding.AwayFromZero));
if (eta.TotalHours >= 1)
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRING_TITLE_HOURS, objectName,
Math.Round(eta.TotalHours, MidpointRounding.AwayFromZero));
if (eta.TotalMinutes >= 1)
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRING_TITLE_MINUTES, objectName,
Math.Round(eta.TotalMinutes, MidpointRounding.AwayFromZero));
}
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRED_TITLE, objectName);
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRED:
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRED_TITLE, objectName);
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_30:
if (_certificateExpiryDate.HasValue && _certificateExpiryDate.Value > Timestamp)
{
var eta = _certificateExpiryDate.Value - Timestamp;
if (eta.TotalDays >= 1)
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRING_TITLE_DAYS, objectName,
Math.Round(eta.TotalDays, MidpointRounding.AwayFromZero));
if (eta.TotalHours >= 1)
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRING_TITLE_HOURS, objectName,
Math.Round(eta.TotalHours, MidpointRounding.AwayFromZero));
if (eta.TotalMinutes >= 1)
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRING_TITLE_MINUTES, objectName,
Math.Round(eta.TotalMinutes, MidpointRounding.AwayFromZero));
}
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRED_TITLE, objectName);
default:
return base.Title;
}
}
}
public override string Description
{
get
{
var objectName = XenObject == null ? Messages.UNKNOWN_OBJECT : XenObject.Name();
switch (Message.Type)
{
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRED:
var pool1 = Helpers.GetPoolOfOne(Connection);
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRED_DESCIRPTION, objectName, pool1.Name(),
AlertExtensions.GetGuiDate(_certificateExpiryDate));
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_07:
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_14:
case Message.MessageType.POOL_CA_CERTIFICATE_EXPIRING_30:
var pool2 = Helpers.GetPoolOfOne(Connection);
return string.Format(Messages.CERTIFICATE_CA_ALERT_EXPIRING_DESCRIPTION,
objectName, pool2.Name(), AlertExtensions.GetGuiDate(_certificateExpiryDate));
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRED:
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRED_DESCIRPTION,
objectName, AlertExtensions.GetGuiDate(_certificateExpiryDate));
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_INTERNAL_CERTIFICATE_EXPIRING_30:
return string.Format(Messages.CERTIFICATE_HOST_INTERNAL_ALERT_EXPIRING_DESCRIPTION,
objectName, AlertExtensions.GetGuiDate(_certificateExpiryDate));
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRED:
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRED_DESCIRPTION, objectName,
AlertExtensions.GetGuiDate(_certificateExpiryDate));
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_30:
return string.Format(Messages.CERTIFICATE_HOST_ALERT_EXPIRING_DESCRIPTION,
objectName, AlertExtensions.GetGuiDate(_certificateExpiryDate));
default:
return base.Title;
}
}
}
public override Action FixLinkAction
{
get
{
if (!(XenObject is Host host))
return null;
switch (Message.Type)
{
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRED:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_30:
var cmd = new InstallCertificateCommand(Program.MainWindow, host);
if (cmd.CanRun())
return () => cmd.Run();
return null;
default:
return null;
}
}
}
public override string FixLinkText
{
get
{
if (!(XenObject is Host))
return null;
switch (Message.Type)
{
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRED:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_07:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_14:
case Message.MessageType.HOST_SERVER_CERTIFICATE_EXPIRING_30:
return Messages.INSTALL_SERVER_CERTIFICATE_ACTION_LINK;
default:
return null;
}
}
}
public override string HelpID => "CertificateAlert";
public override string HelpLinkText => Messages.ALERT_GENERIC_HELP;
}
}

View File

@ -0,0 +1,187 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Actions.GUIActions;
using XenAdmin.Actions.Updates;
using XenAdmin.Core;
using XenAdmin.Dialogs;
using XenAdmin.Dialogs.WarningDialogs;
using XenCenterLib;
namespace XenAdmin.Alerts
{
public class ClientUpdateAlert : Alert
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public readonly ClientVersion NewVersion;
public ClientUpdateAlert(ClientVersion version)
{
NewVersion = version;
_timestamp = NewVersion.TimeStamp;
Checksum = version.Checksum;
}
public override AlertPriority Priority => AlertPriority.Priority5;
public override string WebPageLabel => InvisibleMessages.RELEASE_NOTES_URL;
public override string Name => NewVersion.Name;
public override string Title => string.Format(Messages.ALERT_NEW_VERSION, NewVersion.Name);
public override string Description => string.Format(Messages.ALERT_NEW_VERSION_DETAILS_CLIENT,
NewVersion.Name);
public override Action FixLinkAction
{
get { return () => Program.OpenURL(WebPageLabel); }
}
public override string FixLinkText => string.Format(Messages.ALERT_NEW_VERSION_DOWNLOAD_CLIENT, NewVersion.Version);
public override string AppliesTo => BrandManager.BrandConsole;
public override string HelpID => "XenCenterUpdateAlert";
public string Checksum { get; }
public override bool AllowedToDismiss()
{
return false;
}
public override void Dismiss()
{
//do not dismiss this alert
}
public override bool Equals(Alert other)
{
if (other is ClientUpdateAlert clientAlert)
return NewVersion.VersionAndLang == clientAlert.NewVersion.VersionAndLang;
return base.Equals(other);
}
public static void DownloadAndInstallNewClient(ClientUpdateAlert updateAlert, IWin32Window parent)
{
var outputPathAndFileName = Path.Combine(Path.GetTempPath(), $"{BrandManager.BrandConsole}.msi");
var downloadAndInstallClientAction = new DownloadAndUpdateClientAction(updateAlert.Name, new Uri(updateAlert.NewVersion.Url), outputPathAndFileName, updateAlert.Checksum);
using (var dlg = new ActionProgressDialog(downloadAndInstallClientAction, ProgressBarStyle.Continuous))
{
dlg.ShowCancel = true;
dlg.ShowDialog(parent);
}
if (!downloadAndInstallClientAction.Succeeded)
return;
bool currentTasks = false;
foreach (ActionBase a in ConnectionsManager.History)
{
if (a is MeddlingAction || a.IsCompleted)
continue;
currentTasks = true;
break;
}
if (currentTasks)
{
using (var dlg = new CloseXenCenterWarningDialog(true))
{
if (dlg.ShowDialog(parent) != DialogResult.OK)
{
downloadAndInstallClientAction.ReleaseDownloadedContent();
return;
}
}
}
try
{
Process.Start(outputPathAndFileName);
log.DebugFormat("Update {0} found and install started", updateAlert.Name);
downloadAndInstallClientAction.ReleaseDownloadedContent();
Application.Exit();
}
catch (Exception e)
{
log.Error("Exception occurred when starting the installation process.", e);
downloadAndInstallClientAction.ReleaseDownloadedContent(true);
using (var dlg = new ErrorDialog(Messages.UPDATE_CLIENT_FAILED_INSTALLER_LAUNCH))
dlg.ShowDialog(parent);
}
}
public static void DownloadSource(IWin32Window parent)
{
// If no update no need to show where to save dialog
var clientVersion = Updates.ClientVersions.FirstOrDefault();
if (clientVersion == null)
{
// There is no XCUpdates.xml so direct to website.
Program.OpenURL(InvisibleMessages.WEBSITE_DOWNLOADS);
}
else
{
string outputPathAndFileName;
using (var saveSourceDialog = new SaveFileDialog())
{
saveSourceDialog.FileName = $"{BrandManager.BrandConsole}-v{clientVersion.Version}-source.zip";
saveSourceDialog.DefaultExt = "zip";
saveSourceDialog.Filter = "(*.zip)|*.zip|All files (*.*)|*.*";
saveSourceDialog.InitialDirectory = Win32.GetKnownFolderPath(Win32.KnownFolders.Downloads);
if (saveSourceDialog.ShowDialog(parent) != DialogResult.OK)
{
return;
}
outputPathAndFileName = saveSourceDialog.FileName;
}
var downloadSourceAction = new DownloadSourceAction(clientVersion.Name, new Uri(clientVersion.SourceUrl), outputPathAndFileName);
downloadSourceAction.RunAsync();
}
}
}
}

View File

@ -0,0 +1,108 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Diagnostics;
using System.Xml;
using XenAPI;
namespace XenAdmin.Alerts
{
public class CssExpiryAlert : MessageAlert
{
private readonly DateTime? _cssExpiryDate;
private readonly string _title;
private readonly string _description;
public CssExpiryAlert(Message m)
: base(m)
{
try
{
var doc = new XmlDocument();
doc.LoadXml(m.body);
var nodes = doc.GetElementsByTagName("date");
if (nodes.Count > 0 && Util.TryParseIso8601DateTime(nodes[0].InnerText, out var result))
_cssExpiryDate = result;
}
catch
{
//ignore
}
switch (Message.Type)
{
case Message.MessageType.UPDATES_FEATURE_EXPIRED:
_title = Messages.ALERT_CSS_EXPIRED_TITLE;
_description = string.Format(Messages.ALERT_CSS_EXPIRED_DESCIRPTION, AlertExtensions.GetGuiDate(_cssExpiryDate));
break;
case Message.MessageType.UPDATES_FEATURE_EXPIRING_CRITICAL:
case Message.MessageType.UPDATES_FEATURE_EXPIRING_MAJOR:
case Message.MessageType.UPDATES_FEATURE_EXPIRING_WARNING:
if (_cssExpiryDate.HasValue && _cssExpiryDate.Value > Timestamp)
{
var eta = _cssExpiryDate.Value - Timestamp;
if (eta.TotalDays >= 1)
_title = string.Format(Messages.ALERT_CSS_EXPIRING_TITLE_DAYS, Math.Round(eta.TotalDays, MidpointRounding.AwayFromZero));
else if (eta.TotalHours >= 1)
_title = string.Format(Messages.ALERT_CSS_EXPIRING_TITLE_HOURS, Math.Round(eta.TotalHours, MidpointRounding.AwayFromZero));
else if (eta.TotalMinutes >= 1)
_title = string.Format(Messages.ALERT_CSS_EXPIRING_TITLE_MINUTES, Math.Round(eta.TotalMinutes, MidpointRounding.AwayFromZero));
}
else
{
_title = Messages.ALERT_CSS_EXPIRED_TITLE;
}
_description = string.Format(Messages.ALERT_CSS_EXPIRING_DESCRIPTION, AlertExtensions.GetGuiDate(_cssExpiryDate));
break;
}
}
public override string Title => string.IsNullOrEmpty(_title) ? base.Title : _title;
public override string Description => string.IsNullOrEmpty(_description) ? base.Title : _description;
public override Action FixLinkAction => () => Process.Start(InvisibleMessages.CSS_URL);
public override string FixLinkText => Messages.ALERT_CSS_EXPIRED_LINK_TEXT;
public override string HelpID => "CssExpiryAlert";
public override string HelpLinkText => Messages.ALERT_GENERIC_HELP;
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided

View File

@ -0,0 +1,203 @@
/* Copyright (c) Cloud Software Group, Inc.
*
* 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.Xml;
using XenAdmin.Core;
using XenAPI;
namespace XenAdmin.Alerts
{
public class FailedLoginAttemptAlert : MessageAlert
{
private readonly Pool _pool;
private readonly int _total;
private readonly int _unknown;
private readonly List<Offender> _topOffenders = new List<Offender>();
public FailedLoginAttemptAlert(Message m)
: base(m)
{
_pool = m.Connection.Cache.Pools.FirstOrDefault(p => p.uuid == m.obj_uuid);
try
{
/* - Total and unknown are optional (unknown being absent implies that all the failed
logins came from known sources, and conversely total being absent implies that all
the failed logins came from unknown sources).
- There may be 0 or more known tags.
- Each known tag must contain date and number, but the other tags (ip, originator,
username, useragent) are all optional (though we expect at least one) */
var doc = new XmlDocument();
doc.LoadXml(m.body);
var totalNodes = doc.GetElementsByTagName("total");
if (totalNodes.Count > 0)
int.TryParse(totalNodes[0].InnerText, out _total);
var unknownNodes = doc.GetElementsByTagName("unknown");
if (unknownNodes.Count > 0)
int.TryParse(unknownNodes[0].InnerText, out _unknown);
var knownNodes = doc.GetElementsByTagName("known");
foreach (XmlNode node in knownNodes)
{
var offender = new Offender();
foreach (XmlNode child in node.ChildNodes)
{
switch (child.Name)
{
case "number":
if (int.TryParse(child.InnerText, out var number))
offender.Number = number;
break;
case "date":
if (Util.TryParseIso8601DateTime(child.InnerText, out var date))
offender.Date = date;
break;
case "ip":
offender.Ip = child.InnerText;
break;
case "originator":
offender.Originator = child.InnerText;
break;
case "username":
offender.Username = child.InnerText;
break;
case "useragent":
offender.Useragent = child.InnerText;
break;
}
}
_topOffenders.Add(offender);
}
}
catch
{
//ignore
}
}
public override string Title => _pool == null
? base.Title
: string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_TITLE, _pool.Name());
public override string Description
{
get
{
if (_total == 0 && _unknown > 0)
return string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_DESCRIPTION_ALL_UNKNOWN, _unknown);
var sb = new StringBuilder();
if (_total > 0)
sb.AppendLine(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_DESCRIPTION_TOTAL, _total));
if (_unknown > 0)
sb.AppendLine(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_DESCRIPTION_UNKNOWN, _unknown));
if (_topOffenders.Count > 0)
{
sb.AppendLine(Messages.ALERT_FAILED_LOGIN_ATTEMPT_DESCRIPTION_COMMON);
foreach (var offender in _topOffenders)
sb.AppendLine(offender.ToString());
}
return sb.Length > 0 ? sb.ToString() : base.Title;
}
}
public override Action FixLinkAction => null;
public override string FixLinkText => null;
public override string HelpID => "FailedLoginAttemptAlert";
public override string HelpLinkText => Messages.ALERT_GENERIC_HELP;
private class Offender
{
/// <summary>
/// Number of failed login attempts from this offender
/// </summary>
public int Number { get; set; }
/// <summary>
/// DateTime of last failed login attempt from this offender
/// </summary>
public DateTime? Date { private get; set;}
/// <summary>
/// Offender IP address
/// </summary>
public string Ip { get; set;}
public string Originator { get; set;}
public string Username { get; set;}
public string Useragent { get; set;}
public override string ToString()
{
var entries = new List<string>();
if (!string.IsNullOrEmpty(Ip))
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_IP, Ip));
if (Number > 0)
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_NUMBER, Number));
var friendlyDate = AlertExtensions.GetGuiDate(Date);
if (!string.IsNullOrEmpty(friendlyDate))
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_DATE, friendlyDate));
if (!string.IsNullOrEmpty(Username))
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_USERNAME, Username));
if (!string.IsNullOrEmpty(Originator))
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_ORIGINATOR, Originator));
if (!string.IsNullOrEmpty(Useragent))
entries.Add(string.Format(Messages.ALERT_FAILED_LOGIN_ATTEMPT_OFFENDER_USERAGENT, Useragent));
return $"- {string.Join(", ", entries)}";
}
}
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -30,8 +29,7 @@
*/
using System;
using System.Collections.Generic;
using System.Text;
using XenAdmin.Core;
namespace XenAdmin.Alerts
@ -43,51 +41,21 @@ namespace XenAdmin.Alerts
_timestamp = DateTime.Now;
}
public override AlertPriority Priority { get { return AlertPriority.Priority5; } }
public override AlertPriority Priority => AlertPriority.Priority5;
public override string AppliesTo
{
get
{
return Messages.XENCENTER;
}
}
public override string AppliesTo => BrandManager.BrandConsole;
public override string Description
{
get
{
return Messages.NEWER_GUI_AVAILABLE;
}
}
public override string Description => string.Format(Messages.NEWER_GUI_AVAILABLE, BrandManager.BrandConsole);
public override Action FixLinkAction
{
get { return () => Program.OpenURL(InvisibleMessages.OUT_OF_DATE_WEBSITE); }
get { return () => Program.OpenURL(InvisibleMessages.WEBSITE_DOWNLOADS); }
}
public override string FixLinkText
{
get
{
return Messages.ALERT_NEW_VERSION_DOWNLOAD;
}
}
public override string FixLinkText => Messages.ALERT_NEW_VERSION_DOWNLOAD;
public override string HelpID
{
get
{
return "GuiOldAlert";
}
}
public override string HelpID => "GuiOldAlert";
public override string Title
{
get
{
return Messages.XENCENTER_NEWER_AVAILABLE;
}
}
public override string Title => string.Format(Messages.XENCENTER_NEWER_AVAILABLE, BrandManager.BrandConsole);
}
}

View File

@ -1,5 +1,4 @@
/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
@ -44,7 +43,7 @@ namespace XenAdmin.Alerts.Types
public HotfixEligibilityAlert(IXenConnection connection, XenServerVersion version)
{
Connection = connection;
this.Version = version;
Version = version;
pool = Helpers.GetPoolOfOne(connection);
_timestamp = DateTime.Now;
}
@ -59,8 +58,8 @@ namespace XenAdmin.Alerts.Types
return string.Empty;
var productVersionText = string.Format(Messages.STRING_SPACE_STRING,
Helpers.NaplesOrGreater(Connection) ? Messages.XENSERVER : BrandManager.LegacyProduct,
Helpers.GetMaster(Connection)?.ProductVersionText());
!Helpers.NaplesOrGreater(Connection) || Helpers.CloudOrGreater(Connection) ? BrandManager.ProductBrand : BrandManager.LegacyProduct,
Helpers.GetCoordinator(Connection)?.ProductVersionText());
var unlicensed = pool.IsFreeLicenseOrExpired();
switch (Version.HotfixEligibility)
@ -68,7 +67,7 @@ namespace XenAdmin.Alerts.Types
// all + the EOL date is known -> "Approaching EOL" alert
case hotfix_eligibility.all when Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_TITLE_APPROACHING_EOL,
productVersionText, GetEolDate());
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate));
// premium + unlicensed host -> "EOL for express customers" alert
case hotfix_eligibility.premium when unlicensed:
@ -77,7 +76,7 @@ namespace XenAdmin.Alerts.Types
// premium + licensed host and the EOL date is known -> "Approaching EOL" alert
case hotfix_eligibility.premium when Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_TITLE_APPROACHING_EOL,
productVersionText, GetEolDate());
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate));
// cu -> "EOL for express customers" / "CU for licensed customers" alert
case hotfix_eligibility.cu when pool.IsFreeLicenseOrExpired():
@ -103,9 +102,9 @@ namespace XenAdmin.Alerts.Types
if (pool == null)
return string.Empty;
var versionText = Helpers.GetMaster(Connection)?.ProductVersionText();
var productVersionText = string.Format(Messages.STRING_SPACE_STRING,
Helpers.NaplesOrGreater(Connection) ? Messages.XENSERVER : BrandManager.LegacyProduct,
var versionText = Helpers.GetCoordinator(Connection)?.ProductVersionText();
var productVersionText = string.Format(Messages.STRING_SPACE_STRING,
!Helpers.NaplesOrGreater(Connection) || Helpers.CloudOrGreater(Connection) ? BrandManager.ProductBrand : BrandManager.LegacyProduct,
versionText);
var unlicensed = pool.IsFreeLicenseOrExpired();
@ -114,36 +113,36 @@ namespace XenAdmin.Alerts.Types
// all + the EOL date is known -> "Approaching EOL" alert
case hotfix_eligibility.all when unlicensed && Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_APPROACHING_EOL_FREE,
productVersionText, GetEolDate(), versionText);
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate), versionText);
case hotfix_eligibility.all when Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_APPROACHING_EOL,
productVersionText, GetEolDate(), versionText);
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate), versionText);
// premium + unlicensed host -> "EOL for express customers" alert
case hotfix_eligibility.premium when unlicensed && Version.HotfixEligibilityPremiumDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_FREE,
productVersionText, GetPremiumDate());
productVersionText, AlertExtensions.GetGuiDate(Version.HotfixEligibilityPremiumDate));
// premium + licensed host and the EOL date is known -> "Approaching EOL" alert
case hotfix_eligibility.premium when !unlicensed && Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_APPROACHING_EOL,
productVersionText, GetEolDate(), versionText);
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate), versionText);
// cu -> "EOL for express customers" / "CU for licensed customers" alert
case hotfix_eligibility.cu when unlicensed && Version.HotfixEligibilityPremiumDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_FREE,
productVersionText, GetPremiumDate());
productVersionText, AlertExtensions.GetGuiDate(Version.HotfixEligibilityPremiumDate));
case hotfix_eligibility.cu when !unlicensed && Version.HotfixEligibilityNoneDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_CU, productVersionText,
GetNoneDate(), versionText);
AlertExtensions.GetGuiDate(Version.HotfixEligibilityNoneDate), versionText);
// none -> EOL alert
case hotfix_eligibility.none when unlicensed && Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_EOL_FREE,
productVersionText, GetEolDate());
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate));
case hotfix_eligibility.none when Version.EolDate != DateTime.MinValue:
return string.Format(Messages.HOTFIX_ELIGIBILITY_ALERT_DESCRIPTION_EOL,
productVersionText, GetEolDate());
productVersionText, AlertExtensions.GetGuiDate(Version.EolDate));
// everything else
default:
@ -202,44 +201,5 @@ namespace XenAdmin.Alerts.Types
return false;
}
}
private string GetEolDate()
{
string date = string.Empty;
Program.Invoke(Program.MainWindow, () =>
{
date = HelpersGUI.DateTimeToString(Version.EolDate.ToLocalTime(), Messages.DATEFORMAT_DMY, true);
});
return date;
}
private string GetPremiumDate()
{
string date = string.Empty;
Program.Invoke(Program.MainWindow, () =>
{
date = HelpersGUI.DateTimeToString(Version.HotfixEligibilityPremiumDate.ToLocalTime(),
Messages.DATEFORMAT_DMY, true);
});
return date;
}
private string GetNoneDate()
{
string date = string.Empty;
Program.Invoke(Program.MainWindow, () =>
{
date = HelpersGUI.DateTimeToString(Version.HotfixEligibilityNoneDate.ToLocalTime(),
Messages.DATEFORMAT_DMY, true);
});
return date;
}
}
}

Some files were not shown because too many files have changed in this diff Show More