Code Samples : C# Code
  
C# Code
The following example uses C# to demonstrate how to create a session and close a session and perform a number of actions using the APIs during the session:
List all the APIs, an action that does not require a dedicated session
Retrieve the list of Zerto Virtual Replication events.
Retrieve a filtered list of alerts and then dismiss these alerts
List all the VPGs and all the checkpoints for the first VPG in the list and then perform a failover test using the last checkpoint. After starting the failover test it is then stopped.
Follow the progress of a task until it finishes.
The code includes serialize and deserialize code.
By default the VMware vCenter Server or Microsoft SCVMM username and password are required. To change this to Windows authorization, replace the code: string loginType = args.Length > 4 ? args[4] : "1"; with the following code: string loginType = args.Length > 4 ? args[4] : "0"; in public static void Main(string[] args).
Note: When using a REST client, such as Postman, with Google Chrome, the default authorization is Windows.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using Zerto.Zvm.Api.Interfaces;
using Zerto.Zvm.Api.Interfaces.Alerts;
using Zerto.Zvm.Api.Interfaces.Events;
using Zerto.Zvm.Api.Interfaces.Tasks;
using Zerto.Zvm.Api.Interfaces.Vpgs;
namespace ApiTestExample {
  public class DemoProgram {
    private const string c_reponseInXml = "application/xml";
    private const string c_reponseInJson = "application/json";
    private const string c_authorizationHeader = "x-zerto-session";
 
    private string m_baseAddress;
    private string m_format;
    private string m_sessionId;
 
    //private static string m_responseFormat = c_reponseInXml;
 
    public DemoProgram(string baseAddress, string responseFormat) {
      m_baseAddress = baseAddress;
      m_format = responseFormat;
      m_sessionId = string.Empty;
    }
    public static void Main(string[] args) {
      // Input
      if (args.Length != 5 && args.Length != 4) {
        Console.WriteLine("Usage: DemoProgram <ZVM IP> <ZVM Port> <user> <password> [<login type 0 = windows or 1 = vCenter or SCVMM>]");
        return;
      }
 
      string zvmip = args[0];
      string zvmport = args[1];
      string username = args[2];
      string password = args[3];
      string loginType = args.Length > 4 ? args[4] : "1";
 
      // Connection setting for http
      ServicePointManager.Expect100Continue = true;
      ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
      ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true;
 
      // Construct Object with URL
      // note the required '/' at the end of the uri
      DemoProgram demo = new DemoProgram("https://" + zvmip + ":" + zvmport + "/v1/", c_reponseInJson);
 
      // Actions:
      try {
        //list the APIs - execute request on the base address
        demo.ListApis();
 
        //only APIs listing and starting a session don't require being logged-in
        demo.LogInAndSetSessionId(username, password, type);
 
        // A simple Get action
        demo.GetEvents();
 
        // A Put action using a filter
        demo.DismissAllAlerts();
 
        // Performing a failover test
        demo.FailoverTestVpg();
 
        // Logout
        demo.LogOut();
 
        Console.WriteLine("\n\nPress any key to exit");
        Console.ReadKey();
      }
      catch (WebException wex) { Console.WriteLine(wex); }
    }
    #region Actions that do not require a session
    private void ListApis() {
      string result = ExecuteHttpGet(m_baseAddress, m_format, null);
 
      Console.WriteLine("The result is a list of uri addresses each representing an API:");
      Console.WriteLine("=====================================================");
      List<StringResourceLink> uris = (List<StringResourceLink>)DeserializeObjectFromJson(result, typeof(List<StringResourceLink>));
      foreach (var stringResourceLink in uris) {
        Console.WriteLine(stringResourceLink.ResourceLocation);
      }
    }
    #endregion
    #region login related
    private void LogInAndSetSessionId(string domainUserName, string domainPassword, string loginType) {
      string addSessionUri = m_baseAddress + "session/add";
      HttpWebRequest request = WebRequest.Create(addSessionUri) as HttpWebRequest;
 
      //logging-in is about ADDING a session with the POST http command
      request.Method = "POST";
      request.Timeout = 10000;
      request.ContentLength = 0;
 
      string encodedCredentialsInBasicAuthenticationFormat = GetCredentialsForBasicAuthentication(domainUserName, domainPassword);
      request.Headers.Add("Authorization", encodedCredentialsInBasicAuthenticationFormat);
 
      // Set the content type of the data being posted
      request.ContentType = m_format;
      request.Accept = m_format;
 
      // Body
      byte[] byte1 = new ASCIIEncoding().GetBytes("{\"AuthenticationMethod\":"+ loginType + "}");
      request.ContentLength = byte1.Length;
      Stream newStream = request.GetRequestStream();
      newStream.Write(byte1, 0, byte1.Length);
 
      HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse;
 
      if (httpResponse.StatusCode == HttpStatusCode.OK) {
        //After a successful login your session-id is returned in the 'x-zerto-session' header
        m_sessionId = httpResponse.Headers.Get(c_authorizationHeader);
      }
      else {
        Console.WriteLine("request {0} failed with code: {1}, {2}", request, httpResponse.StatusCode, httpResponse.StatusDescription);
      }
    }
 
    private static string GetCredentialsForBasicAuthentication(string domainUserName, string domainPassword) {
      string prepareUserNamePassword = string.Format("{0}:{1}", domainUserName, domainPassword);
      byte[] credentialsBytes = Encoding.ASCII.GetBytes(prepareUserNamePassword);
      string encodedBasicAuthentication = Convert.ToBase64String(credentialsBytes);
 
      return "Basic " + encodedBasicAuthentication; //note that the space is mandatory
    }
    private void LogOut() {
      string addSessionUri = m_baseAddress + "/session";
      HttpWebRequest request = WebRequest.Create(addSessionUri) as HttpWebRequest;
 
      //logging-out is about DELETING a session, with the DELETE http command
      request.Method = "DELETE";
      request.Timeout = 10000;
 
      //you need to set the id of the session to be deleted --> logged-out
      request.Headers.Add(c_authorizationHeader, m_sessionId);
 
      HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse;
 
      if (httpResponse.StatusCode == HttpStatusCode.OK) {
        m_sessionId = string.Empty;
        Console.WriteLine("\nLogged out - by deleting the session");
      }
      else {
        Console.WriteLine("Request {0} failed with code: {1}, {2}", request, httpResponse.StatusCode, httpResponse.StatusDescription);
      }
    }
    #endregion
    #region example flows
 
    /*
     * Example - get all events, filtering is not used
     */
    private void GetEvents() {
      Console.WriteLine("\nRequest the list of events (no filter is operated):");
      Console.WriteLine("===================================================");
      string apiAddress = m_baseAddress + "events";
      string result = ExecuteHttpGet(apiAddress, m_format, m_sessionId);
      List<EventApi> events = (List<EventApi>)DeserializeObjectFromJson(result, typeof(List<EventApi>));
      Console.WriteLine("Found " + events.Count + " events.");
      // Go Over all events fetching them one by one
      for (int i = 0;i < events.Count;i++) {
        Console.WriteLine((i+1) + ". " + events[i].Description);
      }
    }
    /*
     * Example - dismiss all the 'warning' level alerts that are not already dismissed
     */
    private void DismissAllAlerts() {
      Console.WriteLine("\nDismiss all alerts that are warning level and not dismissed.");
      Console.WriteLine("===========================================================");
      // Do Get fetch all alerts with certain filter
      string apiAddress = m_baseAddress + "alerts?isDismissed=false&level=Error";
      string result = ExecuteHttpGet(apiAddress, m_format, m_sessionId);
      // Deserialize response into zerto api object
      List<AlertApi> alerts = (List<AlertApi>)DeserializeObjectFromJson(result, typeof(List<AlertApi>));
      Console.WriteLine("Found " + alerts.Count + " alerts matching filter.");
      int count = 0;
      // Go Over all alerts fetch and dismiss them one by one
      foreach (var alert in alerts) {
        try {
          Console.WriteLine("Dismiss alert : " + alert.Description);
          string apiAlertAddress = m_baseAddress + "alerts/" + alert.Link.Identifier + "/dismiss";
          ExecuteHttpPost(apiAlertAddress, m_format, m_sessionId, null);
          count++;
        }
        catch (Exception e) {
          Console.WriteLine("error " + e.Message + ".");
        }
        Console.WriteLine("Dismissed " + count + " alerts.");
      }
    }
    /*
     * Example - Failover Test a VPG
     */
    private void FailoverTestVpg() {
      Console.WriteLine("\nDo a Failover Test for the first VPG");
      Console.WriteLine("===================================================");
      // Fetch all vpgs - convert data to a zerto api object
      string apiAddress = m_baseAddress + "vpgs";
      string result = ExecuteHttpGet(apiAddress, m_format, m_sessionId);
      List<VpgApi> vpgs = (List<VpgApi>)DeserializeObjectFromJson(result, typeof(List<VpgApi>));
      Console.WriteLine("Found " + vpgs.Count + " vpgs.");
      // if any vpgs are retrieved, take first one for a failover test
      if (vpgs.Count > 0) {
        VpgApi vpg = vpgs[0];
        Console.WriteLine("Work on Vpg: " + vpg.VpgName + ".");
        // Fetch all checkpoints for the VPG
        string cpApiAddress = m_baseAddress + "vpgs/" + vpg.Link.Identifier + "/checkpoints";
        string cpRes = ExecuteHttpGet(cpApiAddress, m_format, m_sessionId);
        List<CheckpointApi> cps = (List<CheckpointApi>)DeserializeObjectFromJson(cpRes, typeof(List<CheckpointApi>));
        Console.WriteLine("Found " + cps.Count + " valid checkpoints.");
        if (cps.Count > 0) {
          // Post a request for failover test with the latest checkpoint
          FailOverTestStartDataApi fotData = new FailOverTestStartDataApi(cps.Last().CheckpointIdentifier);
          Console.WriteLine("Start Failover Test.");
          string fotApiAddress = m_baseAddress + "vpgs/" + vpg.Link.Identifier + "/failovertest";
          // Wait till the task is done
          bool isFotOk = FollowTask(ExecuteHttpPost(fotApiAddress, m_format, m_sessionId, SerializeObjectToJson(fotData, typeof(FailOverTestStartDataApi))), "Start Failover Test");
          if (isFotOk) {
            Console.WriteLine("Failover is in Test.");
            // Post a request to stop the failover test
            StopFailoverTestDataApi stopFotData = new StopFailoverTestDataApi(true, "OK");
            Console.WriteLine("Stop Failover Test.");
            string sfotApiAddress = m_baseAddress + "vpgs/" + vpg.Link.Identifier + "/failoverteststop";
            bool isStopFotOk = FollowTask(ExecuteHttpPost(sfotApiAddress, m_format, m_sessionId, SerializeObjectToJson(stopFotData, typeof(StopFailoverTestDataApi))), "Stop Failover Test");
            Console.WriteLine(isStopFotOk ? "Failover Test stopped successfully." : "Failover Test not stopped!");
          }
          else {
            Console.WriteLine("Could not start Failover Test.");
          }
        }
        else {
          Console.WriteLine("Vpg has no Checkpoints - cannot Failover Test.");
        }
      }
      Console.WriteLine("Testing completed.");
    }
    /*
     * Example Follow a task id until the task finishes
     */
    private bool FollowTask(string taskId, string operation) {
      bool isSuccess = false;
      if (taskId != null) {
        taskId = (string)DeserializeObjectFromJson(taskId, typeof(string)); // NOTICE output is in json string so needs to be deserialized
        bool isRunning = true;
        do {
          string taskApiAddress = m_baseAddress + "tasks/" + taskId;
          string taskRes = ExecuteHttpGet(taskApiAddress, m_format, m_sessionId);
          TaskApi taskApi = (TaskApi)DeserializeObjectFromJson(taskRes, typeof(TaskApi));
          switch (taskApi.Status.State) {
            case TaskStatusEnumApi.InProgress:
              Console.WriteLine(operation + " Task is at " + (taskApi.Status.Progress) + "%");
              break;
            case TaskStatusEnumApi.Cancelling:
              Console.WriteLine(operation + " Task is aborting.");
              break;
            case TaskStatusEnumApi.Failed:
              Console.WriteLine(operation + " Task failed.");
              isRunning = false;
              break;
            case TaskStatusEnumApi.Completed:
              Console.WriteLine(operation + " Task done.");
              isRunning = false;
              isSuccess = true;
              break;
            default:
              Console.WriteLine(operation + " Task is waiting.");
              break;
          }
          Thread.Sleep(10000);
        } while (isRunning);
      }
      else {
        Console.WriteLine(operation + " Task failed to start.");
      }
      return isSuccess;
    }
    #endregion
    #region General http
    private static string ParseHttpResponse(HttpWebRequest request, string format) {
      string apiResult = null;
      try {
        HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse;
 
        if (httpResponse.StatusCode == HttpStatusCode.OK) {
          using (Stream responseStream = httpResponse.GetResponseStream()) {
            using (StreamReader reader = new StreamReader(responseStream)) {
              apiResult = reader.ReadToEnd();
            }
          }
          if (format == c_reponseInXml) {
            apiResult = PrettyPrintXmlData(apiResult);
          }
        }
        else {
          Console.WriteLine("request {0} failed with code: {1}, {2}", request, httpResponse.StatusCode, httpResponse.StatusDescription);
        }
      }
      catch (WebException wex) { Console.WriteLine(wex); }
      catch (Exception ex) { Console.WriteLine(ex); }
 
      return apiResult;
    }
    public static string ExecuteHttpGet(string url, string format, string sessionId) {
      HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
 
      request.Timeout = 20000;
      request.Method = "GET";
      request.ContentType = "charset=UTF-8";
      request.Accept = format;
 
      //Must add the session-id to every API call, except to listing of APIs and logging-in
      if (sessionId != null) {
        request.Headers.Add(c_authorizationHeader, sessionId);
      }
 
      string apiResult = ParseHttpResponse(request, format);
      return apiResult;
    }
    public static string ExecuteHttpPost(string url, string format, string sessionId, string bodyData) {
      HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
 
      //logging-in is about ADDING a session - using the POST http command
      request.Method = "POST";
      request.Timeout = 10000;
      request.ContentLength = 0;
 
      request.Headers.Add("Authorization", sessionId);
      request.Accept = format;
      request.ContentType = format;
 
      // Set the data and content length of the string being posted.
      byte[] byte1 = new ASCIIEncoding().GetBytes(bodyData);
      request.ContentLength = byte1.Length;
      Stream newStream = request.GetRequestStream();
      newStream.Write(byte1, 0, byte1.Length);
 
      string apiResult = ParseHttpResponse(request, format);
      return apiResult;
    }
    private static string PrettyPrintXmlData(String xmlString) {
      String formattedXmlString = string.Empty;
 
      using (MemoryStream mStream = new MemoryStream()) {
        using (XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode)) {
          var xDoc = new XmlDocument();
 
          try {
            xDoc.LoadXml(xmlString);
            writer.Formatting = Formatting.Indented;
 
            xDoc.WriteContentTo(writer);
            writer.Flush();
            mStream.Flush();
 
            mStream.Position = 0;
 
            using (StreamReader reader = new StreamReader(mStream)) {
              formattedXmlString = reader.ReadToEnd();
            }
 
          }
          catch (XmlException) { }
        }
      }
      return formattedXmlString;
    }
    #endregion
    #region serialize / deserialize
    private string SerializeObjectToJson(Object o, Type type) {
      string output;
      using (var stream = new MemoryStream()) {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(type);
        ser.WriteObject(stream, o);
        stream.Position = 0;
        using (var reader = new StreamReader(stream)) {
          output = reader.ReadToEnd();
        }
      }
      return output;
    }
 
    private static Stream GenerateStreamFromString(string s) {
      return new MemoryStream(Encoding.UTF8.GetBytes(s));
    }
    private Object DeserializeObjectFromJson(string jsonStr, Type type) {
      if (jsonStr == null) {
        return null;
      }
      Object output;
      using (Stream stream = GenerateStreamFromString(jsonStr)) {
        stream.Position = 0;
        DataContractJsonSerializer ser = new DataContractJsonSerializer(type);
        output = ser.ReadObject(stream);
      }
      return output;
    }
    #endregion
 
  }
}
The following is an example output.
The result is a list of uri addresses each representing an API:
=====================================================
https://162.30.77.10:9669/v1/events
https://162.30.77.10:9669/v1/vpgs
https://162.30.77.10:9669/v1/vms
https://162.30.77.10:9669/v1/vras
https://162.30.77.10:9669/v1/peersites
https://162.30.77.10:9669/v1/session
https://162.30.77.10:9669/v1/tasks
https://162.30.77.10:9669/v1/serviceprofiles
https://162.30.77.10:9669/v1/virtualizationsites
https://162.30.77.10:9669/v1/zorgs
https://162.30.77.10:9669/v1/localsite
https://162.30.77.10:9669/v1/alerts
Request the list of events (no filters are used):
===================================================
Found 21 Events.
1. Stop Failover Test. Success. Completed successfully: OK
2. Protection group failover test. Success. Completed successfully.
3. Stop Failover Test. Success. Completed successfully: OK
4. Protection group failover test. Success. Completed successfully.
5. Stop Failover Test. Success. Completed successfully: OK
6. Protection group failover test. Success. Completed successfully.
7. Stop Failover Test. Success. Completed successfully.
8. Protection group failover test. Success. Completed successfully.
9. Stop Failover Test. Success. Completed successfully.
10. Protection group failover test. Success. Completed successfully.
11. Stop Failover Test. Success. Completed successfully.
12. Protection group failover test. Success. Completed successfully.
13. Stop Failover Test. Success. Completed successfully.
14. Protection group failover test. Success. Completed successfully.
15. Stop Failover Test. Success. Completed successfully.
16. Alert turned on at 08/06/2015 14:53:52: The VPG MyVPG has been protected for 15 minutes but the journal history is only 3 minutes.
17. Protection group failover test. Success. Completed successfully.
18. Alert turned off at 08/06/2015 14:40:02 after 0:0:10: Synchronizing with site Site4-Ent2-P1.
19. Pairing. Zerto Virtual Manager = 127.0.0.1, Port = 9081. Success. Completed successfully.
20. Alert turned on at 08/06/2015 14:39:52: Synchronizing with site Site4-Ent2-P1.
21. Protection group creation. Success. Completed successfully.
Dismiss all alerts that are warning level and not dismissed.
===================================================
Found 1 alerts matching filter.
Dismiss alert : The VPG MyVPG has been protected for 1 hour but the journal history is only 4 minutes.
Dismissed 1 alerts.
Do a Failover Test for the first VPG
===================================================
Found 1 vpgs.
Work on Vpg: MyVPG.
Found 60 valid checkpoints.
Start Failover Test.
Start Failover Test Task is at 0%
Start Failover Test Task is at 6%
Start Failover Test Task is at 43%
Start Failover Test Task is at 43%
Start Failover Test Task is at 43%
Start Failover Test Task is at 43%
Start Failover Test Task is at 81%
Start Failover Test Task done.
Failover is in Test.
Stop Failover Test.
Stop Failover Test Task is at 0%
Stop Failover Test Task is at 19%
Stop Failover Test Task is at 19%
Stop Failover Test Task is at 95%
Stop Failover Test Task done.
Failover Test stopped successfully.
Testing completed.
Logged out - by deleting the session