private void RollbackScheduled()

in tools/gsnapshot/Runner.cs [204:338]


    private void RollbackScheduled(Options options) {
      if (!CheckProjectAndInstance(options)) {
        return;
      }

      Dictionary<string, Dictionary<string, Tuple<ComputeData.Disk, ComputeData.Snapshot?>>>
          snapshots = _snapshots
                          .GetScheduledSnapshotsForInstance(
                              options.Project, _instances.AllInstances[options.Instance])
                          .GetAwaiter()
                          .GetResult();

      var rollbackInstance =
          _instances.GetInstance(options.Project, _instances.AllInstances[options.Instance]);

      Dictionary<string, string> allSnapshots = new Dictionary<string, string>();
      _logger.LogInformation(
          $"Found the following scheduled snapshots for {rollbackInstance.Name}:");
      foreach (KeyValuePair<string,
                            Dictionary<string, Tuple<ComputeData.Disk, ComputeData.Snapshot?>>>
                   entry in snapshots) {
        allSnapshots[entry.Key] = entry.Key;
        _logger.LogInformation($"  Snapshot ID: {entry.Key}");
        int diskNameLength = 0, snapshotNameLength = 0, timestampLength = 0;
        foreach (KeyValuePair<string, Tuple<ComputeData.Disk, ComputeData.Snapshot?>> disk in entry
                     .Value) {
          string diskName = _utils.GetLastPart(disk.Key);
          if (diskName.Length > diskNameLength) {
            diskNameLength = diskName.Length;
          }
          if (disk.Value.Item2 != null) {
            if (disk.Value.Item2.Name.Length > snapshotNameLength) {
              snapshotNameLength = disk.Value.Item2.Name.Length;
            }
            string timestamp =
                DateTimeOffset.Parse(disk.Value.Item2.CreationTimestamp).ToLocalTime().ToString();
            if (timestamp.Length > timestampLength) {
              timestampLength = timestamp.Length;
            }
          }
        }

        foreach (KeyValuePair<string, Tuple<ComputeData.Disk, ComputeData.Snapshot?>> disk in entry
                     .Value) {
          string diskName = _utils.GetLastPart(disk.Key);
          string _disk = String.Format("{0,-" + diskNameLength + "}", diskName);
          if (disk.Value.Item2 != null && disk.Value.Item2.StorageBytes != null) {
            string snapshotName = disk.Value.Item2.Name;
            var size = ByteSize.FromBytes((double)disk.Value.Item2.StorageBytes);
            string _snapshot = String.Format("{0,-" + snapshotNameLength + "}", snapshotName);
            string timestamp = String.Format(
                "{0,-" + timestampLength + "}",
                DateTimeOffset.Parse(disk.Value.Item2.CreationTimestamp).ToLocalTime().ToString());

            _logger.LogInformation(
                $"    Disk: {_disk}  Snapshot: {_snapshot}  Timestamp: {timestamp}  Size: {size.ToString()}");
          } else {
            string _snapshot = String.Format("{0,-" + snapshotNameLength + "}", "N/A");
            string timestamp = String.Format("{0,-" + timestampLength + "}", "N/A");
            _logger.LogInformation(
                $"    Disk: {_disk}  Snapshot: {_snapshot}  Timestamp: {timestamp}  Size: N/A");
          }
        }
      }
      string snapshotId = "";
      if (!String.IsNullOrEmpty(options.ScheduledID)) {
        if (snapshots.ContainsKey(options.ScheduledID)) {
          _logger.LogInformation($"Rolling back to snapshot ID: {options.ScheduledID}");
          snapshotId = options.ScheduledID;
        } else {
          _logger.LogCritical($"Unknown snapshot ID specified: {options.ScheduledID}");
          System.Environment.Exit(11);
        }
      }

      if (String.IsNullOrEmpty(snapshotId)) {
        ReadLine.AutoCompletionHandler = new AutoCompletionHandler(allSnapshots);
        var oldColor = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.White;
        snapshotId = ReadLine.Read(
            "Snapshot ID for rollback (empty for all, tab to autocomplete, ^C to cancel)> ");
        Console.ForegroundColor = oldColor;
      }
      if (String.IsNullOrEmpty(snapshotId) || !snapshots.ContainsKey(snapshotId)) {
        _logger.LogCritical($"Unknown snapshot ID specified: {snapshotId}");
        System.Environment.Exit(11);
      }
      Dictionary<string, Tuple<ComputeData.Disk, ComputeData.Snapshot>> rollbacks =
          new Dictionary<string, Tuple<ComputeData.Disk, ComputeData.Snapshot>>();
      foreach (KeyValuePair<string, Tuple<ComputeData.Disk, ComputeData.Snapshot?>> entry in
                   snapshots[snapshotId]) {
        rollbacks[entry.Key] =
            new Tuple<ComputeData.Disk, ComputeData.Snapshot>(entry.Value.Item1, entry.Value.Item2);
      }

      Dictionary<string, ComputeData.Disk?> newDisks =
          _disks
              .CreateScheduledRollbackDisksAsync(options.Project,
                                                 _instances.AllInstances[options.Instance],
                                                 rollbacks, options.EraseVSS)
              .GetAwaiter()
              .GetResult();

      _instances.CheckInstanceRunning(options.Project, _instances.AllInstances[options.Instance],
                                      options.Stop, "rollback");

      string snapshotPrefix = $"gsnapshot-scheduled-{snapshotId}";
      bool done = _disks
                      .AttachNewDisksAsync(options.Project, snapshotPrefix,
                                           _instances.AllInstances[options.Instance], newDisks)
                      .GetAwaiter()
                      .GetResult();
      if (done) {
        _logger.LogInformation($"Rollback finished for snapshot ID {snapshotId}!");
        rollbackInstance =
            _instances.GetInstance(options.Project, _instances.AllInstances[options.Instance]);
        if (rollbackInstance.Status == "TERMINATED") {
          bool startServer = options.Start;
          if (!options.Start) {
            _logger.LogWarning($"Instance is stopped, do you want to start it?");
            startServer = _utils.GetYesNo("Start server (Y/n)?", true);
          }
          if (startServer) {
            _logger.LogInformation($"Starting instance {rollbackInstance.Name}...");
            bool serverStarted =
                _instances.StartInstance(options.Project, _instances.AllInstances[options.Instance])
                    .GetAwaiter()
                    .GetResult();
          }
        }
      } else {
        _logger.LogWarning($"Rollback was not entirely completed.");
      }
      _logger.LogInformation("Instance rollback finished.");
    }