xenadmin/XenAdmin/Controls/PvsCacheStorageRow.cs
Callum McIntyre b3e334654f [CA-229350] PVS allows Memory Only even when no control domain memory available
We now disable the Memory Only option if the available dom0 memory is less than the minimum the spinner supports (1Gb)
2016-11-14 14:59:57 +00:00

228 lines
8.4 KiB
C#

/* Copyright (c) Citrix Systems Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Linq;
using System.Windows.Forms;
using XenAPI;
namespace XenAdmin.Controls
{
public partial class PvsCacheStorageRow : UserControl
{
public Host Host { get; private set; }
public PVS_site PvsSite { get; private set; }
public PVS_cache_storage OrigPvsCacheStorage { get; private set; }
public event EventHandler Changed;
private const decimal MIN_CACHE_SIZE_GB = 1;
private const decimal MAX_CACHE_SIZE_GB = 2 * Util.BINARY_KILO; // 2TB
private const decimal DEFAULT_CACHE_SIZE_GB = 10;
private decimal origCacheSizeGb;
public PvsCacheStorageRow(Host host, PVS_site site)
{
InitializeComponent();
Host = host;
PvsSite = site;
OrigPvsCacheStorage = site != null ? site.PvsCacheStorage(host) : null;
Populate();
}
private void Populate()
{
labelHostName.Text = Host.Name;
// initialize cacheSize
SetupCacheSizeSpinner(OrigPvsCacheStorage == null ? DEFAULT_CACHE_SIZE_GB : (decimal)Util.ToGB(OrigPvsCacheStorage.size, 1, RoundingBehaviour.Nearest),
MIN_CACHE_SIZE_GB,
MAX_CACHE_SIZE_GB);
origCacheSizeGb = numericUpDownCacheSize.Value;
PopulateCacheSrCombobox();
}
private void PopulateCacheSrCombobox()
{
comboBoxCacheSr.Items.Clear();
// add the "Not configured" item first
var notConfiguredItem = new SrComboBoxItem(null, Messages.PVS_CACHE_NOT_CONFIGURED);
comboBoxCacheSr.Items.Add(notConfiguredItem);
comboBoxCacheSr.SelectedItem = notConfiguredItem;
// add Memeory SR; if no memory SR found, add a placeholder (we will create the memory SR in ConfigurePvsCacheAction)
var memorySr =
Host.Connection.Cache.SRs.FirstOrDefault(
s => s.GetSRType(false) == SR.SRTypes.tmpfs && s.CanBeSeenFrom(Host));
if (memorySr == null)
{
// create a placeholder for the memory SR
memorySr = new SR
{
type = SR.SRTypes.tmpfs.ToString(),
name_label = Messages.PVS_CACHE_MEMORY_SR_NAME,
shared = false,
opaque_ref = Helper.NullOpaqueRef
};
}
var enabled = Host.dom0_memory_extra >= numericUpDownCacheSize.Minimum;
var label = enabled ? Messages.PVS_CACHE_MEMORY_ONLY : Messages.PVS_CACHE_MEMORY_ONLY_DISABLED;
var memorySrItem = new SrComboBoxItem(memorySr, label, enabled);
comboBoxCacheSr.Items.Add(memorySrItem);
if (OrigPvsCacheStorage != null && memorySr.opaque_ref == OrigPvsCacheStorage.SR.opaque_ref)
comboBoxCacheSr.SelectedItem = memorySrItem;
// add all suitable SRs
var availableSRs = Host.Connection.Cache.SRs.Where(s => s.CanBeSeenFrom(Host) && SrIsSuitableForPvsCache(s)).ToList();
availableSRs.Sort();
foreach (var sr in availableSRs)
{
var newItem = new SrComboBoxItem(sr, sr.Name);
comboBoxCacheSr.Items.Add(newItem);
if (OrigPvsCacheStorage != null && sr.opaque_ref == OrigPvsCacheStorage.SR.opaque_ref)
comboBoxCacheSr.SelectedItem = newItem;
}
}
private bool SrIsSuitableForPvsCache(SR sr)
{
return sr.Show(Properties.Settings.Default.ShowHiddenVMs) && sr.SupportsVdiCreate() && sr.FreeSpace >= MIN_CACHE_SIZE_GB * Util.BINARY_GIGA;
}
private void SetupCacheSizeSpinner(decimal value, decimal min, decimal max)
{
if (min > max)
max = min;
numericUpDownCacheSize.Minimum = min;
numericUpDownCacheSize.Maximum = max;
if (value < numericUpDownCacheSize.Minimum)
value = numericUpDownCacheSize.Minimum;
if (value > numericUpDownCacheSize.Maximum)
value = numericUpDownCacheSize.Maximum;
numericUpDownCacheSize.Value = value;
}
private bool _showHeader;
public bool ShowHeader
{
get { return _showHeader; }
set
{
_showHeader = value;
labelCacheStorage.Visible = labelCacheSize.Visible = _showHeader;
tableLayoutPanel1.Refresh();
}
}
public SR CacheSr
{
get
{
var selectedItem = (SrComboBoxItem)comboBoxCacheSr.SelectedItem;
return selectedItem != null ? selectedItem.Item : null;
}
}
public long CacheSize
{
get { return (long)numericUpDownCacheSize.Value * Util.BINARY_GIGA; }
}
public bool ValidToSave
{
get { return comboBoxCacheSr.SelectedItem != null && numericUpDownCacheSize.Validate(); }
}
public bool HasChanged
{
get
{
if (OrigPvsCacheStorage == null)
return CacheSr != null;
if (CacheSr == null)
return OrigPvsCacheStorage != null;
return OrigPvsCacheStorage.SR.opaque_ref != CacheSr.opaque_ref || origCacheSizeGb != numericUpDownCacheSize.Value;
}
}
private void SomethingChanged(object sender, EventArgs e)
{
if (Changed != null)
Changed(this, e);
}
private void comboBoxCacheSr_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedSr = CacheSr;
if (selectedSr != null)
{
var maxSize = (decimal)Util.ToGB(selectedSr.GetSRType(false) == SR.SRTypes.tmpfs ? Host.dom0_memory_extra : selectedSr.FreeSpace, 1, RoundingBehaviour.Down);
maxSize = Math.Min(maxSize, MAX_CACHE_SIZE_GB);
if (maxSize != numericUpDownCacheSize.Maximum)
SetupCacheSizeSpinner(numericUpDownCacheSize.Value, numericUpDownCacheSize.Minimum, maxSize);
}
SomethingChanged(this, e);
}
}
public class SrComboBoxItem : IEnableableComboBoxItem
{
public SR Item;
private readonly string _toString;
private readonly bool _enabled;
public SrComboBoxItem(SR sr, string label, bool enabled=true)
{
Item = sr;
_toString = label;
_enabled = enabled;
}
public override string ToString()
{
return _toString;
}
public bool Enabled
{
get { return _enabled; }
}
}
}