xenadmin/XenModel/DockerContainers.cs

265 lines
10 KiB
C#
Raw Normal View History

/* 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.Diagnostics;
using XenAPI;
using XenCenterLib;
using XenAdmin.Network;
using System.Xml;
using System.Linq;
namespace XenAdmin.Model
{
public class DockerContainers
{
public static void InitDockerContainers()
{
Trace.Assert(InvokeHelper.Synchronizer != null);
CollectionChangedWithInvoke = InvokeHelper.InvokeHandler(CollectionChanged);
ConnectionsManager.XenConnections.CollectionChanged += XenConnections_CollectionChanged;
foreach (IXenConnection connection in ConnectionsManager.XenConnectionsCopy)
AddConnection(connection);
}
private static void XenConnections_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
InvokeHelper.BeginInvoke(() =>
{
IXenConnection connection = e.Element as IXenConnection;
switch (e.Action)
{
case CollectionChangeAction.Add:
if (connection != null)
AddConnection(connection);
break;
case CollectionChangeAction.Remove:
if (connection != null)
{
RemoveConnection(connection);
}
else
{
var range = e.Element as List<IXenConnection>;
if (range != null)
foreach (var con in range)
RemoveConnection(con);
}
break;
}
});
}
private static CollectionChangeEventHandler CollectionChangedWithInvoke;
private static void AddConnection(IXenConnection connection)
{
connection.Cache.RegisterCollectionChanged<VM>(CollectionChangedWithInvoke);
connection.XenObjectsUpdated += connection_XenObjectsUpdated;
InvokeHelper.Invoke(delegate()
{
UpdateAll(connection.Cache.VMs);
});
}
private static void RemoveConnection(IXenConnection connection)
{
connection.Cache.DeregisterCollectionChanged<VM>(CollectionChangedWithInvoke);
connection.XenObjectsUpdated -= connection_XenObjectsUpdated;
}
private static void CollectionChanged(Object sender, CollectionChangeEventArgs e)
{
InvokeHelper.AssertOnEventThread();
var vm = e.Element as VM;
Trace.Assert(vm != null, "The item changed is not a VM");
switch (e.Action)
{
case CollectionChangeAction.Add:
vm.PropertyChanged += ServerXenObject_PropertyChanged;
UpdateDockerContainer(vm);
break;
case CollectionChangeAction.Remove:
vm.PropertyChanged -= ServerXenObject_PropertyChanged;
RemoveObject(vm);
break;
default:
System.Diagnostics.Trace.Assert(false);
break;
}
}
static void connection_XenObjectsUpdated(object sender, EventArgs e)
{
IXenConnection connection = sender as IXenConnection;
if (connection == null)
return;
connection.Cache.CheckDockerContainersBatchChange();
}
private static void ServerXenObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Trace.Assert(sender is VM);
VM vm = sender as VM;
if (e.PropertyName == "other_config")
{
UpdateDockerContainer(vm);
}
}
private static void RemoveObject(VM vm)
{
InvokeHelper.AssertOnEventThread();
IXenConnection connection = vm.Connection;
connection.Cache.UpdateDockerContainersForVM(new List<DockerContainer>(), vm);
}
private static void UpdateAll(VM[] vms)
{
foreach (VM vm in vms)
{
vm.PropertyChanged -= ServerXenObject_PropertyChanged;
vm.PropertyChanged += ServerXenObject_PropertyChanged;
UpdateDockerContainer(vm);
}
}
private static void UpdateDockerContainer(VM vm)
{
InvokeHelper.AssertOnEventThread();
if (vm == null)
return;
IXenConnection connection = vm.Connection;
var dockerVMs = GetDockerVMs(vm);
connection.Cache.UpdateDockerContainersForVM(dockerVMs, vm);
}
public static List<DockerContainer> GetContainersFromOtherConfig(VM vm)
{
var containers = new List<DockerContainer>();
var other_config = vm.other_config;
if (other_config.ContainsKey("docker_ps"))
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(other_config["docker_ps"]);
foreach (XmlNode entry in doc.GetElementsByTagName("entry"))
{
//uuid
string id = "";
var propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "id");
if (propertyNode != null)
id = propertyNode.InnerText;
string name = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "names");
if (propertyNode != null)
name = propertyNode.InnerText;
string status = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "status");
if (propertyNode != null)
status = propertyNode.InnerText;
string container = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "container");
if (propertyNode != null)
container = propertyNode.InnerText;
string created = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "created");
if (propertyNode != null)
created = propertyNode.InnerText;
string image = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "image");
if (propertyNode != null)
image = propertyNode.InnerText;
string command = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "command");
if (propertyNode != null)
command = propertyNode.InnerText;
string ports = "";
propertyNode = entry.ChildNodes.Cast<XmlNode>().FirstOrDefault(node => node.Name == "ports");
if (propertyNode != null)
ports = propertyNode.InnerXml;
DockerContainer newContainer = new DockerContainer(vm, id, name, string.Empty, status, container, created, image, command, ports);
// update existing container or add a new one
DockerContainer existingContainer = vm.Connection.Resolve(new XenRef<DockerContainer>(newContainer));
if (existingContainer != null)
{
existingContainer.UpdateFrom(newContainer);
containers.Add(existingContainer);
}
else
containers.Add(newContainer);
}
}
return containers;
}
public static ComparableList<DockerContainer> GetDockerVMs(IXenObject o)
{
var vm = o as VM;
if (vm != null && vm.is_a_real_vm())
{
return new ComparableList<DockerContainer>(DockerContainers.GetContainersFromOtherConfig(vm));
}
return new ComparableList<DockerContainer>();
}
}
}