This class represents an operation on a Google Compute Engine VM instance.
Example #1
0
        private async Task UpdateInstancePortsAsyncImpl(
            GceOperation pendingOperation,
            Instance instance,
            IList <FirewallPort> portsToEnable,
            IList <FirewallPort> portsToDisable)
        {
            try
            {
                s_pendingOperations.Add(pendingOperation);

                // 1) Ensure that the firewall rules for the ports to be enabled are present.
                await EnsureFirewallRules(portsToEnable);

                // 2) Update the tags for the instance.
                var tagsToAdd     = portsToEnable.Select(x => x.Name);
                var tagsToRemove  = portsToDisable.Select(x => x.Name);
                var instanceTags  = instance.Tags?.Items ?? Enumerable.Empty <string>();
                var tagsOperation = SetInstanceTags(
                    instance,
                    instanceTags.Except(tagsToRemove).Union(tagsToAdd).ToList());
                await tagsOperation.OperationTask;
            }
            finally
            {
                s_pendingOperations.Remove(pendingOperation);
            }
        }
Example #2
0
 private Task SetInstanceTagsAsyncImpl(GceOperation pendingOperation, Instance instance, IList <string> tags) =>
 RegisterPendingOperation(pendingOperation, () =>
 {
     var newTags = new Tags
     {
         Items       = tags,
         Fingerprint = instance.Tags.Fingerprint,
     };
     return(Service.Instances.SetTags(newTags, ProjectId, instance.GetZoneName(), instance.Name).ExecuteAsync());
 });
Example #3
0
        /// <summary>
        /// Sets the tags for a GCE instance to <paramref name="tags"/>. The task wrapped by the operation will throw
        /// if the list of tags was modified already, and the fingerprint for the tags doesn't match.
        /// </summary>
        /// <param name="instance">The instance to modify.</param>
        /// <param name="tags">The tags to set.</param>
        /// <returns>The operation.</returns>
        public GceOperation SetInstanceTags(Instance instance, IList <string> tags)
        {
            var operation = new GceOperation(
                operationType: OperationType.SettingTags,
                projectId: ProjectId,
                zoneName: instance.GetZoneName(),
                name: instance.Name);

            operation.OperationTask = SetInstanceTagsAsyncImpl(operation, instance, tags);
            return(operation);
        }
Example #4
0
        /// <summary>
        ///  Starts an instance in the current project, given its <paramref name="zoneName"/> and <paramref name="name"/>.
        /// </summary>
        /// <param name="zoneName">The zone where the instance is located.</param>
        /// <param name="name">The name of the instance.</param>
        /// <returns>The new pending operation.</returns>
        public GceOperation StartInstance(string zoneName, string name)
        {
            var operation = new GceOperation(
                operationType: OperationType.StartInstance,
                projectId: ProjectId,
                zoneName: zoneName,
                name: name);

            operation.OperationTask = StartInstanceImplAsync(operation, zoneName, name);
            return(operation);
        }
Example #5
0
        /// <summary>
        /// Updates the instance ports, enables the <paramref name="portsToEnable"/> and disables the
        /// ports in <paramref name="portsToDisable"/>.
        /// </summary>
        /// <param name="instance">The instance to modify.</param>
        /// <param name="portsToEnable">The list of ports to enable.</param>
        /// <param name="portsToDisable">The list of ports to disable.</param>
        /// <returns>The operation.</returns>
        public GceOperation UpdateInstancePorts(
            Instance instance,
            IList <FirewallPort> portsToEnable,
            IList <FirewallPort> portsToDisable)
        {
            var operation = new GceOperation(
                OperationType.ModifyingFirewall,
                ProjectId,
                instance.GetZoneName(),
                instance.Name);

            operation.OperationTask = UpdateInstancePortsAsyncImpl(operation, instance, portsToEnable, portsToDisable);
            return(operation);
        }
Example #6
0
        private async Task RegisterPendingOperation(GceOperation pendingOperation, Func <Task <Operation> > operationFactory)
        {
            try
            {
                var operation = await operationFactory();

                s_pendingOperations.Add(pendingOperation);
                await WaitAsync(operation);
            }
            catch (GoogleApiException ex)
            {
                Debug.WriteLine($"Failed to call api: {ex.Message}");
                throw new DataSourceException(ex.Message, ex);
            }
            finally
            {
                s_pendingOperations.Remove(pendingOperation);
            }
        }
Example #7
0
 /// <summary>
 /// Stores the given operation in the pending operations list as the operation for this API call
 /// and performs the API call to stop the instance.
 /// </summary>
 /// <param name="pendingOperation">The operation to use for this API call.</param>
 /// <param name="zoneName">The zone where the instance is localed.</param>
 /// <param name="name">The name of the instance.</param>
 /// <returns>The task that will be completed when the API call is complete, including the cleanup.</returns>
 private Task StartInstanceImplAsync(GceOperation pendingOperation, string zoneName, string name) =>
 RegisterPendingOperation(pendingOperation, () => Service.Instances.Start(ProjectId, zoneName, name).ExecuteAsync());
        private async void UpdateInstanceState(GceOperation pendingOperation)
        {
            while (pendingOperation != null && !pendingOperation.OperationTask.IsCompleted)
            {
                // Since there's a pending operation the loading state needs to be set to show
                // progress ui.
                IsLoading = true;

                // Setting the content according to the operation type.
                switch (pendingOperation.OperationType)
                {
                    case OperationType.StartInstance:
                        Caption = String.Format(Resources.CloudExplorerGceInstanceStartingCaption, Instance.Name);
                        break;

                    case OperationType.StopInstance:
                        Caption = String.Format(Resources.CloudExplorerGceInstanceStoppingCaption, Instance.Name);
                        break;

                    case OperationType.SettingTags:
                        Caption = String.Format(Resources.CloudExplorerGceInstanceSettingTagsCaption, Instance.Name);
                        break;

                    case OperationType.ModifyingFirewall:
                        Caption = String.Format(Resources.CloudExplorerGceInstanceUpdatingFirewallCaption, Instance.Name);
                        break;
                }

                // Update the context menu to reflect the state.
                UpdateContextMenu();

                try
                {
                    // Await the end of the task. We can also get here if the task is faulted, 
                    // in which case we need to handle that case.
                    while (true)
                    {
                        // Refresh the instance before waiting for the operation to finish.
                        Instance = await _owner.DataSource.RefreshInstance(Instance);

                        // Wait for the operation to finish up to the timeout, which we will use to refresh the
                        // state of the instance.
                        var result = await Task.WhenAny(pendingOperation.OperationTask, Task.Delay(s_pollTimeout));
                        if (result == pendingOperation.OperationTask)
                        {
                            // Await the task again to get any possible exception.
                            await pendingOperation.OperationTask;
                            break;
                        }
                    }

                    // Refresh the instance state after the operation is finished.
                    Instance = await _owner.DataSource.RefreshInstance(Instance);
                }
                catch (DataSourceException ex)
                {
                    Caption = Instance.Name;
                    IsLoading = false;
                    IsError = true;
                    UpdateContextMenu();

                    Debug.WriteLine($"Previous operation failed.");
                    switch (pendingOperation.OperationType)
                    {
                        case OperationType.StartInstance:
                            GcpOutputWindow.OutputLine(String.Format(Resources.CloudExplorerGceStartOperationFailedMessage, Instance.Name, ex.Message));
                            break;

                        case OperationType.StopInstance:
                            GcpOutputWindow.OutputLine(String.Format(Resources.CloudExplorerGceStopOperationFailedMessage, Instance.Name, ex.Message));
                            break;
                    }

                    // Permanent error.
                    return;
                }

                // See if there are more operations.
                pendingOperation = _owner.DataSource.GetPendingOperation(Instance);
            }

            // Normal state, no pending operations.
            IsLoading = false;
            Caption = Instance.Name;
            UpdateContextMenu();
        }