Skip to content

Commit

Permalink
docs(samples): Add samples for suspending/resuming an instance (#259)
Browse files Browse the repository at this point in the history
* chore(samples): Adding samples for suspend/resume

* Fixing lint problems
  • Loading branch information
m-strzelczyk authored Apr 13, 2022
1 parent 004d3d4 commit 48c82d7
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This is an ingredient file. It is not meant to be run directly. Check the samples/snippets
# folder for complete code samples that are ready to be used.
# Disabling flake8 for the ingredients file, as it would fail F821 - undefined name check.
# flake8: noqa
import time

from google.cloud import compute_v1


# <INGREDIENT resume_instance>
def resume_instance(project_id: str, zone: str, instance_name: str) -> None:
"""
Resume a suspended Google Compute Engine instance (with unencrypted disks).
Args:
project_id: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
instance_name: name of the instance your want to resume.
"""
instance_client = compute_v1.InstancesClient()
op_client = compute_v1.ZoneOperationsClient()

instance = instance_client.get(project=project_id, zone=zone, instance=instance_name)
if instance.status != compute_v1.Instance.Status.SUSPENDED.name:
raise RuntimeError(f"Only suspended instances can be resumed. "
f"Instance {instance_name} is in {instance.status} state.")

op = instance_client.resume_unary(
project=project_id, zone=zone, instance=instance_name
)

start = time.time()
while op.status != compute_v1.Operation.Status.DONE:
op = op_client.wait(operation=op.name, zone=zone, project=project_id)
if time.time() - start >= 300: # 5 minutes
raise TimeoutError()
return
# </INGREDIENT>

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This is an ingredient file. It is not meant to be run directly. Check the samples/snippets
# folder for complete code samples that are ready to be used.
# Disabling flake8 for the ingredients file, as it would fail F821 - undefined name check.
# flake8: noqa
import time

from google.cloud import compute_v1


# <INGREDIENT suspend_instance>
def suspend_instance(project_id: str, zone: str, instance_name: str) -> None:
"""
Suspend a running Google Compute Engine instance.
Args:
project_id: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
instance_name: name of the instance your want to suspend.
"""
instance_client = compute_v1.InstancesClient()
op_client = compute_v1.ZoneOperationsClient()

op = instance_client.suspend_unary(
project=project_id, zone=zone, instance=instance_name
)

start = time.time()
while op.status != compute_v1.Operation.Status.DONE:
op = op_client.wait(operation=op.name, zone=zone, project=project_id)
if time.time() - start >= 300: # 5 minutes
raise TimeoutError()
return
# </INGREDIENT>

21 changes: 21 additions & 0 deletions packages/google-cloud-compute/samples/recipes/instances/resume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# flake8: noqa

# <REGION compute_resume_instance>
# <IMPORTS/>


# <INGREDIENT resume_instance />
# </REGION compute_resume_instance>
21 changes: 21 additions & 0 deletions packages/google-cloud-compute/samples/recipes/instances/suspend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# flake8: noqa

# <REGION compute_suspend_instance>
# <IMPORTS/>


# <INGREDIENT suspend_instance />
# </REGION compute_suspend_instance>
60 changes: 60 additions & 0 deletions packages/google-cloud-compute/samples/snippets/instances/resume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# flake8: noqa


# This file is automatically generated. Please do not modify it directly.
# Find the relevant recipe file in the samples/recipes or samples/ingredients
# directory and apply your changes there.


# [START compute_resume_instance]
import time

from google.cloud import compute_v1


def resume_instance(project_id: str, zone: str, instance_name: str) -> None:
"""
Resume a suspended Google Compute Engine instance (with unencrypted disks).
Args:
project_id: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
instance_name: name of the instance your want to resume.
"""
instance_client = compute_v1.InstancesClient()
op_client = compute_v1.ZoneOperationsClient()

instance = instance_client.get(
project=project_id, zone=zone, instance=instance_name
)
if instance.status != compute_v1.Instance.Status.SUSPENDED.name:
raise RuntimeError(
f"Only suspended instances can be resumed. "
f"Instance {instance_name} is in {instance.status} state."
)

op = instance_client.resume_unary(
project=project_id, zone=zone, instance=instance_name
)

start = time.time()
while op.status != compute_v1.Operation.Status.DONE:
op = op_client.wait(operation=op.name, zone=zone, project=project_id)
if time.time() - start >= 300: # 5 minutes
raise TimeoutError()
return


# [END compute_resume_instance]
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# flake8: noqa


# This file is automatically generated. Please do not modify it directly.
# Find the relevant recipe file in the samples/recipes or samples/ingredients
# directory and apply your changes there.


# [START compute_suspend_instance]
import time

from google.cloud import compute_v1


def suspend_instance(project_id: str, zone: str, instance_name: str) -> None:
"""
Suspend a running Google Compute Engine instance.
Args:
project_id: project ID or project number of the Cloud project your instance belongs to.
zone: name of the zone your instance belongs to.
instance_name: name of the instance your want to suspend.
"""
instance_client = compute_v1.InstancesClient()
op_client = compute_v1.ZoneOperationsClient()

op = instance_client.suspend_unary(
project=project_id, zone=zone, instance=instance_name
)

start = time.time()
while op.status != compute_v1.Operation.Status.DONE:
op = op_client.wait(operation=op.name, zone=zone, project=project_id)
if time.time() - start >= 300: # 5 minutes
raise TimeoutError()
return


# [END compute_suspend_instance]
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import time
import uuid

import google.auth
from google.cloud import compute_v1
import pytest


from ..images.get import get_image_from_family
from ..instances.create import create_instance, disk_from_image
from ..instances.delete import delete_instance
from ..instances.resume import resume_instance
from ..instances.suspend import suspend_instance

PROJECT = google.auth.default()[1]

INSTANCE_ZONE = "europe-central2-b"


def _get_status(instance: compute_v1.Instance) -> compute_v1.Instance.Status:
instance_client = compute_v1.InstancesClient()
return instance_client.get(
project=PROJECT, zone=INSTANCE_ZONE, instance=instance.name
).status


@pytest.fixture
def compute_instance():
instance_name = "test-instance-" + uuid.uuid4().hex[:10]
newest_debian = get_image_from_family(project="ubuntu-os-cloud", family="ubuntu-2004-lts")
disk_type = f"zones/{INSTANCE_ZONE}/diskTypes/pd-standard"
disks = [disk_from_image(disk_type, 100, True, newest_debian.self_link)]
instance = create_instance(
PROJECT, INSTANCE_ZONE, instance_name, disks
)
yield instance

delete_instance(PROJECT, INSTANCE_ZONE, instance_name)


def test_instance_suspend_resume(compute_instance):
assert _get_status(compute_instance) == compute_v1.Instance.Status.RUNNING.name

# Once the machine is running, give it some time to fully start all processes
# before trying to suspend it
time.sleep(45)

suspend_instance(PROJECT, INSTANCE_ZONE, compute_instance.name)

while _get_status(compute_instance) == compute_v1.Instance.Status.SUSPENDING.name:
time.sleep(5)

assert _get_status(compute_instance) == compute_v1.Instance.Status.SUSPENDED.name

resume_instance(PROJECT, INSTANCE_ZONE, compute_instance.name)
assert _get_status(compute_instance) == compute_v1.Instance.Status.RUNNING.name

0 comments on commit 48c82d7

Please sign in to comment.