Start ECS using ak/sk signing

Sample on how to start an ECS instance using an ak/sk request signing.

For complete source code, see samples-doc/aksksigning/ecs-start on GitHub.

Requirements

Environment variables

Environment variable name

Value

Default

ECS_INSTANCE_ID

<ID of ecs instance>

OTC_SDK_PROJECTID

<Project ID>

Needed if ecs instance is in a sub project see Obtaining a Project ID

OTC_SDK_AK

<Access Key>

see: Generating AK and SK

OTC_SDK_SK

<Secret Key>

see: Generating AK and SK

Code

<?php
require_once __DIR__ . '/vendor/autoload.php';

use OTC\Signer;
use OTC\Request;


function checkEnvVars() {
    $required = ['OTC_SDK_PROJECT_ID', 'OTC_SDK_AK', 'OTC_SDK_SK', 'ECS_INSTANCE_ID'];
    $missing = [];
    foreach ($required as $var) {
        $val = getenv($var);
        if ($val === false || $val === '') {
            $missing[] = $var;
        }
    }
    if (!empty($missing)) {
        echo "Error: missing required environment variables:\n";
        foreach ($missing as $var) {
            echo "  - $var\n";
        }
        exit(1);
    }
}

function startECS() {
    checkEnvVars();
    
    $project_id = getenv('OTC_SDK_PROJECT_ID');
    $endpoint = 'ecs.eu-de.otc.t-systems.com';
    $instance_id = getenv('ECS_INSTANCE_ID');

    $signer = new Signer();
    $signer->Key = getenv('OTC_SDK_AK');
    $signer->Secret = getenv('OTC_SDK_SK');

    echo "Starting ECS instance: " . $instance_id . "\n";

    // see https://docs.otc.t-systems.com/elastic-cloud-server/api-ref/apis_recommended/batch_operations/starting_ecss_in_a_batch.html#en-us-topic-0020212207
    $url = 'https://' . $endpoint . '/v1/' . $project_id . '/cloudservers/action';

    $body = json_encode([
        'os-start' => [
            'servers' => [['id' => $instance_id]],
        ],
    ]);

    $headers = [
        'Content-Type' => 'application/json;charset=utf8',
    ];

    if ($project_id !== false && $project_id !== '') {
        // To access resources in a sub-project (e.g. eu_de/myproject)
        // by calling APIs, X-Project-Id of "eu_de/myproject" is needed
        $headers['X-Project-Id'] = $project_id;
    }

    $req = new Request('POST', $url, $headers, $body);

    $curl = $signer->Sign($req);

    // use proxy if defined in environment
    $proxy = getenv('HTTP_PROXY');
    if ($proxy !== false && $proxy !== '') {
        echo "Using HTTP proxy: " . $proxy . "\n";
        curl_setopt($curl, CURLOPT_PROXY, $proxy);
    }

    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HEADER, true);

    $response = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);

    if ($status == 0) {
        echo "Error: " . curl_error($curl) . "\n";
    } else {
        $response_headers = substr($response, 0, $header_size);
        $response_body = substr($response, $header_size);
        echo "Status Code: " . $status . "\n";
        echo "Headers: " . $response_headers . "\n";
        echo "Response Body: " . $response_body . "\n";
    }

    curl_close($curl);
}

startECS();
?>

composer.json

Following is the composer.json file for this sample. It is used to install dependencies.

{
  "name": "opentelekomcloud-community/ecs-start",
  "description": "Sample start an ECS instance",
  "license": "Apache-2.0",
  "type": "project",
  "require": {
    "opentelekomcloud-community/otc-api-sign-sdk-php": "1.0.2"
  }
}

Install dependencies

Install dependencies using composer.

composer update

Running

Run the sample using the following command. Make sure to set the required environment variables first.

php startECS_AKSK.php

Following is a sample output of the script:

Starting ECS instance: cdb29bdd-1235-4e98-90d3-34bb77450393
Using HTTP proxy: http://XXXXXXXX.XXX:8080
Status Code: 200
Headers: HTTP/1.0 200 Connection Established

HTTP/1.1 200
Server: CloudWAF
Date: Tue, 28 Jul 2026 11:30:53 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: CLOUDWAFSESID=e2dad73361814443ad; path=/
Set-Cookie: CLOUDWAFSESTIME=1785238253109; path=/
X-Request-Id: bd67bcc32b5e678f07fec825767676ae
Accept-Ranges: bytes
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Strict-Transport-Security: max-age=31536000; includeSubdomains;
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-XSS-Protection: 1; mode=block;


Response Body: {"job_id":"ff8080829df76048019fa87dee925ca3"}