Использование API Digital Ocean для управления облачными инстансами
() translation by (you can also view the original English article)



Что такое Digital Ocean?
Digital Ocean - один из самых быстрорастущих веб-хостингов, отчасти благодаря быстрым серверам на базе SSD и недорогим ежемесячным планам размещения в 5 долларов США. Спиннинг инстансов на Digital Ocean для тестирования или долгосрочного использования является быстрым, простым и доступным.
Создав образ приложения для перепродажи в Digital Ocean, я провел вас по статье, как запустить инстанс WordPress (или другого приложения) и повторно клонировать его для клиентов. В этом уроке я расскажу вам об использовании API Digital Ocean для программного управления нашими инстансами, также известных как дроплеты, и для автоматизации общих задач. Я также предоставил образец кода для запуска очень простых операций API, написанный на Yii Framework для PHP; вы можете получить код здесь, на Github.
Digital Ocean API
API Digital Ocean позволяет вам управлять дрополетами и ресурсами простым, программным способом, используя HTTP-запросы. Все функциональные возможности, которые вам знакомы на панели управления Digital Ocean, также доступны через API, позволяя вам писать скрипты для сложных действий, которые необходимы вашей ситуации.
В этом уроке мы интегрируем библиотеку API-интерфейса Digital Ocean V2 PHP API Library от разработчика Antoine Corcy в консольное приложение на основе Yii. Вам не нужно знать Yii, чтобы использовать приложение, но вы можете узнать больше о нем здесь: Введение в Yii Framework.
API Digital Ocean аутентифицирует вашу учетную запись через OAuth и состоит из почти десятка областей высокого уровня:
- Accounts: предоставляет основную информацию о вашей учетной записи Digital Ocean.
- Actions: исторический журнал действий на дроплетах вашего аккаунта.
- Domains & Domain Record: позволяет управлять доменами, используемыми для дроплетов в вашей учетной записи, а также связанными с ними DNS-записями.
- Droplets & Droplet Actions: позволяет создавать, выключать, перезапускать, снимок и многое другое для ваших дроплетов.
- Images & Image Actions: позволяет вам перечислить и управлять изображениями снапшотов, которые вы сделали с дроплетов в своей учетной записи.
- SSH Keys: позволяет зарегистрировать ключ SSH для установки при создании дроплета, чтобы не требовалась защита паролем.
- Regions: перечисляет географические регионы, в которых могут создаваться дроплеты Digital Ocean.
- Sizes: перечисляет размеры дроплетов, которые можно использовать при их создании.
Теперь, когда вы немного знаете об API, давайте перейдем к нашему собственному приложению.
Настройка ключей доступа
Чтобы использовать API, вам необходимо активировать токены персонального доступа для своей учетной записи. Войдите в свою учетную запись и зайдите на страницу настроек приложения: https://cloud.digitalocean.com/settings/applications. Нажмите Создать новый токен, как показано ниже:



Обратите внимание на токен доступа ниже - Digital Ocean покажет вам только один раз:



Теперь давайте перейдем к нашему тестовому консольному приложению.
Консольное приложение
В этом уроке мы рассмотрим небольшое консольное приложение, которое я построил и которое выполняет несколько задач, связанных с управлением дроплетов. Вы можете установить приложение самостоятельно из репозитория Tuts + GitHub, а также настроить или расширить его для реализации дополнительных возможностей API. Я разместил подробное руководство по установке консольного приложения на моем веб-сайте. Вы также можете ознакомиться с моим общим руководством по установке приложений Digital Ocean.
Настройка доступа к API
Опять же, мы используем библиотеку Digital Ocean V2 PHP API Library для доступа к API.
Мы создали компонент под названием Ocean.php, который выступает в качестве модели для использования этой библиотеки. Он находится в /app/protected/components/Ocean.php
.
Yii загружает токен доступа из файла Ocean.ini, описанный в Руководстве по установке приложений для Digital Ocean Console, и создает экземпляр объекта API - digitalOcean
.
1 |
<?php
|
2 |
|
3 |
use DigitalOceanV2\Adapter\BuzzAdapter; |
4 |
use DigitalOceanV2\DigitalOceanV2; |
5 |
|
6 |
class Ocean extends CComponent |
7 |
{
|
8 |
private $adapter; |
9 |
private $digitalOcean; |
10 |
|
11 |
function __construct() { |
12 |
// create an adapter with your access token which can be
|
13 |
// generated at https://cloud.digitalocean.com/settings/applications
|
14 |
$this->adapter = new BuzzAdapter(Yii::app()->params['ocean']['access_key']); |
15 |
// create a digital ocean object with the previous adapter
|
16 |
$this->digitalOcean = new DigitalOceanV2($this->adapter); |
17 |
}
|
Получение дроплетов



Теперь давайте получим список наших активных дроплетов. В /app/protected/models/Droplet.php
наш метод sync
вызывает компоненты Ocean и получает дроплеты:
1 |
public function sync() { |
2 |
$ocean = new Ocean(); |
3 |
$droplets = $ocean->getDroplets(); |
4 |
foreach ($droplets as $d) { |
5 |
$droplet_id = $this->add($d); |
6 |
}
|
7 |
}
|
Вот как выглядит метод getDroplets Ocean:
1 |
public function getDroplets() { |
2 |
// return the action api
|
3 |
$action = $this->digitalOcean->droplet(); |
4 |
// return a collection of Action entity
|
5 |
$actions = $action->getAll(); |
6 |
return $actions; |
7 |
}
|
Примечание: основное консольное приложение просто выполняет синхронизацию загрузки дроплетов в одностороннем режиме. Вы можете реализовать больше возможностей самостоятельно, включая удаление дроплетов, которые были удалены в облаке.
Вот наша функция add
. Если дроплет уже существует, мы просто обновляем запись:
1 |
public function add($droplet) { |
2 |
$d = Droplet::model()->findByAttributes(array('droplet_id'=>$droplet->id)); |
3 |
if (empty($d)) { |
4 |
$d = new Droplet; |
5 |
}
|
6 |
$d->user_id = Yii::app()->user->id; |
7 |
$d->droplet_id = $droplet->id; |
8 |
$d->name = $droplet->name; |
9 |
$d->vcpus = $droplet->vcpus; |
10 |
$d->memory = $droplet->memory; |
11 |
$d->disk = $droplet->disk; |
12 |
$d->status = $droplet->status; |
13 |
$d->active =1; |
14 |
$d->created_at = $d->created_at; |
15 |
$d->modified_at =new CDbExpression('NOW()'); |
16 |
$d->save(); |
17 |
return $d->id; |
18 |
}
|
Если вы хотите расширить возможности модели, Digital Ocean предлагает широкий спектр действий API Droplet, и у Corcy есть список наглядных примеров.
Получение образов
Затем мы будем использовать API для получения списка наших текущих образов. Образы представляют собой моментальные снимки, в основном резервные копии, взятые из экземпляра сервера в данный момент времени.



Наша модель Snapshot.php имеет операцию sync
, которая запрашивает список ваших образов и добавляет их отдельно в базу данных:
1 |
public function sync() { |
2 |
$ocean = new Ocean(); |
3 |
$snapshots = $ocean->getSnapshots(); |
4 |
foreach ($snapshots as $i) { |
5 |
$image_id = $this->add($i); |
6 |
if ($image_id!==false) { |
7 |
echo $image_id;lb(); |
8 |
pp($i); |
9 |
}
|
10 |
}
|
11 |
}
|
Вот код getSnapshots
компонента Ocean:
1 |
public function getSnapshots() { |
2 |
// return the action api
|
3 |
$action = $this->digitalOcean->image(); |
4 |
// return a collection of Action entity
|
5 |
$actions = $action->getAll(); |
6 |
return $actions; |
7 |
}
|
Вот код метода add
модели Snapshot - мы игнорируем образы приложений Digital Ocean, которые помечены как общедоступные:
1 |
public function add($snapshot) { |
2 |
$i = Snapshot::model()->findByAttributes(array('image_id'=>$snapshot->id)); |
3 |
if (empty($i)) { |
4 |
$i = new Snapshot; |
5 |
$i->created_at =new CDbExpression('NOW()'); |
6 |
}
|
7 |
if (isset($snapshot->public) and $snapshot->public ==1) { |
8 |
return false; // no need to save public images right now |
9 |
} else |
10 |
$i->user_id = Yii::app()->user->id; |
11 |
$i->image_id = $snapshot->id; |
12 |
$i->name = $snapshot->name; |
13 |
$i->region = $snapshot->regions[0]; |
14 |
$i->active =1; |
15 |
$i->modified_at =new CDbExpression('NOW()'); |
16 |
$i->save(); |
17 |
return $i->id; |
18 |
}
|
Автоматизация создания снимков
Как мы обсуждали в создании образа приложения для перепродажи в Digital Ocean, полезно автоматизировать создание моментальных снимков, которые вы можете передать своим клиентам. К сожалению, в настоящее время нет способа клонировать или передавать образ по ссылке; каждый раз, когда вы переносите моментальный снимок на другой аккаунт.
Поскольку Digital Ocean требует, чтобы вы создавали изображение как дроплет и отключили его, прежде чем делать новый снимок, повторное создание моментальных снимков - это трудоемкий ручной процесс. Это не помогает тому, что Digital Ocean возобновляет дроплеты после снимков - это просто замедляет процесс.
Поскольку API не принимает запросы во время ожидания других операций, мы должны создать таблицу для отслеживания фоновых действий и использовать задание cron для повторного отключения питания, операции моментального снимка. Вот как это работает:
Перейдите на страницу Images и нажмите View для моментального снимка, который вы хотите клонировать. Затем нажмите кнопку Replicate справа.



Это создаст дроплет и добавит запись в таблицу Action с этим image_id
и droplet_id
. end_stage
- это константа, которую вы можете установить, указывая количество создаваемых дубликатов.



Ниже приведен метод replicate()
модели Snapshot:
1 |
public function replicate($id) { |
2 |
// look up image_id
|
3 |
$snapshot = Snapshot::model()->findByAttributes(array('id'=>$id)); |
4 |
// create the droplet
|
5 |
$ocean = new Ocean(); |
6 |
$droplet_id = $ocean->launch_droplet($snapshot->name,$snapshot->region,$snapshot->image_id); |
7 |
// add command to action table with droplet_id and image_id
|
8 |
$a = new Action(); |
9 |
$a->droplet_id = $droplet_id; |
10 |
$a->snapshot_id = $snapshot->image_id; |
11 |
$a->action = Action::ACTION_SNAPSHOT; |
12 |
$a->status = Action::STATUS_ACTIVE; |
13 |
$a->stage = 0; |
14 |
// user settable constant for number of replications to make
|
15 |
$a->end_stage = Snapshot::NUMBER_REPLICATIONS; |
16 |
$a->last_checked = 0; |
17 |
$a->modified_at =new CDbExpression('NOW()'); |
18 |
$a->created_at =new CDbExpression('NOW()'); |
19 |
$a->save(); |
20 |
}
|
Задача cron будет выполнять ping http://ocean.yourdomain.com/daemon/index для регулярной обработки таблицы действий. Любые незавершенные просроченные записи запросят другой снимок.
Вот метод process()
модели Action:
1 |
public function process() { |
2 |
set_time_limit(0); |
3 |
// look for overdue actions
|
4 |
$todo = Action::model()->overdue()->findAllByAttributes(array('status'=>self::STATUS_ACTIVE)); |
5 |
foreach ($todo as $item) { |
6 |
if ($item->action == self::ACTION_SNAPSHOT) { |
7 |
$result = Snapshot::model()->take($item->id); |
8 |
}
|
9 |
}
|
10 |
}
|
Процесс моментального снимка отключит дроплеты, подождите 20 секунд, чтобы дождаться завершения и запросить моментальный снимок.



Вот метод take()
модели Snapshot:
1 |
public function take($action_id) { |
2 |
$result = false; |
3 |
$a = Action::model()->findByPk($action_id); |
4 |
$snapshot = Snapshot::model()->findByAttributes(array('image_id'=>$a->snapshot_id)); |
5 |
$ocean = new Ocean(); |
6 |
// attempt shutdown
|
7 |
// take snapshot
|
8 |
$result = $ocean->snapshot($a->stage,$a->droplet_id,$snapshot->name,$snapshot->region,$snapshot->image_id); |
9 |
// if snapshot was successful
|
10 |
if ($result) { |
11 |
// increment stage
|
12 |
$a->stage+=1; |
13 |
// if last snapshot replication complete, end action
|
14 |
if ($a->stage >= $a->end_stage) |
15 |
$a->status = Action::STATUS_COMPLETE; |
16 |
}
|
17 |
// either way, update last_checked
|
18 |
$a->last_checked = time(); |
19 |
$a->save(); |
20 |
return $result; |
21 |
}
|
Вот код в компоненте Ocean для фактического вызова API:
1 |
public function snapshot($stage,$droplet_id,$name,$region,$image_id,$begin=1,$count=3,$size='512mb') { |
2 |
$no_sleep = false; |
3 |
$name = str_replace("_","-",$name); |
4 |
$droplet = $this->digitalOcean->droplet(); |
5 |
try { |
6 |
echo 'Shutting down '.$droplet_id;lb(); |
7 |
$shutdown = $droplet->shutdown($droplet_id); |
8 |
} catch (Exception $e) { |
9 |
$err = $e->getMessage(); |
10 |
echo 'Caught exception: ', $e->getMessage(), "\n"; |
11 |
if (stristr ( $err , 'already powered off')===false) |
12 |
return false; |
13 |
else
|
14 |
$no_sleep = true; |
15 |
}
|
16 |
if (!$no_sleep) { |
17 |
echo 'Sleep 20 seconds for power off...';lb(); |
18 |
sleep(20); |
19 |
}
|
20 |
echo 'Take snapshot of '.$droplet_id.' named '.$name.'-copy-'.$stage;lb(); |
21 |
try { |
22 |
$snapshot = $droplet->snapshot($droplet_id, $name.'-copy-'.$stage); |
23 |
} catch (Exception $e) { |
24 |
echo 'Caught exception: ', $e->getMessage(), "\n"; |
25 |
return false; |
26 |
}
|
27 |
// shutdown and snapshot successful
|
28 |
return true; |
29 |
}
|
Если вы посетите веб-сайт Digital Ocean для просмотра дроплета, вы увидите текущее действие:



Если моментальный снимок будет успешным, он вернется модели Snapshot. Когда количество повторений этапа репликации завершено, считаем действие завершенным.
Вы можете посетить страницу Images на веб-сайте Digital Ocean, чтобы увидеть ваши реплицированные снимки:



После создания изображений вы можете удалить дроплет вручную - или вы можете расширить код и сделать это, когда STATUS_COMPLETE
будет достигнут. Если вы не удалите дроплет, то с вас за это снимут деньги.
Обратите внимание, что в настоящее время API не предлагает возможность отправки моментального снимка на адрес электронной почты, поэтому вам нужно будет продолжать делать это вручную через веб-интерфейс.
Что дальше?
Я надеюсь, что вам понравилось это руководство и вы считаете, что Digital Ocean может быть полезным сервисом в вашем портфеле инструментов и хостинг-провайдеров. В следующем уроке мы рассмотрим службу Digital Ocean DNS.
Пожалуйста, не стесняйтесь оставлять свои вопросы и комментарии ниже. Вы также можете связаться со мной в Twitter @reifman или отправить мне электронное письмо. Следите за моей страницей инструктора Tuts +, чтобы найти будущие статьи этой серии.