diff --git a/ocaml/idl/datamodel.ml b/ocaml/idl/datamodel.ml index 82f8d1d85ed..5f9ca1d35de 100644 --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -11037,7 +11037,7 @@ let http_actions = ; ( "get_vm_rrds" , ( Get , "/vm_rrds" - , true + , false , [String_query_arg "uuid"; Bool_query_arg "json"] , _R_READ_ONLY , [] @@ -11054,7 +11054,7 @@ let http_actions = ) (* For XC < 8460 compatibility, remove when out of support *) ; ( "get_host_rrds" - , (Get, "/host_rrds", true, [Bool_query_arg "json"], _R_READ_ONLY, []) + , (Get, "/host_rrds", false, [Bool_query_arg "json"], _R_READ_ONLY, []) ) ; ( Constants.get_sr_rrd , ( Get diff --git a/ocaml/sdk-gen/c/README.dist b/ocaml/sdk-gen/c/README.dist index 20095880330..d721728b035 100644 --- a/ocaml/sdk-gen/c/README.dist +++ b/ocaml/sdk-gen/c/README.dist @@ -1,7 +1,7 @@ libxenserver ============ -Copyright (c) 2007-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2007-2026 Cloud Software Group, Inc. All Rights Reserved. libxenserver is a complete SDK for XenServer exposing the XenServer API to C developers. @@ -20,10 +20,10 @@ Reference For XenServer documentation see https://docs.xenserver.com The XenServer Management API Reference is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/management-api +https://docs.xenserver.com/en-us/xenserver/developer/api-reference The XenServer Software Development Kit Guide is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/sdk-guide +https://docs.xenserver.com/en-us/xenserver/developer/sdk-guide A number of examples to help you get started with the SDK is available at https://github.com/xenserver/xenserver-samples @@ -32,7 +32,7 @@ For community content, blogs, and downloads, visit https://www.xenserver.com/blogs and https://www.citrix.com/community/ To network with other developers using XenServer visit -https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver/ +https://community.citrix.com/forums/forum/1118-xenserver-sdk/ Dependencies diff --git a/ocaml/sdk-gen/csharp/FriendlyErrorNames.resx b/ocaml/sdk-gen/csharp/FriendlyErrorNames.resx index 69b5ae29fb9..5786eca65fa 100644 --- a/ocaml/sdk-gen/csharp/FriendlyErrorNames.resx +++ b/ocaml/sdk-gen/csharp/FriendlyErrorNames.resx @@ -91,7 +91,7 @@ The GPU group contains active virtual GPUs and cannot be deleted. - Object has been deleted.{0}:{1} + Could not find the specified object. If it existed before, it may have recently been deleted. {0} {1} This operation cannot be performed because the referenced network is not properly shared. The network must either be entirely virtual or must be physically present via a currently attached PIF on every server. diff --git a/ocaml/sdk-gen/csharp/autogen/README.md b/ocaml/sdk-gen/csharp/autogen/README.md index acc7622ee50..cac10e6a532 100644 --- a/ocaml/sdk-gen/csharp/autogen/README.md +++ b/ocaml/sdk-gen/csharp/autogen/README.md @@ -1,6 +1,6 @@ # XenServer.NET -Copyright (c) 2007-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2007-2026 Cloud Software Group, Inc. All Rights Reserved. XenServer.NET is a complete SDK for XenServer, exposing the XenServer API as .NET classes. It is written in C#. @@ -18,10 +18,10 @@ terms of the BSD 2-Clause license. See LICENSE.txt for details. For XenServer documentation see The XenServer Management API Reference is available at - + The XenServer Software Development Kit Guide is available at - + A number of examples to help you get started with the SDK is available at @@ -30,11 +30,11 @@ For community content, blogs, and downloads, visit and To network with other developers using XenServer visit - + ## Prerequisites -This library requires .NET Standard 2.0. +This library targets .NET Framework 4.6.2, .NET Standard 2.0, and .NET 8.0. ## Dependencies diff --git a/ocaml/sdk-gen/csharp/autogen/src/Event.cs b/ocaml/sdk-gen/csharp/autogen/src/Event.cs index 1eed4e3ef10..ad89ae086c6 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/Event.cs +++ b/ocaml/sdk-gen/csharp/autogen/src/Event.cs @@ -45,22 +45,6 @@ public override void UpdateFrom(Event update) id = update.id; } - [Obsolete("Use the calls setting individual fields of the API object instead.")] - public override string SaveChanges(Session session, string opaqueRef, Event serverObject) - { - if (opaqueRef == null) - { - throw new InvalidOperationException("There is no constructor available for this type; you cannot directly create one on the server."); - } - - Event server = serverObject; - - if (!_id.Equals(server._id)) - set_id(session, opaqueRef, _id); - - return null; - } - public static Event get_record(Session session, string _event) { return session.JsonRpcClient.event_get_record(session.opaque_ref, _event); diff --git a/ocaml/sdk-gen/csharp/autogen/src/HTTP.cs b/ocaml/sdk-gen/csharp/autogen/src/HTTP.cs index 732478828f2..ca26aa3cd09 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/HTTP.cs +++ b/ocaml/sdk-gen/csharp/autogen/src/HTTP.cs @@ -90,10 +90,21 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont [Serializable] public class BadServerResponseException : Exception { + public int StatusCode { get; } + public string InitialLine { get; } + public string Body { get; } + public BadServerResponseException() { } public BadServerResponseException(string message) : base(message) { } + public BadServerResponseException(string message, int statusCode, string initialLine, string body) : base(message) + { + StatusCode = statusCode; + InitialLine = initialLine; + Body = body; + } + public BadServerResponseException(string message, Exception exception) : base(message, exception) { } #if !(NET8_0_OR_GREATER) @@ -195,11 +206,16 @@ private static string ReadLine(Stream stream) private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nodelay, int timeout_ms, List headers = null) { // read headers/fields - string line = ReadLine(stream), initialLine = line, transferEncodingField = null; + string line = ReadLine(stream); + string initialLine = line; + string transferEncodingField = null; + if (string.IsNullOrEmpty(initialLine)) // sanity check return false; + if (headers == null) headers = new List(); + while (!string.IsNullOrWhiteSpace(line)) // IsNullOrWhiteSpace also checks for empty string { line = line.TrimEnd('\r', '\n'); @@ -211,6 +227,7 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod // read chunks string entityBody = ""; + if (!string.IsNullOrEmpty(transferEncodingField)) { int lastChunkSize = -1; @@ -246,13 +263,9 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod entityBody = entityBody.TrimEnd('\r', '\n'); headers.Add(entityBody); // keep entityBody if it's needed for Digest authentication (when qop="auth-int") } - else - { - // todo: handle other transfer types, in case "Transfer-Encoding: Chunked" isn't used - } // handle server response - int code = getResultCode(initialLine); + int code = GetResultCode(initialLine); switch (code) { case 407: // authentication error; caller must handle this case @@ -268,17 +281,32 @@ private static bool ReadHttpHeaders(ref Stream stream, IWebProxy proxy, bool nod return true; // headers need to be sent again default: + var contentLengthHeader = headers + .FirstOrDefault(h => h.StartsWith("Content-Length:", StringComparison.InvariantCultureIgnoreCase)); + + if (contentLengthHeader != null && int.TryParse(contentLengthHeader.Substring(15).Trim(), out var len)) + { + byte[] bytes = new byte[len]; + int total = 0; + int read; + + while (total < len && (read = stream.Read(bytes, total, len - total)) > 0) + total += read; + + entityBody = Encoding.ASCII.GetString(bytes); + } + stream.Close(); - throw new BadServerResponseException(string.Format("Received error code {0} from the server", initialLine)); + throw new BadServerResponseException(string.Format("Received error code {0} from the server", initialLine), code, initialLine, entityBody); } return false; } - private static int getResultCode(string line) + private static int GetResultCode(string line) { string[] bits = line.Split(' '); - return (bits.Length < 2 ? 0 : Int32.Parse(bits[1])); + return bits.Length < 2 ? 0 : Int32.Parse(bits[1]); } public static bool UseSSL(Uri uri) @@ -651,7 +679,7 @@ private static void AuthenticateProxy(ref Stream stream, Uri uri, IWebProxy prox if (authenticatedResponse.Count == 0) throw new BadServerResponseException("No response from the proxy server after authentication attempt."); - switch (getResultCode(authenticatedResponse[0])) + switch (GetResultCode(authenticatedResponse[0])) { case 200: break; diff --git a/ocaml/sdk-gen/csharp/autogen/src/JsonRpc.cs b/ocaml/sdk-gen/csharp/autogen/src/JsonRpc.cs index a790f397320..91a39f53770 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/JsonRpc.cs +++ b/ocaml/sdk-gen/csharp/autogen/src/JsonRpc.cs @@ -163,6 +163,7 @@ public override string ToString() public partial class JsonRpcClient { private int _globalId; + private string _userAgent; #if (NET8_0_OR_GREATER) private static readonly Type ClassType = typeof(JsonRpcClient); @@ -205,6 +206,10 @@ public JsonRpcClient(string baseUrl) Url = baseUrl; JsonRpcUrl = new Uri(new Uri(baseUrl), "/jsonrpc").ToString(); JsonRpcVersion = JsonRpcVersion.v1; + Timeout = Session.STANDARD_TIMEOUT; + UserAgent = Session.DefaultUserAgent; + KeepAlive = true; + AllowAutoRedirect = true; } /// @@ -215,7 +220,13 @@ public JsonRpcClient(string baseUrl) public event Action RequestEvent; public JsonRpcVersion JsonRpcVersion { get; set; } - public string UserAgent { get; set; } + + public string UserAgent + { + get => _userAgent; + set => _userAgent = string.IsNullOrEmpty(value) ? Session.DefaultUserAgent : value; + } + public bool KeepAlive { get; set; } public IWebProxy WebProxy { get; set; } public int Timeout { get; set; } @@ -239,7 +250,7 @@ public JsonRpcClient(string baseUrl) public string JsonRpcUrl { get; private set; } - private void Rpc(string callName, JToken parameters, JsonSerializer serializer) + protected void Rpc(string callName, JToken parameters, JsonSerializer serializer) { Rpc(callName, parameters, serializer); } @@ -516,7 +527,7 @@ private JsonSerializerSettings CreateSettings(IList converters) }; } - private JsonSerializer CreateSerializer(IList converters) + protected JsonSerializer CreateSerializer(IList converters) { var settings = CreateSettings(converters); return JsonSerializer.Create(settings); diff --git a/ocaml/sdk-gen/csharp/autogen/src/README-NuGet.md b/ocaml/sdk-gen/csharp/autogen/src/README-NuGet.md index 0e4a60fffc0..a541ab76d55 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/README-NuGet.md +++ b/ocaml/sdk-gen/csharp/autogen/src/README-NuGet.md @@ -1,6 +1,6 @@ # XenServer.NET -Copyright (c) 2007-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2007-2026 Cloud Software Group, Inc. All Rights Reserved. XenServer.NET is a complete SDK for XenServer, exposing the XenServer API as .NET classes. It is written in C#. @@ -13,35 +13,32 @@ are ideal for developers wishing to use XenServer.NET. XenServer.NET is free software. You can redistribute and modify it under the terms of the BSD 2-Clause license. See LICENSE.txt for details. - ## Reference -For XenServer documentation see https://docs.xenserver.com +For XenServer documentation see The XenServer Management API Reference is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/management-api + The XenServer Software Development Kit Guide is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/sdk-guide + A number of examples to help you get started with the SDK is available at -https://github.com/xenserver/xenserver-samples + For community content, blogs, and downloads, visit -https://www.xenserver.com/blogs and https://www.citrix.com/community + and To network with other developers using XenServer visit -https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver - + ## Prerequisites -This library requires .NET Standard 2.0. - +This library targets .NET Framework 4.6.2, .NET Standard 2.0, and .NET 8.0. ## Dependencies XenServer.NET is dependent upon the following libraries: -- Newtonsoft JSON.NET by James Newton-King (see https://www.newtonsoft.com). +- Newtonsoft JSON.NET by James Newton-King (see ). JSON.NET is licensed under the MIT license. \ No newline at end of file diff --git a/ocaml/sdk-gen/csharp/autogen/src/Session.cs b/ocaml/sdk-gen/csharp/autogen/src/Session.cs index 5d999136833..4ffcaf7aab3 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/Session.cs +++ b/ocaml/sdk-gen/csharp/autogen/src/Session.cs @@ -46,29 +46,16 @@ public partial class Session : XenObject public const int STANDARD_TIMEOUT = 24 * 60 * 60 * 1000; /// - /// This string is used as the HTTP UserAgent for each request. + /// The default HTTP UserAgent for each request. /// - public static string UserAgent = $"XenAPI/{Helper.APIVersionString(API_Version.LATEST)}"; - - /// - /// If null, no proxy is used, otherwise this proxy is used for each request. - /// - public static IWebProxy Proxy = null; - - public API_Version APIVersion = API_Version.UNKNOWN; - - public object Tag; + public static readonly string DefaultUserAgent = $"XenServer.NET/@SDK_VERSION@"; #region Constructors + /// Thrown if 'client' is null public Session(JsonRpcClient client) { - client.Timeout = STANDARD_TIMEOUT; - client.KeepAlive = true; - client.UserAgent = UserAgent; - client.WebProxy = Proxy; - client.AllowAutoRedirect = true; - JsonRpcClient = client; + JsonRpcClient = client ?? throw new ArgumentNullException(nameof(client)); } public Session(string url) : @@ -101,8 +88,7 @@ public Session(Session session) //in the following do not copy over the ConnectionGroupName - if (session.JsonRpcClient != null && - (APIVersion == API_Version.API_2_6 || APIVersion >= API_Version.API_2_8)) + if (APIVersion == API_Version.API_2_6 || APIVersion >= API_Version.API_2_8) { JsonRpcClient = new JsonRpcClient(session.Url) { @@ -119,7 +105,12 @@ public Session(Session session) ServerCertificateValidationCallback = session.JsonRpcClient.ServerCertificateValidationCallback }; } - CopyADFromSession(session); + + //copy AD details + IsLocalSuperuser = session.IsLocalSuperuser; + SessionSubject = session.SessionSubject; + UserSid = session.UserSid; + Permissions = session.Permissions; } #endregion @@ -131,14 +122,7 @@ private static string GetUrl(string hostname, int port) private void SetupSessionDetails() { - SetAPIVersion(); - SetADDetails(); - SetRbacPermissions(); - } - - private void SetAPIVersion() - { - Dictionary, Pool> pools = Pool.get_all_records(this); + var pools = Pool.get_all_records(this); if (pools.Values.Count > 0) { @@ -147,125 +131,92 @@ private void SetAPIVersion() APIVersion = Helper.GetAPIVersion(host.API_version_major, host.API_version_minor); } - if (JsonRpcClient != null) - { - if (APIVersion == API_Version.API_2_6) - JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v1; - else if (APIVersion >= API_Version.API_2_8) - JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v2; - } - } + //the SDK cannot connect to servers with API < 2.5 because JsonRPC was not available - private void CopyADFromSession(Session session) - { - IsLocalSuperuser = session.IsLocalSuperuser; - SessionSubject = session.SessionSubject; - UserSid = session.UserSid; - Roles = session.Roles; - Permissions = session.Permissions; - } - - /// - /// Applies only to API 1.6 (george) and above. - /// - private void SetADDetails() - { - if (APIVersion < API_Version.API_1_6) - { - IsLocalSuperuser = true; - return; - } - - IsLocalSuperuser = get_is_local_superuser(); - if (IsLocalSuperuser) - return; + if (APIVersion == API_Version.API_2_6) + JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v1; + else if (APIVersion >= API_Version.API_2_8) + JsonRpcClient.JsonRpcVersion = JsonRpcVersion.v2; - SessionSubject = get_subject(this, opaque_ref); - UserSid = get_auth_user_sid(); + IsLocalSuperuser = get_is_local_superuser(this, opaque_ref); - // Cache the details of this user to avoid making server calls later - // For example, some users get access to the pool through a group subject and will not be in the main cache - UserDetails.UpdateDetails(UserSid, this); - } - - /// - /// Applies only to API 1.7 (midnight-ride) and above. - /// Older versions have no RBAC, only AD. - /// - private void SetRbacPermissions() - { - if (APIVersion < API_Version.API_1_7) - return; - - // allRoles will contain every role on the server, permissions contains the subset of those that are available to this session. - Permissions = Session.get_rbac_permissions(this, opaque_ref); - Dictionary, Role> allRoles = Role.get_all_records(this); - // every Role object is either a single api call (a permission) or has subroles and contains permissions through its descendants. - // We take out the parent Roles (VM-Admin etc.) into the Session.Roles field - foreach (string s in Permissions) + if (!IsLocalSuperuser) { - foreach (XenRef xr in allRoles.Keys) - { - Role r = allRoles[xr]; - if (r.subroles.Count > 0 && r.name_label == s) - { - r.opaque_ref = xr.opaque_ref; - Roles.Add(r); - break; - } - } + SessionSubject = get_subject(this, opaque_ref); + UserSid = get_auth_user_sid(this, opaque_ref); + + // Cache the details of this user to avoid making server calls later + UserDetails.UpdateDetails(UserSid, this); } - } - public override void UpdateFrom(Session update) - { - throw new Exception("The method or operation is not implemented."); + Permissions = get_rbac_permissions(this, opaque_ref); } - [Obsolete("Use the calls setting individual fields of the API object instead.")] - public override string SaveChanges(Session session, string serverOpaqueRef, Session serverObject) + public override void UpdateFrom(Session update) { throw new Exception("The method or operation is not implemented."); } #region Properties + public API_Version APIVersion { get; private set; } = API_Version.UNKNOWN; + + public object Tag { get; set; } + /// /// Retrieves the current users details from the UserDetails map. These values are only updated when a new session is created. /// public virtual UserDetails CurrentUserDetails => UserSid == null ? null : UserDetails.Sid_To_UserDetails[UserSid]; - public JsonRpcClient JsonRpcClient { get; private set; } + public JsonRpcClient JsonRpcClient { get; } public string Url => JsonRpcClient.Url; + /// + /// The WebProxy to use for each HTTP request. + /// + public IWebProxy Proxy + { + get => JsonRpcClient.WebProxy; + set => JsonRpcClient.WebProxy = value; + } + + /// + /// The UserAgent to use for each HTTP request. If set to null or empty the DefaultUserAgent will be used. + /// + public string UserAgent + { + get => JsonRpcClient.UserAgent; + set => JsonRpcClient.UserAgent = value; + } + public string ConnectionGroupName { - get => JsonRpcClient?.ConnectionGroupName; + get => JsonRpcClient.ConnectionGroupName; set => JsonRpcClient.ConnectionGroupName = value; } public int Timeout { - get => JsonRpcClient?.Timeout ?? STANDARD_TIMEOUT; + get => JsonRpcClient.Timeout; set => JsonRpcClient.Timeout = value; } #if (NET8_0_OR_GREATER) public Func ServerCertificateValidationCallback { - get => JsonRpcClient?.ServerCertificateValidationCallback; + get => JsonRpcClient.ServerCertificateValidationCallback; set => JsonRpcClient.ServerCertificateValidationCallback = value; } #else public RemoteCertificateValidationCallback ServerCertificateValidationCallback { - get => JsonRpcClient?.ServerCertificateValidationCallback; + get => JsonRpcClient.ServerCertificateValidationCallback; set => JsonRpcClient.ServerCertificateValidationCallback = value; } #endif - public ICredentials Credentials => JsonRpcClient?.WebProxy?.Credentials; + public ICredentials Credentials => JsonRpcClient.WebProxy?.Credentials; /// /// Optional headers in name-value pairs to be passed in the HttpWebRequests. The @@ -307,18 +258,12 @@ public Dictionary RequestHeaders public string UserSid { get; private set; } /// - /// All permissions associated with the session at the time of log in. This is the list xapi uses until the session is logged out; + /// All permissions associated with the session at the time of log in. + /// This is the list xapi uses until the session is logged out; /// even if the permitted roles change on the server side, they don't apply until the next session. /// public string[] Permissions { get; private set; } - /// - /// All roles associated with the session at the time of log in. Do not rely on roles for determining what a user can do, - /// instead use Permissions. This list should only be used for UI purposes. - /// - [JsonConverter(typeof(XenRefListConverter))] - public List Roles { get; private set; } = new List(); - #endregion public string[] GetSystemMethods() @@ -328,9 +273,7 @@ public string[] GetSystemMethods() public static Session get_record(Session session, string sessionOpaqueRef) { - Session newSession = new Session(session.Url) { opaque_ref = sessionOpaqueRef }; - newSession.SetAPIVersion(); - return newSession; + return session.JsonRpcClient.session_get_record(session.opaque_ref, sessionOpaqueRef); } public void login_with_password(string username, string password) @@ -344,7 +287,6 @@ public void login_with_password(string username, string password, string version try { opaque_ref = JsonRpcClient.session_login_with_password(username, password, version); - SetupSessionDetails(); } catch (Failure exn) @@ -366,7 +308,6 @@ public void login_with_password(string username, string password, string version try { opaque_ref = JsonRpcClient.session_login_with_password(username, password, version, originator); - SetupSessionDetails(); } catch (Failure exn) @@ -383,6 +324,7 @@ public void login_with_password(string username, string password, string version } } + [Obsolete("Use method login_with_password(string username, string password, string version) instead")] public void login_with_password(string username, string password, API_Version version) { login_with_password(username, password, Helper.APIVersionString(version)); @@ -397,23 +339,18 @@ public void slave_local_login_with_password(string username, string password) public void logout() { - logout(this); + session_logout(this, opaque_ref); + opaque_ref = null; } - - /// - /// Log out of the given session2, using this session for the connection. - /// - /// The session to log out + + [Obsolete("Use static method session_logout(Session session, string opaqueRef) instead")] public void logout(Session session2) { logout(session2.opaque_ref); session2.opaque_ref = null; } - /// - /// Log out of the session with the given reference, using this session for the connection. - /// - /// The session to log out + [Obsolete("Use static method session_logout(Session session, string opaqueRef) instead")] public void logout(string self) { if (self == null) @@ -422,17 +359,25 @@ public void logout(string self) JsonRpcClient.session_logout(self); } + public static void session_logout(Session session, string opaqueRef) + { + session.JsonRpcClient.session_logout(opaqueRef); + } + public void local_logout() { - local_logout(this); + session_local_logout(this, opaque_ref); + opaque_ref = null; } + [Obsolete("Use static method session_local_logout(Session session, string opaqueRef) instead")] public void local_logout(Session session2) { local_logout(session2.opaque_ref); session2.opaque_ref = null; } + [Obsolete("Use static method session_local_logout(Session session, string opaqueRef) instead")] public void local_logout(string opaqueRef) { if (opaqueRef == null) @@ -441,22 +386,23 @@ public void local_logout(string opaqueRef) JsonRpcClient.session_local_logout(opaqueRef); } + public static void session_local_logout(Session session, string opaqueRef) + { + session.JsonRpcClient.session_local_logout(opaqueRef); + } + + [Obsolete("Use static method Session.change_password instead")] public void change_password(string oldPassword, string newPassword) { change_password(this, oldPassword, newPassword); } - /// - /// Change the password on the given session2, using this session for the connection. - /// - /// The session to change - /// - /// - public void change_password(Session session2, string oldPassword, string newPassword) + public static void change_password(Session session, string oldPassword, string newPassword) { - JsonRpcClient.session_change_password(session2.opaque_ref, oldPassword, newPassword); + session.JsonRpcClient.session_change_password(session.opaque_ref, oldPassword, newPassword); } + [Obsolete("Use static method Session.get_this_host instead")] public string get_this_host() { return get_this_host(this, opaque_ref); @@ -467,6 +413,7 @@ public static string get_this_host(Session session, string self) return session.JsonRpcClient.session_get_this_host(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_this_user instead")] public string get_this_user() { return get_this_user(this, opaque_ref); @@ -477,6 +424,7 @@ public static string get_this_user(Session session, string self) return session.JsonRpcClient.session_get_this_user(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_is_local_superuser instead")] public bool get_is_local_superuser() { return get_is_local_superuser(this, opaque_ref); @@ -492,6 +440,7 @@ public static string[] get_rbac_permissions(Session session, string self) return session.JsonRpcClient.session_get_rbac_permissions(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_last_active instead")] public DateTime get_last_active() { return get_last_active(this, opaque_ref); @@ -502,6 +451,7 @@ public static DateTime get_last_active(Session session, string self) return session.JsonRpcClient.session_get_last_active(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_pool instead")] public bool get_pool() { return get_pool(this, opaque_ref); @@ -512,6 +462,7 @@ public static bool get_pool(Session session, string self) return session.JsonRpcClient.session_get_pool(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_subject instead")] public XenRef get_subject() { return get_subject(this, opaque_ref); @@ -522,6 +473,7 @@ public static XenRef get_subject(Session session, string self) return session.JsonRpcClient.session_get_subject(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.get_auth_user_sid instead")] public string get_auth_user_sid() { return get_auth_user_sid(this, opaque_ref); @@ -532,8 +484,7 @@ public static string get_auth_user_sid(Session session, string self) return session.JsonRpcClient.session_get_auth_user_sid(session.opaque_ref, self ?? ""); } - #region AD SID enumeration and bootout - + [Obsolete("Use static method Session.get_all_subject_identifiers instead")] public string[] get_all_subject_identifiers() { return get_all_subject_identifiers(this); @@ -544,6 +495,7 @@ public static string[] get_all_subject_identifiers(Session session) return session.JsonRpcClient.session_get_all_subject_identifiers(session.opaque_ref); } + [Obsolete("Use static method Session.async_get_all_subject_identifiers instead")] public XenRef async_get_all_subject_identifiers() { return async_get_all_subject_identifiers(this); @@ -554,17 +506,18 @@ public static XenRef async_get_all_subject_identifiers(Session session) return session.JsonRpcClient.async_session_get_all_subject_identifiers(session.opaque_ref); } - public string logout_subject_identifier(string subjectIdentifier) + [Obsolete("Use static method Session.logout_subject_identifier instead")] + public void logout_subject_identifier(string subjectIdentifier) { - return logout_subject_identifier(this, subjectIdentifier); + logout_subject_identifier(this, subjectIdentifier); } - public static string logout_subject_identifier(Session session, string subjectIdentifier) + public static void logout_subject_identifier(Session session, string subjectIdentifier) { session.JsonRpcClient.session_logout_subject_identifier(session.opaque_ref, subjectIdentifier); - return string.Empty; } + [Obsolete("Use static method Session.async_logout_subject_identifier instead")] public XenRef async_logout_subject_identifier(string subjectIdentifier) { return async_logout_subject_identifier(this, subjectIdentifier); @@ -575,10 +528,7 @@ public static XenRef async_logout_subject_identifier(Session session, stri return session.JsonRpcClient.async_session_logout_subject_identifier(session.opaque_ref, subjectIdentifier); } - #endregion - - #region other_config stuff - + [Obsolete("Use static method Session.get_other_config instead")] public Dictionary get_other_config() { return get_other_config(this, opaque_ref); @@ -589,6 +539,7 @@ public static Dictionary get_other_config(Session session, strin return session.JsonRpcClient.session_get_other_config(session.opaque_ref, self ?? ""); } + [Obsolete("Use static method Session.set_other_config instead")] public void set_other_config(Dictionary otherConfig) { set_other_config(this, opaque_ref, otherConfig); @@ -599,6 +550,7 @@ public static void set_other_config(Session session, string self, Dictionary : IXenObject where S : XenObject /// public abstract void UpdateFrom(S record); - [Obsolete("Use the calls setting individual fields of the API object instead.")] - public abstract string SaveChanges(Session session, string serverOpaqueRef, S serverObject); - public string opaque_ref { get; set; } public event PropertyChangedEventHandler PropertyChanged; diff --git a/ocaml/sdk-gen/csharp/autogen/src/XenServer.csproj b/ocaml/sdk-gen/csharp/autogen/src/XenServer.csproj index 22acc1de24a..29757b4506b 100644 --- a/ocaml/sdk-gen/csharp/autogen/src/XenServer.csproj +++ b/ocaml/sdk-gen/csharp/autogen/src/XenServer.csproj @@ -1,7 +1,7 @@  0.0.0 - net80;netstandard2.0;net45 + net80;netstandard2.0;net462 Library XenAPI True @@ -11,7 +11,7 @@ $(AssemblyName).NET $(AssemblyName).NET .NET wrapper for the XenServer API - Copyright (c) 2007-2025 Cloud Software Group, Inc. All Rights Reserved. + Copyright (c) 2007-2026 Cloud Software Group, Inc. All Rights Reserved. citrix hypervisor virtualization sdk jsonrpc .net c# xen xenserver BSD-2-Clause https://github.com/xapi-project/xen-api diff --git a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml index a442a4ede40..c6e941792c6 100644 --- a/ocaml/sdk-gen/csharp/gen_csharp_binding.ml +++ b/ocaml/sdk-gen/csharp/gen_csharp_binding.ml @@ -356,35 +356,7 @@ and gen_class out_chan cls = ) ) ; - print - ";\n\ - \ }\n\n\ - \ [Obsolete(\"Use the calls setting individual fields of the API \ - object instead.\")]\n\ - \ public override string SaveChanges(Session session, string \ - opaqueRef, %s server)\n\ - \ {\n\ - \ if (opaqueRef == null)\n\ - \ {" - exposed_class_name ; - - if cls.gen_constructor_destructor then - print - "\n\ - \ var reference = create(session, this);\n\ - \ return reference == null ? null : reference.opaque_ref;\n" - else - print - "\n\ - \ System.Diagnostics.Debug.Assert(false, \"Cannot create \ - instances of this type on the server\");\n\ - \ return \"\";\n" ; - - print " }\n else\n {\n" ; - - gen_save_changes out_chan exposed_class_name messages contents ; - - print "\n }\n }\n" ; + print ";\n }\n\n" ; let gen_exposed_method_overloads cls message = let generator x = gen_exposed_method cls message x in @@ -606,63 +578,6 @@ and exposed_call_params message classname params = in String.concat ", " ("session.opaque_ref" :: exposedParams) -(* 'messages' are methods, 'contents' are fields *) -and gen_save_changes out_chan exposed_class_name messages contents = - let fields = List.concat_map flatten_content contents in - let fields2 = - List.filter - (fun fr -> fr.qualifier == RW && not (List.mem "public" fr.full_name)) - fields - in - (* Find all StaticRO fields which have corresponding messages (methods) of the form set_readonlyField *) - let readonlyFieldsWithSetters = - List.filter - (fun field -> - field.qualifier == StaticRO - && List.exists - (fun msg -> - msg.msg_name = String.concat "" ["set_"; full_name field] - ) - messages - ) - fields - in - let length = List.length fields2 + List.length readonlyFieldsWithSetters in - let print format = fprintf out_chan format in - if length == 0 then - print - " throw new InvalidOperationException(\"This type has no \ - read/write properties\");" - else ( - List.iter (gen_save_changes_to_field out_chan exposed_class_name) fields2 ; - (* Generate calls to any set_ methods *) - List.iter - (gen_save_changes_to_field out_chan exposed_class_name) - readonlyFieldsWithSetters ; - print "\n return null;" - ) - -and flatten_content content = - match content with - | Field fr -> - [fr] - | Namespace (_, c) -> - List.concat_map flatten_content c - -and gen_save_changes_to_field out_chan exposed_class_name fr = - let print format = fprintf out_chan format in - let full_name_fr = full_name fr in - let equality = - (* Use AreEqual2 - see CA-19220 *) - sprintf "Helper.AreEqual2(_%s, server._%s)" full_name_fr full_name_fr - in - print - " if (!%s)\n\ - \ {\n\ - \ %s.set_%s(session, opaqueRef, _%s);\n\ - \ }\n" - equality exposed_class_name full_name_fr full_name_fr - and gen_exposed_field out_chan cls content = match content with | Field fr -> diff --git a/ocaml/sdk-gen/go/README.md b/ocaml/sdk-gen/go/README.md index 33e7eef8a38..984128d4d67 100644 --- a/ocaml/sdk-gen/go/README.md +++ b/ocaml/sdk-gen/go/README.md @@ -1,6 +1,6 @@ # XenServer SDK for Go -Copyright (c) 2023-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2023-2026 Cloud Software Group, Inc. All Rights Reserved. XenServer SDK for Go is a complete SDK for XenServer, exposing the XenServer API as Go module. It is written in Go. @@ -18,10 +18,10 @@ terms of the BSD 2-Clause license. See LICENSE for details. For XenServer documentation see The XenServer Management API Reference is available at - + The XenServer Software Development Kit Guide is available at - + A number of examples to help you get started with the SDK is available at @@ -30,7 +30,7 @@ For community content, blogs, and downloads, visit and To network with other developers using XenServer visit - + ## Prerequisites diff --git a/ocaml/sdk-gen/java/autogen/xen-api/pom.xml b/ocaml/sdk-gen/java/autogen/xen-api/pom.xml index 5dc18e7ec61..460743379b2 100644 --- a/ocaml/sdk-gen/java/autogen/xen-api/pom.xml +++ b/ocaml/sdk-gen/java/autogen/xen-api/pom.xml @@ -8,7 +8,7 @@ jar XenServer Java SDK Mavenized build of the XenServer SDK for Java. - https://docs.xenserver.com/en-us/xenserver/8/developer + https://docs.xenserver.com/en-us/xenserver/developer Cloud Software Group, Inc. https://www.cloud.com @@ -55,7 +55,7 @@ com.fasterxml.jackson.core jackson-databind - 2.16.1 + 2.21.2 org.apache.httpcomponents.client5 @@ -90,7 +90,7 @@ maven-compiler-plugin 3.12.1 - 11 + 17 -Xlint:deprecation -Xlint:unchecked diff --git a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/Connection.java b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/Connection.java index bc8b5c644e4..bc1fccb99d5 100644 --- a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/Connection.java +++ b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/Connection.java @@ -68,29 +68,6 @@ public Connection(JsonRpcClient jsonRpcClient) { this.client = jsonRpcClient; } - /** - * Creates a connection to a particular server using a given url. This object can then be passed - * in to any other API calls. - *

- * Note this constructor does NOT call Session.loginWithPassword; the programmer is responsible for calling it, - * passing the Connection as a parameter. No attempt to connect to the server is made until login is called. - *

- * When this constructor is used, a call to dispose() will do nothing. The programmer is responsible for manually - * logging out the Session. - * - * @param httpClient The HttpClient used to make calls, this will be used by the underlying {@link #client} for handling requests - * @param url The URL of the server to connect to. Should be of the form http(s)://host-url/jsonrpc or http(s)://host-url. - * @param requestTimeout The reply timeout for JSON-RPC calls in seconds - * @deprecated This constructor is deprecated. To set the {@code requestTimeout} please {@link #setRequestTimeout(int)}. You may also use the {@link com.xensource.xenapi.JsonRpcClient#setRequestTimeout(int)} - * method of this object's {@link #client}. This option is only advisable if you are managing your own {@link com.xensource.xenapi.JsonRpcClient} as the underlying - * {@link #client} for this object. - */ - @Deprecated - public Connection(CloseableHttpClient httpClient, URL url, int requestTimeout) { - this.client = new JsonRpcClient(httpClient, url); - this.client.setRequestTimeout(requestTimeout); - } - /** * Creates a connection to a particular server using a given url. This object can then be passed * in to any other API calls. @@ -110,31 +87,6 @@ public Connection(URL url) { this.client = new JsonRpcClient(url); } - /** - * Creates a connection to a particular server using a given url. This object can then be passed - * in to any other API calls. - *

- * Note this constructor does NOT call Session.loginWithPassword; the programmer is responsible for calling it, - * passing the Connection as a parameter. No attempt to connect to the server is made until login is called. - *

- * When this constructor is used, a call to dispose() will do nothing. The programmer is responsible for manually - * logging out the Session. - * - * @param url The URL of the server to connect to. Should be of the form http(s)://host-url/jsonrpc or http(s)://host-url. - * @param requestTimeout The reply timeout for JSON-RPC calls in seconds - * @param connectionTimeout The connection timeout for JSON-RPC calls in seconds - * @deprecated This constructor is deprecated. To set {@code requestTimeout} or {@code connectionTimeout} please use {@link #setRequestTimeout(int)} or {@link #setConnectionTimeout(int)} respectively. - * You may also use the {@link com.xensource.xenapi.JsonRpcClient#setRequestTimeout(int)} method of this object's {@link #client}. - * This option is only advisable if you are managing your own {@link com.xensource.xenapi.JsonRpcClient} as the underlying - * {@link #client} for this object. - */ - @Deprecated - public Connection(URL url, int requestTimeout, int connectionTimeout) { - this.client = new JsonRpcClient(url); - this.client.setRequestTimeout(requestTimeout); - this.client.setConnectionTimeout(connectionTimeout); - } - /** * Creates a connection to a particular server using a given url. This object can then be passed * in to any other API calls. @@ -159,36 +111,6 @@ public Connection(URL url, String sessionReference) { this.sessionReference = sessionReference; } - /** - * Creates a connection to a particular server using a given url. This object can then be passed - * in to any other API calls. - *

- * Note this constructor does NOT call Session.loginWithPassword; the programmer is responsible for calling it, - * passing the Connection as a parameter. No attempt to connect to the server is made until login is called. - *

- * When this constructor is used, a call to dispose() will do nothing. The programmer is responsible for manually - * logging out the Session. - * - * @param url The URL of the server to connect to. Should be of the form http(s)://host-url/jsonrpc or http(s)://host-url. - * @param sessionReference A reference to a logged-in Session. Any method calls on this Connection will use it. - * This constructor does not call Session.loginWithPassword, and dispose() on the resulting - * Connection object does not call Session.logout. The programmer is responsible for - * ensuring the Session is logged in and out correctly. - * @param requestTimeout The reply timeout for JSON-RPC calls in seconds - * @param connectionTimeout The connection timeout for JSON-RPC calls in seconds - * @deprecated This constructor is deprecated. To set {@code requestTimeout} or {@code connectionTimeout} please use {@link #setRequestTimeout(int)} or {@link #setConnectionTimeout(int)} respectively. - * You may also use the {@link com.xensource.xenapi.JsonRpcClient#setRequestTimeout(int)} method of this object's {@link #client}. - * This option is only advisable if you are managing your own {@link com.xensource.xenapi.JsonRpcClient} as the underlying - * {@link #client} for this object. - */ - @Deprecated - public Connection(URL url, String sessionReference, int requestTimeout, int connectionTimeout) { - this.client = new JsonRpcClient(url); - this.client.setRequestTimeout(requestTimeout); - this.client.setConnectionTimeout(connectionTimeout); - this.sessionReference = sessionReference; - } - /** * Set the timeout in seconds for every request made by this object's {@link #client}. * If not set the value defaults to {@value JsonRpcClient#DEFAULT_REQUEST_TIMEOUT}. diff --git a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/CustomDateDeserializer.java b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/CustomDateDeserializer.java index 63be5c1c458..d3d43df7bc1 100644 --- a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/CustomDateDeserializer.java +++ b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/CustomDateDeserializer.java @@ -49,7 +49,7 @@ public class CustomDateDeserializer extends StdDeserializer { /** * Array of {@link SimpleDateFormat} objects representing the date formats * used in xen-api responses. - *
+ *
* RFC-3339 date formats can be returned in either Zulu or time zone agnostic. * This list is not an exhaustive list of formats supported by RFC-3339, rather * a set of formats that will enable the deserialization of xen-api dates. diff --git a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/JsonRpcClient.java b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/JsonRpcClient.java index 9d1389eaf28..f3db8252446 100644 --- a/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/JsonRpcClient.java +++ b/ocaml/sdk-gen/java/autogen/xen-api/src/main/java/com/xensource/xenapi/JsonRpcClient.java @@ -53,15 +53,14 @@ /** * Provides a JSON-RPC v2.0 client for making remote procedure calls to xapi's backend URL. - *
+ *
* This class enables the communication to the JSON-RPC backend. The client utilizes the HttpClient class for * sending HTTP POST requests with JSON payloads and the ObjectMapper class from the Jackson library for * serialization and deserialization of JSON data. - *
+ *
* The client can be customised by passing it as a parameter to corresponding constructor, enabling custom * handling of requests. - *
- *
+ *
* By default, the timeout for requests is set to {@value #DEFAULT_REQUEST_TIMEOUT}. The default timeout for connecting to the * JSON-RPC backend is set to {@value #DEFAULT_CONNECTION_TIMEOUT} seconds. The maximum number of concurrent connections handled * by the underlying {@link PoolingHttpClientConnectionManager} is {@value #MAX_CONCURRENT_CONNECTIONS}. diff --git a/ocaml/sdk-gen/java/autogen/xen-api/src/main/resources/README.txt b/ocaml/sdk-gen/java/autogen/xen-api/src/main/resources/README.txt index f5d13f889f5..4d469b5efcf 100644 --- a/ocaml/sdk-gen/java/autogen/xen-api/src/main/resources/README.txt +++ b/ocaml/sdk-gen/java/autogen/xen-api/src/main/resources/README.txt @@ -1,7 +1,7 @@ XenServerJava ============= -Copyright (c) 2007-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2007-2026 Cloud Software Group, Inc. All Rights Reserved. XenServerJava is a complete SDK for XenServer, exposing the XenServer API as Java classes. @@ -21,10 +21,10 @@ Reference For XenServer documentation see https://docs.xenserver.com The XenServer Management API Reference is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/management-api +https://docs.xenserver.com/en-us/xenserver/developer/api-reference The XenServer Software Development Kit Guide is available at -https://docs.xenserver.com/en-us/xenserver/8/developer/sdk-guide +https://docs.xenserver.com/en-us/xenserver/developer/sdk-guide A number of examples to help you get started with the SDK is available at https://github.com/xenserver/xenserver-samples @@ -33,7 +33,7 @@ For community content, blogs, and downloads, visit https://www.xenserver.com/blogs and https://www.citrix.com/community/ To network with other developers using XenServer visit -https://discussions.citrix.com/forum/101-hypervisor-formerly-xenserver/ +https://community.citrix.com/forums/forum/1118-xenserver-sdk/ Dependencies diff --git a/ocaml/sdk-gen/java/main.ml b/ocaml/sdk-gen/java/main.ml index 9fdab7102a4..ca779c54058 100644 --- a/ocaml/sdk-gen/java/main.ml +++ b/ocaml/sdk-gen/java/main.ml @@ -501,15 +501,6 @@ let get_types_json types = ("name", `String type_string) ; ("class_name", `String class_name) ; ("method_name", `String method_name) - ; ( "suppress_unchecked_warning" - , `Bool - ( match t with - | Map _ | Record _ | Option (Record _) | Option (Map _) -> - true - | _ -> - false - ) - ) ; ( "generate_reference_task_result_func" , `Bool generate_reference_task_result_func ) diff --git a/ocaml/sdk-gen/java/templates/Class.mustache b/ocaml/sdk-gen/java/templates/Class.mustache index 658deeb05f2..e96d2914145 100644 --- a/ocaml/sdk-gen/java/templates/Class.mustache +++ b/ocaml/sdk-gen/java/templates/Class.mustache @@ -61,9 +61,10 @@ public class {{class_name}} extends XenAPIObject { protected final String ref; /** - * For internal use only. + * Creates an object from a given XenAPI reference (OpaqueRef) + * @param ref The OpaqueRef from which to create the object. */ - {{{class_name}}}(String ref) { + public {{{class_name}}}(String ref) { this.ref = ref; } @@ -79,21 +80,17 @@ public class {{class_name}} extends XenAPIObject { * If obj is a {{{class_name}}}, compares XenAPI references for equality. */ @Override - public boolean equals(Object obj) - { - if (obj instanceof {{{class_name}}}) - { + public boolean equals(Object obj) { + if (obj instanceof {{{class_name}}}) { {{{class_name}}} other = ({{{class_name}}}) obj; return other.ref.equals(this.ref); - } else - { + } else { return false; } } @Override - public int hashCode() - { + public int hashCode() { return ref.hashCode(); } diff --git a/ocaml/sdk-gen/java/templates/Types.mustache b/ocaml/sdk-gen/java/templates/Types.mustache index 4da97c774cd..67906c33029 100644 --- a/ocaml/sdk-gen/java/templates/Types.mustache +++ b/ocaml/sdk-gen/java/templates/Types.mustache @@ -40,50 +40,46 @@ import java.util.regex.Pattern; */ public class Types { - /** - * Interface for all Record classes - */ - public interface Record - { - /** - * Convert a Record to a Map - */ - Map toMap(); - } - /** - * Base class for all XenAPI Exceptions - */ - public static class XenAPIException extends IOException { - public final String shortDescription; - public final String[] errorDescription; - XenAPIException(String shortDescription) - { - this.shortDescription = shortDescription; - this.errorDescription = null; - } - XenAPIException(String[] errorDescription) - { - this.errorDescription = errorDescription; - if (errorDescription.length > 0) - { - shortDescription = errorDescription[0]; - } else - { - shortDescription = ""; - } - } - public String toString() - { - if (errorDescription == null) - { - return shortDescription; - } else if (errorDescription.length == 0) - { - return ""; - } + /** + * Interface for all Record classes + */ + public interface Record + { + /** + * Convert a Record to a Map + */ + Map toMap(); + } + /** + * Base class for all XenAPI Exceptions + */ + public static class XenAPIException extends IOException { + public final String shortDescription; + public final String[] errorDescription; + + XenAPIException(String shortDescription) { + this.shortDescription = shortDescription; + this.errorDescription = null; + } + + XenAPIException(String[] errorDescription) { + this.errorDescription = errorDescription; + if (errorDescription.length > 0) { + shortDescription = errorDescription[0]; + } else { + shortDescription = ""; + } + } + + public String toString() { + if (errorDescription == null) { + return shortDescription; + } else if (errorDescription.length == 0) { + return ""; + } + StringBuilder sb = new StringBuilder(); - for (int i = 0; i < errorDescription.length - 1; i++) - { + for (int i = 0; i < errorDescription.length - 1; i++) { sb.append(errorDescription[i]); } sb.append(errorDescription[errorDescription.length - 1]); @@ -91,33 +87,30 @@ public class Types } } - /** - * Thrown if the response from the server contains an invalid status. - */ - public static class BadServerResponse extends XenAPIException - { - public BadServerResponse(JsonRpcResponseError responseError) - { - super(String.valueOf(responseError)); - } - } + /** + * Thrown if the response from the server contains an invalid status. + */ + public static class BadServerResponse extends XenAPIException { + public BadServerResponse(JsonRpcResponseError responseError) { + super(String.valueOf(responseError)); + } + } - /** - * Checks the provided server response was successful. If the call - * failed, throws a XenAPIException. If the server - * returned an invalid response, throws a BadServerResponse. - * Otherwise, returns the server response as passed in. - */ - public static void checkError(JsonRpcResponseError response) throws XenAPIException, BadServerResponse - { + /** + * Checks the provided server response was successful. If the call + * failed, throws a XenAPIException. If the server + * returned an invalid response, throws a BadServerResponse. + * Otherwise, returns the server response as passed in. + */ + public static void checkError(JsonRpcResponseError response) throws XenAPIException, BadServerResponse { var errorData = response.data; - if(errorData.length == 0){ + if(errorData.length == 0) { throw new BadServerResponse(response); } var errorName = response.message; {{#errors}} - if (errorName.equals("{{{name}}}")){ + if (errorName.equals("{{{name}}}")) { {{#err_params}} String p{{{index}}} = errorData.length > {{{index}}} ? errorData[{{{index}}}] : ""; {{/err_params}} @@ -180,37 +173,12 @@ public class Types /** * Create a new BadAsyncResult */ - public BadAsyncResult(String result) - { + public BadAsyncResult(String result) { super(result); this.result = result; } } - {{#types}} - /** - * Converts an {@link Object} to a {@link {{{name}}}} object. - *
- * This method takes an {@link Object} as input and attempts to convert it into a {@link {{{name}}}} object. - * If the input object is null, the method returns null. Otherwise, it creates a new {@link {{{name}}}} - * object using the input object's {@link String} representation. - *
- * @param object The {@link Object} to be converted to a {@link {{{name}}}} object. - * @return A {@link {{{name}}}} object created from the input {@link Object}'s {@link String} representation, - * or null if the input object is null. - * @deprecated this method will not be publicly exposed in future releases of this package. - */ - @Deprecated{{#suppress_unchecked_warning}} - @SuppressWarnings("unchecked"){{/suppress_unchecked_warning}} - public static {{{name}}} {{{method_name}}}(Object object) { - if (object == null) { - return null; - } - {{{method_body}}} - } - - {{/types}} - {{#types}}{{#generate_reference_task_result_func}} /** * Attempt to convert the {@link Task}'s result to a {@link {{{name}}}} object. @@ -218,12 +186,13 @@ public class Types * @param task The task from which to fetch the result. * @param connection The connection * @return the instantiated object if a valid value was found, null otherwise. - * @throws BadServerResponse Thrown if the response from the server contains an invalid status. + * @throws BadServerResponse if the response from the server contains an invalid status. * @throws XenAPIException if the call failed. - * @throws IOException if an error occurs during a send or receive. This includes cases where a payload is invalid JSON. + * @throws IOException if an error occurs during send or receive. This includes cases where a payload is invalid JSON. */ public static {{class_name}} to{{class_name}}(Task task, Connection connection) throws IOException { - return Types.to{{class_name}}(parseResult(task.getResult(connection))); + String result = parseResult(task.getResult(connection)); + return result == null || result.isEmpty() ? null : new {{class_name}}(result); } {{/generate_reference_task_result_func}} @@ -238,16 +207,4 @@ public class Types return matcher.group(1); } - - public static EventBatch toEventBatch(Object object) { - if (object == null) { - return null; - } - Map map = (Map) object; - EventBatch batch = new EventBatch(); - batch.token = toString(map.get("token")); - batch.validRefCounts = map.get("valid_ref_counts"); - batch.events = toSetOfEventRecord(map.get("events")); - return batch; - } } diff --git a/ocaml/sdk-gen/powershell/autogen/README.md b/ocaml/sdk-gen/powershell/autogen/README.md index 40812c3f7c8..dc4b260c6ba 100644 --- a/ocaml/sdk-gen/powershell/autogen/README.md +++ b/ocaml/sdk-gen/powershell/autogen/README.md @@ -1,6 +1,6 @@ # XenServer PowerShell Module -Copyright (c) 2013-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2013-2026 Cloud Software Group, Inc. All Rights Reserved. The XenServer PowerShell Module is a complete SDK for XenServer, exposing the XenServer API as Windows PowerShell cmdlets. @@ -18,10 +18,10 @@ terms of the BSD 2-Clause license. See LICENSE.txt for details. For XenServer documentation see The XenServer Management API Reference is available at - + The XenServer Software Development Kit Guide is available at - + A number of examples to help you get started with the SDK is available at @@ -30,11 +30,11 @@ For community content, blogs, and downloads, visit and To network with other developers using XenServer visit - + ## Prerequisites -This library requires .NET 6.0 and PowerShell 7.2 or greater. +This library requires .NET 8.0 and PowerShell 7.4 or greater. ## Dependencies diff --git a/ocaml/sdk-gen/powershell/autogen/README_51.md b/ocaml/sdk-gen/powershell/autogen/README_51.md index 24ac038ee3c..47bd82e15c5 100644 --- a/ocaml/sdk-gen/powershell/autogen/README_51.md +++ b/ocaml/sdk-gen/powershell/autogen/README_51.md @@ -1,6 +1,6 @@ # XenServer PowerShell Module -Copyright (c) 2013-2025 Cloud Software Group, Inc. All Rights Reserved. +Copyright (c) 2013-2026 Cloud Software Group, Inc. All Rights Reserved. The XenServer PowerShell Module is a complete SDK for XenServer, exposing the XenServer API as Windows PowerShell cmdlets. @@ -18,10 +18,10 @@ terms of the BSD 2-Clause license. See LICENSE.txt for details. For XenServer documentation see The XenServer Management API Reference is available at - + The XenServer Software Development Kit Guide is available at - + A number of examples to help you get started with the SDK is available at @@ -30,11 +30,11 @@ For community content, blogs, and downloads, visit and To network with other developers using XenServer visit - + ## Prerequisites -This library requires .NET Framework 4.5 or greater and PowerShell 5.1 or greater. +This library requires .NET Framework 4.6.2 or greater and PowerShell 5.1 or greater. ## Dependencies diff --git a/ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs b/ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs index d22d5eadee0..943c91a7642 100644 --- a/ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs +++ b/ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs @@ -30,11 +30,7 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Management.Automation; -using System.Reflection; -using System.Xml; - using XenAPI; namespace Citrix.XenServer @@ -44,11 +40,6 @@ internal class CommonCmdletFunctions private const string SessionsVariable = "global:Citrix.XenServer.Sessions"; private const string DefaultSessionVariable = "global:XenServer_Default_Session"; - static CommonCmdletFunctions() - { - Session.UserAgent = string.Format("XenServerPSModule/{0}", Assembly.GetExecutingAssembly().GetName().Version); - } - internal static Dictionary GetAllSessions(PSCmdlet cmdlet) { object obj = cmdlet.SessionState.PSVariable.GetValue(SessionsVariable); diff --git a/ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs b/ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs index 52cb8e21e54..8f60885d057 100644 --- a/ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs +++ b/ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs @@ -52,9 +52,12 @@ public class ConnectXenServerCommand : PSCmdlet private readonly object _certificateValidationLock = new object(); + private static readonly string DefaultUserAgent = $"XenServerPSModule/@SDK_VERSION@"; + public ConnectXenServerCommand() { Port = 443; + Originator = DefaultUserAgent; } #region Cmdlet Parameters @@ -85,7 +88,10 @@ public ConnectXenServerCommand() public string[] OpaqueRef { get; set; } [Parameter] - public string Originator { get; set; } = "XenServerPSModule/" + Helper.APIVersionString(API_Version.LATEST); + public string Originator { get; set; } + + [Parameter(HelpMessage = "The UserAgent to use for the requests to the server")] + public string UserAgent { get; set; } [Parameter] public SwitchParameter PassThru { get; set; } @@ -193,7 +199,7 @@ protected override void ProcessRecord() Session session; if (string.IsNullOrEmpty(OpaqueRef[i])) { - session = new Session(Url[i]); + session = new Session(Url[i]) { UserAgent = UserAgent }; try { session.login_with_password(connUser, connPassword, Helper.APIVersionString(API_Version.LATEST), Originator); @@ -235,12 +241,15 @@ protected override void ProcessRecord() }); } + if (inner != null) + throw inner; + throw; } } else { - session = new Session(Url[i], OpaqueRef[i]); + session = new Session(Url[i], OpaqueRef[i]){ UserAgent = UserAgent }; } session.Tag = Creds; diff --git a/ocaml/sdk-gen/powershell/autogen/src/XenServerPowerShell.csproj b/ocaml/sdk-gen/powershell/autogen/src/XenServerPowerShell.csproj index 35c2fc8fa42..c6f0390ff9a 100644 --- a/ocaml/sdk-gen/powershell/autogen/src/XenServerPowerShell.csproj +++ b/ocaml/sdk-gen/powershell/autogen/src/XenServerPowerShell.csproj @@ -1,7 +1,7 @@ 0.0.0 - net8.0;net45 + net8.0;net462 Library True @@ -12,7 +12,7 @@ - + diff --git a/ocaml/sdk-gen/powershell/gen_powershell_binding.ml b/ocaml/sdk-gen/powershell/gen_powershell_binding.ml index ed84c2c7120..467b5b65c7e 100644 --- a/ocaml/sdk-gen/powershell/gen_powershell_binding.ml +++ b/ocaml/sdk-gen/powershell/gen_powershell_binding.ml @@ -17,11 +17,15 @@ module TypeSet = Set.Make (struct let compare = compare end) -let destdir = "autogen-out/src" +let destdir = "autogen-out" + +let srcdir = "autogen-out/src" let templdir = "templates" -type cmdlet = {filename: string; content: string} +type cmdlet = {cmdletname: string; content: string} + +let cmdlets_to_export = ref [] let api = Datamodel_utils.named_self := true ; @@ -68,6 +72,21 @@ let maps = ref TypeSet.empty let generated x = not (List.mem x.name ["blob"; "session"; "debug"; "event"; "vtpm"]) +let rec is_last x list = + match list with + | [] -> + false + | hd :: [] -> + if hd = x then + true + else + false + | hd :: tl -> + if hd = x then + false + else + is_last x tl + let rec main () = let json = `O @@ -91,7 +110,7 @@ let rec main () = in render_file ("ConvertTo-XenRef.mustache", "ConvertTo-XenRef.cs") - json templdir destdir ; + json templdir srcdir ; http_actions |> List.filter (fun (_, (_, _, sdk, _, _, _)) -> sdk) @@ -100,9 +119,45 @@ let rec main () = let filtered_classes = List.filter generated classes in let cmdlets = List.concat_map gen_cmdlets filtered_classes in - List.iter (fun x -> write_file x.filename x.content) cmdlets ; + List.iter (fun x -> write_file x.cmdletname x.content) cmdlets ; - filtered_classes |> List.iter gen_destructor + filtered_classes |> List.iter gen_destructor ; + + cmdlets_to_export := + [ + "Connect-XenServer" + ; "Disconnect-XenServer" + ; "Get-XenSession" + ; "Receive-XenPoolPatch" + ; "Send-XenOemPatchStream" + ; "Wait-XenTask" + ; "ConvertTo-XenRef" + ] + @ !cmdlets_to_export ; + + cmdlets_to_export := List.sort String.compare !cmdlets_to_export ; + + let module_json = + `O + [ + ( "cmdlets_to_export" + , `A + (List.map + (fun x -> + `O + [ + ("cmdlet_to_export", `String x) + ; ("is_last", `Bool (is_last x !cmdlets_to_export)) + ] + ) + !cmdlets_to_export + ) + ) + ] + in + render_file + ("XenServerPSModule.mustache", "XenServerPSModule.psd1") + module_json templdir destdir (****************) (* Http actions *) @@ -161,9 +216,11 @@ and gen_http_action action = ) ] in + let cmdlet_name = sprintf "%s-Xen%s" commonVerb stem in render_file - ("HttpAction.mustache", sprintf "%s-Xen%s.cs" commonVerb stem) - json templdir destdir + ("HttpAction.mustache", sprintf "%s.cs" cmdlet_name) + json templdir srcdir ; + cmdlets_to_export := cmdlet_name :: !cmdlets_to_export (*************************) (* Autogenerated cmdlets *) @@ -174,30 +231,30 @@ and gen_cmdlets obj = let cmdlets = [ - {filename= sprintf "Get-Xen%s.cs" stem; content= gen_class obj classname} + {cmdletname= sprintf "Get-Xen%s" stem; content= gen_class obj classname} ; { - filename= sprintf "New-Xen%s.cs" stem + cmdletname= sprintf "New-Xen%s" stem ; content= gen_constructor obj classname (List.filter is_constructor messages) } ; { - filename= sprintf "Remove-Xen%sProperty.cs" stem + cmdletname= sprintf "Remove-Xen%sProperty" stem ; content= gen_remover obj classname (List.filter is_remover messages) } ; { - filename= sprintf "Add-Xen%s.cs" stem + cmdletname= sprintf "Add-Xen%s" stem ; content= gen_adder obj classname (List.filter is_adder messages) } ; { - filename= sprintf "Set-Xen%s.cs" stem + cmdletname= sprintf "Set-Xen%s" stem ; content= gen_setter obj classname (List.filter is_setter messages) } ; { - filename= sprintf "Get-Xen%sProperty.cs" stem + cmdletname= sprintf "Get-Xen%sProperty" stem ; content= gen_getter obj classname (List.filter is_getter messages) } ; { - filename= sprintf "Invoke-Xen%s.cs" stem + cmdletname= sprintf "Invoke-Xen%s" stem ; content= gen_invoker obj classname (List.filter is_invoke messages) } ] @@ -205,8 +262,10 @@ and gen_cmdlets obj = cmdlets |> List.filter (fun x -> x.content <> "") -and write_file filename content = - let fn = Filename.concat destdir filename in +and write_file cmdletname content = + let filename = sprintf "%s.cs" cmdletname in + let fn = Filename.concat srcdir filename in + cmdlets_to_export := cmdletname :: !cmdlets_to_export ; with_output fn (fun x -> output_string x content) (*********************************) @@ -617,11 +676,13 @@ and gen_destructor obj = ; ("has_name", `Bool (has_name obj)) ] in + let cmdlet_name = + sprintf "Remove-Xen%s" (ocaml_class_to_csharp_class classname) + in render_file - ( "Remove-XenObject.mustache" - , sprintf "Remove-Xen%s.cs" (ocaml_class_to_csharp_class classname) - ) - json templdir destdir + ("Remove-XenObject.mustache", sprintf "%s.cs" cmdlet_name) + json templdir srcdir ; + cmdlets_to_export := cmdlet_name :: !cmdlets_to_export | _ -> assert false diff --git a/ocaml/sdk-gen/powershell/autogen/XenServerPSModule.psd1 b/ocaml/sdk-gen/powershell/templates/XenServerPSModule.mustache similarity index 90% rename from ocaml/sdk-gen/powershell/autogen/XenServerPSModule.psd1 rename to ocaml/sdk-gen/powershell/templates/XenServerPSModule.mustache index 968dfddce70..29336b1dec2 100644 --- a/ocaml/sdk-gen/powershell/autogen/XenServerPSModule.psd1 +++ b/ocaml/sdk-gen/powershell/templates/XenServerPSModule.mustache @@ -37,7 +37,7 @@ GUID = 'D695A8B9-039A-443C-99A4-0D48D7C6AD76' #Copyright Author = '' CompanyName = 'Cloud Software Group, Inc' -Copyright = 'Copyright (c) 2013-2025 Cloud Software Group, Inc. All rights reserved.' +Copyright = 'Copyright (c) 2013-2026 Cloud Software Group, Inc. All rights reserved.' # Requirements PowerShellVersion = '@PS_VERSION@' @@ -67,7 +67,11 @@ FileList = @('about_XenServer.help.txt', #Public interface FunctionsToExport = '' -CmdletsToExport = '*' +CmdletsToExport = @( +{{#cmdlets_to_export}} + '{{cmdlet_to_export}}'{{^is_last}},{{/is_last}} +{{/cmdlets_to_export}} +) VariablesToExport = @('Citrix.XenServer.Sessions','XenServer_Default_Session') AliasesToExport = '*'