diff --git a/XenAdmin/Commands/Controls/ContextMenuBuilder.cs b/XenAdmin/Commands/Controls/ContextMenuBuilder.cs index d543655e0..1dde41ccf 100644 --- a/XenAdmin/Commands/Controls/ContextMenuBuilder.cs +++ b/XenAdmin/Commands/Controls/ContextMenuBuilder.cs @@ -917,6 +917,7 @@ namespace XenAdmin.Commands items.AddIfEnabled(new AssignGroupToolStripMenuItem(mainWindow, selection, true)); items.AddSeparator(); + items.AddIfEnabled(new VtpmCommand(mainWindow, selection)); items.AddIfEnabled(new InstallToolsCommand(mainWindow, selection)); items.AddSeparator(); diff --git a/XenAdmin/Commands/VtpmCommand.cs b/XenAdmin/Commands/VtpmCommand.cs new file mode 100644 index 000000000..8d2f44964 --- /dev/null +++ b/XenAdmin/Commands/VtpmCommand.cs @@ -0,0 +1,86 @@ +/* Copyright (c) Citrix Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +using System.Collections.Generic; +using XenAdmin.Core; +using XenAdmin.Dialogs; +using XenAPI; + +namespace XenAdmin.Commands +{ + internal class VtpmCommand : Command + { + public VtpmCommand() + { + } + + public VtpmCommand(IMainWindow mainWindow, VM vm) + : base(mainWindow, vm) + { + } + + public VtpmCommand(IMainWindow mainWindow, IEnumerable selection) + : base(mainWindow, selection) + { + } + + protected override bool CanRunCore(SelectedItemCollection selection) + { + return selection.Count == 1 && + selection[0].XenObject is VM vm && + !Helpers.FeatureForbidden(vm, Host.RestrictVtpm) && + Helpers.XapiEqualOrGreater_vtpmtag(vm.Connection) && + vm.IsUEFIEnabled(); + } + + protected override string GetCantRunReasonCore(IXenObject item) + { + if (item is VM vm && + !Helpers.FeatureForbidden(vm, Host.RestrictVtpm) && + Helpers.XapiEqualOrGreater_vtpmtag(vm.Connection) && + !vm.IsUEFIEnabled()) + return Messages.COMMAND_VTPM_DISABLED_NON_UEFI; + + return base.GetCantRunReasonCore(item); + } + + protected override void RunCore(SelectedItemCollection selection) + { + var vm = selection[0].XenObject as VM; + new VtpmManagementDialog(vm).ShowPerXenObject(vm, MainWindowCommandInterface.Form); + } + + public override string ContextMenuText => MenuText; + + public override string MenuText => Messages.COMMAND_VTPM_MENU; + } +} diff --git a/XenAdmin/Dialogs/NetworkingProperties.Designer.cs b/XenAdmin/Dialogs/NetworkingProperties.Designer.cs index 42b04d1d6..200737716 100644 --- a/XenAdmin/Dialogs/NetworkingProperties.Designer.cs +++ b/XenAdmin/Dialogs/NetworkingProperties.Designer.cs @@ -112,8 +112,6 @@ namespace XenAdmin.Dialogs this.Controls.Add(this.linkLabelTellMeMore); this.Controls.Add(this.BlurbLabel); this.Name = "NetworkingProperties"; - this.HelpButtonClicked += new System.ComponentModel.CancelEventHandler(this.NetworkingProperties_HelpButtonClicked); - this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.NetworkingProperties_HelpRequested); this.Controls.SetChildIndex(this.okButton, 0); this.Controls.SetChildIndex(this.cancelButton, 0); this.Controls.SetChildIndex(this.splitContainer, 0); diff --git a/XenAdmin/Dialogs/NetworkingProperties.cs b/XenAdmin/Dialogs/NetworkingProperties.cs index 0a055a0b5..b23138169 100644 --- a/XenAdmin/Dialogs/NetworkingProperties.cs +++ b/XenAdmin/Dialogs/NetworkingProperties.cs @@ -629,16 +629,6 @@ namespace XenAdmin.Dialogs return (XenAPI.Network)((NetworkingPropertiesPage)verticalTabs.Items[0]).NetworkComboBox.SelectedItem; } - private void NetworkingProperties_HelpButtonClicked(object sender, CancelEventArgs e) - { - HelpManager.Launch("NetworkingProperties"); - } - - private void NetworkingProperties_HelpRequested(object sender, HelpEventArgs hlpevent) - { - HelpManager.Launch("NetworkingProperties"); - } - private void splitContainer_Panel1_Resize(object sender, EventArgs e) { ResizeVerticalTabs(verticalTabs.Items.Count); diff --git a/XenAdmin/Dialogs/PropertiesDialog.Designer.cs b/XenAdmin/Dialogs/PropertiesDialog.Designer.cs index 53ecef19e..b54db8f96 100644 --- a/XenAdmin/Dialogs/PropertiesDialog.Designer.cs +++ b/XenAdmin/Dialogs/PropertiesDialog.Designer.cs @@ -76,6 +76,7 @@ namespace XenAdmin.Dialogs resources.ApplyResources(this, "$this"); this.Name = "PropertiesDialog"; this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.PropertiesDialog_FormClosed); + this.Move += new System.EventHandler(this.PropertiesDialog_Move); this.splitContainer.Panel1.ResumeLayout(false); this.splitContainer.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); diff --git a/XenAdmin/Dialogs/PropertiesDialog.cs b/XenAdmin/Dialogs/PropertiesDialog.cs index 156401b96..e93bde5f3 100755 --- a/XenAdmin/Dialogs/PropertiesDialog.cs +++ b/XenAdmin/Dialogs/PropertiesDialog.cs @@ -569,7 +569,7 @@ namespace XenAdmin.Dialogs } } - private void PropertiesDialog_Moved(object sender, EventArgs e) + private void PropertiesDialog_Move(object sender, EventArgs e) { HideToolTips(); } diff --git a/XenAdmin/Dialogs/VerticallyTabbedDialog.cs b/XenAdmin/Dialogs/VerticallyTabbedDialog.cs index 33a2786f6..0eb288489 100644 --- a/XenAdmin/Dialogs/VerticallyTabbedDialog.cs +++ b/XenAdmin/Dialogs/VerticallyTabbedDialog.cs @@ -63,11 +63,9 @@ namespace XenAdmin.Dialogs TabTitle.Font = titleFont; } - public VerticalTabs.IVerticalTab[] Tabs => - verticalTabs.Items.Cast().ToArray(); + public VerticalTabs.IVerticalTab[] Tabs => verticalTabs.Items.Cast().ToArray(); - public VerticalTabs.IVerticalTab SelectedTab => - verticalTabs.SelectedItem as VerticalTabs.IVerticalTab; + public VerticalTabs.IVerticalTab SelectedTab => verticalTabs.SelectedItem as VerticalTabs.IVerticalTab; protected void SelectPage(VerticalTabs.IVerticalTab page) { @@ -79,34 +77,27 @@ namespace XenAdmin.Dialogs private void verticalTabs_SelectedIndexChanged(object sender, EventArgs e) { - ListBox listBox = sender as ListBox; - if (sender == null) - return; + if (sender is ListBox listBox && + listBox.SelectedItem is VerticalTabs.IVerticalTab editPage && + editPage is Control control) + { + TabImage.Image = editPage.Image; + TabTitle.Text = GetTabTitle(editPage); - VerticalTabs.IVerticalTab editPage = listBox.SelectedItem as VerticalTabs.IVerticalTab; - if (editPage == null) - return; + control.Show(); + control.BringToFront(); - Control control = editPage as Control; - if (control == null) - return; - - TabImage.Image = editPage.Image; - TabTitle.Text = GetTabTitle(editPage); - - control.Show(); - control.BringToFront(); - - foreach(Control other in ContentPanel.Controls) - if (other != control) + foreach (Control other in ContentPanel.Controls) { - other.Hide(); + if (other != control) + other.Hide(); } + } } protected virtual string GetTabTitle(VerticalTabs.IVerticalTab verticalTab) { - return verticalTab != null ? verticalTab.Text : String.Empty; + return verticalTab != null ? verticalTab.Text : string.Empty; } /// @@ -119,8 +110,7 @@ namespace XenAdmin.Dialogs if (!DesignMode) return; - VerticalTabs.IVerticalTab verticalTab = e.Control as VerticalTabs.IVerticalTab; - if (verticalTab == null) + if (!(e.Control is VerticalTabs.IVerticalTab verticalTab)) return; foreach (VerticalTabs.IVerticalTab vt in verticalTabs.Items) @@ -138,8 +128,7 @@ namespace XenAdmin.Dialogs if (!DesignMode) return; - VerticalTabs.IVerticalTab verticalTab = e.Control as VerticalTabs.IVerticalTab; - if (verticalTab == null) + if (!(e.Control is VerticalTabs.IVerticalTab verticalTab)) return; verticalTabs.Items.Remove(verticalTab); diff --git a/XenAdmin/Dialogs/VtmpManagementDialog.Designer.cs b/XenAdmin/Dialogs/VtmpManagementDialog.Designer.cs new file mode 100644 index 000000000..0af905df4 --- /dev/null +++ b/XenAdmin/Dialogs/VtmpManagementDialog.Designer.cs @@ -0,0 +1,149 @@ +namespace XenAdmin.Dialogs +{ + partial class VtpmManagementDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + UnregisterEvents(); + if (components != null) + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VtpmManagementDialog)); + this.BlurbLabel = new System.Windows.Forms.Label(); + this.addButton = new System.Windows.Forms.Button(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.toolTipContainerAdd = new XenAdmin.Controls.ToolTipContainer(); + this.labelNoVtpms = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.blueBorder.SuspendLayout(); + this.toolTipContainerAdd.SuspendLayout(); + this.SuspendLayout(); + // + // ContentPanel + // + resources.ApplyResources(this.ContentPanel, "ContentPanel"); + // + // verticalTabs + // + this.verticalTabs.BorderStyle = System.Windows.Forms.BorderStyle.None; + resources.ApplyResources(this.verticalTabs, "verticalTabs"); + this.verticalTabs.MouseClick += new System.Windows.Forms.MouseEventHandler(this.verticalTabs_MouseClick); + this.verticalTabs.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.verticalTabs_DrawItem); + this.verticalTabs.MouseMove += new System.Windows.Forms.MouseEventHandler(this.verticalTabs_MouseMove); + // + // cancelButton + // + this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + resources.ApplyResources(this.cancelButton, "cancelButton"); + this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + // + // okButton + // + resources.ApplyResources(this.okButton, "okButton"); + // + // splitContainer + // + this.splitContainer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + resources.ApplyResources(this.splitContainer, "splitContainer"); + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.BackColor = System.Drawing.SystemColors.Window; + this.splitContainer.Panel1.Controls.Add(this.toolTipContainerAdd); + this.splitContainer.Panel1.Resize += new System.EventHandler(this.splitContainer_Panel1_Resize); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.labelNoVtpms); + // + // blueBorder + // + resources.ApplyResources(this.blueBorder, "blueBorder"); + // + // BlurbLabel + // + resources.ApplyResources(this.BlurbLabel, "BlurbLabel"); + this.BlurbLabel.Name = "BlurbLabel"; + this.BlurbLabel.UseMnemonic = false; + // + // addButton + // + this.addButton.BackColor = System.Drawing.SystemColors.Window; + this.addButton.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.addButton, "addButton"); + this.addButton.FlatAppearance.BorderSize = 0; + this.addButton.FlatAppearance.MouseDownBackColor = System.Drawing.Color.Transparent; + this.addButton.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent; + this.addButton.Image = global::XenAdmin.Properties.Resources.sl_add_storage_system_small_16; + this.addButton.Name = "addButton"; + this.addButton.UseVisualStyleBackColor = false; + this.addButton.Click += new System.EventHandler(this.addButton_Click); + // + // toolTipContainerAdd + // + this.toolTipContainerAdd.Controls.Add(this.addButton); + this.toolTipContainerAdd.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.toolTipContainerAdd, "toolTipContainerAdd"); + this.toolTipContainerAdd.Name = "toolTipContainerAdd"; + // + // labelNoVtpms + // + this.labelNoVtpms.BackColor = System.Drawing.SystemColors.Window; + resources.ApplyResources(this.labelNoVtpms, "labelNoVtpms"); + this.labelNoVtpms.Name = "labelNoVtpms"; + // + // VtpmManagementDialog + // + resources.ApplyResources(this, "$this"); + this.Controls.Add(this.BlurbLabel); + this.Name = "VtpmManagementDialog"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; + this.Controls.SetChildIndex(this.okButton, 0); + this.Controls.SetChildIndex(this.cancelButton, 0); + this.Controls.SetChildIndex(this.splitContainer, 0); + this.Controls.SetChildIndex(this.BlurbLabel, 0); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.blueBorder.ResumeLayout(false); + this.toolTipContainerAdd.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label BlurbLabel; + private System.Windows.Forms.Button addButton; + private System.Windows.Forms.ToolTip toolTip; + private Controls.ToolTipContainer toolTipContainerAdd; + private System.Windows.Forms.Label labelNoVtpms; + } +} diff --git a/XenAdmin/Dialogs/VtmpManagementDialog.cs b/XenAdmin/Dialogs/VtmpManagementDialog.cs new file mode 100644 index 000000000..a8de92c0c --- /dev/null +++ b/XenAdmin/Dialogs/VtmpManagementDialog.cs @@ -0,0 +1,320 @@ +/* Copyright (c) Citrix Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using XenAdmin.Actions; +using XenAdmin.Core; +using XenAdmin.Help; +using XenAPI; + + +namespace XenAdmin.Dialogs +{ + public partial class VtpmManagementDialog : VerticallyTabbedDialog + { + private readonly VM _vm; + private bool _toolTipVisible; + private XenRef _selectedVtpm; + + public VtpmManagementDialog(VM vm) + { + InitializeComponent(); + _vm = vm; + RegisterEvents(); + } + + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + + Text = string.Format(Text, _vm.Name().Ellipsise(50)); + BlurbLabel.Text = string.Format(BlurbLabel.Text, _vm.Name().Ellipsise(80)); + RefreshTabs(); + } + + private void RegisterEvents() + { + _vm.PropertyChanged += _vm_PropertyChanged; + } + + private void UnregisterEvents() + { + _vm.PropertyChanged -= _vm_PropertyChanged; + } + + private VtpmManagementPage CreateVtpmPage(VTPM vtpm) + { + var page = new VtpmManagementPage(vtpm) + { + Parent = ContentPanel, + TabStop = true, + Dock = DockStyle.Fill + }; + page.RemoveButtonClicked += Page_RemoveButtonClicked; + return page; + } + + private void RefreshTabs() + { + if (verticalTabs.SelectedItem is VtpmManagementPage p) + _selectedVtpm = new XenRef(p.Vtpm.opaque_ref); + else + _selectedVtpm = null; + + var tabsToRemove = (from object tab in verticalTabs.Items + let page = tab as VtpmManagementPage + where page != null && _vm.VTPMs.All(t => t.opaque_ref != page.Vtpm.opaque_ref) + select page).ToList(); + + foreach (var tab in tabsToRemove) + { + verticalTabs.Items.Remove(tab); + ContentPanel.Controls.Remove(tab); + } + + var newVtpmPages = new List(); + + foreach (var vtpmRef in _vm.VTPMs) + { + var page = FindTabFromVtpm(vtpmRef); + if (page == null) + { + VTPM vtpm = _vm.Connection.Resolve(vtpmRef); + if (vtpm != null) + { + page = CreateVtpmPage(vtpm); + newVtpmPages.Add(page); + } + } + + page?.Repopulate(); + } + + verticalTabs.Items.AddRange(newVtpmPages.ToArray()); + ResizeVerticalTabs(); + + VtpmManagementPage selectedPage = null; + if (_selectedVtpm != null) + selectedPage = FindTabFromVtpm(_selectedVtpm); + else if (verticalTabs.Items.Count > 0) + selectedPage = verticalTabs.Items[0] as VtpmManagementPage; + + verticalTabs.SelectedItem = selectedPage; + + blueBorder.Visible = verticalTabs.SelectedItem != null; + labelNoVtpms.Visible = verticalTabs.SelectedItem == null; + + addButton.Enabled = _vm.CanAddVtpm(out var cannotReason); + if (string.IsNullOrEmpty(cannotReason)) + toolTipContainerAdd.RemoveAll(); + else + toolTipContainerAdd.SetToolTip(cannotReason); + } + + private VtpmManagementPage FindTabFromVtpm(XenRef vtpmRef) + { + foreach (var tab in verticalTabs.Items) + { + if (tab is VtpmManagementPage page && page.Vtpm.opaque_ref == vtpmRef.opaque_ref) + return page; + } + + return null; + } + + private void AddVtpm() + { + if (!_vm.Connection.Session.IsLocalSuperuser && !Registry.DontSudo && + _vm.Connection.Session.Roles.All(r => r.name_label != Role.MR_ROLE_VM_ADMIN)) + { + var currentRoles = _vm.Connection.Session.Roles; + currentRoles.Sort(); + + var msg = string.Format(Messages.VTPM_RBAC_RESTRICTION_CREATE, currentRoles[0].FriendlyName(), + Role.FriendlyName(Role.MR_ROLE_VM_ADMIN)); + + using (var dlg = new ErrorDialog(msg)) + dlg.ShowDialog(Parent); + + return; + } + + var action = new NewVtpmAction(_vm.Connection, _vm); + using (var dlg = new ActionProgressDialog(action, ProgressBarStyle.Marquee)) + dlg.ShowDialog(this); + } + + private void RemoveVtpm(VTPM vtpm) + { + HideTooltip(); + + using (var dlg = new WarningDialog(Messages.VTPM_REMOVE_WARNING, ThreeButtonDialog.ButtonYes, ThreeButtonDialog.ButtonNo)) + { + if (dlg.ShowDialog() != DialogResult.Yes) + return; + } + + if (!_vm.Connection.Session.IsLocalSuperuser && !Registry.DontSudo && + _vm.Connection.Session.Roles.All(r => r.name_label != Role.MR_ROLE_VM_ADMIN)) + { + var currentRoles = _vm.Connection.Session.Roles; + currentRoles.Sort(); + + var msg = string.Format(Messages.VTPM_RBAC_RESTRICTION_REMOVE, currentRoles[0].FriendlyName(), + Role.FriendlyName(Role.MR_ROLE_VM_ADMIN)); + + using (var dlg = new ErrorDialog(msg)) + dlg.ShowDialog(Parent); + + return; + } + + var action = new RemoveVtpmAction(vtpm.Connection, vtpm); + using (var dlg = new ActionProgressDialog(action, ProgressBarStyle.Marquee)) + dlg.ShowDialog(this); + } + + private void ResizeVerticalTabs() + { + int maxHeight = splitContainer.Panel1.Height - toolTipContainerAdd.Height; + verticalTabs.Height = Math.Min(maxHeight, verticalTabs.Items.Count * verticalTabs.ItemHeight); + toolTipContainerAdd.Top = verticalTabs.Top + verticalTabs.Height; + } + + private void ShowTooltip(Point location) + { + if (!_toolTipVisible) + { + Cursor = Cursors.Hand; + var msg = _vm.CanRemoveVtpm(out var cannotReason) ? Messages.VTPM_REMOVE : cannotReason; + + if (!string.IsNullOrEmpty(cannotReason)) + { + toolTip.Show(msg, verticalTabs, location.X, location.Y + 20); + _toolTipVisible = true; + } + } + } + + private void HideTooltip() + { + toolTip.Hide(verticalTabs); + _toolTipVisible = false; + Cursor = Cursors.Default; + } + + #region Event handlers + + private void _vm_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (!(sender is VM)) + return; + + if (e.PropertyName != "power_state" && e.PropertyName != "VTPMs") + return; + + Program.Invoke(this, RefreshTabs); + } + + private void splitContainer_Panel1_Resize(object sender, EventArgs e) + { + ResizeVerticalTabs(); + } + + private void verticalTabs_DrawItem(object sender, DrawItemEventArgs e) + { + int pageIndex = e.Index; + if (pageIndex < 0 || verticalTabs.Items.Count <= pageIndex) + return; + + if (!(verticalTabs.Items[pageIndex] is VtpmManagementPage page)) + return; + + var deleteIcon = _vm.CanRemoveVtpm(out _) ? Images.StaticImages._000_Abort_h32bit_16 : Images.StaticImages._000_Abort_gray_h32bit_16; + + page.DeleteIconBounds = new Rectangle(e.Bounds.Right - deleteIcon.Width - (32 - deleteIcon.Width) / 2, + e.Bounds.Y + (32 - deleteIcon.Height) / 2, deleteIcon.Width, deleteIcon.Height); + + e.Graphics.DrawImage(deleteIcon, page.DeleteIconBounds); + } + + private void verticalTabs_MouseMove(object sender, MouseEventArgs e) + { + int pageIndex = verticalTabs.IndexFromPoint(e.Location); + if (pageIndex < 0 || verticalTabs.Items.Count <= pageIndex) + return; + + if (!(verticalTabs.Items[pageIndex] is VtpmManagementPage page)) + return; + + if (page.DeleteIconBounds.Contains(e.Location)) + ShowTooltip(e.Location); + else + HideTooltip(); + } + + private void verticalTabs_MouseClick(object sender, MouseEventArgs e) + { + int pageIndex = verticalTabs.IndexFromPoint(e.Location); + if (pageIndex < 0 || verticalTabs.Items.Count <= pageIndex) + return; + + if (!(verticalTabs.Items[pageIndex] is VtpmManagementPage page)) + return; + + if (page.DeleteIconBounds.Contains(e.Location) && _vm.CanRemoveVtpm(out _)) + RemoveVtpm(page.Vtpm); + } + + private void Page_RemoveButtonClicked(VtpmManagementPage page) + { + RemoveVtpm(page.Vtpm); + } + + private void addButton_Click(object sender, EventArgs e) + { + AddVtpm(); + } + + private void cancelButton_Click(object sender, EventArgs e) + { + DialogResult = DialogResult.Cancel; + Close(); + } + + #endregion + } +} \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtmpManagementDialog.ja.resx b/XenAdmin/Dialogs/VtmpManagementDialog.ja.resx new file mode 100644 index 000000000..996c28dd8 --- /dev/null +++ b/XenAdmin/Dialogs/VtmpManagementDialog.ja.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtmpManagementDialog.resx b/XenAdmin/Dialogs/VtmpManagementDialog.resx new file mode 100644 index 000000000..46dc3b4df --- /dev/null +++ b/XenAdmin/Dialogs/VtmpManagementDialog.resx @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 536, 327 + + + + 1 + + + ContentPanel + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + blueBorder + + + 1 + + + + Top + + + 213, 255 + + + 0 + + + verticalTabs + + + XenAdmin.Controls.VerticalTabs, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel1 + + + 0 + + + 700, 426 + + + 3 + + + Close + + + cancelButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 620, 426 + + + 2 + + + False + + + okButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 3 + + + 12, 46 + + + Fill + + + Flat + + + Segoe UI, 9pt + + + MiddleLeft + + + NoControl + + + 0, 0 + + + 88, 25 + + + 0 + + + A&dd vTPM + + + MiddleLeft + + + ImageBeforeText + + + addButton + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolTipContainerAdd + + + 1 + + + Segoe UI, 9pt + + + 0, 300 + + + 0, 0, 0, 0 + + + 88, 25 + + + 1 + + + toolTipContainerAdd + + + XenAdmin.Controls.ToolTipContainer, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + splitContainer.Panel1 + + + 1 + + + splitContainer.Panel1 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 0 + + + Fill + + + Segoe UI, 9pt + + + 0, 0 + + + 542, 372 + + + 0 + + + There are no vTPMs attached to this VM. + + + MiddleCenter + + + labelNoVtpms + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel2 + + + 1 + + + splitContainer.Panel2 + + + System.Windows.Forms.SplitterPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer + + + 1 + + + 763, 374 + + + 215 + + + 1 + + + splitContainer + + + System.Windows.Forms.SplitContainer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + 542, 372 + + + 0 + + + blueBorder + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + splitContainer.Panel2 + + + 0 + + + Top, Left, Right + + + Segoe UI, 9pt + + + NoControl + + + 12, 9 + + + 763, 34 + + + 0 + + + Attach, remove, and configure vTPMs on '{0}'. + + + BlurbLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + 17, 17 + + + True + + + 96, 96 + + + 784, 461 + + + Tahoma, 8pt + + + 800, 500 + + + Trusted Platform Module (TPM) Manager - {0} + + + toolTip + + + System.Windows.Forms.ToolTip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + VtpmManagementDialog + + + XenAdmin.Dialogs.VerticallyTabbedDialog, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtmpManagementDialog.zh-CN.resx b/XenAdmin/Dialogs/VtmpManagementDialog.zh-CN.resx new file mode 100644 index 000000000..996c28dd8 --- /dev/null +++ b/XenAdmin/Dialogs/VtmpManagementDialog.zh-CN.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtpmManagementPage.Designer.cs b/XenAdmin/Dialogs/VtpmManagementPage.Designer.cs new file mode 100644 index 000000000..09797e9ac --- /dev/null +++ b/XenAdmin/Dialogs/VtpmManagementPage.Designer.cs @@ -0,0 +1,148 @@ +namespace XenAdmin.Dialogs +{ + partial class VtpmManagementPage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) + { + UnregisterEvents(); + + if (components != null) + components.Dispose(); + } + + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VtpmManagementPage)); + this.tableLayoutPanelBody = new System.Windows.Forms.TableLayoutPanel(); + this.buttonReset = new System.Windows.Forms.Button(); + this.groupBoxProperties = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.labelProtectedKey = new System.Windows.Forms.Label(); + this.labelUniqueValue = new System.Windows.Forms.Label(); + this.labelProtectedValue = new System.Windows.Forms.Label(); + this.labelUniqueKey = new System.Windows.Forms.Label(); + this.toolTipContainerRemove = new XenAdmin.Controls.ToolTipContainer(); + this.buttonRemove = new System.Windows.Forms.Button(); + this.tableLayoutPanelBody.SuspendLayout(); + this.groupBoxProperties.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.toolTipContainerRemove.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanelBody + // + this.tableLayoutPanelBody.BackColor = System.Drawing.Color.Transparent; + resources.ApplyResources(this.tableLayoutPanelBody, "tableLayoutPanelBody"); + this.tableLayoutPanelBody.Controls.Add(this.buttonReset, 0, 2); + this.tableLayoutPanelBody.Controls.Add(this.groupBoxProperties, 0, 0); + this.tableLayoutPanelBody.Controls.Add(this.toolTipContainerRemove, 1, 2); + this.tableLayoutPanelBody.Name = "tableLayoutPanelBody"; + // + // buttonReset + // + resources.ApplyResources(this.buttonReset, "buttonReset"); + this.buttonReset.Name = "buttonReset"; + this.buttonReset.UseVisualStyleBackColor = true; + this.buttonReset.Click += new System.EventHandler(this.buttonReset_Click); + // + // groupBoxProperties + // + this.tableLayoutPanelBody.SetColumnSpan(this.groupBoxProperties, 2); + this.groupBoxProperties.Controls.Add(this.tableLayoutPanel1); + resources.ApplyResources(this.groupBoxProperties, "groupBoxProperties"); + this.groupBoxProperties.Name = "groupBoxProperties"; + this.groupBoxProperties.TabStop = false; + // + // tableLayoutPanel1 + // + resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1"); + this.tableLayoutPanel1.Controls.Add(this.labelProtectedKey, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.labelUniqueValue, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.labelProtectedValue, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.labelUniqueKey, 0, 1); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + // + // labelProtectedKey + // + resources.ApplyResources(this.labelProtectedKey, "labelProtectedKey"); + this.labelProtectedKey.Name = "labelProtectedKey"; + // + // labelUniqueValue + // + resources.ApplyResources(this.labelUniqueValue, "labelUniqueValue"); + this.labelUniqueValue.Name = "labelUniqueValue"; + // + // labelProtectedValue + // + resources.ApplyResources(this.labelProtectedValue, "labelProtectedValue"); + this.labelProtectedValue.Name = "labelProtectedValue"; + // + // labelUniqueKey + // + resources.ApplyResources(this.labelUniqueKey, "labelUniqueKey"); + this.labelUniqueKey.Name = "labelUniqueKey"; + // + // toolTipContainerRemove + // + this.toolTipContainerRemove.Controls.Add(this.buttonRemove); + resources.ApplyResources(this.toolTipContainerRemove, "toolTipContainerRemove"); + this.toolTipContainerRemove.Name = "toolTipContainerRemove"; + // + // buttonRemove + // + resources.ApplyResources(this.buttonRemove, "buttonRemove"); + this.buttonRemove.Image = global::XenAdmin.Properties.Resources._000_Abort_h32bit_16; + this.buttonRemove.Name = "buttonRemove"; + this.buttonRemove.Tag = ""; + this.buttonRemove.UseVisualStyleBackColor = true; + this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click); + // + // VtpmManagementPage + // + this.BackColor = System.Drawing.Color.Transparent; + this.Controls.Add(this.tableLayoutPanelBody); + this.DoubleBuffered = true; + resources.ApplyResources(this, "$this"); + this.Name = "VtpmManagementPage"; + this.tableLayoutPanelBody.ResumeLayout(false); + this.groupBoxProperties.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.toolTipContainerRemove.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TableLayoutPanel tableLayoutPanelBody; + private System.Windows.Forms.Button buttonRemove; + private System.Windows.Forms.Button buttonReset; + private System.Windows.Forms.Label labelProtectedKey; + private System.Windows.Forms.GroupBox groupBoxProperties; + private System.Windows.Forms.Label labelUniqueKey; + private System.Windows.Forms.Label labelUniqueValue; + private System.Windows.Forms.Label labelProtectedValue; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private Controls.ToolTipContainer toolTipContainerRemove; + } +} diff --git a/XenAdmin/Dialogs/VtpmManagementPage.cs b/XenAdmin/Dialogs/VtpmManagementPage.cs new file mode 100644 index 000000000..cf05e1549 --- /dev/null +++ b/XenAdmin/Dialogs/VtpmManagementPage.cs @@ -0,0 +1,114 @@ +/* Copyright (c) Citrix Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using XenAdmin.Controls; +using XenAdmin.Core; +using XenAPI; + + +namespace XenAdmin.Dialogs +{ + public partial class VtpmManagementPage : UserControl, VerticalTabs.IVerticalTab + { + public event Action RemoveButtonClicked; + + public VtpmManagementPage(VTPM vtpm) + { + InitializeComponent(); + buttonReset.Visible = false; + Vtpm = vtpm; + RegisterEvents(); + } + + public override string Text => Messages.VTPM; + public VTPM Vtpm { get; } + public string SubText { get; } + public Image Image => Images.StaticImages.tpm; + public Rectangle DeleteIconBounds { get; set; } + + private void RegisterEvents() + { + Vtpm.PropertyChanged += Vtpm_PropertyChanged; + } + + private void UnregisterEvents() + { + Vtpm.PropertyChanged -= Vtpm_PropertyChanged; + } + + public void Repopulate() + { + UpdateProperties(); + UpdateButtons(); + } + + private void UpdateProperties() + { + labelProtectedValue.Text = Vtpm.is_protected.ToYesNoStringI18n(); + labelUniqueValue.Text = Vtpm.is_unique.ToYesNoStringI18n(); + } + + private void UpdateButtons() + { + var vm = Vtpm.Connection.Resolve(Vtpm.VM); + string cannotReason = null; + buttonRemove.Enabled = vm!= null && vm.CanRemoveVtpm(out cannotReason); + + if (buttonRemove.Enabled) + toolTipContainerRemove.RemoveAll(); + else if (!string.IsNullOrEmpty(cannotReason)) + toolTipContainerRemove.SetToolTip(cannotReason); + } + + private void Vtpm_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (!(sender is VTPM)) + return; + + if (e.PropertyName == "is_protected" || e.PropertyName == "is_unique") + Program.Invoke(this, UpdateProperties); + } + + private void buttonRemove_Click(object sender, EventArgs e) + { + RemoveButtonClicked?.Invoke(this); + } + + private void buttonReset_Click(object sender, EventArgs e) + { + //TODO: + } + } +} diff --git a/XenAdmin/Dialogs/VtpmManagementPage.ja.resx b/XenAdmin/Dialogs/VtpmManagementPage.ja.resx new file mode 100644 index 000000000..2a701b682 --- /dev/null +++ b/XenAdmin/Dialogs/VtpmManagementPage.ja.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtpmManagementPage.resx b/XenAdmin/Dialogs/VtpmManagementPage.resx new file mode 100644 index 000000000..3b6999fd1 --- /dev/null +++ b/XenAdmin/Dialogs/VtpmManagementPage.resx @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 2 + + + + 3, 301 + + + 83, 23 + + + 1 + + + &Clear vTPM + + + buttonReset + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanelBody + + + 0 + + + 2 + + + True + + + 0, 5 + + + + 0, 5, 5, 5 + + + 56, 13 + + + 0 + + + Protected: + + + labelProtectedKey + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 0 + + + True + + + 61, 28 + + + 0, 5, 5, 5 + + + 90, 13 + + + 3 + + + labelUniqueValue + + + labelUniqueValue + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 1 + + + True + + + 61, 5 + + + 0, 5, 5, 5 + + + 102, 13 + + + 1 + + + labelProtectedValue + + + labelProtectedValue + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 2 + + + True + + + 0, 28 + + + 0, 5, 5, 5 + + + 44, 13 + + + 2 + + + Unique: + + + labelUniqueKey + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 3 + + + Fill + + + 3, 16 + + + 3, 0, 3, 0 + + + 2 + + + 393, 81 + + + 0 + + + tableLayoutPanel1 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxProperties + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="labelProtectedKey" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="labelUniqueValue" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="labelProtectedValue" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="labelUniqueKey" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="AutoSize,0,Percent,100" /><Rows Styles="AutoSize,0,Percent,100" /></TableLayoutSettings> + + + Fill + + + 3, 3 + + + 399, 100 + + + 0 + + + Properties + + + groupBoxProperties + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanelBody + + + 1 + + + Fill + + + NoControl + + + 0, 0 + + + 5, 0, 0, 0 + + + 118, 23 + + + 0 + + + &Remove vTPM + + + ImageBeforeText + + + buttonRemove + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolTipContainerRemove + + + 1 + + + 284, 301 + + + 118, 23 + + + 2 + + + toolTipContainerRemove + + + XenAdmin.Controls.ToolTipContainer, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + tableLayoutPanelBody + + + 2 + + + Fill + + + 0, 0 + + + 3 + + + 405, 327 + + + 0 + + + tableLayoutPanelBody + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="buttonReset" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="groupBoxProperties" Row="0" RowSpan="1" Column="0" ColumnSpan="2" /><Control Name="toolTipContainerRemove" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /></Controls><Columns Styles="Percent,100,AutoSize,0" /><Rows Styles="AutoSize,0,Percent,100,AutoSize,0" /></TableLayoutSettings> + + + True + + + 3, 3, 0, 3 + + + 405, 327 + + + VtpmManagementPage + + + System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/XenAdmin/Dialogs/VtpmManagementPage.zh-CN.resx b/XenAdmin/Dialogs/VtpmManagementPage.zh-CN.resx new file mode 100644 index 000000000..2a701b682 --- /dev/null +++ b/XenAdmin/Dialogs/VtpmManagementPage.zh-CN.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/XenAdmin/Images.cs b/XenAdmin/Images.cs index bc6243694..2f5c2e5d1 100644 --- a/XenAdmin/Images.cs +++ b/XenAdmin/Images.cs @@ -598,6 +598,7 @@ namespace XenAdmin // the following are generated from Resources using: // cat Resources.Designer.cs | grep 'internal static System.Drawing.Bitmap' | sed "s/ {//g" | awk -F"Bitmap " '{print"public static Bitmap " $2 " = Properties.Resources." $2 ";"}' public static Bitmap _000_Abort_h32bit_16 = Properties.Resources._000_Abort_h32bit_16; + public static Bitmap _000_Abort_gray_h32bit_16 = Properties.Resources._000_Abort_gray_h32bit_16; public static Bitmap _000_AddApplicationServer_h32bit_16 = Properties.Resources._000_AddApplicationServer_h32bit_16; public static Bitmap _000_AddApplicationServer_h32bit_24 = Properties.Resources._000_AddApplicationServer_h32bit_24; public static Bitmap _000_AddIPAddress_h32bit_16 = Properties.Resources._000_AddIPAddress_h32bit_16; @@ -895,6 +896,7 @@ namespace XenAdmin public static Bitmap tools_notinstalled_16x = Properties.Resources.tools_notinstalled_16x; public static Bitmap tools_outofdate_16x = Properties.Resources.tools_outofdate_16x; public static Bitmap tools_uptodate_16x = Properties.Resources.tools_uptodate_16x; + public static Bitmap tpm = Properties.Resources.tpm; public static Bitmap tree_minus = Properties.Resources.tree_minus; public static Bitmap tree_plus = Properties.Resources.tree_plus; public static Bitmap tshadowdown = Properties.Resources.tshadowdown; diff --git a/XenAdmin/Images/000_Abort_gray_h32bit_16.png b/XenAdmin/Images/000_Abort_gray_h32bit_16.png new file mode 100644 index 000000000..a990c6abc Binary files /dev/null and b/XenAdmin/Images/000_Abort_gray_h32bit_16.png differ diff --git a/XenAdmin/Images/tpm.png b/XenAdmin/Images/tpm.png new file mode 100644 index 000000000..c958463ed Binary files /dev/null and b/XenAdmin/Images/tpm.png differ diff --git a/XenAdmin/MainWindow.Designer.cs b/XenAdmin/MainWindow.Designer.cs index 28e97b5e2..2a44f1ccf 100644 --- a/XenAdmin/MainWindow.Designer.cs +++ b/XenAdmin/MainWindow.Designer.cs @@ -207,6 +207,8 @@ namespace XenAdmin this.snapshotToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.convertToTemplateToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.exportToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); + this.toolStripSeparator32 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMenuItemVtpm = new XenAdmin.Commands.CommandToolStripMenuItem(); this.disableCbtToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.enablePVSReadcachingToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.disablePVSReadcachingToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); @@ -268,6 +270,7 @@ namespace XenAdmin this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripSeparator(); this.viewApplicationLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripMenuItemCfu = new System.Windows.Forms.ToolStripMenuItem(); this.xenSourceOnTheWebToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.xenCenterPluginsOnlineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); @@ -284,7 +287,6 @@ namespace XenAdmin this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelErrors = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelAlerts = new System.Windows.Forms.ToolStripStatusLabel(); - this.toolStripMenuItemCfu = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -1377,6 +1379,8 @@ namespace XenAdmin this.snapshotToolStripMenuItem, this.convertToTemplateToolStripMenuItem, this.exportToolStripMenuItem, + this.toolStripSeparator32, + this.toolStripMenuItemVtpm, this.disableCbtToolStripMenuItem, this.enablePVSReadcachingToolStripMenuItem, this.disablePVSReadcachingToolStripMenuItem, @@ -1468,6 +1472,17 @@ namespace XenAdmin this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; resources.ApplyResources(this.exportToolStripMenuItem, "exportToolStripMenuItem"); // + // toolStripSeparator32 + // + this.toolStripSeparator32.Name = "toolStripSeparator32"; + resources.ApplyResources(this.toolStripSeparator32, "toolStripSeparator32"); + // + // toolStripMenuItemVtpm + // + this.toolStripMenuItemVtpm.Command = new XenAdmin.Commands.VtpmCommand(); + this.toolStripMenuItemVtpm.Name = "toolStripMenuItemVtpm"; + resources.ApplyResources(this.toolStripMenuItemVtpm, "toolStripMenuItemVtpm"); + // // disableCbtToolStripMenuItem // this.disableCbtToolStripMenuItem.Command = new XenAdmin.Commands.DisableChangedBlockTrackingCommand(); @@ -1874,6 +1889,12 @@ namespace XenAdmin this.toolStripMenuItem17.Name = "toolStripMenuItem17"; resources.ApplyResources(this.toolStripMenuItem17, "toolStripMenuItem17"); // + // toolStripMenuItemCfu + // + this.toolStripMenuItemCfu.Name = "toolStripMenuItemCfu"; + resources.ApplyResources(this.toolStripMenuItemCfu, "toolStripMenuItemCfu"); + this.toolStripMenuItemCfu.Click += new System.EventHandler(this.toolStripMenuItemCfu_Click); + // // xenSourceOnTheWebToolStripMenuItem // this.xenSourceOnTheWebToolStripMenuItem.Name = "xenSourceOnTheWebToolStripMenuItem"; @@ -2007,12 +2028,6 @@ namespace XenAdmin this.statusLabelAlerts.VisitedLinkColor = System.Drawing.SystemColors.ControlDarkDark; this.statusLabelAlerts.Click += new System.EventHandler(this.statusLabelAlerts_Click); // - // toolStripMenuItemCfu - // - this.toolStripMenuItemCfu.Name = "toolStripMenuItemCfu"; - resources.ApplyResources(this.toolStripMenuItemCfu, "toolStripMenuItemCfu"); - this.toolStripMenuItemCfu.Click += new System.EventHandler(this.toolStripMenuItemCfu_Click); - // // MainWindow // resources.ApplyResources(this, "$this"); @@ -2297,6 +2312,8 @@ namespace XenAdmin private System.Windows.Forms.ToolStripMenuItem relNotesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem downloadInstallToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemCfu; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator32; + private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemVtpm; } } diff --git a/XenAdmin/MainWindow.cs b/XenAdmin/MainWindow.cs index ecfac193c..fe8dc001f 100755 --- a/XenAdmin/MainWindow.cs +++ b/XenAdmin/MainWindow.cs @@ -61,7 +61,7 @@ using XenCenterLib; using System.Linq; using XenAdmin.Controls.GradientPanel; using XenAdmin.Help; -using System.IO; + namespace XenAdmin { @@ -1769,13 +1769,19 @@ namespace XenAdmin conversionToolStripMenuItem.Available = conn != null && conn.Cache.VMs.Any(v => v.IsConversionVM()); installToolsToolStripMenuItem.Available = SelectionManager.Selection.Any(v => !Helpers.StockholmOrGreater(v.Connection)); toolStripMenuItemInstallCertificate.Available = Helpers.StockholmOrGreater(conn); + toolStripMenuItemRotateSecret.Available = SelectionManager.Selection.Any(s => s.Connection != null && Helpers.StockholmOrGreater(s.Connection) && !s.Connection.Cache.Hosts.Any(Host.RestrictPoolSecretRotation)); + toolStripMenuItemEnableTls.Available = SelectionManager.Selection.Any(s => s.Connection != null && Helpers.Post82X(s.Connection) && Helpers.XapiEqualOrGreater_1_290_0(s.Connection) && !s.Connection.Cache.Hosts.Any(Host.RestrictCertificateVerification) && s.Connection.Cache.Pools.Any(p => !p.tls_verification_enabled)); + + toolStripMenuItemVtpm.Available = SelectionManager.Selection.Any(s => + s.Connection != null && Helpers.Post82X(s.Connection) && Helpers.XapiEqualOrGreater_vtpmtag(s.Connection) && + !s.Connection.Cache.Hosts.Any(Host.RestrictVtpm)); } private void xenSourceOnTheWebToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/XenAdmin/MainWindow.resx b/XenAdmin/MainWindow.resx index 41cce683f..a5a9447e3 100644 --- a/XenAdmin/MainWindow.resx +++ b/XenAdmin/MainWindow.resx @@ -2311,130 +2311,139 @@ &Server - 242, 22 + 264, 22 &New VM... - 242, 22 + 264, 22 &Start/Shut down - 242, 22 + 264, 22 Res&ume on Server - 242, 22 + 264, 22 M&igrate to Server - 242, 22 + 264, 22 Start &on Server - 239, 6 + 261, 6 - 242, 22 + 264, 22 Assign to Snaps&hot Schedule... - 242, 22 + 264, 22 Assign to &vApp - 239, 6 + 261, 6 - 242, 22 + 264, 22 &Copy VM - 242, 22 + 264, 22 &Move VM - 242, 22 + 264, 22 Ta&ke a Snapshot - 242, 22 + 264, 22 Convert to &Template - 242, 22 + 264, 22 &Export... + + 261, 6 + + + 264, 22 + + + Trusted Plat&form Module Manager... + - 242, 22 + 264, 22 D&isable Changed Block Tracking - 242, 22 + 264, 22 - 242, 22 + 264, 22 - 239, 6 + 261, 6 - 242, 22 + 264, 22 installToolsToolStripMenuItem - 242, 22 + 264, 22 Send Ctrl+&Alt+Del - 239, 6 + 261, 6 - 242, 22 + 264, 22 &Delete VM - 239, 6 + 261, 6 - 242, 22 + 264, 22 PluginItemsPlaceHolder - 242, 22 + 264, 22 P&roperties @@ -3651,6 +3660,18 @@ XenAdmin.Commands.CommandToolStripMenuItem, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + toolStripSeparator32 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolStripMenuItemVtpm + + + XenAdmin.Commands.CommandToolStripMenuItem, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + disableCbtToolStripMenuItem @@ -4017,6 +4038,12 @@ System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripMenuItemCfu + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + xenSourceOnTheWebToolStripMenuItem @@ -4095,12 +4122,6 @@ System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - toolStripMenuItemCfu - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - MainWindow diff --git a/XenAdmin/MainWindowTreeBuilder.cs b/XenAdmin/MainWindowTreeBuilder.cs index 5524142a8..b7c6e1bdb 100644 --- a/XenAdmin/MainWindowTreeBuilder.cs +++ b/XenAdmin/MainWindowTreeBuilder.cs @@ -39,6 +39,7 @@ using XenAPI; using XenAdmin.XenSearch; using XenAdmin.Core; using System.Drawing; +using System.Linq; namespace XenAdmin @@ -396,8 +397,13 @@ namespace XenAdmin private VirtualTreeNode AddVMNode(VM vm) { + if (vm.Connection.Cache.Hosts.Any(Host.RestrictVtpm) && + vm.is_a_template && + vm.platform.TryGetValue("vtpm", out var result) && result.ToLower() == "true") + return null; + bool hidden = vm.IsHidden(); - string name = hidden ? String.Format(Messages.X_HIDDEN, vm.Name()) : vm.Name(); + string name = hidden ? string.Format(Messages.X_HIDDEN, vm.Name()) : vm.Name(); return AddNode(name, Images.GetIconFor(vm), hidden, vm); } diff --git a/XenAdmin/Properties/Resources.Designer.cs b/XenAdmin/Properties/Resources.Designer.cs index 8dbc4e975..b4a874d84 100755 --- a/XenAdmin/Properties/Resources.Designer.cs +++ b/XenAdmin/Properties/Resources.Designer.cs @@ -60,6 +60,16 @@ namespace XenAdmin.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap _000_Abort_gray_h32bit_16 { + get { + object obj = ResourceManager.GetObject("_000_Abort_gray_h32bit_16", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -2169,16 +2179,6 @@ namespace XenAdmin.Properties { return ((System.Drawing.Bitmap)(obj)); } } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap rocky_16x { - get { - object obj = ResourceManager.GetObject("rocky_16x", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } /// /// Looks up a localized resource of type System.Drawing.Bitmap. @@ -2800,6 +2800,16 @@ namespace XenAdmin.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap rocky_16x { + get { + object obj = ResourceManager.GetObject("rocky_16x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -3110,6 +3120,16 @@ namespace XenAdmin.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap tpm { + get { + object obj = ResourceManager.GetObject("tpm", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/XenAdmin/Properties/Resources.resx b/XenAdmin/Properties/Resources.resx index 8084c62d1..1ef09033c 100755 --- a/XenAdmin/Properties/Resources.resx +++ b/XenAdmin/Properties/Resources.resx @@ -1132,4 +1132,10 @@ ..\..\Branding\Images\RightArrow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\000_Abort_gray_h32bit_16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Images\tpm.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/XenAdmin/TabPages/GeneralTabPage.Designer.cs b/XenAdmin/TabPages/GeneralTabPage.Designer.cs index e4e82cf5b..2ec0b21e9 100644 --- a/XenAdmin/TabPages/GeneralTabPage.Designer.cs +++ b/XenAdmin/TabPages/GeneralTabPage.Designer.cs @@ -77,6 +77,8 @@ namespace XenAdmin.TabPages this.panelGeneral = new System.Windows.Forms.Panel(); this.pdSectionGeneral = new XenAdmin.Controls.PDSection(); this.tableLayoutPanelButtons = new System.Windows.Forms.TableLayoutPanel(); + this.panel1DeviceSecurity = new System.Windows.Forms.Panel(); + this.pdSectionDeviceSecurity = new XenAdmin.Controls.PDSection(); this.pageContainerPanel.SuspendLayout(); this.panel2.SuspendLayout(); this.panelReadCaching.SuspendLayout(); @@ -100,6 +102,7 @@ namespace XenAdmin.TabPages this.panelCertificate.SuspendLayout(); this.panelGeneral.SuspendLayout(); this.tableLayoutPanelButtons.SuspendLayout(); + this.panel1DeviceSecurity.SuspendLayout(); this.SuspendLayout(); // // pageContainerPanel @@ -133,6 +136,7 @@ namespace XenAdmin.TabPages // resources.ApplyResources(this.panel2, "panel2"); this.panel2.Controls.Add(this.panelReadCaching); + this.panel2.Controls.Add(this.panel1DeviceSecurity); this.panel2.Controls.Add(this.panelDockerInfo); this.panel2.Controls.Add(this.panelDockerVersion); this.panel2.Controls.Add(this.panelStorageLinkSystemCapabilities); @@ -423,6 +427,19 @@ namespace XenAdmin.TabPages this.tableLayoutPanelButtons.Controls.Add(this.linkLabelExpand, 4, 0); this.tableLayoutPanelButtons.Name = "tableLayoutPanelButtons"; // + // panel1DeviceSecurity + // + resources.ApplyResources(this.panel1DeviceSecurity, "panel1DeviceSecurity"); + this.panel1DeviceSecurity.Controls.Add(this.pdSectionDeviceSecurity); + this.panel1DeviceSecurity.Name = "panel1DeviceSecurity"; + // + // pdSectionDeviceSecurity + // + this.pdSectionDeviceSecurity.BackColor = System.Drawing.Color.Gainsboro; + resources.ApplyResources(this.pdSectionDeviceSecurity, "pdSectionDeviceSecurity"); + this.pdSectionDeviceSecurity.Name = "pdSectionDeviceSecurity"; + this.pdSectionDeviceSecurity.ShowCellToolTips = false; + // // GeneralTabPage // resources.ApplyResources(this, "$this"); @@ -455,6 +472,7 @@ namespace XenAdmin.TabPages this.panelGeneral.ResumeLayout(false); this.tableLayoutPanelButtons.ResumeLayout(false); this.tableLayoutPanelButtons.PerformLayout(); + this.panel1DeviceSecurity.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -507,5 +525,7 @@ namespace XenAdmin.TabPages private System.Windows.Forms.TableLayoutPanel tableLayoutPanelButtons; private System.Windows.Forms.Panel panelCertificate; private Controls.PDSection pdSectionCertificate; + private System.Windows.Forms.Panel panel1DeviceSecurity; + private Controls.PDSection pdSectionDeviceSecurity; } } diff --git a/XenAdmin/TabPages/GeneralTabPage.cs b/XenAdmin/TabPages/GeneralTabPage.cs index a499f593f..b5205a211 100644 --- a/XenAdmin/TabPages/GeneralTabPage.cs +++ b/XenAdmin/TabPages/GeneralTabPage.cs @@ -428,6 +428,7 @@ namespace XenAdmin.TabPages GenerateVCPUsBox(); GenerateDockerInfoBox(); GenerateReadCachingBox(); + GenerateDeviceSecurityBox(); } // hide all the sections which haven't been populated, those that have make sure are visible @@ -1637,6 +1638,22 @@ namespace XenAdmin.TabPages } } + private void GenerateDeviceSecurityBox() + { + if (!(xenObject is VM vm) || Helpers.FeatureForbidden(vm, Host.RestrictVtpm) || + !Helpers.XapiEqualOrGreater_vtpmtag(vm.Connection)) + return; + + PDSection s = pdSectionDeviceSecurity; + + if (vm.VTPMs.Count > 0) + { + s.AddEntry(Messages.VTPM, + vm.VTPMs.Count == 1 ? Messages.VTPM_ATTACHED_ONE : string.Format(Messages.VTPM_ATTACHED_MANY, vm.VTPMs.Count), + new CommandToolStripMenuItem(new VtpmCommand(Program.MainWindow, vm), true)); + } + } + private static bool VMCanChooseHomeServer(VM vm) { if (vm != null && !vm.is_a_template) diff --git a/XenAdmin/TabPages/GeneralTabPage.resx b/XenAdmin/TabPages/GeneralTabPage.resx index 978ec67a7..dccfb8e82 100644 --- a/XenAdmin/TabPages/GeneralTabPage.resx +++ b/XenAdmin/TabPages/GeneralTabPage.resx @@ -169,7 +169,7 @@ Top - 0, 836 + 0, 880 0, 5, 0, 5 @@ -192,6 +192,75 @@ 0 + + True + + + GrowAndShrink + + + Top + + + 0, 5 + + + 900, 9999999 + + + 0, 34 + + + 1, 1, 1, 1 + + + Device Security + + + 715, 34 + + + 0 + + + pdSectionDeviceSecurity + + + XenAdmin.Controls.PDSection, [XenCenter_No_Space]Main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + + + panel1DeviceSecurity + + + 0 + + + Top + + + 0, 836 + + + 0, 5, 0, 5 + + + 715, 44 + + + 20 + + + panel1DeviceSecurity + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel2 + + + 1 + True @@ -259,7 +328,7 @@ panel2 - 1 + 2 True @@ -328,7 +397,7 @@ panel2 - 2 + 3 True @@ -397,7 +466,7 @@ panel2 - 3 + 4 True @@ -466,7 +535,7 @@ panel2 - 4 + 5 True @@ -535,7 +604,7 @@ panel2 - 5 + 6 True @@ -604,7 +673,7 @@ panel2 - 6 + 7 True @@ -673,7 +742,7 @@ panel2 - 7 + 8 True @@ -742,7 +811,7 @@ panel2 - 8 + 9 True @@ -811,7 +880,7 @@ panel2 - 9 + 10 True @@ -880,7 +949,7 @@ panel2 - 10 + 11 True @@ -949,7 +1018,7 @@ panel2 - 11 + 12 True @@ -1018,7 +1087,7 @@ panel2 - 12 + 13 True @@ -1087,7 +1156,7 @@ panel2 - 13 + 14 True @@ -1156,7 +1225,7 @@ panel2 - 14 + 15 True @@ -1225,7 +1294,7 @@ panel2 - 15 + 16 True @@ -1294,7 +1363,7 @@ panel2 - 16 + 17 True @@ -1363,7 +1432,7 @@ panel2 - 17 + 18 True @@ -1432,7 +1501,7 @@ panel2 - 18 + 19 True @@ -1501,7 +1570,7 @@ panel2 - 19 + 20 Fill diff --git a/XenAdmin/Wizards/NewVMWizard/Page_Template.cs b/XenAdmin/Wizards/NewVMWizard/Page_Template.cs index e9d6fc6d6..f8fc597f0 100644 --- a/XenAdmin/Wizards/NewVMWizard/Page_Template.cs +++ b/XenAdmin/Wizards/NewVMWizard/Page_Template.cs @@ -37,6 +37,7 @@ using XenAPI; using XenAdmin.Controls; using XenCenterLib; using System.Collections; +using System.Linq; using XenAdmin.Core; @@ -45,6 +46,7 @@ namespace XenAdmin.Wizards.NewVMWizard public partial class Page_Template : XenTabPage { private bool templatesLoaded; + private VM m_selectedTemplate; public Page_Template() { @@ -80,20 +82,11 @@ namespace XenAdmin.Wizards.NewVMWizard } } - public override string Text - { - get { return Messages.NEWVMWIZARD_TEMPLATEPAGE_NAME; } - } + public override string Text => Messages.NEWVMWIZARD_TEMPLATEPAGE_NAME; - public override string PageTitle - { - get { return Messages.NEWVMWIZARD_TEMPLATEPAGE_TITLE; } - } + public override string PageTitle => Messages.NEWVMWIZARD_TEMPLATEPAGE_TITLE; - public override string HelpID - { - get { return "Template"; } - } + public override string HelpID => "Template"; public override List> PageSummary { @@ -112,9 +105,8 @@ namespace XenAdmin.Wizards.NewVMWizard #endregion - public bool CopyBiosStrings { get { return checkBoxCopyBiosStrings.Checked; } } + public bool CopyBiosStrings => checkBoxCopyBiosStrings.Checked; - private VM m_selectedTemplate; public VM SelectedTemplate { get @@ -141,25 +133,29 @@ namespace XenAdmin.Wizards.NewVMWizard private void AddRows() { - List SelectedRows = new List(); + List selectedRows = new List(); + foreach (TemplatesGridViewItem item in TemplatesGridView.SelectedRows) - { - SelectedRows.Add(item); - } + selectedRows.Add(item); TemplatesGridView.SuspendLayout(); TemplatesGridView.Rows.Clear(); + foreach (VM vm in Connection.Cache.VMs) { if (!vm.is_a_template || !vm.Show(Properties.Settings.Default.ShowHiddenVMs)) continue; + if (vm.Connection.Cache.Hosts.Any(Host.RestrictVtpm) && + vm.platform.TryGetValue("vtpm", out var result) && result.ToLower() == "true") + continue; + TemplatesGridView.Rows.Add(new TemplatesGridViewItem(vm)); } foreach (TemplatesGridViewItem temp in TemplatesGridView.Rows) { - if (SelectedRows.Contains(temp)) + if (selectedRows.Contains(temp)) temp.Selected = true; } @@ -171,12 +167,9 @@ namespace XenAdmin.Wizards.NewVMWizard private void RefreshRows() { - var rows = new List(); foreach (DataGridViewRow row in TemplatesGridView.Rows) - { rows.Add(row); - } TemplatesGridView.Rows.Clear(); @@ -244,22 +237,25 @@ namespace XenAdmin.Wizards.NewVMWizard { public int Compare(object x, object y) { - TemplatesGridViewItem xItem = (TemplatesGridViewItem)x; - TemplatesGridViewItem yItem = (TemplatesGridViewItem)y; + var xItem = x as TemplatesGridViewItem; + var yItem = y as TemplatesGridViewItem; - int xScore = xItem.SortOrder; - int yScore = yItem.SortOrder; + if (xItem == null && yItem == null) + return 0; + if (xItem == null) + return -1; + if (yItem == null) + return 1; - if (xScore != yScore) - return (xScore - yScore); - else - { - int result = StringUtility.NaturalCompare(xItem.Template.Name(), yItem.Template.Name()); - if (result != 0) - return result; - else - return xItem.Template.opaque_ref.CompareTo(yItem.Template.opaque_ref); - } + int result = xItem.SortOrder - yItem.SortOrder; + if (result != 0) + return result; + + result = StringUtility.NaturalCompare(xItem.Template.Name(), yItem.Template.Name()); + if (result != 0) + return result; + + return xItem.Template.opaque_ref.CompareTo(yItem.Template.opaque_ref); } } @@ -276,20 +272,16 @@ namespace XenAdmin.Wizards.NewVMWizard if (template.IsHidden()) SortOrder += (int)VM.VmTemplateType.Count; - var ImageCell = new DataGridViewImageCell(false) - { - ValueType = typeof(Image), - Value = typ.ToBitmap() - }; - var TypeCell = new DataGridViewTextBoxCell { Value = typ.ToDisplayString() }; - var NameCell = new DataGridViewTextBoxCell { Value = template.Name() }; + var imageCell = new DataGridViewImageCell(false) {ValueType = typeof(Image), Value = typ.ToBitmap()}; + var typeCell = new DataGridViewTextBoxCell {Value = typ.ToDisplayString()}; + var nameCell = new DataGridViewTextBoxCell {Value = template.Name()}; - Cells.AddRange(ImageCell, NameCell, TypeCell); + Cells.AddRange(imageCell, nameCell, typeCell); } public bool Equals(TemplatesGridViewItem other) { - return Template.Equals(other.Template); + return Template.Equals(other?.Template); } } } diff --git a/XenAdmin/XenAdmin.csproj b/XenAdmin/XenAdmin.csproj index 150b60a91..dd26de29a 100755 --- a/XenAdmin/XenAdmin.csproj +++ b/XenAdmin/XenAdmin.csproj @@ -111,6 +111,7 @@ + Component @@ -303,6 +304,18 @@ InstallCertificateDialog.cs + + UserControl + + + VtpmManagementPage.cs + + + Form + + + VtmpManagementDialog.cs + UserControl @@ -1803,6 +1816,28 @@ InstallCertificateDialog.cs + + VtpmManagementPage.cs + + + VtpmManagementPage.cs + Designer + + + VtpmManagementPage.cs + + + VtmpManagementDialog.cs + Designer + + + VtmpManagementDialog.cs + Designer + + + VtmpManagementDialog.cs + Designer + ConfirmationOptionsPage.cs @@ -4305,6 +4340,7 @@ + @@ -4555,6 +4591,7 @@ + diff --git a/XenModel/Actions/VtpmAction.cs b/XenModel/Actions/VtpmAction.cs new file mode 100644 index 000000000..5d45a5109 --- /dev/null +++ b/XenModel/Actions/VtpmAction.cs @@ -0,0 +1,75 @@ +/* Copyright (c) Citrix Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +using XenAdmin.Network; +using XenAPI; + +namespace XenAdmin.Actions +{ + public class NewVtpmAction : AsyncAction + { + private readonly VM _vm; + + public VTPM Vtpm { get; private set; } + + public NewVtpmAction(IXenConnection connection, VM vm) + : base(connection, "", "", false) + { + _vm = vm; + + ApiMethodsToRoleCheck.Add("vtpm.create"); + } + + protected override void Run() + { + var vtpmRef = VTPM.create(Session, _vm.opaque_ref, true); + Vtpm = Connection.TryResolveWithTimeout(vtpmRef); + } + } + + public class RemoveVtpmAction : AsyncAction + { + private readonly VTPM _vtpm; + + public RemoveVtpmAction(IXenConnection connection, VTPM vtpm) + : base(connection, "", "", false) + { + _vtpm = vtpm; + + ApiMethodsToRoleCheck.AddRange("vtpm.destroy"); + } + + protected override void Run() + { + VTPM.destroy(Session, _vtpm.opaque_ref); + } + } +} diff --git a/XenModel/FriendlyNames.Designer.cs b/XenModel/FriendlyNames.Designer.cs index b75d2585e..420d1497c 100644 --- a/XenModel/FriendlyNames.Designer.cs +++ b/XenModel/FriendlyNames.Designer.cs @@ -429,6 +429,15 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to vTPM's root CAs and other related debug information. + /// + public static string Description_host_system_status_vtpm { + get { + return ResourceManager.GetString("Description-host.system_status-vtpm", resourceCulture); + } + } + /// /// Looks up a localized string similar to Logs and status information from the WLB server monitoring this pool.. /// @@ -1293,6 +1302,15 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to vTPM. + /// + public static string Label_host_system_status_vtpm { + get { + return ResourceManager.GetString("Label-host.system_status-vtpm", resourceCulture); + } + } + /// /// Looks up a localized string similar to Workload Balancing status. /// diff --git a/XenModel/FriendlyNames.resx b/XenModel/FriendlyNames.resx index 795b98949..27faafe9e 100644 --- a/XenModel/FriendlyNames.resx +++ b/XenModel/FriendlyNames.resx @@ -240,6 +240,9 @@ Crash dumps files from the VNCTerm daemon + + vTPM's root CAs and other related debug information + Logs and status information from the WLB server monitoring this pool. @@ -528,6 +531,9 @@ VNCTerm crash dumps + + vTPM + Workload Balancing status diff --git a/XenModel/Messages.Designer.cs b/XenModel/Messages.Designer.cs index dfe3f45e0..d8f38434e 100755 --- a/XenModel/Messages.Designer.cs +++ b/XenModel/Messages.Designer.cs @@ -19,7 +19,7 @@ namespace XenAdmin { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class Messages { @@ -8024,6 +8024,33 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to Resetting the vTPM that is attached to a VM to its original state may result in the deactivation of some security features on the VM. Do you want to continue?. + /// + public static string COMMAND_RESET_VTPM_WARNING { + get { + return ResourceManager.GetString("COMMAND_RESET_VTPM_WARNING", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to TPM is supported only for VMs using the UEFI or UEFI secure boot modes.. + /// + public static string COMMAND_VTPM_DISABLED_NON_UEFI { + get { + return ResourceManager.GetString("COMMAND_VTPM_DISABLED_NON_UEFI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mana&ge vTPMs.... + /// + public static string COMMAND_VTPM_MENU { + get { + return ResourceManager.GetString("COMMAND_VTPM_MENU", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0}: for use with Common Criteria versions of {1} only. /// @@ -40598,6 +40625,120 @@ namespace XenAdmin { } } + /// + /// Looks up a localized string similar to Trusted Platform Module. + /// + public static string VTPM { + get { + return ResourceManager.GetString("VTPM", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} vTPMs are attached to this VM.. + /// + public static string VTPM_ATTACHED_MANY { + get { + return ResourceManager.GetString("VTPM_ATTACHED_MANY", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A vTPM is attached to this VM.. + /// + public static string VTPM_ATTACHED_ONE { + get { + return ResourceManager.GetString("VTPM_ATTACHED_ONE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The maximum number of vTPMs that can be attached to this VM is {0}.. + /// + public static string VTPM_MAX_REACHED { + get { + return ResourceManager.GetString("VTPM_MAX_REACHED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are no vTPMs attached to this VM.. + /// + public static string VTPM_NONE_ATTACHED { + get { + return ResourceManager.GetString("VTPM_NONE_ATTACHED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You need to shut down this VM before you can attach a new vTPM to it.. + /// + public static string VTPM_POWER_STATE_WRONG_ATTACH { + get { + return ResourceManager.GetString("VTPM_POWER_STATE_WRONG_ATTACH", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You need to shut down the VM before you can remove this vTPM.. + /// + public static string VTPM_POWER_STATE_WRONG_REMOVE { + get { + return ResourceManager.GetString("VTPM_POWER_STATE_WRONG_REMOVE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A {0} user does not have sufficient permissions to attach a vTPM to a VM. Please login using an account with one of the following roles: + /// + ///{1}. + /// + public static string VTPM_RBAC_RESTRICTION_CREATE { + get { + return ResourceManager.GetString("VTPM_RBAC_RESTRICTION_CREATE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A {0} user does not have sufficient permissions to remove a vTPM from a VM. Please login using an account with one of the following roles: + /// + ///{1}. + /// + public static string VTPM_RBAC_RESTRICTION_REMOVE { + get { + return ResourceManager.GetString("VTPM_RBAC_RESTRICTION_REMOVE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A {0} user does not have sufficient permissions to reset the vTPM that is attached to a VM to its original state. Please login using an account with one of the following roles: + /// + ///{1}. + /// + public static string VTPM_RBAC_RESTRICTION_RESET { + get { + return ResourceManager.GetString("VTPM_RBAC_RESTRICTION_RESET", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove vTPM. + /// + public static string VTPM_REMOVE { + get { + return ResourceManager.GetString("VTPM_REMOVE", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removing the vTPM may result in the deactivation of some security features on the VM and prevent it from starting. Do you want to continue?. + /// + public static string VTPM_REMOVE_WARNING { + get { + return ResourceManager.GetString("VTPM_REMOVE_WARNING", resourceCulture); + } + } + /// /// Looks up a localized string similar to Waiting. /// diff --git a/XenModel/Messages.resx b/XenModel/Messages.resx index c2bf0e310..cd54afce8 100755 --- a/XenModel/Messages.resx +++ b/XenModel/Messages.resx @@ -2891,6 +2891,15 @@ Do you want to assign these VMs to the schedule '{0}' instead? &Collapse Children + + Resetting the vTPM that is attached to a VM to its original state may result in the deactivation of some security features on the VM. Do you want to continue? + + + TPM is supported only for VMs using the UEFI or UEFI secure boot modes. + + + Mana&ge vTPMs... + {0}: for use with Common Criteria versions of {1} only @@ -14018,6 +14027,48 @@ Schedule: Volumes + + Trusted Platform Module + + + {0} vTPMs are attached to this VM. + + + A vTPM is attached to this VM. + + + The maximum number of vTPMs that can be attached to this VM is {0}. + + + There are no vTPMs attached to this VM. + + + You need to shut down this VM before you can attach a new vTPM to it. + + + You need to shut down the VM before you can remove this vTPM. + + + A {0} user does not have sufficient permissions to attach a vTPM to a VM. Please login using an account with one of the following roles: + +{1} + + + A {0} user does not have sufficient permissions to remove a vTPM from a VM. Please login using an account with one of the following roles: + +{1} + + + A {0} user does not have sufficient permissions to reset the vTPM that is attached to a VM to its original state. Please login using an account with one of the following roles: + +{1} + + + Remove vTPM + + + Removing the vTPM may result in the deactivation of some security features on the VM and prevent it from starting. Do you want to continue? + Waiting diff --git a/XenModel/Network/Cache.cs b/XenModel/Network/Cache.cs index 065fe8574..a8a4c457d 100755 --- a/XenModel/Network/Cache.cs +++ b/XenModel/Network/Cache.cs @@ -101,6 +101,7 @@ namespace XenAdmin.Network private readonly ChangeableDictionary, VM_appliance> _vm_appliance = new ChangeableDictionary, VM_appliance>(); private readonly ChangeableDictionary, Crashdump> _crashdump = new ChangeableDictionary, Crashdump>(); private readonly ChangeableDictionary, Certificate> _certificates = new ChangeableDictionary, Certificate>(); + private readonly ChangeableDictionary, VTPM> _vtpms = new ChangeableDictionary, VTPM>(); #pragma warning restore 0414 @@ -200,6 +201,8 @@ namespace XenAdmin.Network public VM[] VMs => contents(_vm); + public VTPM[] VTPMs => contents(_vtpms); + private static T[] contents(ChangeableDictionary, T> d) where T : XenObject { diff --git a/XenModel/Utils/Helpers.Versions.cs b/XenModel/Utils/Helpers.Versions.cs index 43ac85aef..595512f16 100644 --- a/XenModel/Utils/Helpers.Versions.cs +++ b/XenModel/Utils/Helpers.Versions.cs @@ -439,6 +439,13 @@ namespace XenAdmin.Core return host == null || ProductVersionCompare(host.GetXapiVersion(), "22.20.0") >= 0; } + public static bool XapiEqualOrGreater_vtpmtag(IXenConnection conn) + { + //TODO: replace with correct tag + var coordinator = GetCoordinator(conn); + return coordinator == null || ProductVersionCompare(coordinator.GetXapiVersion(), "22.23.0.66.g56cd7935e-next") >= 0; + } + #endregion } } diff --git a/XenModel/Utils/Helpers.cs b/XenModel/Utils/Helpers.cs index eec22a62e..51f2dff00 100755 --- a/XenModel/Utils/Helpers.cs +++ b/XenModel/Utils/Helpers.cs @@ -553,8 +553,7 @@ namespace XenAdmin.Core /// public static bool FeatureForbidden(IXenObject iXenObject, Predicate restrictionTest) { - IXenConnection connection = (iXenObject == null ? null : iXenObject.Connection); - return FeatureForbidden(connection, restrictionTest); + return FeatureForbidden(iXenObject?.Connection, restrictionTest); } public static bool FeatureForbidden(IXenConnection xenConnection, Predicate restrictionTest) diff --git a/XenModel/XenAPI-Extensions/Host.cs b/XenModel/XenAPI-Extensions/Host.cs index 578c11d6e..49336ba8c 100644 --- a/XenModel/XenAPI-Extensions/Host.cs +++ b/XenModel/XenAPI-Extensions/Host.cs @@ -463,6 +463,11 @@ namespace XenAPI return BoolKeyPreferTrue(h.license_params, "restrict_corosync"); } + public static bool RestrictVtpm(Host h) + { + return BoolKeyPreferTrue(h.license_params, "restrict_vtpm"); + } + #region Experimental Features public static bool CorosyncDisabled(Host h) diff --git a/XenModel/XenAPI-Extensions/VM.cs b/XenModel/XenAPI-Extensions/VM.cs index 7b809a4af..093cf88f0 100644 --- a/XenModel/XenAPI-Extensions/VM.cs +++ b/XenModel/XenAPI-Extensions/VM.cs @@ -62,6 +62,7 @@ namespace XenAPI public const long MAX_SOCKETS = 16; // current hard limit in Xen: CA-198276 private XmlDocument xdRecommendations = null; + public const int MAX_ALLOWED_VTPMS = 1; public int MaxVCPUsAllowed() { @@ -1795,6 +1796,38 @@ namespace XenAPI { return last_boot_CPU_flags == null || last_boot_CPU_flags.Count == 0; } + + public bool CanAddVtpm(out string cannotReason) + { + cannotReason = null; + + if (VTPMs.Count >= VM.MAX_ALLOWED_VTPMS) + { + cannotReason = string.Format(Messages.VTPM_MAX_REACHED, VM.MAX_ALLOWED_VTPMS); + return false; + } + + if (power_state != vm_power_state.Halted) + { + cannotReason = Messages.VTPM_POWER_STATE_WRONG_ATTACH; + return false; + } + + return true; + } + + public bool CanRemoveVtpm(out string cannotReason) + { + cannotReason = null; + + if (power_state != vm_power_state.Halted) + { + cannotReason = Messages.VTPM_POWER_STATE_WRONG_REMOVE; + return false; + } + + return true; + } } public struct VMStartupOptions diff --git a/XenModel/XenAPI/FriendlyErrorNames.Designer.cs b/XenModel/XenAPI/FriendlyErrorNames.Designer.cs index c10b25943..02ed86869 100755 --- a/XenModel/XenAPI/FriendlyErrorNames.Designer.cs +++ b/XenModel/XenAPI/FriendlyErrorNames.Designer.cs @@ -5483,6 +5483,15 @@ namespace XenAPI { } } + /// + /// Looks up a localized string similar to Guidance for the update has changed. + /// + public static string UPDATE_GUIDANCE_CHANGED { + get { + return ResourceManager.GetString("UPDATE_GUIDANCE_CHANGED", resourceCulture); + } + } + /// /// Looks up a localized string similar to The specified update has been applied and cannot be destroyed.. /// @@ -6725,6 +6734,15 @@ namespace XenAPI { } } + /// + /// Looks up a localized string similar to The VM cannot be associated with more VTPMs.. + /// + public static string VTPM_MAX_AMOUNT_REACHED { + get { + return ResourceManager.GetString("VTPM_MAX_AMOUNT_REACHED", resourceCulture); + } + } + /// /// Looks up a localized string similar to WLB rejected our configured authentication details.. /// diff --git a/XenModel/XenAPI/FriendlyErrorNames.resx b/XenModel/XenAPI/FriendlyErrorNames.resx index c1aae6629..7ab17cdb0 100755 --- a/XenModel/XenAPI/FriendlyErrorNames.resx +++ b/XenModel/XenAPI/FriendlyErrorNames.resx @@ -1934,6 +1934,9 @@ Authorized Roles: {1} The update failed to apply. View logs for more details. + + Guidance for the update has changed + The specified update has been applied and cannot be destroyed. @@ -2342,6 +2345,9 @@ Authorized Roles: {1} You attempted an operation on VM {0} that was judged to be unsafe by the server. This can happen if the VM would run on a CPU that has a potentially incompatible set of feature flags to those the VM requires. If you want to override this warning then use the 'force' option. + + The VM cannot be associated with more VTPMs. + WLB rejected our configured authentication details. diff --git a/XenModel/XenAPI/JsonRpcClient.cs b/XenModel/XenAPI/JsonRpcClient.cs index 67dd3d01c..746635334 100755 --- a/XenModel/XenAPI/JsonRpcClient.cs +++ b/XenModel/XenAPI/JsonRpcClient.cs @@ -11855,34 +11855,6 @@ namespace XenAPI return Rpc>("VTPM.get_by_uuid", new JArray(session, _uuid ?? ""), serializer); } - public XenRef vtpm_create(string session, VTPM _record) - { - var converters = new List {new XenRefConverter()}; - var serializer = CreateSerializer(converters); - return Rpc>("VTPM.create", new JArray(session, _record.ToJObject()), serializer); - } - - public XenRef async_vtpm_create(string session, VTPM _record) - { - var converters = new List {new XenRefConverter()}; - var serializer = CreateSerializer(converters); - return Rpc>("Async.VTPM.create", new JArray(session, _record.ToJObject()), serializer); - } - - public void vtpm_destroy(string session, string _vtpm) - { - var converters = new List {}; - var serializer = CreateSerializer(converters); - Rpc("VTPM.destroy", new JArray(session, _vtpm ?? ""), serializer); - } - - public XenRef async_vtpm_destroy(string session, string _vtpm) - { - var converters = new List {new XenRefConverter()}; - var serializer = CreateSerializer(converters); - return Rpc>("Async.VTPM.destroy", new JArray(session, _vtpm ?? ""), serializer); - } - public string vtpm_get_uuid(string session, string _vtpm) { var converters = new List {}; @@ -11904,6 +11876,62 @@ namespace XenAPI return Rpc>("VTPM.get_backend", new JArray(session, _vtpm ?? ""), serializer); } + public persistence_backend vtpm_get_persistence_backend(string session, string _vtpm) + { + var converters = new List {new persistence_backendConverter()}; + var serializer = CreateSerializer(converters); + return Rpc("VTPM.get_persistence_backend", new JArray(session, _vtpm ?? ""), serializer); + } + + public bool vtpm_get_is_unique(string session, string _vtpm) + { + var converters = new List {}; + var serializer = CreateSerializer(converters); + return Rpc("VTPM.get_is_unique", new JArray(session, _vtpm ?? ""), serializer); + } + + public bool vtpm_get_is_protected(string session, string _vtpm) + { + var converters = new List {}; + var serializer = CreateSerializer(converters); + return Rpc("VTPM.get_is_protected", new JArray(session, _vtpm ?? ""), serializer); + } + + public XenRef vtpm_create(string session, string _vm, bool _is_unique) + { + var converters = new List {new XenRefConverter(), new XenRefConverter()}; + var serializer = CreateSerializer(converters); + return Rpc>("VTPM.create", new JArray(session, _vm ?? "", _is_unique), serializer); + } + + public XenRef async_vtpm_create(string session, string _vm, bool _is_unique) + { + var converters = new List {new XenRefConverter(), new XenRefConverter()}; + var serializer = CreateSerializer(converters); + return Rpc>("Async.VTPM.create", new JArray(session, _vm ?? "", _is_unique), serializer); + } + + public void vtpm_destroy(string session, string _vtpm) + { + var converters = new List {}; + var serializer = CreateSerializer(converters); + Rpc("VTPM.destroy", new JArray(session, _vtpm ?? ""), serializer); + } + + public XenRef async_vtpm_destroy(string session, string _vtpm) + { + var converters = new List {new XenRefConverter()}; + var serializer = CreateSerializer(converters); + return Rpc>("Async.VTPM.destroy", new JArray(session, _vtpm ?? ""), serializer); + } + + public List> vtpm_get_all(string session) + { + var converters = new List {new XenRefListConverter()}; + var serializer = CreateSerializer(converters); + return Rpc>>("VTPM.get_all", new JArray(session), serializer); + } + public Dictionary, VTPM> vtpm_get_all_records(string session) { var converters = new List {new XenRefXenObjectMapConverter()}; diff --git a/XenModel/XenAPI/Proxy.cs b/XenModel/XenAPI/Proxy.cs index 47e1299c9..6df844283 100755 --- a/XenModel/XenAPI/Proxy.cs +++ b/XenModel/XenAPI/Proxy.cs @@ -6794,22 +6794,6 @@ namespace XenAPI Response vtpm_get_by_uuid(string session, string _uuid); - [XmlRpcMethod("VTPM.create")] - Response - vtpm_create(string session, Proxy_VTPM _record); - - [XmlRpcMethod("Async.VTPM.create")] - Response - async_vtpm_create(string session, Proxy_VTPM _record); - - [XmlRpcMethod("VTPM.destroy")] - Response - vtpm_destroy(string session, string _vtpm); - - [XmlRpcMethod("Async.VTPM.destroy")] - Response - async_vtpm_destroy(string session, string _vtpm); - [XmlRpcMethod("VTPM.get_uuid")] Response vtpm_get_uuid(string session, string _vtpm); @@ -6822,6 +6806,38 @@ namespace XenAPI Response vtpm_get_backend(string session, string _vtpm); + [XmlRpcMethod("VTPM.get_persistence_backend")] + Response + vtpm_get_persistence_backend(string session, string _vtpm); + + [XmlRpcMethod("VTPM.get_is_unique")] + Response + vtpm_get_is_unique(string session, string _vtpm); + + [XmlRpcMethod("VTPM.get_is_protected")] + Response + vtpm_get_is_protected(string session, string _vtpm); + + [XmlRpcMethod("VTPM.create")] + Response + vtpm_create(string session, string _vm, bool _is_unique); + + [XmlRpcMethod("Async.VTPM.create")] + Response + async_vtpm_create(string session, string _vm, bool _is_unique); + + [XmlRpcMethod("VTPM.destroy")] + Response + vtpm_destroy(string session, string _vtpm); + + [XmlRpcMethod("Async.VTPM.destroy")] + Response + async_vtpm_destroy(string session, string _vtpm); + + [XmlRpcMethod("VTPM.get_all")] + Response + vtpm_get_all(string session); + [XmlRpcMethod("VTPM.get_all_records")] Response vtpm_get_all_records(string session); @@ -9527,6 +9543,9 @@ namespace XenAPI public string uuid; public string VM; public string backend; + public string persistence_backend; + public bool is_unique; + public bool is_protected; } [XmlRpcMissingMapping(MappingAction.Ignore)] diff --git a/XenModel/XenAPI/VM.cs b/XenModel/XenAPI/VM.cs index 10c00ef0a..1f546e07a 100755 --- a/XenModel/XenAPI/VM.cs +++ b/XenModel/XenAPI/VM.cs @@ -3544,7 +3544,7 @@ namespace XenAPI /// The session /// The opaque_ref of the given vm /// The target host - /// Extra configuration operations + /// Extra configuration operations: force, live, copy, compress. Each is a boolean option, taking 'true' or 'false' as a value. Option 'compress' controls the use of stream compression during migration. public static void pool_migrate(Session session, string _vm, string _host, Dictionary _options) { if (session.JsonRpcClient != null) @@ -3560,7 +3560,7 @@ namespace XenAPI /// The session /// The opaque_ref of the given vm /// The target host - /// Extra configuration operations + /// Extra configuration operations: force, live, copy, compress. Each is a boolean option, taking 'true' or 'false' as a value. Option 'compress' controls the use of stream compression during migration. public static XenRef async_pool_migrate(Session session, string _vm, string _host, Dictionary _options) { if (session.JsonRpcClient != null) diff --git a/XenModel/XenAPI/VTPM.cs b/XenModel/XenAPI/VTPM.cs index 3fccdfcaf..e98a120a5 100644 --- a/XenModel/XenAPI/VTPM.cs +++ b/XenModel/XenAPI/VTPM.cs @@ -54,11 +54,17 @@ namespace XenAPI public VTPM(string uuid, XenRef VM, - XenRef backend) + XenRef backend, + persistence_backend persistence_backend, + bool is_unique, + bool is_protected) { this.uuid = uuid; this.VM = VM; this.backend = backend; + this.persistence_backend = persistence_backend; + this.is_unique = is_unique; + this.is_protected = is_protected; } /// @@ -93,6 +99,9 @@ namespace XenAPI uuid = record.uuid; VM = record.VM; backend = record.backend; + persistence_backend = record.persistence_backend; + is_unique = record.is_unique; + is_protected = record.is_protected; } internal void UpdateFrom(Proxy_VTPM proxy) @@ -100,6 +109,9 @@ namespace XenAPI uuid = proxy.uuid == null ? null : proxy.uuid; VM = proxy.VM == null ? null : XenRef.Create(proxy.VM); backend = proxy.backend == null ? null : XenRef.Create(proxy.backend); + persistence_backend = proxy.persistence_backend == null ? (persistence_backend) 0 : (persistence_backend)Helper.EnumParseDefault(typeof(persistence_backend), (string)proxy.persistence_backend); + is_unique = (bool)proxy.is_unique; + is_protected = (bool)proxy.is_protected; } /// @@ -116,6 +128,12 @@ namespace XenAPI VM = Marshalling.ParseRef(table, "VM"); if (table.ContainsKey("backend")) backend = Marshalling.ParseRef(table, "backend"); + if (table.ContainsKey("persistence_backend")) + persistence_backend = (persistence_backend)Helper.EnumParseDefault(typeof(persistence_backend), Marshalling.ParseString(table, "persistence_backend")); + if (table.ContainsKey("is_unique")) + is_unique = Marshalling.ParseBool(table, "is_unique"); + if (table.ContainsKey("is_protected")) + is_protected = Marshalling.ParseBool(table, "is_protected"); } public Proxy_VTPM ToProxy() @@ -124,6 +142,9 @@ namespace XenAPI result_.uuid = uuid ?? ""; result_.VM = VM ?? ""; result_.backend = backend ?? ""; + result_.persistence_backend = persistence_backend_helper.ToString(persistence_backend); + result_.is_unique = is_unique; + result_.is_protected = is_protected; return result_; } @@ -136,15 +157,18 @@ namespace XenAPI return Helper.AreEqual2(this._uuid, other._uuid) && Helper.AreEqual2(this._VM, other._VM) && - Helper.AreEqual2(this._backend, other._backend); + Helper.AreEqual2(this._backend, other._backend) && + Helper.AreEqual2(this._persistence_backend, other._persistence_backend) && + Helper.AreEqual2(this._is_unique, other._is_unique) && + Helper.AreEqual2(this._is_protected, other._is_protected); } public override string SaveChanges(Session session, string opaqueRef, VTPM server) { if (opaqueRef == null) { - var reference = create(session, this); - return reference == null ? null : reference.opaque_ref; + System.Diagnostics.Debug.Assert(false, "Cannot create instances of this type on the server"); + return ""; } else { @@ -180,62 +204,6 @@ namespace XenAPI return XenRef.Create(session.XmlRpcProxy.vtpm_get_by_uuid(session.opaque_ref, _uuid ?? "").parse()); } - /// - /// Create a new VTPM instance, and return its handle. - /// First published in XenServer 4.0. - /// - /// The session - /// All constructor arguments - public static XenRef create(Session session, VTPM _record) - { - if (session.JsonRpcClient != null) - return session.JsonRpcClient.vtpm_create(session.opaque_ref, _record); - else - return XenRef.Create(session.XmlRpcProxy.vtpm_create(session.opaque_ref, _record.ToProxy()).parse()); - } - - /// - /// Create a new VTPM instance, and return its handle. - /// First published in XenServer 4.0. - /// - /// The session - /// All constructor arguments - public static XenRef async_create(Session session, VTPM _record) - { - if (session.JsonRpcClient != null) - return session.JsonRpcClient.async_vtpm_create(session.opaque_ref, _record); - else - return XenRef.Create(session.XmlRpcProxy.async_vtpm_create(session.opaque_ref, _record.ToProxy()).parse()); - } - - /// - /// Destroy the specified VTPM instance. - /// First published in XenServer 4.0. - /// - /// The session - /// The opaque_ref of the given vtpm - public static void destroy(Session session, string _vtpm) - { - if (session.JsonRpcClient != null) - session.JsonRpcClient.vtpm_destroy(session.opaque_ref, _vtpm); - else - session.XmlRpcProxy.vtpm_destroy(session.opaque_ref, _vtpm ?? "").parse(); - } - - /// - /// Destroy the specified VTPM instance. - /// First published in XenServer 4.0. - /// - /// The session - /// The opaque_ref of the given vtpm - public static XenRef async_destroy(Session session, string _vtpm) - { - if (session.JsonRpcClient != null) - return session.JsonRpcClient.async_vtpm_destroy(session.opaque_ref, _vtpm); - else - return XenRef.Create(session.XmlRpcProxy.async_vtpm_destroy(session.opaque_ref, _vtpm ?? "").parse()); - } - /// /// Get the uuid field of the given VTPM. /// First published in XenServer 4.0. @@ -278,6 +246,132 @@ namespace XenAPI return XenRef.Create(session.XmlRpcProxy.vtpm_get_backend(session.opaque_ref, _vtpm ?? "").parse()); } + /// + /// Get the persistence_backend field of the given VTPM. + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + /// The session + /// The opaque_ref of the given vtpm + public static persistence_backend get_persistence_backend(Session session, string _vtpm) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_get_persistence_backend(session.opaque_ref, _vtpm); + else + return (persistence_backend)Helper.EnumParseDefault(typeof(persistence_backend), (string)session.XmlRpcProxy.vtpm_get_persistence_backend(session.opaque_ref, _vtpm ?? "").parse()); + } + + /// + /// Get the is_unique field of the given VTPM. + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + /// The session + /// The opaque_ref of the given vtpm + public static bool get_is_unique(Session session, string _vtpm) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_get_is_unique(session.opaque_ref, _vtpm); + else + return (bool)session.XmlRpcProxy.vtpm_get_is_unique(session.opaque_ref, _vtpm ?? "").parse(); + } + + /// + /// Get the is_protected field of the given VTPM. + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + /// The session + /// The opaque_ref of the given vtpm + public static bool get_is_protected(Session session, string _vtpm) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_get_is_protected(session.opaque_ref, _vtpm); + else + return (bool)session.XmlRpcProxy.vtpm_get_is_protected(session.opaque_ref, _vtpm ?? "").parse(); + } + + /// + /// Create a new VTPM instance, and return its handle. + /// First published in XenServer 4.0. + /// + /// The session + /// The VM reference the VTPM will be attached to + /// Whether the VTPM must be unique + public static XenRef create(Session session, string _vm, bool _is_unique) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_create(session.opaque_ref, _vm, _is_unique); + else + return XenRef.Create(session.XmlRpcProxy.vtpm_create(session.opaque_ref, _vm ?? "", _is_unique).parse()); + } + + /// + /// Create a new VTPM instance, and return its handle. + /// First published in XenServer 4.0. + /// + /// The session + /// The VM reference the VTPM will be attached to + /// Whether the VTPM must be unique + public static XenRef async_create(Session session, string _vm, bool _is_unique) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.async_vtpm_create(session.opaque_ref, _vm, _is_unique); + else + return XenRef.Create(session.XmlRpcProxy.async_vtpm_create(session.opaque_ref, _vm ?? "", _is_unique).parse()); + } + + /// + /// Destroy the specified VTPM instance, along with its state. + /// First published in XenServer 4.0. + /// + /// The session + /// The opaque_ref of the given vtpm + public static void destroy(Session session, string _vtpm) + { + if (session.JsonRpcClient != null) + session.JsonRpcClient.vtpm_destroy(session.opaque_ref, _vtpm); + else + session.XmlRpcProxy.vtpm_destroy(session.opaque_ref, _vtpm ?? "").parse(); + } + + /// + /// Destroy the specified VTPM instance, along with its state. + /// First published in XenServer 4.0. + /// + /// The session + /// The opaque_ref of the given vtpm + public static XenRef async_destroy(Session session, string _vtpm) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.async_vtpm_destroy(session.opaque_ref, _vtpm); + else + return XenRef.Create(session.XmlRpcProxy.async_vtpm_destroy(session.opaque_ref, _vtpm ?? "").parse()); + } + + /// + /// Return a list of all the VTPMs known to the system. + /// First published in XenServer 4.0. + /// + /// The session + public static List> get_all(Session session) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_get_all(session.opaque_ref); + else + return XenRef.Create(session.XmlRpcProxy.vtpm_get_all(session.opaque_ref).parse()); + } + + /// + /// Get all the VTPM Records at once, in a single XML RPC call + /// First published in XenServer 4.0. + /// + /// The session + public static Dictionary, VTPM> get_all_records(Session session) + { + if (session.JsonRpcClient != null) + return session.JsonRpcClient.vtpm_get_all_records(session.opaque_ref); + else + return XenRef.Create(session.XmlRpcProxy.vtpm_get_all_records(session.opaque_ref).parse()); + } + /// /// Unique identifier/object reference /// @@ -296,7 +390,7 @@ namespace XenAPI private string _uuid = ""; /// - /// the virtual machine + /// The virtual machine the TPM is attached to /// [JsonConverter(typeof(XenRefConverter))] public virtual XenRef VM @@ -314,7 +408,7 @@ namespace XenAPI private XenRef _VM = new XenRef(Helper.NullOpaqueRef); /// - /// the domain where the backend is located + /// The domain where the backend is located (unused) /// [JsonConverter(typeof(XenRefConverter))] public virtual XenRef backend @@ -329,6 +423,61 @@ namespace XenAPI } } } - private XenRef _backend = new XenRef(Helper.NullOpaqueRef); + private XenRef _backend = new XenRef("OpaqueRef:NULL"); + + /// + /// The backend where the vTPM is persisted + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + [JsonConverter(typeof(persistence_backendConverter))] + public virtual persistence_backend persistence_backend + { + get { return _persistence_backend; } + set + { + if (!Helper.AreEqual(value, _persistence_backend)) + { + _persistence_backend = value; + NotifyPropertyChanged("persistence_backend"); + } + } + } + private persistence_backend _persistence_backend = persistence_backend.xapi; + + /// + /// Whether the contents are never copied, satisfying the TPM spec + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + public virtual bool is_unique + { + get { return _is_unique; } + set + { + if (!Helper.AreEqual(value, _is_unique)) + { + _is_unique = value; + NotifyPropertyChanged("is_unique"); + } + } + } + private bool _is_unique = false; + + /// + /// Whether the contents of the VTPM are secured according to the TPM spec + /// Experimental. First published in 22.23.0.66.g56cd7935e-next. + /// + public virtual bool is_protected + { + get { return _is_protected; } + set + { + if (!Helper.AreEqual(value, _is_protected)) + { + _is_protected = value; + NotifyPropertyChanged("is_protected"); + } + } + } + private bool _is_protected = false; } } diff --git a/XenModel/XenAPI/persistence_backend.cs b/XenModel/XenAPI/persistence_backend.cs new file mode 100644 index 000000000..06a164a8b --- /dev/null +++ b/XenModel/XenAPI/persistence_backend.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) Citrix Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1) Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2) 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 Newtonsoft.Json; + + +namespace XenAPI +{ + [JsonConverter(typeof(persistence_backendConverter))] + public enum persistence_backend + { + /// + /// This VTPM is persisted in XAPI's DB + /// + xapi, + unknown + } + + public static class persistence_backend_helper + { + public static string ToString(persistence_backend x) + { + return x.StringOf(); + } + } + + public static partial class EnumExt + { + public static string StringOf(this persistence_backend x) + { + switch (x) + { + case persistence_backend.xapi: + return "xapi"; + default: + return "unknown"; + } + } + } + + internal class persistence_backendConverter : XenEnumConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + writer.WriteValue(((persistence_backend)value).StringOf()); + } + } +} \ No newline at end of file diff --git a/XenModel/XenModel.csproj b/XenModel/XenModel.csproj index e762de60f..50f7b099e 100755 --- a/XenModel/XenModel.csproj +++ b/XenModel/XenModel.csproj @@ -163,6 +163,7 @@ + @@ -409,6 +410,7 @@ + diff --git a/XenModel/XenObjectDownloader.cs b/XenModel/XenObjectDownloader.cs index a9297a68b..b6b525859 100644 --- a/XenModel/XenObjectDownloader.cs +++ b/XenModel/XenObjectDownloader.cs @@ -156,7 +156,6 @@ namespace XenAdmin.Core { case "session": case "event": - case "vtpm": case "user": case "secret": // We don't track events on these objects diff --git a/XenModel/XenSearch/GroupAlg.cs b/XenModel/XenSearch/GroupAlg.cs index 65ce7cede..7e9381d79 100644 --- a/XenModel/XenSearch/GroupAlg.cs +++ b/XenModel/XenSearch/GroupAlg.cs @@ -34,6 +34,7 @@ using System.Collections.Generic; using XenAdmin.Model; using XenAdmin.Network; using System.Collections; +using System.Linq; using XenAPI; using XenAdmin.Core; using XenCenterLib; @@ -108,11 +109,14 @@ namespace XenAdmin.XenSearch if (XenAdminConfigManager.Provider.ObjectIsHidden(o.opaque_ref)) return true; - if (o is VM) + if (o is VM vm) { - VM vm = o as VM; - if (vm.is_control_domain - || !vm.Show(XenAdminConfigManager.Provider.ShowHiddenVMs)) + if (vm.Connection.Cache.Hosts.Any(Host.RestrictVtpm) && + vm.is_a_template && + vm.platform.TryGetValue("vtpm", out var result) && result.ToLower() == "true") + return true; + + if (vm.is_control_domain || !vm.Show(XenAdminConfigManager.Provider.ShowHiddenVMs)) return true; // Hide VMs on non-live hosts @@ -120,9 +124,8 @@ namespace XenAdmin.XenSearch if (host != null && !host.IsLive()) return true; } - else if (o is SR) + else if (o is SR sr) { - SR sr = o as SR; if (!sr.Show(XenAdminConfigManager.Provider.ShowHiddenVMs) || sr.IsToolsSR()) return true; @@ -131,16 +134,13 @@ namespace XenAdmin.XenSearch if (host != null && !host.IsLive()) return true; } - else if (o is XenAPI.Network) + else if (o is XenAPI.Network network) { - XenAPI.Network network = o as XenAPI.Network; - return !network.Show(XenAdminConfigManager.Provider.ShowHiddenVMs); } - else if (o is Folder) + else if (o is Folder folder) { // Hide the root folder - Folder folder = o as Folder; return folder.IsRootFolder; }