diff --git a/XenAdmin/Images.cs b/XenAdmin/Images.cs index f24810fb0..60c005337 100644 --- a/XenAdmin/Images.cs +++ b/XenAdmin/Images.cs @@ -286,6 +286,10 @@ namespace XenAdmin if (storageLinkRepository != null) return GetIconFor(storageLinkRepository); + DockerContainer dockerContainer = o as DockerContainer; + if (dockerContainer != null) + return GetIconFor(dockerContainer); + System.Diagnostics.Trace.Assert(false, "You asked for an icon for a type I don't recognise!"); @@ -562,5 +566,18 @@ namespace XenAdmin { return pif.IsPrimaryManagementInterface() ? Icons.PifPrimary : Icons.PifSecondary; } + + public static Icons GetIconFor(DockerContainer dockerContainer) + { + switch (dockerContainer.power_state) + { + case vm_power_state.Paused: + return Icons.VmSuspended; + case vm_power_state.Running: + return Icons.VmRunning; + default: + return Icons.VmStopped; + } + } } } diff --git a/XenAdmin/MainWindowTreeBuilder.cs b/XenAdmin/MainWindowTreeBuilder.cs index c3e498215..da459b31a 100644 --- a/XenAdmin/MainWindowTreeBuilder.cs +++ b/XenAdmin/MainWindowTreeBuilder.cs @@ -444,7 +444,22 @@ namespace XenAdmin { bool hidden = vm.IsHidden; string name = hidden ? String.Format(Messages.X_HIDDEN, vm.Name) : vm.Name; - return AddNode(name, Images.GetIconFor(vm), hidden, vm); + //return AddNode(name, Images.GetIconFor(vm), hidden, vm); + + var vmNode = AddNode(name, Images.GetIconFor(vm), hidden, vm); + + var containers = vm.GetContainers(); + foreach (var dockerContainer in containers) + { + VirtualTreeNode containerNode = new VirtualTreeNode(dockerContainer.Name.Ellipsise(1000)) + { + Tag = dockerContainer, + ImageIndex = (int)Images.GetIconFor(dockerContainer), + SelectedImageIndex = (int)Images.GetIconFor(dockerContainer) + }; + vmNode.Nodes.Add(containerNode); + } + return vmNode; } private VirtualTreeNode AddVmApplianceNode(VM_appliance appliance) diff --git a/XenModel/DockerContainer.cs b/XenModel/DockerContainer.cs new file mode 100644 index 000000000..59a241e71 --- /dev/null +++ b/XenModel/DockerContainer.cs @@ -0,0 +1,210 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +using System; +using XenAPI; +using XenAdmin.Core; + +namespace XenAdmin.Model +{ + public class DockerContainer : XenObject, IComparable + { + public DockerContainer() + { + } + + public DockerContainer(VM parent, string uuid, string name, string description, string status, string container) + : this() + { + this.parent = parent; + this.Connection = parent.Connection; + this.uuid = uuid; + this.name_label = name; + this.name_description = description; + this.status = status; + this.container = container; + } + + public VM Parent + { + get { return parent; } + } + private readonly VM parent; + + /// + /// Unique identifier/object reference + /// + public virtual string uuid + { + get { return _uuid; } + set + { + if (!Helper.AreEqual(value, _uuid)) + { + _uuid = value; + Changed = true; + NotifyPropertyChanged("uuid"); + } + } + } + private string _uuid; + + /// + /// a human-readable name + /// + public virtual string name_label + { + get { return _name_label; } + set + { + if (!Helper.AreEqual(value, _name_label)) + { + _name_label = value; + Changed = true; + NotifyPropertyChanged("name_label"); + } + } + } + private string _name_label; + + /// + /// a notes field containing human-readable description + /// + public virtual string name_description + { + get { return _name_description; } + set + { + if (!Helper.AreEqual(value, _name_description)) + { + _name_description = value; + Changed = true; + NotifyPropertyChanged("name_description"); + } + } + } + private string _name_description; + + /// + /// a notes field containing status description + /// + public virtual string status + { + get { return _status; } + set + { + if (!Helper.AreEqual(value, _status)) + { + _status = value; + Changed = true; + NotifyPropertyChanged("status"); + } + } + } + private string _status; + + /// + /// a notes field containing container (id) + /// + public virtual string container + { + get { return _container; } + set + { + if (!Helper.AreEqual(value, _container)) + { + _container = value; + Changed = true; + NotifyPropertyChanged("container"); + } + } + } + private string _container; + + public override string ToString() + { + return _name_label; + } + + public override bool Equals(object obj) + { + DockerContainer other = obj as DockerContainer; + + return other != null && + name_label.Equals(other.name_label); + } + + + public override int GetHashCode() + { + return name_label.GetHashCode(); + } + + #region IComparable Members + + + public override int CompareTo(DockerContainer other) + { + if (other == null) + return 1; + + return StringUtility.NaturalCompare(_name_label, other._name_label); + } + + #endregion + + public override void UpdateFrom(DockerContainer update) + { + } + + public override string SaveChanges(Session session, string _serverOpaqueRef, DockerContainer serverObject) + { + return String.Empty; + } + + public override string Name + { + get + { + return name_label; + } + } + + public vm_power_state power_state + { + get { + return status.StartsWith("Up") + ? (status.EndsWith("(paused)") ? vm_power_state.Paused : vm_power_state.Running) + : vm_power_state.Halted; + } + } + } +} diff --git a/XenModel/XenAPI-Extensions/VM.cs b/XenModel/XenAPI-Extensions/VM.cs index cfbc9cc92..a323ab542 100644 --- a/XenModel/XenAPI-Extensions/VM.cs +++ b/XenModel/XenAPI-Extensions/VM.cs @@ -38,6 +38,7 @@ using System.Xml; using Citrix.XenCenter; using XenAdmin; using XenAdmin.Core; +using XenAdmin.Model; using XenAdmin.Network; @@ -1568,6 +1569,43 @@ namespace XenAPI return string.Format(Messages.CPU_TOPOLOGY_STRING_N_SOCKET_1_CORE, sockets); return string.Format(Messages.CPU_TOPOLOGY_STRING_N_SOCKET_N_CORE, sockets, cores); } + + public List GetContainers() + { + var containers = new List(); + if (other_config.ContainsKey("docker_ps")) + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(other_config["docker_ps"]); + + foreach (XmlNode entry in doc.GetElementsByTagName("entry")) + { + string id = ""; + var propertyNode = entry.ChildNodes.Cast().FirstOrDefault(node => node.Name == "id"); + if (propertyNode != null) + id = propertyNode.InnerText; + + string name = ""; + propertyNode = entry.ChildNodes.Cast().FirstOrDefault(node => node.Name == "names"); + if (propertyNode != null) + name = propertyNode.InnerText; + + string status = ""; + propertyNode = entry.ChildNodes.Cast().FirstOrDefault(node => node.Name == "status"); + if (propertyNode != null) + status = propertyNode.InnerText; + + string container = ""; + propertyNode = entry.ChildNodes.Cast().FirstOrDefault(node => node.Name == "container"); + if (propertyNode != null) + container = propertyNode.InnerText; + + DockerContainer dockerContainer = new DockerContainer(this, id, name, "", status, container); + containers.Add(dockerContainer); + } + } + return containers; + } } public struct VMStartupOptions diff --git a/XenModel/XenModel.csproj b/XenModel/XenModel.csproj index 51fb7cbf3..3ccdba6f5 100644 --- a/XenModel/XenModel.csproj +++ b/XenModel/XenModel.csproj @@ -130,6 +130,7 @@ +