Использование утилиты Cloudmonkey для взаимодействия с облаком Cloud2 через API

В основе облака Cloud2 лежит открытый продукт Cloudstack. Использовать Cloudstack можно как через Web UI, так и с помощью других инструментов, которые используют API платформы для взаимодействия с ней. На сегодняшний день широко распространены четыре интерфейса, которые хорошо поддерживают Cloudstack:

  • RESTful API, который лежит в основе всего и может использоваться из любой среды разработки;
  • утилита командной строки Cloudmonkey, которая позволяет взаимодействовать с платформой с помощью консоли;
  • пакет CS для Python;
  • система программно определяемого конфигурирования Ansible.

В этой статье мы рассмотрим интерфейс командной строки Cloudmonkey, который может широко использоваться как в качестве замены Web UI, так и для решений автоматизации операций.

Настройка Cloudmonkey

Существует две версии Cloudmonkey — старая, которая использует Python, и новая, которая переписана на Go. В данном руководстве мы будем использовать новую версию пакета.

Для начала утилиту необходимо скачать для вашей платформы. На данный момент актуальна утилита версии 6.0:

Рассмотрим пример установки и проверки работоспособности для ОС Linux:

$ sudo wget -O /usr/local/bin/cmk https://github.com/apache/cloudstack-cloudmonkey/releases/download/6.0.0/cmk.linux.x86-64

$ sudo chmod 755 /usr/local/bin/cmk

$ cmk -v

Apache CloudStack 🐵 CloudMonkey 6.0.0 (build: 74ff37c, 2019-03-05T17:27:26+0530)

Следующим шагом необходимо установить корректные настройки в файле конфигурации утилиты, расположенном по пути ~/.cmk/config.

$ cat ~/.cmk/config 
prompt          = 🐱
asyncblock      = true
timeout         = 1800
output          = json
paramcompletion = true
verifycert      = true
profile         = localcloud

[localcloud]
url       = http://localhost:8080/client/api
username  = admin
password  = password
domain    = /
apikey    = 
secretkey = 

Вам необходимо изменить ряд полей в файле конфигурации:

  • localcloud.url заполнить https://ru.cloud-2.io/client/api
  • localcloud.username заполнить выданным вам именем, которым вы пользуетесь для входа в аккаунт;
  • localcloud.password заполнить выданным вам паролем;
  • localcloud.domain заполнить выданным вам доменом.

Опционально вы можете изменить следующие параметры:

  • prompt, если вам не надо лишних котиков в выводе;
  • output, который определяет в каком виде подаются данные запросов: json, text, table, column, csv

Если вы не хотите указывать пароль пользователя, предпочитая использовать ApiKey, SecretKey, вы можете найти эти данные в интерфейсе:

В результате, ваш конфигурационный файл примет вид, похожий на следующий:

prompt          = 🐱
asyncblock      = true
timeout         = 1800
output          = json
paramcompletion = true
verifycert      = true
profile         = localcloud

[localcloud]
url       = https://ru.cloud-2.io/client/api
username  = user1234
password  = secret
domain    = /premium
apikey    = 
secretkey = 

Проверим работоспособность утилиты:

$ cmk sync
Discovered 145 APIs

$ cmk list users
{
  "count": 1,
  "user": [
    {
      "account": "user1234",
      "accountid": "255b9ca4-be97-4d0a-b9a0-7986dffc4541",
      "accounttype": 0,
      "apikey": "secret",
      "created": "2019-07-26T11:22:54+0700",
      "domain": "premium",
      "domainid": "3a64a197-d74c-4b63-a1b1-3e1487de13fc",
      "email": "user@host.com",
      "firstname": "user1234",
      "id": "6ca6e6b2-dac5-458e-8d55-0b1002194595",
      "iscallerchilddomain": false,
      "isdefault": false,
      "lastname": "premium",
      "roleid": "a12d96f4-5b63-4d75-b092-b4248a9d50df",
      "rolename": "domainuser",
      "roletype": "User",
      "state": "enabled",
      "timezone": "Asia/Novosibirsk",
      "username": "user1234",
      "usersource": "native"
    }
  ]
}

Если вам удалось выполнить предыдущие вызовы успешно, значит, утилита успешно настроена.

Работа в интерактивном режиме

Если вы запустите cmk без аргументов, утилита перейдет в интерактивный режим, где вы можете вводить команды и получать ответы на них:

С помощью нажатия на Tab, вы можете получить подсказки для взаимодействия с системой и перемещаться по командам.

Работа в командном режиме

В командном режиме вы можете указывать действия как аргументы командной строки. Этот режим наиболее удобен для решения задач автоматизации:

$ cmk list virtualmachines filter=id,name,displayname,cpunumber,memory
{
  "count": 2,
  "virtualmachine": [
    {
      "cpunumber": 4,
      "displayname": "host-1",
      "id": "bbd73851-01fd-46df-a483-e1fa008007f8",
      "memory": 8192,
      "name": "vm-bbd73851-01fd-46df-a483-e1fa008007f8"
    },
    {
      "cpunumber": 4,
      "displayname": "host-2",
      "id": "1a249b1d-a416-42da-8161-781970399ad2",
      "memory": 8192,
      "name": "vm-1a249b1d-a416-42da-8161-781970399ad2"
    }
  ]
}

Для успешного использования утилиты важно понимать каким образом используется Cloudstack API. Далее мы рассмотрим несколько примеров того, как использовать утилиту для решения конкретных задач.

Создание виртуальной машины

Просмотрим список доступных рекомендованных шаблонов для Ubuntu Linux:

(localcloud) 🐱 > list templates templatefilter=featured filter=id,name keyword=ubuntu
{
  "count": 4,
  "template": [
    {
      "id": "dfd5bec6-8580-4a9b-b92f-d98ff1987e94",
      "name": "docker-ce-ubuntu-1804"
    },
    {
      "id": "9689ca4f-e5d4-49d6-932d-a3c879a88363",
      "name": "ubuntu-1804-IAC"
    },
    {
      "id": "365a7ea2-7e84-4831-b0a5-9454507f3968",
      "name": "ubuntu-1804-np-nolvm-10gb"
    },
    {
      "id": "8f10ba65-7296-41d6-ba13-023ed6e8b90e",
      "name": "ubuntu-1604-np-nolvm-10gb"
    }
  ]
}

Просмотрим доступный список зон:

(localcloud) 🐱 > list zones filter=id,name
{
  "count": 1,
  "zone": [
    {
      "id": "d477bb3f-3592-4503-8f2a-da3d878dd476",
      "name": "Tomsk"
    }
  ]
}
(localcloud) 🐱 > list serviceofferings filter=id,name
{
  "count": 12,
  "serviceoffering": [
    {
      "id": "f97089b2-1fe5-41d1-8609-ee321cc4e659",
      "name": "small.1c1g"
    },
    {
      "id": "42478074-4e32-4b5e-a42c-40ef71192aad",
      "name": "small.2c2g"
    },
    {
      "id": "e8a91e0b-c1b2-4af7-85ce-78d7655335f6",
      "name": "highcpu.2c4g"
    },
    {
      "id": "b4ce56c0-173f-498d-8fc6-73a83d931b72",
      "name": "highcpu.4c8g"
    },
    {
      "id": "00edbd5a-5ee3-4e69-a1ab-60903ba288c3",
      "name": "highcpu.4c12g"
    },
    {
      "id": "6cf86f10-b6a8-4e3c-b4d3-0eca4eac2ab7",
      "name": "highcpu.4c16g"
    },
    {
      "id": "36ee5c32-8729-4096-af39-6175a9eecb3d",
      "name": "highcpu.6c24g"
    },
    {
      "id": "b3f828d7-4082-4a3b-8664-f537d85a4278",
      "name": "highcpu.8c32g"
    },
    {
      "id": "974bfe18-9c6a-47f1-aa03-db7f95241e8f",
      "name": "highcpu.12c48g"
    },
    {
      "id": "3756e673-3ed5-4cd9-8751-5b432e07c044",
      "name": "highcpu.16c64g"
    },
    {
      "id": "8e565f94-a6b5-4f36-a5dc-a061663ec605",
      "name": "highcpu.24c96g"
    },
    {
      "id": "347ce165-fe04-4f95-a449-59c4263fec58",
      "name": "highcpu.32c128g"
    }
  ]
}

Определим, какой у аккаунта UUID домена:

(localcloud) 🐱 > list accounts filter=domainid
{
  "account": [
    {
      "domainid": "3a64a197-d74c-4b63-a1b1-3e1487de13fc"
    }
  ],
  "count": 1
}

Определим данные группы безопасности:

(localcloud) 🐱 > list securitygroups filter=id,name
{
  "count": 1,
  "securitygroup": [
    {
      "id": "34651333-a7f6-4332-b8a5-143fc4922910",
      "name": "default"
    }
  ]
}

Создадим виртуальную машину (переносы сделаны для лучшей читаемости команды):

(localcloud) 🐱 > deploy virtualmachine 
           displayname=vm 
           serviceofferingid=f97089b2-1fe5-41d1-8609-ee321cc4e659 
           zoneid=d477bb3f-3592-4503-8f2a-da3d878dd476 
           templateid=365a7ea2-7e84-4831-b0a5-9454507f3968 
           securitygroupids=34651333-a7f6-4332-b8a5-143fc4922910

после некоторого ожидания:

{
  "virtualmachine": {
    "account": "cloud2test17180",
    "affinitygroup": [],
    "cpunumber": 1,
    "cpuspeed": 2000,
    "created": "2019-10-09T13:00:59+0700",
    "details": {
      "cpuOvercommitRatio": "100",
      "memoryOvercommitRatio": "1.0",
      "rootDiskController": "scsi"
    },
    "displayname": "vm",
    "domain": "premium",
    "domainid": "3a64a197-d74c-4b63-a1b1-3e1487de13fc",
    "guestosid": "b795fd32-c69b-11e7-bdcf-0242ac110004",
    "haenable": false,
    "hypervisor": "KVM",
    "id": "0debc6b9-eea0-4b47-aed6-bc5447abde47",
    "isdynamicallyscalable": false,
    "jobid": "ee54936b-b980-495d-aa3f-dbb9039af5fd",
    "jobstatus": 0,
    "memory": 1024,
    "name": "vm-0debc6b9-eea0-4b47-aed6-bc5447abde47",
    "nic": [
      {
        "broadcasturi": "vlan://untagged",
        "extradhcpoption": [],
        "gateway": "176.120.28.1",
        "id": "8be34b40-94f7-4858-b0c0-ac52c9ce574d",
        "ip6address": "2001:67c:20dc:1c00:1c00:c9ff:fe00:2da",
        "ip6cidr": "2001:67C:20DC:1C00::/64",
        "ip6gateway": "2001:67C:20DC:1C00::1",
        "ipaddress": "176.120.29.221",
        "isdefault": true,
        "macaddress": "1e:00:c9:00:02:da",
        "netmask": "255.255.254.0",
        "networkid": "23439a1d-b48b-4f9b-ba1d-ab8e696124c2",
        "networkname": "defaultGuestNetwork",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Shared"
      }
    ],
    "ostypeid": 256,
    "password": "W8tHfX",
    "passwordenabled": true,
    "rootdeviceid": 0,
    "rootdevicetype": "ROOT",
    "securitygroup": [
      {
        "account": "cloud2test17180",
        "description": "Default Security Group",
        "egressrule": [],
        "id": "34651333-a7f6-4332-b8a5-143fc4922910",
        "ingressrule": [],
        "name": "default",
        "tags": [],
        "virtualmachineids": []
      }
    ],
    "serviceofferingid": "f97089b2-1fe5-41d1-8609-ee321cc4e659",
    "serviceofferingname": "small.1c1g",
    "state": "Running",
    "tags": [],
    "templatedisplaytext": "Ubuntu 18.04 Server NoLVM 64-bit (31052019-1902)",
    "templateid": "365a7ea2-7e84-4831-b0a5-9454507f3968",
    "templatename": "ubuntu-1804-np-nolvm-10gb",
    "userid": "e3db5dab-f855-402b-bb44-552e6f068ce4",
    "username": "cloud2test17180",
    "zoneid": "d477bb3f-3592-4503-8f2a-da3d878dd476",
    "zonename": "Tomsk"
  }
}

Обратите внимание на поле password, где возвращается пароль к созданной машине.

Останов виртуальной машины

(localcloud) 🐱 > list virtualmachines filter=id,displayname
{
  "count": 1,
  "virtualmachine": [
    {
      "displayname": "vm",
      "id": "0debc6b9-eea0-4b47-aed6-bc5447abde47"
    }
  ]
}
(localcloud) 🐱 > stop virtualmachine id=0debc6b9-eea0-4b47-aed6-bc5447abde47

Запуск виртуальной машины

(localcloud) 🐱 > start virtualmachine id=0debc6b9-eea0-4b47-aed6-bc5447abde47

Удаление виртуальной машины

(localcloud) 🐱 > expunge virtualmachine id=0debc6b9-eea0-4b47-aed6-bc5447abde47

Самый простой способ понять как использовать тот или иной вызов API — чтение документации и анализ запросов Web UI с помощью средств браузера.