Using IBM Cloud Code Engine to Turn Virtual Server Instances On/Off in an Automated/Scheduled Manner

3 min read

How to turn Virtual Server Instances (VSI) on and off within the IBM Cloud® VPC (Virtual Private Cloud) infrastructure.

IBM Cloud® Code Engine is a fully managed, serverless platform that runs your containerized workloads, including web apps, microservices, event-driven functions or batch jobs. Code Engine even builds container images for you from your source code. Because these workloads are all hosted within the same Kubernetes infrastructure, all of them can seamlessly work together. The Code Engine experience is designed so that you can focus on writing code and not on the infrastructure that is needed to host it.

Note to reader: This process can be applied to schedule any other commands/actions that use API on IBM Cloud. Just import any other modules you need to (be sure to include them in requirements.txt if using something other than the listed SDK) and modify the perform action at the end of the script to do what you need done.

Pseudo code/flow

  • Create a script that will be given instance IDs and an action (start or stop) to apply to the instances.
  • Create two jobs, one that will start all the instances and one that will stop all the instances.
  • Schedule these jobs to be executed so all the instances start at 7:00 AM and stop at 7:00PM.

The script

We chose Python as the language for the script because it is widely accepted in FaaS-like environments. To get Python to work easily with IBM Cloud VPC (where our VSIs reside) it’s recommended to install the IBM Cloud VPC python SDK, so this is included as a requirement for our Python script:

Command:

cat actionVSI.py

Sample output:

import os
from ibm_vpc import VpcV1
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

#Authenticate user on IBM Cloud to do VPC VSI commands
API_KEY = os.environ['api_key']
authenticator = IAMAuthenticator(API_KEY)
service = VpcV1(authenticator=authenticator)

#Set API endpoints
service.set_service_url('https://br-sao.iaas.cloud.ibm.com/v1')

#Get the required action from environment variable
VSIaction = os.environ['action']

# List of instance ID to perform action
instance_ids = []

# Read list from environment variables (assume there will not be more that 100 VSIs)
for VSI in range(1,100):
    try:
        instance_ids.append(os.environ['VSI_' + str(VSI)])
    except:
        break

# Perform action on list
for instance_id in instance_ids:
    response = service.create_instance_action(
        instance_id,
        type = VSIaction,
    )

The script will receive/gather the following information from environment variables (these are stored in configmaps and secrets for Code Engine):

  • Instance IDs (from VSI_1, VSI_2,… VSI_n variables)
  • Action (from the action variable)
  • API KEY (from the api_key variable)

For this example, we are creating a very slim (alpine) Python container to execute this script. Therefore, we need a Dockerfile:

Command:

cat Dockerfile

Sample output: 

FROM python:3.8.3-alpine
COPY . /app
WORKDIR /app
RUN pip install --upgrade -r requirements.txt
CMD python ./actionVSI.py

This Dockerfile selects the alpine Python 3.8.3 image, which at the time of writing was the latest version (so change accordingly). The Dockerfile also installs the IBM Cloud VPC SDK as mentioned above:

Command:

cat requirements.txt

Sample output:

ibm-vpc>=0.10.0

You can test these locally with Docker, but this is beyond the scope of this document. However, if you have any problems and need to troubleshoot, the suggested approach is to first run the Python script locally and then try it in a local container with Docker.

Step-by-step instructions

Now to get this scheduled and running in Code Engine, you’ll need to go through the steps below:

Install the IBM Cloud CLI with Code Engine module by following the instructions on IBM Cloud Docs.

Create the project:

Command:

ibmcloud ce project create -n Test_Instance_StartAndStop

Select the project:

Command:

ibmcloud ce project select -n Test_Instance_StartAndStop

Create API secrets:

Command (remember to substitute your API KEY for the value <YourApiKey>):

ibmcloud ce secret create --name api-key --from-literal " api_key=<Your API Key>"

Create the VSI configmap:

Command:

ibmcloud ce configmap create --name vsi-id --from-env-file ../vsi-id.txt

Contents of the file:

Command:

cat ../vsi-id.txt

Sample output:

VSI_1='02u7_a9941f61-e7eb-4ce6-8935-c02471d3d0bd'
VSI_2='02u7_0a7effa8-e8e0-44da-ab50-68786f830b42'
VSI_3='02u7_d7a22fdd-f5af-4179-b489-3450669b306d'
VSI_4='02u7_d3077e84-9d93-48f2-80ca-2e21a053d548'
VSI_5='02u7_7dbb4c31-ab13-4469-894a-f040d4b8d418'

Create actions start and stop literal variables:

Command:

ibmcloud ce configmap create --name action-start --from-literal action=start

Sample output:

Creating configmap 'action-start'...
OK
Run 'ibmcloud ce configmap get -n action-start' to see more details.

Command:

ibmcloud ce configmap create --name action-stop --from-literal action=stop

Sample output:

Creating configmap 'action-stop'...
OK
Run 'ibmcloud ce configmap get -n action-stop' to see more details.

Create the job for starting the instances by using all that we’ve created so far (VSI configmap data set, secret API key and the action). You’ll also set the CPU and Memory requirements for the lowest possible setting (1/8 CPU and 250 MB of memory):

Command:

ibmcloud ce job create --name actionvsi-start --build-source . --wait --cpu .125 --memory .25G --env-from-secret api-key --env-from-configmap vsi-id --env-from-configmap action-start

Sample output:

Creating job 'actionvsi-start'...
Creating build 'actionvsi-start-build-220506-122817967'...
Packaging files to upload from source path '.'...
Submitting build run 'actionvsi-start-run-220506-122817967'...
Creating image 'private.us.icr.io/ce--3fe45-nlg73169h4n/job-actionvsi-start'...
Waiting for build run to complete...
Build run status: 'Running'
Build run completed successfully.
Run 'ibmcloud ce buildrun get -n actionvsi-start-run-220506-122817967' to check the build run status.
OK

Create a job for stopping the instances, just as we did for starting:

Command:

ibmcloud ce job create --name actionvsi-stop --build-source . --wait --cpu .125 --memory .25G --env-from-secret api-key --env-from-configmap vsi-id --env-from-configmap action-stop

Sample output:

Creating job 'actionvsi-stop'...
Creating build 'actionvsi-stop-build-220506-123157457'...
Packaging files to upload from source path '.'...
Submitting build run 'actionvsi-stop-run-220506-123157457'...
Creating image 'private.us.icr.io/ce--3fe45-nlg73169h4n/job-actionvsi-stop'...
Waiting for build run to complete...
Build run status: 'Running'
Build run completed successfully.
Run 'ibmcloud ce buildrun get -n actionvsi-stop-run-220506-123157457' to check the build run status.
OK

If you are curious, you can check on the UI — Code Engine > Projects > Your Project Name > Jobs and click on the star job, then Configuration, then Environment variables:

If you are curious, you can check on the UI — Code Engine > Projects > Your Project Name > Jobs and click on the star job, then Configuration, then Environment variables:

You can also follow the job runs, submit jobs and do everything else through the UI, should you choose to do so. I prefer to stick to CLI as I find it easier to document.

Time to test the jobs we have created. As you can see below, there are five instances that end in vsi-0-01 — these are my test instances for this script. They are all in a stopped state:

Time to test the jobs we have created. As you can see below, there are five instances that end in vsi-0-01 — these are my test instances for this script. They are all in a stopped state:

Let’s run the start job and turn the instances on (or to a started state):

Command:

ibmcloud ce jobrun submit --name start-test-run --job actionvsi-start

Sample output:

Getting job 'actionvsi-start'...
Submitting job run 'start-test-run'...
Run 'ibmcloud ce jobrun get -n start-test-run' to check the job run status.
OK

Optionally, you can check on the state of the job run by executing the suggested command, so let’s do that:

Command:

ibmcloud ce jobrun get -n start-test-run

Sample output:

Getting jobrun 'start-test-run'...
Getting instances of jobrun 'start-test-run'...
Getting events of jobrun 'start-test-run'...
Run 'ibmcloud ce jobrun events -n start-test-run' to get the system events of the job run instances.
Run 'ibmcloud ce jobrun logs -f -n start-test-run' to follow the logs of the job run instances.
OK

Name:          start-test-run  
ID:            d051f6a5-6026-429d-92ce-c7626b4115ed  
Project Name:  Test_Instance_StartAndStop
Project ID:    bfe86bd8-e9e4-4aef-8b21-f53635404fda  
Age:           52s  
Created:       2022-05-06T12:36:35-04:00  

Job Ref:                actionvsi-start  
Environment Variables:    
  Type                      Name          Value  
  ConfigMap full reference  action-start    
  ConfigMap full reference  vsi-id          
  Secret full reference     api-key         
Image:                  private.us.icr.io/ce--3fe45-nlg73169h4n/job-actionvsi-start  
Resource Allocation:      
  CPU:                0.125  
  Ephemeral Storage:  400M  
  Memory:             250M  
Registry Secrets:         
  ce-auto-icr-private-us-south  

Runtime:      
  Array Indices:       0  
  Max Execution Time:  7200  
  Retry Limit:         3  

Status:       
  Completed:          11s  
  Instance Statuses:    
    Succeeded:  1  
  Conditions:         
    Type      Status  Last Probe  Last Transition  
    Pending   True    51s         51s  
    Running   True    31s         31s  
    Complete  True    11s         11s  

Events:       
  Type    Reason     Age                Source                Messages  
  Normal  Updated    12s (x4 over 52s)  batch-job-controller  Updated JobRun "start-test-run"  
  Normal  Completed  12s                batch-job-controller  JobRun completed successfully  

Instances:    
  Name                Running  Status     Restarts  Age  
  start-test-run-0-0  0/1      Succeeded  0         52s

Optionally, you can also check the state via the UI:

Optionally, you can also check the state via the UI:

Once the job has finished successfully, we can go back and check on the instances:

Once that the job has finished successfully, we can go back and check on the instances:

Test successful! Now repeat for the stop action.

Test stopping all the instances:

Command:

ibmcloud ce jobrun submit --name stop-test-run --job actionvsi-stop

Sample output:

Getting job 'actionvsi-stop'...
Submitting job run 'stop-test-run'...
Run 'ibmcloud ce jobrun get -n stop-test-run' to check the job run status.
OK

Check if the job ran successfully:

Command:

ibmcloud ce jobrun get -n stop-test-run

Sample output:

Getting jobrun 'stop-test-run'...
Getting instances of jobrun 'stop-test-run'...
Getting events of jobrun 'stop-test-run'...
Run 'ibmcloud ce jobrun events -n stop-test-run' to get the system events of the job run instances.
Run 'ibmcloud ce jobrun logs -f -n stop-test-run' to follow the logs of the job run instances.
OK

Name:          stop-test-run  
ID:            18c1952b-0892-4f2d-be2c-47fb3e4cf4e0  
Project Name:  Test_Instance_StartAndStop  
Project ID:    bfe86bd8-e9e4-4aef-8b21-f53635404fda  
Age:           21s  
Created:       2022-05-06T12:39:18-04:00  

Job Ref:                actionvsi-stop  
Environment Variables:    
  Type                      Name         Value  
  ConfigMap full reference  action-stop    
  ConfigMap full reference  vsi-id         
  Secret full reference     api-key        
Image:                  private.us.icr.io/ce--3fe45-nlg73169h4n/job-actionvsi-stop  
Resource Allocation:      
  CPU:                0.125  
  Ephemeral Storage:  400M  
  Memory:             250M  
Registry Secrets:         
  ce-auto-icr-private-us-south  

Runtime:      
  Array Indices:       0  
  Max Execution Time:  7200  
  Retry Limit:         3  

Status:       
  Completed:          3s  
  Instance Statuses:    
    Succeeded:  1  
  Conditions:         
    Type      Status  Last Probe  Last Transition  
    Pending   True    21s         21s  
    Running   True    12s         12s  
    Complete  True    3s          3s  

Events:       
  Type    Reason     Age               Source                Messages  
  Normal  Updated    3s (x4 over 21s)  batch-job-controller  Updated JobRun "stop-test-run"  
  Normal  Completed  3s                batch-job-controller  JobRun completed successfully  

Instances:    
  Name               Running  Status     Restarts  Age  
  stop-test-run-0-0  0/1      Succeeded  0         21s

Again, you can also check via the UI:

Again, you can also check via the UI:

Let’s check the instances once more to see that all the five resources with VSI at the end (the same set that were started) are now stopped:

Let’s check the instances once more to see that all the five resources with VSI at the end (the same set that were started) are now stopped:

Now that we’re certain both jobs work, we can schedule them with CRON:

Turns on at 7:00 AM (Sao Paulo, Brazil time zone) every weekday:

Command:

ibmcloud ce sub cron create --name cron-sub-actionvsi-start --destination actionvsi-start --destination-type job --schedule '0 7 * * 1-5' --time-zone "America/Sao_Paulo"

Sample output:

Creating cron event subscription 'cron-sub-actionvsi-start'...
Run 'ibmcloud ce subscription cron get -n cron-sub-actionvsi-start' to check the cron event subscription status.
OK

Turns off at 7:00 PM every weekday:

Command:

ibmcloud ce sub cron create --name cron-sub-actionvsi-stop --destination actionvsi-stop --destination-type job --schedule '0 19 * * 1-5' --time-zone "America/Sao_Paulo"

Sample output:

Creating cron event subscription 'cron-sub-actionvsi-stop'...
Run 'ibmcloud ce subscription cron get -n cron-sub-actionvsi-stop' to check the cron event subscription status.
OK

Learn more

The blog post describes how you can use IBM Cloud Code Engine to run a scheduled script that will perform any desired actions via API on IBM Cloud. In this example, we explored turning a set of VSIs (Virtual Server Instances) on and off at a specific time of the day, which is useful because it reduces costs by turning off infrastructure when it is not needed.

Be the first to hear about news, product updates, and innovation from IBM Cloud