This commit is contained in:
Stephen Turner 2015-03-09 17:51:33 +00:00
commit 1ff2dc93a5
12 changed files with 268 additions and 67 deletions

View File

@ -34,11 +34,14 @@ namespace XenAdmin.TabPages
this.ButtonPanel = new System.Windows.Forms.Panel();
this.RefreshTime = new System.Windows.Forms.Label();
this.TreePanel = new System.Windows.Forms.Panel();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.DetailtreeView = new System.Windows.Forms.TreeView();
this.label1 = new System.Windows.Forms.Label();
this.RefreshTimer = new System.Windows.Forms.Timer(this.components);
this.pageContainerPanel.SuspendLayout();
this.ButtonPanel.SuspendLayout();
this.TreePanel.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.SuspendLayout();
//
// pageContainerPanel
@ -68,15 +71,27 @@ namespace XenAdmin.TabPages
// TreePanel
//
resources.ApplyResources(this.TreePanel, "TreePanel");
this.TreePanel.Controls.Add(this.DetailtreeView);
this.TreePanel.Controls.Add(this.tableLayoutPanel2);
this.TreePanel.Controls.Add(this.ButtonPanel);
this.TreePanel.Name = "TreePanel";
//
// tableLayoutPanel2
//
resources.ApplyResources(this.tableLayoutPanel2, "tableLayoutPanel2");
this.tableLayoutPanel2.Controls.Add(this.DetailtreeView, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.label1, 0, 0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
//
// DetailtreeView
//
resources.ApplyResources(this.DetailtreeView, "DetailtreeView");
this.DetailtreeView.Name = "DetailtreeView";
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// RefreshTimer
//
this.RefreshTimer.Tick += new System.EventHandler(this.RefreshTimer_Tick);
@ -91,6 +106,8 @@ namespace XenAdmin.TabPages
this.ButtonPanel.ResumeLayout(false);
this.ButtonPanel.PerformLayout();
this.TreePanel.ResumeLayout(false);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -101,8 +118,10 @@ namespace XenAdmin.TabPages
private System.Windows.Forms.Panel TreePanel;
private System.Windows.Forms.Panel ButtonPanel;
private System.Windows.Forms.Label RefreshTime;
private System.Windows.Forms.TreeView DetailtreeView;
private System.Windows.Forms.Timer RefreshTimer;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.TreeView DetailtreeView;
private System.Windows.Forms.Label label1;
}
}

View File

@ -145,21 +145,34 @@ namespace XenAdmin.TabPages
{
if (cachedResult == currentResult)
return;
cachedResult = currentResult;
DetailtreeView.Nodes.Clear();
XmlDocument doc = new XmlDocument();
doc.LoadXml(currentResult);
IEnumerator ienum = doc.GetEnumerator();
XmlNode docker_inspect;
while (ienum.MoveNext())
IEnumerator firstEnum = doc.GetEnumerator();
XmlNode node;
while (firstEnum.MoveNext())
{
docker_inspect = (XmlNode) ienum.Current;
if (docker_inspect.NodeType != XmlNodeType.XmlDeclaration)
node = (XmlNode)firstEnum.Current;
if (node.NodeType != XmlNodeType.XmlDeclaration)
{
TreeNode rootNode = new TreeNode();
CreateTree(docker_inspect, rootNode);
DetailtreeView.Nodes.Add(rootNode);
//we are on the root element now (docker_inspect)
//using the following enumerator to iterate through the children nodes and to build related sub-trees
//note that we are intentionally not adding the root node to the tree (UX decision)
var secondEnum = node.GetEnumerator();
while (secondEnum.MoveNext())
{
//recursively building the tree
TreeNode rootNode = new TreeNode();
CreateTree((XmlNode)secondEnum.Current, rootNode);
//adding the current sub-tree to the TreeView
DetailtreeView.Nodes.Add(rootNode);
}
}
}
}

View File

@ -125,18 +125,24 @@
<data name="TreePanel.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="tableLayoutPanel2.ColumnCount" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="DetailtreeView.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="DetailtreeView.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
<value>7, 31</value>
</data>
<data name="DetailtreeView.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>7, 3, 9, 3</value>
</data>
<data name="DetailtreeView.Size" type="System.Drawing.Size, System.Drawing">
<value>816, 333</value>
<value>803, 299</value>
</data>
<data name="DetailtreeView.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
<value>1</value>
</data>
<data name="&gt;&gt;DetailtreeView.Name" xml:space="preserve">
<value>DetailtreeView</value>
@ -145,11 +151,80 @@
<value>System.Windows.Forms.TreeView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;DetailtreeView.Parent" xml:space="preserve">
<value>TreePanel</value>
<value>tableLayoutPanel2</value>
</data>
<data name="&gt;&gt;DetailtreeView.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="label1.Font" type="System.Drawing.Font, System.Drawing">
<value>Segoe UI, 11.25pt</value>
</data>
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>3, 0</value>
</data>
<data name="label1.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>3, 0, 0, 2</value>
</data>
<data name="label1.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 6, 10, 0</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>65, 26</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Details</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
</data>
<data name="&gt;&gt;label1.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label1.Parent" xml:space="preserve">
<value>tableLayoutPanel2</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="tableLayoutPanel2.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="tableLayoutPanel2.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
</data>
<data name="tableLayoutPanel2.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 0, 0, 0</value>
</data>
<data name="tableLayoutPanel2.RowCount" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="tableLayoutPanel2.Size" type="System.Drawing.Size, System.Drawing">
<value>819, 333</value>
</data>
<data name="tableLayoutPanel2.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="&gt;&gt;tableLayoutPanel2.Name" xml:space="preserve">
<value>tableLayoutPanel2</value>
</data>
<data name="&gt;&gt;tableLayoutPanel2.Type" xml:space="preserve">
<value>System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;tableLayoutPanel2.Parent" xml:space="preserve">
<value>TreePanel</value>
</data>
<data name="&gt;&gt;tableLayoutPanel2.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="tableLayoutPanel2.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
<value>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;TableLayoutSettings&gt;&lt;Controls&gt;&lt;Control Name="DetailtreeView" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;Control Name="label1" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /&gt;&lt;/Controls&gt;&lt;Columns Styles="Percent,100" /&gt;&lt;Rows Styles="AutoSize,0,Percent,100" /&gt;&lt;/TableLayoutSettings&gt;</value>
</data>
<data name="RefreshTime.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
@ -180,6 +255,9 @@
<data name="RefreshButton.Location" type="System.Drawing.Point, System.Drawing">
<value>4, 7</value>
</data>
<data name="RefreshButton.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>9, 3, 3, 3</value>
</data>
<data name="RefreshButton.Size" type="System.Drawing.Size, System.Drawing">
<value>74, 23</value>
</data>
@ -208,7 +286,7 @@
<value>0, 333</value>
</data>
<data name="ButtonPanel.Size" type="System.Drawing.Size, System.Drawing">
<value>816, 42</value>
<value>819, 42</value>
</data>
<data name="ButtonPanel.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
@ -229,7 +307,7 @@
<value>3, 3</value>
</data>
<data name="TreePanel.Size" type="System.Drawing.Size, System.Drawing">
<value>816, 375</value>
<value>819, 375</value>
</data>
<data name="TreePanel.TabIndex" type="System.Int32, mscorlib">
<value>3</value>

View File

@ -448,7 +448,7 @@
<value>27</value>
</data>
<data name="TitleLabel.Text" xml:space="preserve">
<value>Docker Processes</value>
<value>Container Processes</value>
</data>
<data name="TitleLabel.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>MiddleLeft</value>

View File

@ -383,7 +383,10 @@ namespace XenAdmin.TabPages
public void EnableDisableEdit()
{
buttonProperties.Enabled = xenObject != null && !xenObject.Locked && xenObject.Connection != null && xenObject.Connection.IsConnected;
buttonProperties.Visible = !(xenObject is DockerContainer);
//keeping it seperate
if (xenObject is DockerContainer)
buttonProperties.Enabled = false;
}
public void BuildList()
@ -468,7 +471,6 @@ namespace XenAdmin.TabPages
generateMultipathBootBox();
generateVCPUsBox();
generateDockerInfoBox();
generateDockerVersionBox();
generateReadCachingBox();
}
@ -1372,7 +1374,11 @@ namespace XenAdmin.TabPages
s.AddEntry(Messages.CONTAINER_IMAGE, dockerContainer.image.Length != 0 ? dockerContainer.image : Messages.NONE);
s.AddEntry(Messages.CONTAINER, dockerContainer.container.Length != 0 ? dockerContainer.container : Messages.NONE);
s.AddEntry(Messages.CONTAINER_COMMAND, dockerContainer.command.Length != 0 ? dockerContainer.command : Messages.NONE);
s.AddEntry(Messages.CONTAINER_PORTS, dockerContainer.ports.Length != 0 ? dockerContainer.ports : Messages.NONE);
var ports = dockerContainer.PortList.Select(p => p.Description);
if (ports.Count() > 0)
{
s.AddEntry(Messages.CONTAINER_PORTS, string.Join(Environment.NewLine, ports));
}
s.AddEntry(Messages.UUID, dockerContainer.uuid.Length != 0 ? dockerContainer.uuid : Messages.NONE);
}
}
@ -1554,50 +1560,19 @@ namespace XenAdmin.TabPages
if (info == null)
return;
PDSection s = pdSectionDockerInfo;
addStringEntry(s, Messages.DOCKER_INFO_NGOROUTINES, info.NGoroutines);
addStringEntry(s, Messages.DOCKER_INFO_ROOT_DIR, info.DockerRootDir);
addStringEntry(s, Messages.DOCKER_INFO_DRIVER_STATUS, info.DriverStatus);
addStringEntry(s, Messages.OPERATING_SYSTEM, info.OperatingSystem); ;
addStringEntry(s, Messages.CONTAINER, info.Containers);
addStringEntry(s, Messages.MEMORY, Util.MemorySizeString(Convert.ToDouble(info.MemTotal)));
addStringEntry(s, Messages.DOCKER_INFO_DRIVER, info.Driver);
addStringEntry(s, Messages.DOCKER_INFO_INDEX_SERVER_ADDRESS, info.IndexServerAddress);
addStringEntry(s, Messages.DOCKER_INFO_INITIATE_PATH, info.InitPath);
addStringEntry(s, Messages.DOCKER_INFO_EXECUTION_DRIVER, info.ExecutionDriver);
addStringEntry(s, Messages.NAME, info.Name);
addStringEntry(s, Messages.DOCKER_INFO_NCPU, info.NCPU);
addStringEntry(s, Messages.DOCKER_INFO_DEBUG, info.Debug);
addStringEntry(s, Messages.ID, info.ID);
addStringEntry(s, Messages.DOCKER_INFO_IPV4_FORWARDING, info.IPv4Forwarding);
addStringEntry(s, Messages.DOCKER_INFO_KERNEL_VERSION, info.KernelVersion);
addStringEntry(s, Messages.DOCKER_INFO_NFD, info.NFd);
addStringEntry(s, Messages.DOCKER_INFO_INITIATE_SHA1, info.InitSha1);
addStringEntry(s, Messages.DOCKER_INFO_LABELS, info.Labels);
addStringEntry(s, Messages.DOCKER_INFO_MEMORY_LIMIT, Util.MemorySizeString(Convert.ToDouble(info.MemoryLimit)));
addStringEntry(s, Messages.DOCKER_INFO_SWAP_LIMIT, info.SwapLimit);
addStringEntry(s, Messages.CONTAINER_IMAGE, info.Images);
addStringEntry(s, Messages.DOCKER_INFO_NEVENT_LISTENER, info.NEventsListener);
}
private void generateDockerVersionBox()
{
VM vm = xenObject as VM;
if (vm == null)
return;
VM_Docker_Version version = vm.DockerVersion;
if (version == null)
return;
PDSection s = pdSectionDockerVersion;
addStringEntry(s, Messages.DOCKER_INFO_KERNEL_VERSION, version.KernelVersion);
addStringEntry(s, Messages.DOCKER_INFO_ARCH, version.Arch);
PDSection s = pdSectionDockerInfo;
addStringEntry(s, Messages.DOCKER_INFO_API_VERSION, version.ApiVersion);
addStringEntry(s, Messages.DOCKER_INFO_VERSION, version.Version);
addStringEntry(s, Messages.DOCKER_INFO_GIT_COMMIT, version.GitCommit);
addStringEntry(s, Messages.OPERATING_SYSTEM, version.Os);
addStringEntry(s, Messages.DOCKER_INFO_GO_VERSION, version.GoVersion);
addStringEntry(s, Messages.DOCKER_INFO_DRIVER, info.Driver);
addStringEntry(s, Messages.DOCKER_INFO_INDEX_SERVER_ADDRESS, info.IndexServerAddress);
addStringEntry(s, Messages.DOCKER_INFO_EXECUTION_DRIVER, info.ExecutionDriver);
addStringEntry(s, Messages.DOCKER_INFO_IPV4_FORWARDING, info.IPv4Forwarding);
}
private bool CPUsIdentical(IEnumerable<Host_cpu> cpus)

View File

@ -211,7 +211,7 @@
<value>1, 1, 1, 1</value>
</data>
<data name="pdSectionDockerInfo.SectionTitle" xml:space="preserve">
<value>Docker Information</value>
<value>Container Management - Docker Status</value>
</data>
<data name="pdSectionDockerInfo.Size" type="System.Drawing.Size, System.Drawing">
<value>712, 34</value>

View File

@ -30,6 +30,8 @@
*/
using System;
using System.Collections.Generic;
using System.Xml;
using XenAPI;
using XenAdmin.Core;
@ -302,5 +304,71 @@ namespace XenAdmin.Model
return string.Format(Messages.CONTAINER_ON_VM_TITLE, Name, parent.Name, parent.LocationString);
}
}
public List<DockerContainerPort> PortList
{
get
{
var portList = new List<DockerContainerPort>();
if (string.IsNullOrEmpty(ports))
return portList;
var xmlDoc = new XmlDocument();
try
{
xmlDoc.LoadXml("<items>" + ports + "</items>"); // wrap the ports into a root node
var items = xmlDoc.GetElementsByTagName("item");
foreach (XmlNode node in items)
{
var item = new DockerContainerPort();
foreach (XmlNode child in node.ChildNodes)
{
switch (child.Name)
{
case "IP":
item.Address = child.InnerText;
break;
case "PublicPort":
item.PublicPort = child.InnerText;
break;
case "PrivatePort":
item.PrivatePort = child.InnerText;
break;
case "Type":
item.Protocol = child.InnerText;
break;
}
}
portList.Add(item);
}
}
catch { }
return portList;
}
}
public struct DockerContainerPort
{
public string Address, PublicPort, PrivatePort, Protocol;
public string Description
{
get
{
var list = new List<string>();
if (!string.IsNullOrEmpty(Address))
list.Add(string.Format(Messages.CONTAINER_PORTS_ADDRESS, Address));
if (!string.IsNullOrEmpty(PublicPort))
list.Add(string.Format(Messages.CONTAINER_PORTS_PUBLIC_PORT, PublicPort));
if (!string.IsNullOrEmpty(PrivatePort))
list.Add(string.Format(Messages.CONTAINER_PORTS_PRIVATE_PORT, PrivatePort));
if (!string.IsNullOrEmpty(Protocol))
list.Add(string.Format(Messages.CONTAINER_PORTS_PROTOCOL, Protocol));
return string.Join("; ", list);
}
}
}
}
}

View File

@ -230,7 +230,7 @@ namespace XenAdmin.Model
string ports = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "ports");
if (propertyNode != null)
ports = propertyNode.InnerText;
ports = propertyNode.InnerXml;
DockerContainer newContainer = new DockerContainer(vm, id, name, string.Empty, status, container, created, image, command, ports);

View File

@ -1582,7 +1582,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Xen.
/// Looks up a localized string similar to XenServer.
/// </summary>
public static string Label_host_XenMemory {
get {

View File

@ -529,7 +529,7 @@
<value>VMs</value>
</data>
<data name="Label-host.XenMemory" xml:space="preserve">
<value>Xen</value>
<value>XenServer</value>
</data>
<data name="Label-host.address" xml:space="preserve">
<value>Address</value>

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34209
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -7878,6 +7878,42 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Address: {0}.
/// </summary>
public static string CONTAINER_PORTS_ADDRESS {
get {
return ResourceManager.GetString("CONTAINER_PORTS_ADDRESS", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Private port: {0}.
/// </summary>
public static string CONTAINER_PORTS_PRIVATE_PORT {
get {
return ResourceManager.GetString("CONTAINER_PORTS_PRIVATE_PORT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Protocol: {0}.
/// </summary>
public static string CONTAINER_PORTS_PROTOCOL {
get {
return ResourceManager.GetString("CONTAINER_PORTS_PROTOCOL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Public port: {0}.
/// </summary>
public static string CONTAINER_PORTS_PUBLIC_PORT {
get {
return ResourceManager.GetString("CONTAINER_PORTS_PUBLIC_PORT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to contains.
/// </summary>
@ -10491,7 +10527,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Docker Detail.
/// Looks up a localized string similar to Container Details.
/// </summary>
public static string DOCKER_DETAIL_TAB_TITLE {
get {
@ -10698,7 +10734,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Docker Processes.
/// Looks up a localized string similar to Container Processes.
/// </summary>
public static string DOCKER_PROCESS_TAB_TITLE {
get {

18
XenModel/Messages.resx Normal file → Executable file
View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@ -2849,6 +2849,18 @@ You can only connect to a single Citrix XenServer Express Edition server at a ti
<data name="CONTAINER_PORTS" xml:space="preserve">
<value>Ports</value>
</data>
<data name="CONTAINER_PORTS_ADDRESS" xml:space="preserve">
<value>Address: {0}</value>
</data>
<data name="CONTAINER_PORTS_PRIVATE_PORT" xml:space="preserve">
<value>Private port: {0}</value>
</data>
<data name="CONTAINER_PORTS_PROTOCOL" xml:space="preserve">
<value>Protocol: {0}</value>
</data>
<data name="CONTAINER_PORTS_PUBLIC_PORT" xml:space="preserve">
<value>Public port: {0}</value>
</data>
<data name="CONTAINS" xml:space="preserve">
<value>contains</value>
</data>
@ -3728,7 +3740,7 @@ This will also delete its subfolders.</value>
<value>A memory range cannot be set for these VMs.</value>
</data>
<data name="DOCKER_DETAIL_TAB_TITLE" xml:space="preserve">
<value>Docker Detail</value>
<value>Container Details</value>
</data>
<data name="DOCKER_INFO_API_VERSION" xml:space="preserve">
<value>Api Version</value>
@ -3797,7 +3809,7 @@ This will also delete its subfolders.</value>
<value>Version</value>
</data>
<data name="DOCKER_PROCESS_TAB_TITLE" xml:space="preserve">
<value>Docker Processes</value>
<value>Container Processes</value>
</data>
<data name="DOES_NOT_USE" xml:space="preserve">
<value>does not use</value>