OpenStack CLI

V předchozí části labu jsme se soustředili na ovládání skrze grafické rozhraní. Proč tedy vůbec má smysl znát příkazovou řádku?

  • Příkazová řádka je open source a využívá OpenStack API, takže funguje stejně v různých modifikací OpenStack od různých výrobců – to co se naučíte se vám hodí v mnoha situacích

  • V některých operacích je příkazová řádka rychlejší

  • Ovládat infrastrukturu můžete i z minimálního systému bez grafického prostředí

  • Příkazy můžete skriptovat, tedy vytvářet jednoduché „aplikace“, které dávkovým způsobem budou provádět nějaké operace nebo provádět pravidelné záležitosti (například sestavíte nějaké demo prostředí, které dáte k rozbití a po ukončení takové session skriptem vrátíte demo do původního stavu)

  • Některé funkce jsou dostupné pouze tímto způsobem – běžný vývoj je, že nová funkce je jako první k dispozici v příkazové řádce a později v grafickém interface

Pokročilejší uživatel by tedy měl CLI znát, stojí to za to.

Příkazová řádka OpenStack je implementovaná jako Python aplikace, kterou můžete nainstalovat prakticky kamkoli - v našem případě je pro vás připravena na labServer. Historicky měl každý projekt svou vlastní aplikaci. Pro práci se servery jse volali „nova“, pro storage „cinder“, pro image „glance“ a tak dál. V tuto chvíli HPE a komunita pracuje na novém moderním integrovaném projektu příkazové řádky, pro který nemusíte znát kódové názvy jednotlivých součástek OpenStack. Naprostou většinu operací už můžete provádět tímto novým způsobem (a tomu se budeme v labu věnovat), ale mohou být stále ještě speciality, pro které použijete původní příkazy (například práce s LBaaS v základním lab guide byla přes příkaz „neutron“). Dá se očevat, že tato univerzální příkazová řádka bude i nadále růst svými vlastnostmi a díky konceptu plug-inů je navíc velmi dobře rozšiřitelná. Přesto některé novější projekty a funkce mohou pro některé operace vyžadovat nativní příkazovou řádku (tedu tu vyvíjenou v rámci konkrétního projektu).

Abychom nemuseli neustále dokola zadávat komunikační parametry jako je login do OpenStack, uložíme si je do proměnných prostředí. Ve vašem domovském adresáři na labServer je pro vás připraven soubor stack, který to udělá (klidně si ho prohlédněte). Načtěte ho do prostředí.

    tomas@labserver:~$ source stack

Příkazy vždy začínají slovem openstack, pak následuje podstatné jméno (s čím chcete něco dělat) a sloveso (co s tím chcete dělat) a pak případné další detaily. Vypište si seznam možných příkazů.

    tomas@labserver:~$ openstack --help

    usage: openstack [--version] [-v | -q] [--log-file LOG_FILE] [-h] [--debug]

    ...

    Command-line interface to the OpenStack APIs

    optional arguments:

    ...

    Commands:

      access token create  Create an access token

      aggregate add host  Add host to aggregate

      ...

      server add security group  Add security group to server

      server add volume  Add volume to server

      server create  Create a new server

      server delete  Delete server(s)

      server dump create  Create a dump file in server(s)

      server image create  Create a new disk image from a running server

      server list    List servers

      server lock    Lock server(s). A non-admin user will not be able to execute actions

      server migrate  Migrate server to different host

      server pause   Pause server(s)

      server reboot  Perform a hard or soft server reboot

      server rebuild  Rebuild server

      server remove security group  Remove security group from server

      server remove volume  Remove volume from server

      server rescue  Put server in rescue mode

      server resize  Scale server to a new flavor

      server restore  Restore server(s)

      server resume  Resume server(s)

      server set     Set server properties

      server shelve  Shelve server(s)

      server show    Show server details

      server ssh     SSH to server

      server start   Start server(s).

      server stop    Stop server(s).

      server suspend  Suspend server(s)

      server unlock  Unlock server(s)

      server unpause  Unpause server(s)

      server unrescue  Restore server from rescue mode

      server unset   Unset server properties

      server unshelve  Unshelve server(s)

      ...

      zone transfer request show  Show Zone Transfer Request Details

Nebo (a to budeme v našem labu preferovat) zadáte příkaz rovnou celý. Takhle si tedy vypíšeme nám dostupné Flavors.

    tomas@labserver:~$ openstack flavor list

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | ID                                   | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | 1                                    | m1.tiny   |   512 |    1 |         0 |     1 | True      |

    | 2                                    | m1.small  |  2048 |   20 |         0 |     1 | True      |

    | 3                                    | m1.medium |  4096 |   40 |         0 |     2 | True      |

    | 3ef6acf8-b0ae-45d0-ae0f-990b956aaa79 | l1.medium |  4096 |   10 |         0 |     2 | True      |

    | 4                                    | m1.large  |  8192 |   80 |         0 |     4 | True      |

    | 5                                    | m1.xlarge | 16384 |  160 |         0 |     8 | True      |

    | e81cf7b8-0c43-4114-a5ef-f4e56316dc0e | l1.small  |  2048 |    5 |         0 |     1 | True      |

    | fc17693b-ff34-4b23-98a6-acebc7da5ce3 | web.tiny  |   512 |    5 |         0 |     1 | True      |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

A pokud nás zajímají detaily některého z nich, použijeme show.

    tomas@labserver:~$ openstack flavor show m1.medium

    +----------------------------+-----------+

    | Field                      | Value     |

    +----------------------------+-----------+

    | OS-FLV-DISABLED:disabled   | False     |

    | OS-FLV-EXT-DATA:ephemeral  | 0         |

    | disk                       | 40        |

    | id                         | 3         |

    | name                       | m1.medium |

    | os-flavor-access:is_public | True      |

    | properties                 |           |

    | ram                        | 4096      |

    | rxtx_factor                | 1.0       |

    | swap                       |           |

    | vcpus                      | 2         |

    +----------------------------+-----------+

Pokud si chcete nechat poradit, použijte help.

    tomas@labserver:~$ openstack help image list

    usage: openstack image list [-h] [-f {csv,json,table,value,yaml}] [-c COLUMN]

                                [--max-width <integer>] [--noindent]

                                [--quote {all,minimal,none,nonnumeric}]

                                [--public | --private | --shared]

                                [--property <key=value>] [--long]

                                [--sort <key>[:<direction>]] [--limit <limit>]

                                [--marker <marker>]

    List available images

    optional arguments:

      -h, --help            show this help message and exit

      --public              List only public images

      --private             List only private images

      --shared              List only shared images

      --property <key=value>

                            Filter output based on property

      --long                List additional fields in output

      --sort <key>[:<direction>]

                            Sort output by selected keys and directions(asc or

                            desc) (default: asc), multiple keys and directions can

                            be specified separated by comma

      --limit <limit>       Maximum number of images to display.

      --marker <marker>     The last image (name or ID) of the previous page.

                            Display list of images after marker. Display all

                            images if not specified.

    output formatters:

      output formatter options

      -f {csv,json,table,value,yaml}, --format {csv,json,table,value,yaml}

                            the output format, defaults to table

      -c COLUMN, --column COLUMN

                            specify the column(s) to include, can be repeated

    table formatter:

      --max-width <integer>

                            Maximum display width, 0 to disable

    json formatter:

      --noindent            whether to disable indenting the JSON

    CSV Formatter:

      --quote {all,minimal,none,nonnumeric}

                            when to include quotes, defaults to nonnumeric

Můžete volit různé formátování výstupu, zobrazovat jen některé sloupce apod.

    tomas@labserver:~$ openstack image list --max-width 40

    +--------------------------------------+--------------+--------+

    | ID                                   | Name         | Status |

    +--------------------------------------+--------------+--------+

    | acc333be-44f7-48fe-962d-4bcd96c7800e | CentOS 6     | active |

    | fe14d439-75af-45d0-9084-08479e4a58c8 | web-server   | active |

    | 61de0c96-c30b-4207-924a-bb9188448878 | mujImage     | active |

    | 73fd1e9e-9370-4dc1-ac06-a6a9a598df14 | CoreOS       | active |

    | 767ec27b-0eed-43ea-9631-9115aaa78f05 | Stackato     | active |

    | bb0eba2a-6ce1-4393-b89f-4a219add5da7 | Ubutnu_14.04 | active |

    | e9664fca-74b0-4a59-95e9-87a1a844d031 | Cirros       | active |

    | 04d32087-6a66-4d04-8481-cdb3b8b472a3 | Ubuntu_16.04 | active |

    +--------------------------------------+--------------+--------+

    tomas@labserver:~$ openstack image list -f yaml

    - ID: acc333be-44f7-48fe-962d-4bcd96c7800e

      Name: CentOS 6

      Status: active

    - ID: fe14d439-75af-45d0-9084-08479e4a58c8

      Name: web-server

      Status: active

    - ID: 61de0c96-c30b-4207-924a-bb9188448878

      Name: mujImage

      Status: active

    - ID: 73fd1e9e-9370-4dc1-ac06-a6a9a598df14

      Name: CoreOS

      Status: active

    - ID: 767ec27b-0eed-43ea-9631-9115aaa78f05

      Name: Stackato

      Status: active

    - ID: bb0eba2a-6ce1-4393-b89f-4a219add5da7

      Name: Ubutnu_14.04

      Status: active

    - ID: e9664fca-74b0-4a59-95e9-87a1a844d031

      Name: Cirros

      Status: active

    - ID: 04d32087-6a66-4d04-8481-cdb3b8b472a3

      Name: Ubuntu_16.04

      Status: active

    tomas@labserver:~$ openstack image list -f csv

    "ID","Name","Status"

    "acc333be-44f7-48fe-962d-4bcd96c7800e","CentOS 6","active"

    "fe14d439-75af-45d0-9084-08479e4a58c8","web-server","active"

    "61de0c96-c30b-4207-924a-bb9188448878","mujImage","active"

    "73fd1e9e-9370-4dc1-ac06-a6a9a598df14","CoreOS","active"

    "767ec27b-0eed-43ea-9631-9115aaa78f05","Stackato","active"

    "bb0eba2a-6ce1-4393-b89f-4a219add5da7","Ubutnu_14.04","active"

    "e9664fca-74b0-4a59-95e9-87a1a844d031","Cirros","active"

    "04d32087-6a66-4d04-8481-cdb3b8b472a3","Ubuntu_16.04","active"

    tomas@labserver:~$ openstack image list -f json

    [

      {

        "Status": "active",

        "ID": "acc333be-44f7-48fe-962d-4bcd96c7800e",

        "Name": "CentOS 6"

      },

      {

        "Status": "active",

        "ID": "fe14d439-75af-45d0-9084-08479e4a58c8",

        "Name": "web-server"

      },

      {

        "Status": "active",

        "ID": "61de0c96-c30b-4207-924a-bb9188448878",

        "Name": "mujImage"

      },

      {

        "Status": "active",

        "ID": "73fd1e9e-9370-4dc1-ac06-a6a9a598df14",

        "Name": "CoreOS"

      },

      {

        "Status": "active",

        "ID": "767ec27b-0eed-43ea-9631-9115aaa78f05",

        "Name": "Stackato"

      },

      {

        "Status": "active",

        "ID": "bb0eba2a-6ce1-4393-b89f-4a219add5da7",

        "Name": "Ubutnu_14.04"

      },

      {

        "Status": "active",

        "ID": "e9664fca-74b0-4a59-95e9-87a1a844d031",

        "Name": "Cirros"

      },

      {

        "Status": "active",

        "ID": "04d32087-6a66-4d04-8481-cdb3b8b472a3",

        "Name": "Ubuntu_16.04"

      }

    ]

    tomas@labserver:~$ openstack image list -f value -c Name

    CentOS 6

    web-server

    mujImage

    CoreOS

    Stackato

    Ubutnu_14.04

    Cirros

    Ubuntu_16.04

    tomas@labserver:~$ openstack image list --property name=Cirros

    +--------------------------------------+--------+--------+

    | ID                                   | Name   | Status |

    +--------------------------------------+--------+--------+

    | e9664fca-74b0-4a59-95e9-87a1a844d031 | Cirros | active |

    +--------------------------------------+--------+--------+

Zkusme nastartovat instanci. Nejprve si zjistěme názvy sítí, klíčů apod.

    tomas@labserver:~$ openstack network list

    +--------------------------------------+---------+--------------------------------------+

    | ID                                   | Name    | Subnets                              |

    +--------------------------------------+---------+--------------------------------------+

    | d4712d32-e929-4c20-9b9c-fe9fe66b85f6 | ext-net | 46c758ce-febc-413d-b2cf-72f45e9df8b0 |

    | e99ab504-8e64-47c7-b33c-3f056a1c6844 | Web-sit | a5f5b1d2-8d0f-4edf-ab07-0717d1277378 |

    | 5431eac3-92cb-4464-8cd2-51ceb6804ed4 | mojeSit | 231efe61-4aa3-45ba-8904-4fdd3b1baabd |

    +--------------------------------------+---------+--------------------------------------+



    tomas@labserver:~$ openstack keypair list

    +---------+-------------------------------------------------+

    | Name    | Fingerprint                                     |

    +---------+-------------------------------------------------+

    | mujKlic | 02:67:48:85:e2:bc:d1:05:f7:35:10:55:57:6d:d4:90 |

    +---------+-------------------------------------------------+



    tomas@labserver:~$ openstack image list --max-width 50

    +--------------------------------------+--------------+--------+

    | ID                                   | Name         | Status |

    +--------------------------------------+--------------+--------+

    | acc333be-44f7-48fe-962d-4bcd96c7800e | CentOS 6     | active |

    | fe14d439-75af-45d0-9084-08479e4a58c8 | web-server   | active |

    | 61de0c96-c30b-4207-924a-bb9188448878 | mujImage     | active |

    | 73fd1e9e-9370-4dc1-ac06-a6a9a598df14 | CoreOS       | active |

    | 767ec27b-0eed-43ea-9631-9115aaa78f05 | Stackato     | active |

    | bb0eba2a-6ce1-4393-b89f-4a219add5da7 | Ubutnu_14.04 | active |

    | e9664fca-74b0-4a59-95e9-87a1a844d031 | Cirros       | active |

    | 04d32087-6a66-4d04-8481-cdb3b8b472a3 | Ubuntu_16.04 | active |

    +--------------------------------------+--------------+--------+



    tomas@labserver:~$ openstack flavor list

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | ID                                   | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+

    | 1                                    | m1.tiny   |   512 |    1 |         0 |     1 | True      |

    | 2                                    | m1.small  |  2048 |   20 |         0 |     1 | True      |

    | 3                                    | m1.medium |  4096 |   40 |         0 |     2 | True      |

    | 3ef6acf8-b0ae-45d0-ae0f-990b956aaa79 | l1.medium |  4096 |   10 |         0 |     2 | True      |

    | 4                                    | m1.large  |  8192 |   80 |         0 |     4 | True      |

    | 5                                    | m1.xlarge | 16384 |  160 |         0 |     8 | True      |

    | e81cf7b8-0c43-4114-a5ef-f4e56316dc0e | l1.small  |  2048 |    5 |         0 |     1 | True      |

    | fc17693b-ff34-4b23-98a6-acebc7da5ce3 | web.tiny  |   512 |    5 |         0 |     1 | True      |

    +--------------------------------------+-----------+-------+------+-----------+-------+-----------+



    tomas@labserver:~$ openstack security group list

    +---------------------------+--------------+---------------------------+---------------------------+

    | ID                        | Name         | Description               | Project                   |

    +---------------------------+--------------+---------------------------+---------------------------+

    | 42fa6ec7-86b2-4ca0-92f8-6 | default      | Default security group    | d2811986367044f9a5d9efa18 |

    | a2c70f2a3a7               |              |                           | 0e746cd                   |

    | 616f4f6f-ba2a-4768-b1f9-3 | WebServery   | Webova farma pro moji     | d2811986367044f9a5d9efa18 |

    | 011e49a7d19               |              | aplikaci                  | 0e746cd                   |

    | 73ead103-f579-4681-9b0a-  | WebFrontend  | Povoleni portu 80 a 443   | d2811986367044f9a5d9efa18 |

    | 652623b49b44              |              |                           | 0e746cd                   |

    | 95e4e1e7-966b-            | SSH+ICMP     | Povoluje SSH přístup a    | d2811986367044f9a5d9efa18 |

    | 4a10-8512-a985a2791229    |              | ICMP                      | 0e746cd                   |

    | b4720c8e-66a6-4964-9ec1-a | MojeAplikace | Skupina aplikacnich       | d2811986367044f9a5d9efa18 |

    | 4c58565b02b               |              | serveru                   | 0e746cd                   |

    +---------------------------+--------------+---------------------------+---------------------------+

Nastartujme dvě instance.

    tomas@labserver:~$ openstack server create serverCLI --image Cirros --flavor m1.tiny --security-group default --key-name mujKlic --nic net-id=5431eac3-92cb-4464-8cd2-51ceb6804ed4 --min 2 --max 2 --max-width 40

    +--------------------------------------+------------------------------------------+

    | Field                                | Value                                    |

    +--------------------------------------+------------------------------------------+

    | OS-DCF:diskConfig                    | MANUAL                                   |

    | OS-EXT-AZ:availability_zone          |                                          |

    | OS-EXT-STS:power_state               | 0                                        |

    | OS-EXT-STS:task_state                | scheduling                               |

    | OS-EXT-STS:vm_state                  | building                                 |

    | OS-SRV-USG:launched_at               | None                                     |

    | OS-SRV-USG:terminated_at             | None                                     |

    | accessIPv4                           |                                          |

    | accessIPv6                           |                                          |

    | addresses                            |                                          |

    | adminPass                            | Wzo6Pvv68bke                             |

    | config_drive                         |                                          |

    | created                              | 2016-07-13T07:34:15Z                     |

    | flavor                               | m1.tiny (1)                              |

    | hostId                               |                                          |

    | id                                   | a6900235-c5f8-4acd-afc1-a37c62b08c6f     |

    | image                                | Cirros (e9664fca-                        |

    |                                      | 74b0-4a59-95e9-87a1a844d031)             |

    | key_name                             | mujKlic                                  |

    | name                                 | serverCLI-1                              |

    | os-extended-volumes:volumes_attached | []                                       |

    | progress                             | 0                                        |

    | project_id                           | d2811986367044f9a5d9efa180e746cd         |

    | properties                           |                                          |

    | security_groups                      | [{u'name': u'default'}]                  |

    | status                               | BUILD                                    |

    | updated                              | 2016-07-13T07:34:15Z                     |

    | user_id                              | d64afca221d64d5cab4592d4dbb3736f         |

    +--------------------------------------+------------------------------------------+

Vypište si servery - zatím se teprve budují.

    tomas@labserver:~$ openstack server list

    +--------------------------------------+-------------+--------+----------------------------------+

    | ID                                   | Name        | Status | Networks                         |

    +--------------------------------------+-------------+--------+----------------------------------+

    | c0736530-0bd1-40b0-952b-c421ab086384 | serverCLI-2 | BUILD  |                                  |

    | a6900235-c5f8-4acd-afc1-a37c62b08c6f | serverCLI-1 | BUILD  |                                  |

    | f5b52c8b-4c0e-4840-b1d5-ff2a42edec7d | mujWEB-2    | ACTIVE | Web-sit=192.168.2.7              |

    | 30640cc6-5494-4d7e-a95a-2afb621929cb | mujWEB-1    | ACTIVE | Web-sit=192.168.2.6, 10.201.0.12 |

    | 0a5b959f-1e6e-4e82-b5dc-c3c74aaa9722 | mojeVM-2    | ACTIVE | mojeSit=192.168.1.3              |

    | 133fbcb2-7e6e-43c9-9b89-00777d823116 | mojeVM-1    | ACTIVE | mojeSit=192.168.1.4              |

    +--------------------------------------+-------------+--------+----------------------------------+

Po chvilce budou nahoře.

    tomas@labserver:~$ openstack server list

    +--------------------------------------+-------------+--------+----------------------------------+

    | ID                                   | Name        | Status | Networks                         |

    +--------------------------------------+-------------+--------+----------------------------------+

    | c0736530-0bd1-40b0-952b-c421ab086384 | serverCLI-2 | ACTIVE | mojeSit=192.168.1.25             |

    | a6900235-c5f8-4acd-afc1-a37c62b08c6f | serverCLI-1 | ACTIVE | mojeSit=192.168.1.24             |

    | f5b52c8b-4c0e-4840-b1d5-ff2a42edec7d | mujWEB-2    | ACTIVE | Web-sit=192.168.2.7              |

    | 30640cc6-5494-4d7e-a95a-2afb621929cb | mujWEB-1    | ACTIVE | Web-sit=192.168.2.6, 10.201.0.12 |

    | 0a5b959f-1e6e-4e82-b5dc-c3c74aaa9722 | mojeVM-2    | ACTIVE | mojeSit=192.168.1.3              |

    | 133fbcb2-7e6e-43c9-9b89-00777d823116 | mojeVM-1    | ACTIVE | mojeSit=192.168.1.4              |

    +--------------------------------------+-------------+--------+----------------------------------+

Vytvořme teď dva volumy ve storage.

    tomas@labserver:~$ openstack volume create volCLI_1 --size 1

    +---------------------+--------------------------------------+

    | Field               | Value                                |

    +---------------------+--------------------------------------+

    | attachments         | []                                   |

    | availability_zone   | nova                                 |

    | bootable            | false                                |

    | consistencygroup_id | None                                 |

    | created_at          | 2016-07-13T07:39:05.764205           |

    | description         | None                                 |

    | encrypted           | False                                |

    | id                  | 703db71c-704e-45c1-9232-370f66d9c2b6 |

    | multiattach         | False                                |

    | name                | volCLI_1                             |

    | properties          |                                      |

    | replication_status  | disabled                             |

    | size                | 1                                    |

    | snapshot_id         | None                                 |

    | source_volid        | None                                 |

    | status              | creating                             |

    | type                | None                                 |

    | user_id             | d64afca221d64d5cab4592d4dbb3736f     |

    +---------------------+--------------------------------------+

    tomas@labserver:~$ openstack volume create volCLI_2 --size 1

    +---------------------+--------------------------------------+

    | Field               | Value                                |

    +---------------------+--------------------------------------+

    | attachments         | []                                   |

    | availability_zone   | nova                                 |

    | bootable            | false                                |

    | consistencygroup_id | None                                 |

    | created_at          | 2016-07-13T07:39:12.881373           |

    | description         | None                                 |

    | encrypted           | False                                |

    | id                  | 23f8e7f6-d20c-4ee4-af91-8926a6ed54f2 |

    | multiattach         | False                                |

    | name                | volCLI_2                             |

    | properties          |                                      |

    | replication_status  | disabled                             |

    | size                | 1                                    |

    | snapshot_id         | None                                 |

    | source_volid        | None                                 |

    | status              | creating                             |

    | type                | None                                 |

    | user_id             | d64afca221d64d5cab4592d4dbb3736f     |

    +---------------------+--------------------------------------+

    tomas@labserver:~$ openstack volume list

    +--------------------------------------+--------------+-----------+------+-------------+

    | ID                                   | Display Name | Status    | Size | Attached to |

    +--------------------------------------+--------------+-----------+------+-------------+

    | 23f8e7f6-d20c-4ee4-af91-8926a6ed54f2 | volCLI_2     | available |    1 |             |

    | 703db71c-704e-45c1-9232-370f66d9c2b6 | volCLI_1     | available |    1 |             |

    +--------------------------------------+--------------+-----------+------+-------------+

A napojme je k serverům.

    tomas@labserver:~$ openstack server add volume serverCLI-1 volCLI_1

    tomas@labserver:~$ openstack server add volume serverCLI-2 volCLI_2

    tomas@labserver:~$ openstack volume list -c 'Display Name' -c 'Attached to'

    +--------------+--------------------------------------+

    | Display Name | Attached to                          |

    +--------------+--------------------------------------+

    | volCLI_2     | Attached to serverCLI-2 on /dev/vdb  |

    | volCLI_1     | Attached to serverCLI-1 on /dev/vdb  |

    +--------------+--------------------------------------+

Teď můžeme třeba přidat pravidlo do Security Group

    tomas@labserver:~$ openstack security group rule list default

    +-----------------------------+-------------+----------+------------+------------------------------+

    | ID                          | IP Protocol | IP Range | Port Range | Remote Security Group        |

    +-----------------------------+-------------+----------+------------+------------------------------+

    | 078835cb-                   | None        | None     |            | 42fa6ec7-86b2-4ca0-92f8-6a2c |

    | 0a46-4d14-bd78-75df9959262f |             |          |            | 70f2a3a7                     |

    | 6799a98d-107c-              | None        | None     |            | None                         |

    | 4c13-bd00-80450acaf4f2      |             |          |            |                              |

    | 9ce1d475-e9d4-4a01-8294-882 | None        | None     |            | None                         |

    | 168bbaab3                   |             |          |            |                              |

    | cfa37ecc-a6ff-48ea-977a-    | None        | None     |            | 42fa6ec7-86b2-4ca0-92f8-6a2c |

    | 137086076f49                |             |          |            | 70f2a3a7                     |

    +-----------------------------+-------------+----------+------------+------------------------------+

    tomas@labserver:~$ openstack security group rule create default --dst-port 22:22

    +-------------------+--------------------------------------+

    | Field             | Value                                |

    +-------------------+--------------------------------------+

    | direction         | ingress                              |

    | ethertype         | IPv4                                 |

    | headers           |                                      |

    | id                | 2b01ea61-a9eb-41e1-b3a2-23e4cd16f1ea |

    | port_range_max    | 22                                   |

    | port_range_min    | 22                                   |

    | project_id        | d2811986367044f9a5d9efa180e746cd     |

    | protocol          | tcp                                  |

    | remote_group_id   | None                                 |

    | remote_ip_prefix  | 0.0.0.0/0                            |

    | security_group_id | 42fa6ec7-86b2-4ca0-92f8-6a2c70f2a3a7 |

    +-------------------+--------------------------------------+

    tomas@labserver:~$ openstack security group rule list default

    +-----------------------------+-------------+-----------+------------+-----------------------------+

    | ID                          | IP Protocol | IP Range  | Port Range | Remote Security Group       |

    +-----------------------------+-------------+-----------+------------+-----------------------------+

    | 078835cb-                   | None        | None      |            | 42fa6ec7-86b2-4ca0-92f8-6a2 |

    | 0a46-4d14-bd78-75df9959262f |             |           |            | c70f2a3a7                   |

    | 2b01ea61-a9eb-              | tcp         | 0.0.0.0/0 | 22:22      | None                        |

    | 41e1-b3a2-23e4cd16f1ea      |             |           |            |                             |

    | 6799a98d-107c-              | None        | None      |            | None                        |

    | 4c13-bd00-80450acaf4f2      |             |           |            |                             |

    | 9ce1d475-e9d4-4a01-8294-882 | None        | None      |            | None                        |

    | 168bbaab3                   |             |           |            |                             |

    | cfa37ecc-a6ff-48ea-977a-    | None        | None      |            | 42fa6ec7-86b2-4ca0-92f8-6a2 |

    | 137086076f49                |             |           |            | c70f2a3a7                   |

    +-----------------------------+-------------+-----------+------------+-----------------------------+

A na závěr pojďme instance i volume smazat a abychom nemuseli vždy obě vypisovat, zkusíme si propojit dva příkazy dohromady přes pipu. Takhle si vypíšeme instance, které obsahují znaky „CLI“.

    tomas@labserver:~$ openstack server list -f value -c Name | grep CLI

    serverCLI-2

    serverCLI-1

Využijme tohoto příkazu uvnitř příkazu na mazání.

    tomas@labserver:~$ openstack server delete $(openstack server list -f value -c Name | grep CLI)

Podobně to můžeme dělat s volume.

    tomas@labserver:~$ openstack volume delete $(openstack volume list -f value -c 'Display Name' | grep CLI)

Shell skriptování

Pokud pracujete s klientem v Linux prostředí můžete vytvářet jednoduché skripty pro bash shell. Na labServeru najdete dva triviální příklady.

První skript vezme slova, která mu předáte a podle toho založí příslušný počet volumů tohoto názvu.

    tomas@labserver:~/bash-cli$ cat vytvorVolume.sh

    for vol in "$@"

    do

        openstack volume create $vol --size 1

    done

Druhý skript si vypíše všechny (! opatrně, ať tam nemáte něco, co chcete zachovat) volumy vašeho tenantu a pak je promaže.

    tomas@labserver:~/bash-cli$ cat smazVsechnyVolume.sh

    for vol in $(openstack volume list -f value -c ID)

    do

       openstack volume delete $vol

    done

    echo Smazano!

Jednoduché ... takhle to vypadá.

    tomas@labserver:~$ cd bash-cli/

    tomas@labserver:~/bash-cli$ chmod +x *

    tomas@labserver:~/bash-cli$ ./vytvorVolume.sh volA volB volC

    +---------------------+--------------------------------------+

    | Field               | Value                                |

    +---------------------+--------------------------------------+

    | attachments         | []                                   |

    | availability_zone   | nova                                 |

    | bootable            | false                                |

    | created_at          | 2015-12-11T11:14:14.281163           |

    | display_description | None                                 |

    | display_name        | volA                                 |

    | encrypted           | False                                |

    | id                  | 2288b737-f03b-4671-981a-0b5773caa857 |

    | multiattach         | false                                |

    | properties          |                                      |

    | size                | 1                                    |

    | snapshot_id         | None                                 |

    | source_volid        | None                                 |

    | status              | creating                             |

    | type                | vsa_thin                             |

    +---------------------+--------------------------------------+

    +---------------------+--------------------------------------+

    | Field               | Value                                |

    +---------------------+--------------------------------------+

    | attachments         | []                                   |

    | availability_zone   | nova                                 |

    | bootable            | false                                |

    | created_at          | 2015-12-11T11:14:15.896893           |

    | display_description | None                                 |

    | display_name        | volB                                 |

    | encrypted           | False                                |

    | id                  | c62c8f11-d475-4ee7-a349-343cff111f84 |

    | multiattach         | false                                |

    | properties          |                                      |

    | size                | 1                                    |

    | snapshot_id         | None                                 |

    | source_volid        | None                                 |

    | status              | creating                             |

    | type                | vsa_thin                             |

    +---------------------+--------------------------------------+

    +---------------------+--------------------------------------+

    | Field               | Value                                |

    +---------------------+--------------------------------------+

    | attachments         | []                                   |

    | availability_zone   | nova                                 |

    | bootable            | false                                |

    | created_at          | 2015-12-11T11:14:17.541467           |

    | display_description | None                                 |

    | display_name        | volC                                 |

    | encrypted           | False                                |

    | id                  | 3baa5b53-54de-46c9-b94c-dbb00930292c |

    | multiattach         | false                                |

    | properties          |                                      |

    | size                | 1                                    |

    | snapshot_id         | None                                 |

    | source_volid        | None                                 |

    | status              | creating                             |

    | type                | vsa_thin                             |

    +---------------------+--------------------------------------+

    +--------------------------------------+--------------+-----------+------+-------------+

    | ID                                   | Display Name | Status    | Size | Attached to |

    +--------------------------------------+--------------+-----------+------+-------------+

    | 3baa5b53-54de-46c9-b94c-dbb00930292c | volC         | available |    1 |             |

    | c62c8f11-d475-4ee7-a349-343cff111f84 | volB         | available |    1 |             |

    | 2288b737-f03b-4671-981a-0b5773caa857 | volA         | available |    1 |             |

    +--------------------------------------+--------------+-----------+------+-------------+

    tomas@labserver:~/bash-cli$ ./smazVsechnyVolume.sh

    Smazano!

    tomas@labserver:~/bash-cli$ openstack volume list

    tomas@labserver:~/bash-cli$

SDK a Python

OpenStack přichází se sadou RESTful API, které můžete využít v jakékoli aplikaci. Toto velmi jednoduché rozhraní využívá principů známých z webové komunikace a nevyžaduje tak žádné speciální binární klienty či knihovny. Aby to bylo ještě jednodušší, existuje řada knihoven přímo pro různé programovací jazyky, která přinese vyšší abstrakce. Protože OpenStack je napsaný v Python, tak knihovna právě pro tento jazyk je velmi dobře zpracována. Pojďme si ji v labu vyzkoušet. Pokud nejste programátoři, nevadí - alespoň nahlédněte do kódu. I na pár řádkách se da udělat něco celkem užitečného a vytvoříte si představu, jak mohou vaši vývojaři jednoduše zakomponovat OpenStack do svých aplikací či webových portálů.

Načtěte si komunikační proměnné, skočte do adresáře python-stack (tam jsou hotové „aplikace“) a učiňte je spustitelnými.

    tomas@labserver:~$ source stack

    tomas@labserver:~$ cd python-stack/

    tomas@labserver:~/python-stack$ chmod +x *

První náš příklad bude jednoduché vypsání serverů, imagů a flavorů do konzole. Prohledněte si obsah souboru vypsat.py. Nejprve si načteme přihlašovací údaje z prostředí a pak provedeme jednoduchý cyklus. Pro každý server, který získáme z kolece všech serverů, vypíšeme jeho jméno. Totéž pro image a flavory. Nic složitého.

Takhle vypadá kód.

    #!/usr/bin/python

    from openstack import connection

    import os

    auth_args = {

        'auth_url': os.environ['OS_AUTH_URL'],

        'project_name': os.environ['OS_PROJECT_NAME'],

        'username': os.environ['OS_USERNAME'],

        'password': os.environ['OS_PASSWORD'],

        'user_domain_id': os.environ['OS_USER_DOMAIN_ID'],

        'project_domain_id': os.environ['OS_PROJECT_DOMAIN_ID'],

    }

    conn = connection.Connection(**auth_args)

    print "Servery:"

    print "--------"

    for server in conn.compute.servers():

        print server.name

    print

    print "Image:"

    print "------"

    for image in conn.compute.images():

        print image.name

    print

    print "Flavor:"

    print "-------"

    for flavor in conn.compute.flavors():

        print flavor.name

A tohle dělá po spuštění.

    tomas@labserver:~/python-stack$ python vypsat.py

    Servery:

    --------

    mujWEB-2

    mujWEB-1

    mojeVM-2

    mojeVM-1

    Image:

    ------

    CentOS 6

    web-server

    mujImage

    CoreOS

    Stackato

    Ubutnu_14.04

    Cirros

    Ubuntu_16.04

    Flavor:

    -------

    m1.tiny

    m1.small

    m1.medium

    l1.medium

    m1.large

    m1.xlarge

    l1.small

    web.tiny

V druhém příkladě uděláme něco podobného, ale tentokrát chceme, aby to byla webová aplikace (volíme primitivní, jen na ukázku). Chceme aplikaci se zabudovaným webovým serverem, na který se připojíme a dostaneme seznam flavorů. V rámci labu je pro něj vyhrazen port 7123 - v jeden okamžik ho může spustit jen jeden z vás (prostřídejte se).

Toto je kód v souboru web_list.py. Jediný rozdíl oproti předchozímu je, že vypisujee údaje v HTML tabulce zabudovaného Python Bottle web serveru.

    #!/usr/bin/python

    from openstack import connection

    import os

    from bottle import route, run

    auth_args = {

        'auth_url': os.environ['OS_AUTH_URL'],

        'project_name': os.environ['OS_PROJECT_NAME'],

        'username': os.environ['OS_USERNAME'],

        'password': os.environ['OS_PASSWORD'],

        'user_domain_id': os.environ['OS_USER_DOMAIN_ID'],

        'project_domain_id': os.environ['OS_PROJECT_DOMAIN_ID'],

    }

    conn = connection.Connection(**auth_args)

    @route('/')

    def app():

        vystup = "<table><TR><TD>Flavors</TD></TR>"

        for flavor in conn.compute.flavors():

            vystup = vystup + "<TR><TD>" + flavor.name + "</TD></TR>"

        vystup = vystup + "</table>"

        return vystup

    run(host='0.0.0.0', port=7123)

Spusťte aplikaci. V rámci labu jsme za NAT a tento port je sdílený, tento test tedy budeme zkoušet pojednom.

    tomas@labserver:~/python-stack$ python web_list.py

    Bottle v0.12.9 server starting up (using WSGIRefServer())...

    Listening on http://0.0.0.0:7123/

    Hit Ctrl-C to quit.

Ze svého notebooku se připojte na 16.21.188.201:7123

Výborně, webová aplikace nám funguje. Vraťte se do konzole labServer a aplikaci ukončete (CTRL+C).

Na závěr naznačíme už něco, co by mohlo být pro někoho užitečné. Nabídneme spuštění instance z našeho vlastního webového formuláře. Prohlédněme si obsah soubor web_vm.py. V hlavní části webu neděláme nic moc nového. Načítáme si flavory, image a sítě, ale všechno balíme do HTML formuláře. Uživatel si tak vybere co by chtěl a také svůj server nějak pojmenuje. Jakmile klikne na tlačítko Vytvor zavolá se funkce vytvor(). Ta převezme vyplněné údaje a na základě nich zavolá OpenStack pro vytvoření příslušného serveru.

    #!/usr/bin/python

    from openstack import connection

    import os

    from bottle import route, run, request

    auth_args = {

        'auth_url': os.environ['OS_AUTH_URL'],

        'project_name': os.environ['OS_PROJECT_NAME'],

        'username': os.environ['OS_USERNAME'],

        'password': os.environ['OS_PASSWORD'],

        'user_domain_id': os.environ['OS_USER_DOMAIN_ID'],

        'project_domain_id': os.environ['OS_PROJECT_DOMAIN_ID'],

    }

    conn = connection.Connection(**auth_args)

    @route('/')

    def app():

        vystup = """<!DOCTYPE html>

                 <html>

                 <body>

                 <form action="vytvor">

                 Nazev VM:<br>

                 <input type="text" name="nazev" value="nejakejmeno">

                 <br><br>

                 Flavor:<br>

                 <select name="flavor">"""

        for flavor in conn.compute.flavors():

            vystup = vystup + '<option value="{}">{}</option>'.format(flavor.name, flavor.name)

        vystup = vystup + """

                 </select>

                 <br><br>

                 Image:<br>

                 <select name="image">"""

        for image in conn.compute.images():

            vystup = vystup + '<option value="{}">{}</option>'.format(image.name, image.name)

        vystup = vystup + """

                 </select>

                 <br><br>

        Sit:<br>

        <select name="sit">"""

        for sit in conn.network.networks():

            vystup = vystup + '<option value="{}">{}</option>'.format(sit.name, sit.name)

        vystup = vystup + """

                 </select>

                 <br><br>

                 <input type="submit" value="Vytvor">

                 </form>

                 </body>

                 </html>"""

        return vystup

    @route('/vytvor')

    def vytvor():

        nazev = request.query.nazev

        image = conn.compute.find_image(request.query.image)

        flavor = conn.compute.find_flavor(request.query.flavor)

        network = conn.network.find_network(request.query.sit)

        server = conn.compute.create_server(

            name=nazev, image_id=image.id, flavor_id=flavor.id,

            networks=[{"uuid": network.id}])

        return "<h1>Pozadavek zadan</h1>"

    run(host='0.0.0.0', port=7123)

Spusťte aplikaci a připojte se na web. Vyberte si a klikněte na vytvoř.

    tomas@labserver:~/python-stack$ python web_vm.py

    Bottle v0.12.9 server starting up (using WSGIRefServer())...

    Listening on http://0.0.0.0:7123/

    Hit Ctrl-C to quit.

Přesvěčte se, že všechno dopadlo dle očekávání.

    tomas@labserver:~/python-stack$ openstack server list

    +--------------------------------------+-------------+--------+----------------------------------+

    | ID                                   | Name        | Status | Networks                         |

    +--------------------------------------+-------------+--------+----------------------------------+

    | 80793528-7a5f-43ca-975c-668e3fc4c47d | nejakejmeno | ACTIVE | mojeSit=192.168.1.28             |

    | f5b52c8b-4c0e-4840-b1d5-ff2a42edec7d | mujWEB-2    | ACTIVE | Web-sit=192.168.2.7              |

    | 30640cc6-5494-4d7e-a95a-2afb621929cb | mujWEB-1    | ACTIVE | Web-sit=192.168.2.6, 10.201.0.12 |

    | 0a5b959f-1e6e-4e82-b5dc-c3c74aaa9722 | mojeVM-2    | ACTIVE | mojeSit=192.168.1.3              |

    | 133fbcb2-7e6e-43c9-9b89-00777d823116 | mojeVM-1    | ACTIVE | mojeSit=192.168.1.4              |

    +--------------------------------------+-------------+--------+----------------------------------+

V této části bylo cílem představit možnosti API a SDK, nikoli ukázat jak kvalitně programovat. Příklady berte jako demonstraci možností a ne něco, co v této podobě chcete provozovat. Pokud je vaším cílem příjemný česky mluvící portál pro koncové uživatele, podívejte se také na hotové a velmi mocné komerční řešení HPE Cloud Service Automation.

Ansible pro OpenStack

Dlouho jsem rozmýšlel kam použití Ansible pro ovládání OpenStack zařadit. Má blíže k této kapitole, která je o skriptování a programování nad OpenStack API nebo spíše k orchestraci s prostředky jako je OpenStack Heat, Terraform nebo HPE Cloud Service Automation?

Podobně jako orchestrační nástroje přináší Ansible příjemnou abstrakci a například zda se má zdroj vytvořit nebo odstranit je stejné volání, jen se state označí za present nebo absent. To je fajn - ve skriptech to takhle jednoduché mít nebudete. Dále Ansible přináší idempotenci, tedy playbook (sadu úloh) můžete spustit několikrát po sobě a nerozbije se to. Ansible nejde a tupě nevytvoří zdroj (třeba instanci serveru nebo volume), ale nejprve si zjistí, jestli tam už je a jestli jeho stav odpovídá požadovanému. Tohle dostanete „zadarmo“, nemusíte kolem toho psát potřebné zjišťovací příkazy, jako byste museli ve skriptu. Ansible je tedy rozhodně mnohem víc, než pouhé skriptování. A navíc je lidsky čitelný bez znalosti programovacího jazyka.

Na druhou stranu Ansible cloud moduly nefungují plně deklarativním způsobem (já ti řeknu jakou infrastrukturu chci a ty to nějak zařiď), jsou spíše imperativní (já ti řeknu krok za krokem co máš dělat). Například tedy záleží na pořadí. Když chcete vytvořit server a síť, musíte nejdřív udělat síť a pak v ní spustit server. Když to chcete smazat, musíte nejdřív smazat server a pak síť (tedy opačně). Ansible vás od tohoto neodstínil, tedy není deklarativní. Pokud v desired state své infrastruktury chcete například vymazat jeden server, nestačí ho vymazat z předpisu - musíte spustit celou sekvenci a u tohoto serveru dát stav absent. Nenaplňuje to tedy představu, že předpis je verzovatelným obrazem infrastruktury. Pokud si pro Ansible napíšete vlastní role, můžete se k těmto stavům přiblížit, ale nic z toho pro vás není připraveno. Z těchto důvodů myslím zatím Ansible nepatří mezi deklarativní orchestrátory jako je OpenStack Heat, Terraform nebo HPE CSA. Přesto má smysl se jím zabývat - svoje „skriptování“ posunete o pár úrovní výš a nemusíte být programátoři !

Začněme tím, že si načteme komunikační proměnné a skočíme do adresáře s příklady.

    tomas@labserver:~$ source stack

    tomas@labserver:~$ cd ansible-openstack/

Prohlédněme si první nejjednodušší playbook.

    tomas@labserver:~/ansible-openstack$ cat instance.yml

    ---

    - hosts: localhost

      tasks:

      - name: Nacti vsechny instance

        os_server_facts:

      - name: Vypis co vis o instancich

        debug:

          var: openstack_servers

Tento se připojí do našeho OpenStack a stáhne si informace o instancích, které nám vnitřně uloží. Pracovat s nimi teď nebudeme, jen si vypíšeme, co všechno Ansible našel (výpis zkrátím, je toho hodně).

    tomas@labserver:~/ansible-openstack$ ansible-playbook instance.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Nacti vsechny instance] **************************************************

    ok: [localhost]

    TASK [Vypis co vis o instancich] ***********************************************

    ok: [localhost] => {

        "openstack_servers": [

            {

                "HUMAN_ID": true,

                "NAME_ATTR": "name",

                "OS-DCF:diskConfig": "MANUAL",

                "OS-EXT-AZ:availability_zone": "nova",

                "OS-EXT-STS:power_state": 1,

                "OS-EXT-STS:task_state": null,

                "OS-EXT-STS:vm_state": "active",

                "OS-SRV-USG:launched_at": "2016-07-13T09:13:08.000000",

                "OS-SRV-USG:terminated_at": null,

                "accessIPv4": "",

                "accessIPv6": "",

                "addresses": {

                    "mojeSit": [

                        {

                            "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:e0:f5:16",

                            "OS-EXT-IPS:type": "fixed",

                            "addr": "192.168.1.28",

                            "version": 4

                        }

                    ]

                },

                "az": "nova",

                "cloud": "envvars",

                "config_drive": "",

                "created": "2016-07-13T09:12:48Z",

                "flavor": {

                    "id": "1"

                },

                "hostId": "68ff6a39dcf97a8a393687602a5c590725b49be174727d2e972b4508",

                "human_id": "nejakejmeno",

                "id": "80793528-7a5f-43ca-975c-668e3fc4c47d",

                "image": {

                    "id": "e9664fca-74b0-4a59-95e9-87a1a844d031"

                },

                "interface_ip": "",

                "key_name": null,

                "metadata": {},

                "name": "nejakejmeno",

                "networks": {

                    "mojeSit": [

                        "192.168.1.28"

                    ]

                },

                "os-extended-volumes:volumes_attached": [],

                "private_v4": "192.168.1.28",

                "progress": 0,

                "public_v4": "",

                "public_v6": "",

                "region": "",

                "request_ids": [],

                "security_groups": [

                    {

                        "name": "default"

                    }

                ],

                "status": "ACTIVE",

                "tenant_id": "d2811986367044f9a5d9efa180e746cd",

                "updated": "2016-07-13T09:13:08Z",

                "user_id": "d64afca221d64d5cab4592d4dbb3736f",

                "volumes": [],

                "x_openstack_request_ids": []

            },

            {

                ...

                "human_id": "mujweb-2",

            },

            {

                ...

                "human_id": "mujweb-1",

                ...

            },

            {

                ...

                "human_id": "mojevm-1",

                ...

            }

        ]

    }

    PLAY RECAP *********************************************************************

    localhost                  : ok=3    changed=0    unreachable=0    failed=0

Uvedené parametry můžeme dál použít v našem předpisu, ale my se pustíme do něčeho jiného. Pojďme si prohlédnout extrémně jednoduchý playbook na vytváření volume ve storage.

    tomas@labserver:~/ansible-openstack$ cat storage.yml

    ---

    - hosts: localhost

      vars:

        stav: present

        disky:

          - AnsibleVol1

          - AnsibleVol2

      tasks:

      - name: Ujisti se, ze volume je v pozadovanem stavu

        os_volume:

          state: "{{ stav }}"

          size: 1

          display_name: "{{ item }}"

        with_items: "{{ disky }}"

Co tady děláme? Na začátku jsme definovali dvě proměnné - stav a disky. Ve stavu máme napsáno present, tedy chceme disky vytvořit (pokud už neexistují). V disky máme výčet jmen disků. V playbook máme jedinou úlohu a tou je právě vytvoření disku. Jako parametr mu zadáváme state, velikost disku a také jeho jméno. To ovšem nahrazujeme proměnnou „item“. O co jde? Na konci tasku máme with_items, tedy že tento krok chceme opakovat pro všechny členy výčtu „disky“. Ansible tedy projde tento seznam a disky postupně vytvoří. To co byste při programování řešili nějakou smyčkou můžete v Ansible udělat takhle - lidsky přívětivě, čitelně a přístupně i pro neprogramátory.

Spusťte playbook a ověřte, že disky skutečně existují.

    tomas@labserver:~/ansible-openstack$ ansible-playbook storage.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Ujisti se, ze volume je v pozadovanem stavu] *****************************

    changed: [localhost] => (item=AnsibleVol1)

    changed: [localhost] => (item=AnsibleVol2)

    PLAY RECAP *********************************************************************

    localhost                  : ok=2    changed=1    unreachable=0    failed=0

    tomas@labserver:~/ansible-openstack$ openstack volume list

    +--------------------------------------+--------------+-----------+------+-------------+

    | ID                                   | Display Name | Status    | Size | Attached to |

    +--------------------------------------+--------------+-----------+------+-------------+

    | 9f472e2f-2add-4ab8-9cb6-572edc9312d0 | AnsibleVol2  | available |    1 |             |

    | 8beca9c0-fb9d-4519-b62f-5a7674ec782f | AnsibleVol1  | available |    1 |             |

    +--------------------------------------+--------------+-----------+------+-------------+

Všimněte si, že u tasku máme slovo „changed“. Ansible tím říká, že požadovaný stav neodpovídal skutečnému (tedy, že disk neexistoval) a proto provedl změnu. Pojďme teď jeden disk ručně vymazat a spustit playbook znova.

    tomas@labserver:~/ansible-openstack$ openstack volume delete AnsibleVol1

    tomas@labserver:~/ansible-openstack$ ansible-playbook storage.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Ujisti se, ze volume je v pozadovanem stavu] *****************************

    changed: [localhost] => (item=AnsibleVol1)

    ok: [localhost] => (item=AnsibleVol2)

    PLAY RECAP *********************************************************************

    localhost                  : ok=2    changed=1    unreachable=0    failed=0

Vidíte? Ansible znovu vytvořil chybějící volume, ale s existujícím nic nedělal, jen ověřil, že existuje.

Při spouštění playbooku můžeme modifikovat proměnnou stav a tím požadovat, že disky nesmí existovat. Zkusme si to.

    tomas@labserver:~/ansible-openstack$ ansible-playbook storage.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Ujisti se, ze volume je v pozadovanem stavu] *****************************

    changed: [localhost] => (item=AnsibleVol1)

    ok: [localhost] => (item=AnsibleVol2)

    PLAY RECAP *********************************************************************

    localhost                  : ok=2    changed=1    unreachable=0    failed=0

    tomas@labserver:~/ansible-openstack$ ansible-playbook storage.yml -e stav=absent

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Ujisti se, ze volume je v pozadovanem stavu] *****************************

    changed: [localhost] => (item=AnsibleVol1)

    changed: [localhost] => (item=AnsibleVol2)

    PLAY RECAP *********************************************************************

    localhost                  : ok=2    changed=1    unreachable=0    failed=0

    tomas@labserver:~/ansible-openstack$ openstack volume list

    tomas@labserver:~/ansible-openstack$

Základy jsme si vyzkoušeli a pojďme k něčemu trošku komplexnějšímu a také užitečnějšímu. Využijeme Ansible k poskládání ucelenější infrastruktury. Prohlédněte si playbook.

    tomas@labserver:~/ansible-openstack$ cat infra.yml

    ---

    - hosts: localhost

      vars:

        stav: present

        porty:

          - 22

          - 80

          - 443

          - 8080

        servery:

          - AnsibleIns1

          - AnsibleIns2

      tasks:

      - name: Pokud je to pozadovano, smaz server

        os_server:

          state: "{{ stav }}"

          name: "{{ item }}"

          image: Cirros

          flavor: m1.tiny

          network: AnsibleNet

        with_items: "{{ servery }}"

        when: stav == "absent"

      - name: Ujisti se, ze Security Group je v pozadovanem stavu

        os_security_group:

          state: "{{ stav }}"

          name: AnsibleSG

      - name: Ujisti se, ze Security Group povoluje potrebne porty

        os_security_group_rule:

          security_group: AnsibleSG

          protocol: tcp

          port_range_min: "{{ item }}"

          port_range_max: "{{ item }}"

        with_items: "{{ porty }}"

        when: stav == "present"

      - name: Pokud je to pozadovano, smaz router

        os_router:

          state: "{{ stav }}"

          name: AnsibleRouter

          network: ext-net

          interfaces:

            - AnsibleSub

        when: stav == "absent"

      - name: Ujisti se, ze mame vytvorenou sit

        os_network:

          state: "{{ stav }}"

          name: AnsibleNet

      - name: Ujisti se, ze v siti je potrebny subnet

        os_subnet:

          network_name: AnsibleNet

          name: AnsibleSub

          cidr: 192.168.77.1/24

        when: stav == "present"

      - name: Pokud je to pozadovano, vytvor router a pripoj sit

        os_router:

          state: "{{ stav }}"

          name: AnsibleRouter

          network: ext-net

          interfaces:

            - AnsibleSub

        when: stav == "present"

      - name: Ujisti se, ze servery jsou vytvoreny

        os_server:

          name: "{{ item }}"

          image: Cirros

          flavor: m1.tiny

          network: AnsibleNet

        with_items: "{{ servery }}"

        when: stav == "present"

Pracujeme vlastně stále stejným konceptem, jen jsme přidali víc zdrojů. Na začátku si definujeme výčet TCP portů, které naše servery používají (pro nastavení security group firewallu, tedy mikrosegmentace) a definujeme výčet s názvy serverů. Všimněte si, že aby fungovala i varianta s mazáním (stav „absent“) už nestačí jen poslat tento stav ve stejném pořadí, ale něco musíme dělat jinak (například server vytvářet jako poslední, ale mazat jako první). Proto někdy používáme „when“, což znamená, že krok se provede pouze za určitých okolností. Náš playbook tedy vytvoří síť, router s připojenou sítí a s napojením ven, security group včetně pravidel a dva servery. V praxi bychom to jistě rozšířili třeba o load-balancer a k instancím vytvořili a napojili volume.

Spusťme playbook.

    tomas@labserver:~/ansible-openstack$ ansible-playbook infra.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Pokud je to pozadovano, smaz server] *************************************

    skipping: [localhost] => (item=AnsibleIns1)

    skipping: [localhost] => (item=AnsibleIns2)

    TASK [Ujisti se, ze Security Group je v pozadovanem stavu] *********************

    changed: [localhost]

    TASK [Ujisti se, ze Security Group povoluje potrebne porty] ********************

    changed: [localhost] => (item=22)

    changed: [localhost] => (item=80)

    changed: [localhost] => (item=443)

    changed: [localhost] => (item=8080)

    TASK [Pokud je to pozadovano, smaz router] *************************************

    skipping: [localhost]

    TASK [Ujisti se, ze mame vytvorenou sit] ***************************************

    changed: [localhost]

    TASK [Ujisti se, ze v siti je potrebny subnet] *********************************

    changed: [localhost]

    TASK [Pokud je to pozadovano, vytvor router a pripoj sit] **********************

    changed: [localhost]

    TASK [Ujisti se, ze servery jsou vytvoreny] ************************************

    changed: [localhost] => (item=AnsibleIns1)

    changed: [localhost] => (item=AnsibleIns2)

    PLAY RECAP *********************************************************************

    localhost                  : ok=7    changed=6    unreachable=0    failed=0

Podívejte se, jakou infrastrukturu jsme vytvořili.

Co když se rozhodneme třeba ještě jeden server přidat a také přidat ještě port 8443? Pokud bychom měli předpis v nějakém version control systému (třeba v Gitu), můžeme ho změnit a commitovat. V našem případě to uděláme tak, že si vytvoříme kopii souboru s názvem v2:

    tomas@labserver:~/ansible-openstack$ cp infra.yml infra-v2.yml

V definici proměnných přidejme jeden port jeden server.

    ---

    - hosts: localhost

      vars:

        stav: present

        porty:

          - 22

          - 80

          - 443

          - 8080

          - 8443

        servery:

          - AnsibleIns1

          - AnsibleIns2

          - AnsibleIns3

Spusťte playbook a všimněte si, že Ansible přidal jen to, co bylo skutečně potřeba (sledujte „changed“ vs. „ok“).

    tomas@labserver:~/ansible-openstack$ ansible-playbook infra-v2.yml

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Pokud je to pozadovano, smaz server] *************************************

    skipping: [localhost] => (item=AnsibleIns1)

    skipping: [localhost] => (item=AnsibleIns2)

    skipping: [localhost] => (item=AnsibleIns3)

    TASK [Ujisti se, ze Security Group je v pozadovanem stavu] *********************

    ok: [localhost]

    TASK [Ujisti se, ze Security Group povoluje potrebne porty] ********************

    ok: [localhost] => (item=22)

    ok: [localhost] => (item=80)

    ok: [localhost] => (item=443)

    ok: [localhost] => (item=8080)

    changed: [localhost] => (item=8443)

    TASK [Pokud je to pozadovano, smaz router] *************************************

    skipping: [localhost]

    TASK [Ujisti se, ze mame vytvorenou sit] ***************************************

    ok: [localhost]

    TASK [Ujisti se, ze v siti je potrebny subnet] *********************************

    ok: [localhost]

    TASK [Pokud je to pozadovano, vytvor router a pripoj sit] **********************

    ok: [localhost]

    TASK [Ujisti se, ze servery jsou vytvoreny] ************************************

    ok: [localhost] => (item=AnsibleIns1)

    ok: [localhost] => (item=AnsibleIns2)

    changed: [localhost] => (item=AnsibleIns3)

    PLAY RECAP *********************************************************************

    localhost                  : ok=7    changed=2    unreachable=0    failed=0

Na závěr spustíme playbook s příznakem pro vymazání infrastruktury.

    tomas@labserver:~/ansible-openstack$ ansible-playbook infra-v2.yml -e stav=absent

     [WARNING]: provided hosts list is empty, only localhost is available

    PLAY [localhost] ***************************************************************

    TASK [setup] *******************************************************************

    ok: [localhost]

    TASK [Pokud je to pozadovano, smaz server] *************************************

    changed: [localhost] => (item=AnsibleIns1)

    changed: [localhost] => (item=AnsibleIns2)

    changed: [localhost] => (item=AnsibleIns3)

    TASK [Ujisti se, ze Security Group je v pozadovanem stavu] *********************

    changed: [localhost]

    TASK [Ujisti se, ze Security Group povoluje potrebne porty] ********************

    skipping: [localhost] => (item=22)

    skipping: [localhost] => (item=80)

    skipping: [localhost] => (item=443)

    skipping: [localhost] => (item=8080)

    skipping: [localhost] => (item=8443)

    TASK [Pokud je to pozadovano, smaz router] *************************************

    changed: [localhost]

    TASK [Ujisti se, ze mame vytvorenou sit] ***************************************

    changed: [localhost]

    TASK [Ujisti se, ze v siti je potrebny subnet] *********************************

    skipping: [localhost]

    TASK [Pokud je to pozadovano, vytvor router a pripoj sit] **********************

    skipping: [localhost]

    TASK [Ujisti se, ze servery jsou vytvoreny] ************************************

    skipping: [localhost] => (item=AnsibleIns1)

    skipping: [localhost] => (item=AnsibleIns2)

    skipping: [localhost] => (item=AnsibleIns3)

    PLAY RECAP *********************************************************************

    localhost                  : ok=5    changed=4    unreachable=0    failed=0