Skip to content

Commit 8c9b754

Browse files
author
Konstantina Chremmou
authored
SDK fixes including CP-53003 (#6210)
Commits best reviewed separately. - CP-53003: Use JsonRpc v1.0 by default and switch to v2.0 once the API version is known. - Removal of deprecated methods and unused internal methods. - Refactoring to fix some inefficiencies when loading and saving certificates in PS.
2 parents fbaad2b + fa1bf90 commit 8c9b754

File tree

4 files changed

+88
-135
lines changed

4 files changed

+88
-135
lines changed

ocaml/sdk-gen/csharp/autogen/src/Session.cs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,15 @@ public Session(JsonRpcClient client)
6565
client.KeepAlive = true;
6666
client.UserAgent = UserAgent;
6767
client.WebProxy = Proxy;
68-
client.JsonRpcVersion = JsonRpcVersion.v2;
6968
client.AllowAutoRedirect = true;
7069
JsonRpcClient = client;
7170
}
7271

73-
[Obsolete("Use Session(string url) { Timeout = ... }; instead.")]
74-
public Session(int timeout, string url)
75-
: this(new JsonRpcClient(url))
76-
{
77-
JsonRpcClient.Timeout = timeout;
78-
}
79-
8072
public Session(string url) :
8173
this(new JsonRpcClient(url))
8274
{
8375
}
8476

85-
[Obsolete("Use Session(string host, int port) { Timeout = ... }; instead.")]
86-
public Session(int timeout, string host, int port)
87-
: this(timeout, GetUrl(host, port))
88-
{
89-
}
90-
9177
public Session(string host, int port)
9278
: this(GetUrl(host, port))
9379
{
@@ -100,23 +86,6 @@ public Session(string url, string opaqueRef)
10086
SetupSessionDetails();
10187
}
10288

103-
/// <summary>
104-
/// Create a new Session instance, using the given instance and timeout. The connection details and Xen-API session handle will be
105-
/// copied from the given instance, but a new connection will be created. Use this if you want a duplicate connection to a host,
106-
/// for example when you need to cancel an operation that is blocking the primary connection.
107-
/// </summary>
108-
/// <param name="session"></param>
109-
/// <param name="timeout"></param>
110-
[Obsolete("Use Session(Session session) { Timeout = ... }; instead.")]
111-
public Session(Session session, int timeout)
112-
: this(session)
113-
{
114-
if (JsonRpcClient != null)
115-
{
116-
JsonRpcClient.Timeout = timeout;
117-
}
118-
}
119-
12089
/// <summary>
12190
/// Create a new Session instance, using the given instance. The connection details
12291
/// and Xen-API session handle will be copied from the given instance, but a new
@@ -175,6 +144,14 @@ private void SetAPIVersion()
175144
Host host = Host.get_record(this, pool.master);
176145
APIVersion = Helper.GetAPIVersion(host.API_version_major, host.API_version_minor);
177146
}
147+
148+
if (JsonRpcClient != null)
149+
{
150+
if (APIVersion == API_Version.API_2_6)
151+
JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v1;
152+
else if (APIVersion >= API_Version.API_2_8)
153+
JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v2;
154+
}
178155
}
179156

180157
private void CopyADFromSession(Session session)

ocaml/sdk-gen/csharp/templates/ApiVersion.mustache

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@
2828
*/
2929

3030
using System;
31-
using System.Collections;
32-
using System.Collections.Generic;
33-
3431

3532
namespace XenAPI
3633
{
@@ -63,8 +60,7 @@ namespace XenAPI
6360
{
6461
try
6562
{
66-
return (API_Version)Enum.Parse(typeof(API_Version),
67-
string.Format("API_{0}_{1}", major, minor));
63+
return (API_Version)Enum.Parse(typeof(API_Version), $"API_{major}_{minor}");
6864
}
6965
catch (ArgumentException)
7066
{
@@ -82,30 +78,14 @@ namespace XenAPI
8278
{
8379
string[] tokens = version.Split('.');
8480
int major, minor;
85-
if (tokens.Length == 2 && int.TryParse(tokens[0], out major) && int.TryParse(tokens[1], out minor))
81+
if (tokens.Length == 2 &&
82+
int.TryParse(tokens[0], out major) &&
83+
int.TryParse(tokens[1], out minor))
8684
{
8785
return GetAPIVersion(major, minor);
8886
}
8987
}
9088
return API_Version.UNKNOWN;
9189
}
92-
93-
/// <summary>
94-
/// Return a positive number if the given session's API version is greater than the given
95-
/// API_version, negative if it is less, and 0 if they are equal.
96-
/// </summary>
97-
internal static int APIVersionCompare(Session session, API_Version v)
98-
{
99-
return (int)session.APIVersion - (int)v;
100-
}
101-
102-
/// <summary>
103-
/// Return true if the given session's API version is greater than or equal to the given
104-
/// API_version.
105-
/// </summary>
106-
internal static bool APIVersionMeets(Session session, API_Version v)
107-
{
108-
return APIVersionCompare(session, v) >= 0;
109-
}
11090
}
11191
}

ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs

Lines changed: 5 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,11 @@
3939

4040
namespace Citrix.XenServer
4141
{
42-
class CommonCmdletFunctions
42+
internal class CommonCmdletFunctions
4343
{
4444
private const string SessionsVariable = "global:Citrix.XenServer.Sessions";
45-
4645
private const string DefaultSessionVariable = "global:XenServer_Default_Session";
4746

48-
private const string KnownServerCertificatesFilePathVariable = "global:KnownServerCertificatesFilePath";
49-
5047
static CommonCmdletFunctions()
5148
{
5249
Session.UserAgent = string.Format("XenServerPSModule/{0}", Assembly.GetExecutingAssembly().GetName().Version);
@@ -78,72 +75,12 @@ internal static void SetDefaultXenSession(PSCmdlet cmdlet, Session session)
7875
cmdlet.SessionState.PSVariable.Set(DefaultSessionVariable, session);
7976
}
8077

81-
internal static string GetKnownServerCertificatesFilePathVariable(PSCmdlet cmdlet)
82-
{
83-
var knownCertificatesFilePathObject = cmdlet.SessionState.PSVariable.GetValue(KnownServerCertificatesFilePathVariable);
84-
if (knownCertificatesFilePathObject is PSObject psObject)
85-
return psObject.BaseObject as string;
86-
return knownCertificatesFilePathObject?.ToString() ?? string.Empty;
87-
}
88-
8978
internal static string GetUrl(string hostname, int port)
9079
{
91-
return string.Format("{0}://{1}:{2}", port == 80 ? "http" : "https", hostname, port);
92-
}
93-
94-
public static Dictionary<string, string> LoadCertificates(PSCmdlet cmdlet)
95-
{
96-
Dictionary<string, string> certificates = new Dictionary<string, string>();
97-
var knownServerCertificatesFilePath = GetKnownServerCertificatesFilePathVariable(cmdlet);
98-
99-
if (File.Exists(knownServerCertificatesFilePath))
100-
{
101-
XmlDocument doc = new XmlDocument();
102-
doc.Load(knownServerCertificatesFilePath);
103-
104-
foreach (XmlNode node in doc.GetElementsByTagName("certificate"))
105-
{
106-
XmlAttribute hostAtt = node.Attributes?["hostname"];
107-
XmlAttribute fngprtAtt = node.Attributes?["fingerprint"];
108-
109-
if (hostAtt != null && fngprtAtt != null)
110-
certificates[hostAtt.Value] = fngprtAtt.Value;
111-
}
112-
}
113-
114-
return certificates;
115-
}
116-
117-
public static void SaveCertificates(PSCmdlet cmdlet, Dictionary<string, string> certificates)
118-
{
119-
var knownServerCertificatesFilePath = GetKnownServerCertificatesFilePathVariable(cmdlet);
120-
string dirName = Path.GetDirectoryName(knownServerCertificatesFilePath);
121-
122-
if (!Directory.Exists(dirName))
123-
Directory.CreateDirectory(dirName);
124-
125-
XmlDocument doc = new XmlDocument();
126-
XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
127-
doc.AppendChild(decl);
128-
XmlNode node = doc.CreateElement("certificates");
129-
130-
foreach (KeyValuePair<string, string> cert in certificates)
131-
{
132-
XmlNode certNode = doc.CreateElement("certificate");
133-
XmlAttribute hostname = doc.CreateAttribute("hostname");
134-
XmlAttribute fingerprint = doc.CreateAttribute("fingerprint");
135-
hostname.Value = cert.Key;
136-
fingerprint.Value = cert.Value;
137-
certNode.Attributes?.Append(hostname);
138-
certNode.Attributes?.Append(fingerprint);
139-
node.AppendChild(certNode);
140-
}
141-
142-
doc.AppendChild(node);
143-
doc.Save(knownServerCertificatesFilePath);
80+
return $"{(port == 80 ? "http" : "https")}://{hostname}:{port}";
14481
}
14582

146-
public static string FingerprintPrettyString(string fingerprint)
83+
internal static string FingerprintPrettyString(string fingerprint)
14784
{
14885
List<string> pairs = new List<string>();
14986
while (fingerprint.Length > 1)
@@ -157,7 +94,7 @@ public static string FingerprintPrettyString(string fingerprint)
15794
return string.Join(":", pairs.ToArray());
15895
}
15996

160-
public static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
97+
internal static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
16198
{
16299
if (tbl == null)
163100
return null;
@@ -169,7 +106,7 @@ public static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
169106
return dict;
170107
}
171108

172-
public static Hashtable ConvertDictionaryToHashtable<T, S>(Dictionary<T, S> dict)
109+
internal static Hashtable ConvertDictionaryToHashtable<T, S>(Dictionary<T, S> dict)
173110
{
174111
if (dict == null)
175112
return null;

ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,24 @@
2929

3030
using System;
3131
using System.Collections.Generic;
32+
using System.IO;
3233
using System.Management.Automation;
3334
using System.Net;
3435
using System.Net.Security;
3536
using System.Runtime.InteropServices;
3637
using System.Security;
3738
using System.Security.Cryptography;
3839
using System.Security.Cryptography.X509Certificates;
40+
using System.Xml;
3941
using XenAPI;
4042

4143
namespace Citrix.XenServer.Commands
4244
{
4345
[Cmdlet("Connect", "XenServer")]
4446
public class ConnectXenServerCommand : PSCmdlet
4547
{
48+
private const string CertificatesPathVariable = "global:KnownServerCertificatesFilePath";
49+
4650
private readonly object _certificateValidationLock = new object();
4751

4852
public ConnectXenServerCommand()
@@ -214,7 +218,10 @@ protected override void ProcessRecord()
214218
{
215219
if (ShouldContinue(ex.Message, ex.Caption))
216220
{
217-
AddCertificate(ex.Hostname, ex.Fingerprint);
221+
var certPath = GetCertificatesPath();
222+
var certificates = LoadCertificates(certPath);
223+
certificates[ex.Hostname] = ex.Fingerprint;
224+
SaveCertificates(certPath, certificates);
218225
i--;
219226
continue;
220227
}
@@ -254,13 +261,6 @@ protected override void ProcessRecord()
254261
WriteObject(newSessions.Values, true);
255262
}
256263

257-
private void AddCertificate(string hostname, string fingerprint)
258-
{
259-
var certificates = CommonCmdletFunctions.LoadCertificates(this);
260-
certificates[hostname] = fingerprint;
261-
CommonCmdletFunctions.SaveCertificates(this, certificates);
262-
}
263-
264264
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
265265
{
266266
if (sslPolicyErrors == SslPolicyErrors.None)
@@ -277,11 +277,11 @@ private bool ValidateServerCertificate(object sender, X509Certificate certificat
277277

278278
bool trusted = VerifyInAllStores(new X509Certificate2(certificate));
279279

280-
var certificates = CommonCmdletFunctions.LoadCertificates(this);
280+
var certPath = GetCertificatesPath();
281+
var certificates = LoadCertificates(certPath);
281282

282-
if (certificates.ContainsKey(hostname))
283+
if (certificates.TryGetValue(hostname, out var fingerprintOld))
283284
{
284-
string fingerprintOld = certificates[hostname];
285285
if (fingerprintOld == fingerprint)
286286
return true;
287287

@@ -295,7 +295,7 @@ private bool ValidateServerCertificate(object sender, X509Certificate certificat
295295
}
296296

297297
certificates[hostname] = fingerprint;
298-
CommonCmdletFunctions.SaveCertificates(this, certificates);
298+
SaveCertificates(certPath, certificates);
299299
return true;
300300
}
301301
}
@@ -312,6 +312,65 @@ private bool VerifyInAllStores(X509Certificate2 certificate2)
312312
return false;
313313
}
314314
}
315+
316+
private string GetCertificatesPath()
317+
{
318+
var certPathObject = SessionState.PSVariable.GetValue(CertificatesPathVariable);
319+
320+
return certPathObject is PSObject psObject
321+
? psObject.BaseObject as string
322+
: certPathObject?.ToString() ?? string.Empty;
323+
}
324+
325+
private Dictionary<string, string> LoadCertificates(string certPath)
326+
{
327+
var certificates = new Dictionary<string, string>();
328+
329+
if (File.Exists(certPath))
330+
{
331+
var doc = new XmlDocument();
332+
doc.Load(certPath);
333+
334+
foreach (XmlNode node in doc.GetElementsByTagName("certificate"))
335+
{
336+
var hostAtt = node.Attributes?["hostname"];
337+
var fngprtAtt = node.Attributes?["fingerprint"];
338+
339+
if (hostAtt != null && fngprtAtt != null)
340+
certificates[hostAtt.Value] = fngprtAtt.Value;
341+
}
342+
}
343+
344+
return certificates;
345+
}
346+
347+
private void SaveCertificates(string certPath, Dictionary<string, string> certificates)
348+
{
349+
string dirName = Path.GetDirectoryName(certPath);
350+
351+
if (!Directory.Exists(dirName))
352+
Directory.CreateDirectory(dirName);
353+
354+
XmlDocument doc = new XmlDocument();
355+
XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
356+
doc.AppendChild(decl);
357+
XmlNode node = doc.CreateElement("certificates");
358+
359+
foreach (KeyValuePair<string, string> cert in certificates)
360+
{
361+
XmlNode certNode = doc.CreateElement("certificate");
362+
XmlAttribute hostname = doc.CreateAttribute("hostname");
363+
XmlAttribute fingerprint = doc.CreateAttribute("fingerprint");
364+
hostname.Value = cert.Key;
365+
fingerprint.Value = cert.Value;
366+
certNode.Attributes?.Append(hostname);
367+
certNode.Attributes?.Append(fingerprint);
368+
node.AppendChild(certNode);
369+
}
370+
371+
doc.AppendChild(node);
372+
doc.Save(certPath);
373+
}
315374
}
316375

317376
internal abstract class CertificateValidationException : Exception

0 commit comments

Comments
 (0)