0
votes

I have the following need. I would like every day at 5:00 am to restart my instance, so I read the best way to automate it would be using Cloud Scheduler and Cloud Function, but I am not aware of these two GCP features.

I created two schedules in the Cloud Scheduler where my VM instance STOP at 5:00 am and another one that START at 5:10 am, but I don't know how to proceed in Cloud Function to end my process.

Could someone help me with this? hug to everyone!

See how are my project error log when trying to implement

ERROR

{ "jobName": "projects/my-project/locations/us-central1/jobs/Stop", "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished", "status": "INTERNAL", "url": "https://us-central1-my-project.cloudfunctions.net/power/stop?zone=us-central1-a&instance=my-instance", "targetType": "HTTP" }

###############

    {
insertId: "1klx7n3g18eq5zs"
jsonPayload: {
jobName: "projects/my-project/locations/us-central1/jobs/Stop"
@type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
status: "INTERNAL"
url: "https://us-central1-my-project.cloudfunctions.net/power/stop?zone=us-central1-a&instance=my-instance"
targetType: "HTTP"
}
httpRequest: {
status: 500
}
resource: {
type: "cloud_scheduler_job"
labels: {
location: "us-central1"
project_id: "my-project"
job_id: "Stop"
}
}
timestamp: "2020-08-07T08:00:06.896367090Z"
severity: "ERROR"
logName: "projects/my-project/logs/cloudscheduler.googleapis.com%2Fexecutions"
receiveTimestamp: "2020-08-07T08:00:06.896367090Z"
}
1

1 Answers

0
votes

I have the same use case on my project, and I use this python function in order to start and stop a vm, my function can handle the paths start and stop

from flask import Flask, request, abort
import os
import logging

app = Flask(__name__)


@app.route('/')
@app.route('/<path:path>')
def power(path=None):
    #this libraries are mandatory to reach compute engine api
    from googleapiclient import discovery
    from oauth2client.client import GoogleCredentials


    #the function will take the service account of your function
    credentials = GoogleCredentials.get_application_default()

    #this line is to specify the api that we gonna use, in this case compute engine    
    service = discovery.build('compute', 'v1', credentials=credentials, cache_discovery=False)
    logging.getLogger('googleapiclient.discovery_cache').setLevel(logging.ERROR)

    # Project ID for this request.
    project = yourprojectID  # Update placeholder value.
    zone = request.args.get('zone', None)
    instance = request.args.get('instance', None)

    #call the method to start or stop the instance
    if (request.path == "/stop"):
        req = service.instances().stop(project=project, zone=zone, instance=instance)

    elif (request.path == "/start"):
        req = service.instances().start(project=project, zone=zone, instance=instance)
    else:
        abort(418)
    #execute the command
    response = req.execute()

    print(response)
    return ("OK")


if __name__ == '__main__':
    app.run(port=3000, debug=True)

requirements.txt file

google-api-python-client
oauth2client
flask

Scheduler config

  1. Create a service account with functions.invoker permission within your function
  2. Create new Cloud scheduler job
  3. Specify the frequency in cron format.
  4. Specify HTTP as the target type.
  5. Add the URL of your cloud function and method as always.
  6. Select the token OIDC from the Auth header dropdown
  7. Add the service account email in the Service account text box.
  8. In audience field you must only need to write the URL of the function without any additional parameter

On cloud scheduler, I hit my function by using these URLs

https://us-central1-yourprojectID.cloudfunctions.net/power/stop?zone=us-central1-a&instance=instance-1

https://us-central1-yourprojectID.cloudfunctions.net/power/stop?zone=us-central1-a&instance=instance-1

and I used this audience

https://us-central1-yourprojectID.cloudfunctions.net/power

please replace yourprojectID in the code and in the URLs

us-central1 is the region where my function is located, power is the name of my function, us-central1-a is the zone where my instance is located and instance-1 is the name of my instance

update for java

Cloud functions supports java11 and maven but this is on beta

first you need this dependencies, please add the following lines to your pom.xml file:

    <dependency>
      <groupId>com.google.apis</groupId>
      <artifactId>google-api-services-compute</artifactId>
      <version>beta-rev20200629-1.30.10</version>
    </dependency>
    <dependency>
      <groupId>com.google.api-client</groupId>
      <artifactId>google-api-client</artifactId>
      <version>1.30.10</version>
    </dependency>

Cloud function to START a VM

package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Operation;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;

public class Example implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception, IOException, GeneralSecurityException {
    
    
    // Project ID for this request.
    String project = "my-project"; // TODO: Update placeholder value.

    // The name of the zone for this request.
    String zone = "my-zone"; // TODO: Update placeholder value.

    // Name of the instance resource to start.
    String instance = "my-instance"; // TODO: Update placeholder value.

    Compute computeService = createComputeService();

    // you can change the method start to stop 
    Compute.Instances.Start request = computeService.instances().start(project, zone, instance);
    
    Operation xresponse = xrequest.execute();

    // TODO: Change code below to process the `response` object:
    System.out.println(xresponse);

    BufferedWriter writer = response.getWriter();
    writer.write("Done");


  }

  public static Compute createComputeService() throws IOException, GeneralSecurityException {
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

    GoogleCredential credential = GoogleCredential.getApplicationDefault();
    if (credential.createScopedRequired()) {
      credential =
          credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
    }

    return new Compute.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Google-ComputeSample/0.1")
        .build();
  }

}

For more information you can check this document in this document are some examples in different programming languages