Общие сведения

ВступлениеПодготовка к запускуАрхитектура платформы TestoПорядок запускаПолитика запуска тестов

Обучающие материалы по Testo для Hyper-V

Часть 1. Самый первый тестЧасть 2. Устанавливаем Ubuntu ServerЧасть 3. Доступ в Интернет из виртуальной машиныЧасть 4. Гостевые дополненияЧасть 5. ПараметрыЧасть 6. КешированиеЧасть 7. Связываем две машины по сетиЧасть 8. ФлешкиЧасть 9. МакросыЧасть 10. Конструкция ifЧасть 11. No snapshotsЧасть 12. Управление мышкойЧасть 13. Импортирование жёстких дисковЧасть 14. JS-селекторыЧасть 15. Циклы

Обучающие материалы по Testo для QEMU

Часть 1. Самый первый тестЧасть 2. Устанавливаем Ubuntu ServerЧасть 3. Гостевые дополненияЧасть 4. ПараметрыЧасть 5. КешированиеЧасть 6. Доступ в Интернет из виртуальной машиныЧасть 7. Связываем две машины по сетиЧасть 8. ФлешкиЧасть 9. МакросыЧасть 10. Конструкция ifЧасть 11. No snapshotsЧасть 12. Управление мышкойЧасть 13. Импортирование жёстких дисковЧасть 14. JS-селекторыЧасть 15. ЦиклыЧасть 16. Макросы с объявлениями

Спецификация языка

Общая структура скриптовых файловБазовые конструкции языкаOбъявление виртуальной машиныОбъявление виртуального флеш-накопителяОбъявление виртуальной сетиПараметрыОбъявление тестовМакросыДействия с виртуальными машинамиДействия с мышкойПоиск изображений на экранеДействия с виртуальными флеш-накопителямиУсловияЦиклыСписок идентификаторов клавиш

Запросы на языке Javascript

Общая концепция построения JS-селекторовВстроенные глобальные функции JavascriptИсключенияКласс TextTensorКласс ImgTensorКласс Point

Часть 8. Флешки

С чем Вы познакомитесь

В этой части вы познакомитесь с механизмом виртуальных флешек в платформе Testo.

Начальные условия

  1. Платформа Testo установлена.
  2. Установлен менеджер виртуальных машин virt-manager.
  3. На хостовой машине имеется доступ в Интернет
  4. Имеется установочный образ Ubuntu server 16.04 с расположением /opt/iso/ubuntu_server.iso. Местоположение и название установочного файла может быть другим, в этом случае нужно будет соответствующим образом поправить параметр ISO_DIR, передаваемый через командную строку во время запуска тестов.
  5. Имеется образ с гостевыми дополнениями Testo в одной папке с установочным образом Ubuntu.
  6. (Рекомендовано) Настроена подсветка синтаксиса Testo-lang в Sublime Text 3.
  7. (Рекомендовано) Проделаны шаги из седьмой части.

Вступление

Помимо виртуальных сетей и виртуальных машин, в платформе Testo есть ещё один вид виртуальных сущностей - виртуальные флешки. Виртуальные флешки могут использоваться в двух случаях:

  1. Для передачи файлов между виртуальными машинами, не используя для этого сеть;
  2. Загрузка файлов в виртуальную машину из хоста и обратно, если нет возможности использовать гостевые дополнения и действие copyto.

При этом для флешек в платформе Testo есть два важных свойства:

  1. При успешном завершении теста, в котором участвовала флешка, для этой флешки фиксируется её состояние (как и для виртуальных машин), так что можно быть уверенным, что в ходе выполнения теста флешка всегда находится в правильном состоянии;
  2. Атрибуты флешки (в том числе целостность файлов, которые передаются внутрь гостевой системы через флешку) участвуют в подсчете целостности теста, в котором было обращение к флешке. То есть, как и в случае с действием copyto, вы можете быть уверены, что платформа Testo отследит изменение файлов, участвующих в тесте, и запустит тест заново при необходимости.

Есть также и важное ограничение в использовании флешек в платформе Testo: если флешка была подключена к виртуальной машине в ходе теста, то до окончания теста эту флешку необходимо отключить.

Также на текущий момент не допускается одновременное подключение двух и более флешек в одну виртуальную машину.

В этом уроке мы познакомимся с виртуальными флешками и всеми особенностями их использования.

С чего начать?

Давайте представим, что нам необходимо передать файл из машины client в машину server и по какой-то причине мы не хотим пользоваться передачей файлов по сети. В этой ситуации нам как раз может помочь виртуальная флешка. Для того, чтобы объявить виртуальную флешку, используется директива flash.

flash exchange_flash {
    fs: "ntfs"
    size: 16Mb
}

Флешки объявляются схожим образом с виртуальными машинами и сетями: директива flash, уникальное среди флешек имя, а также набор атрибутов, часть которых являются обязательными. Для флешек обязательных атрибута два:

  1. fs - тип файловой системы. В нашем случае это ntfs;
  2. size - размер флешки. Нам будет более чем достаточно 16 Мегабайт.

Как и в случае с виртуальными машинами, объявление флешки само по себе не приводит к её созданию. Флешка создаётся только при запуске теста, в котором эта флешка фигурирует.

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

#обратите внимание, тест отнаследован не от test_ping,
#а от тех же client_prepare и server_prepare
#То есть test_ping и exchange_files_with_flash лежат на одном уровне
#иерархии в дереве тестов
test exchange_files_with_flash: client_prepare, server_prepare {
    client {
        #Создаём файл, который нужно будет передать на сервер
        exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"

        plug flash exchange_flash
        sleep 5s
        exec bash """
            mount /dev/sdb1 /media
            cp /tmp/copy_me_to_server.txt /media
            umount /media
        """

        unplug flash exchange_flash
    }

    server {
        plug flash exchange_flash
        sleep 5s
        exec bash """
            mount /dev/sdb1 /media
            cp /media/copy_me_to_server.txt /tmp
            umount /media
            cat /tmp/copy_me_to_server.txt
        """

        unplug flash exchange_flash
    }
}

В целом, тест достаточно прямолинеен: на клиенте мы создаем файл, который необходимо передать на сервер, затем выполняем действие plug flash, которое подключает новое устройство к виртуальной машине (то же самое происходит когда человек вставляет флешку в компьютер).

Т.к. в Ubuntu Server не предусмотрено автоматическое монтирование флешки в файловую систему, нам необходимо сделать это самостоятельно. После подключения флешки нужно выждать несколько секунд, чтобы ОС успела отреагировать на новое подключенное устройство. Вставленная флешка внутри виртуальной машины будет видна как устройство /dev/sdb, от которого нам требуется первый раздел (то есть устройство /dev/sdb1). Монтируем этот раздел, копируем на флешку файл, отмонтируем устройство и безопасно извлекаем флешку.

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

Попробуем все это запустить (на этот момент все предыдущие тесты должны быть закешированы чтобы получился такой вывод):

user$ sudo testo run ~/testo/hello_world.testo --stop_on_fail --param ISO_DIR /opt/iso --test_spec exchange_files_with_flash
UP-TO-DATE TESTS:
client_install_ubuntu
client_install_guest_additions
client_unplug_nat
client_prepare
server_install_ubuntu
server_install_guest_additions
server_unplug_nat
server_prepare
TESTS TO RUN:
exchange_files_with_flash
[ 89%] Preparing the environment for test exchange_files_with_flash
[ 89%] Restoring snapshot client_prepare for virtual machine client
[ 89%] Restoring snapshot server_prepare for virtual machine server
[ 89%] Creating flash drive exchange_flash
[ 89%] Taking snapshot initial for flash drive exchange_flash
[ 89%] Running test exchange_files_with_flash
[ 89%] Executing bash command in virtual machine client with timeout 10m
+ echo 'Hello from client!'
[ 89%] Plugging flash drive exchange_flash into virtual machine client
[ 89%] Sleeping in virtual machine client for 5s
[ 89%] Executing bash command in virtual machine client with timeout 10m
+ mount /dev/sdb1 /media
+ cp /tmp/copy_me_to_server.txt /media
+ umount /media
[ 89%] Unplugging flash drive exchange_flash from virtual machine client
[ 89%] Plugging flash drive exchange_flash into virtual machine server
[ 89%] Sleeping in virtual machine server for 5s
[ 89%] Executing bash command in virtual machine server with timeout 10m
+ mount /dev/sdb1 /media
+ cp /media/copy_me_to_server.txt /tmp
+ umount /media
+ cat /tmp/copy_me_to_server.txt
Hello from client!
[ 89%] Unplugging flash drive exchange_flash from virtual machine server
[ 89%] Taking snapshot exchange_files_with_flash for flash drive exchange_flash
[ 89%] Taking snapshot exchange_files_with_flash for virtual machine client
[ 89%] Taking snapshot exchange_files_with_flash for virtual machine server
[100%] Test exchange_files_with_flash PASSED in 0h:0m:19s
PROCESSED TOTAL 9 TESTS IN 0h:0m:19s
UP-TO-DATE: 8
RUN SUCCESSFULLY: 1
FAILED: 0
user$

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

Также еще раз необходимо напомнить, что в конце теста состояние флешки фиксируется, и если в более поздних тестах на эту флешку будут записаны новые файлы, они не будут проявляться в более ранних тестах.

Еще раз остановимся на замечании, что все флешки необходимо вытащить из виртуальных машин перед завершением теста. Если это условие не будет соблюдено, при фиксации результатов теста будет получена ошибка.

Копирование файлов из хоста с помощью флешки

Давайте рассмотрим второй сценарий использования виртуальных флешек - передача файлов с хоста на виртуальные машины при невозможности/нежелательности использования гостевых дополнений.

Для этого в объявлении флешки необходимо указать ещё один атрибут folder.

flash exchange_flash {
    fs: "ntfs"
    size: 16Mb
    folder: "./folder_to_copy"
}

В этом атрибуте необходимо указать путь к папке на хосте, которую необходимо скопировать на флешку. Можно использовать относительный путь, в этом случае он будет начинаться с того места. где расположен сам файл с тестовыми сценариями. В качестве folder нельзя указывать один файл, это обязательно должна быть папка.

Сама папка скопирована на флешку не будет - в корень файловой системы на флешке копируется лишь содержимое папки, указанной в атрибуте folder. Можно рассматривать папку folder как точку монтирования, содержимое которой транслируется на файловую систему флешки

Давайте представим, что по какой то причине мы не можем воспользоваться действием copyto в виртуальной машине client и не можем передать скрипт rename_net.sh для переименования сетевых интерфейсов внутри виртуальной машины. В этом случае мы как раз можем воспользоваться флешкой.

Создайте папку folder_to_copy в той же папке, что и файл hello_world.testo и скопируйте файл rename_net.sh внутрь folder_to_copy. Теперь надо лишь немного подправить тест client_prepare:

test client_prepare: client_unplug_nat {
    client {
        plug flash exchange_flash
        sleep 5s
        exec bash """
            mount /dev/sdb1 /media
            cp /media/rename_net.sh /opt/rename_net.sh
            umount /media
        """
        unplug flash exchange_flash
        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:aa server_side
            ip a a 192.168.1.2/24 dev server_side
            ip l s server_side up
            ip ad
        """
    }
}

Попробуем запустить все тесты

user$ sudo testo run ~/testo/hello_world.testo --stop_on_fail --param ISO_DIR /opt/iso
Because of the cache loss, Testo is scheduled to run the following tests:
- client_prepare
- test_ping
- exchange_files_with_flash
Do you confirm running them? [y/N]: y
UP-TO-DATE TESTS:
server_install_ubuntu
server_install_guest_additions
server_unplug_nat
server_prepare
client_install_ubuntu
client_install_guest_additions
client_unplug_nat
TESTS TO RUN:
client_prepare
test_ping
exchange_files_with_flash
[ 70%] Preparing the environment for test client_prepare
[ 70%] Restoring snapshot client_unplug_nat for virtual machine client
[ 70%] Creating flash drive exchange_flash
[ 70%] Taking snapshot initial for flash drive exchange_flash
[ 70%] Running test client_prepare
[ 70%] Plugging flash drive exchange_flash into virtual machine client
[ 70%] Sleeping in virtual machine client for 5s
[ 70%] Executing bash command in virtual machine client with timeout 10m
+ mount /dev/sdb1 /media
+ cp /media/rename_net.sh /opt/rename_net.sh
+ umount /media
[ 70%] Unplugging flash drive exchange_flash from virtual machine client
[ 70%] Executing bash command in virtual machine client with timeout 10m
+ chmod +x /opt/rename_net.sh
+ /opt/rename_net.sh 52:54:00:00:00:aa server_side
Renaming success
+ ip a a 192.168.1.2/24 dev server_side
+ ip l s server_side up
+ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: server_side: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:00:00:aa brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 scope global server_side
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe00:aa/64 scope link tentative
valid_lft forever preferred_lft forever
[ 70%] Taking snapshot client_prepare for flash drive exchange_flash
[ 70%] Taking snapshot client_prepare for virtual machine client
[ 80%] Test client_prepare PASSED in 0h:0m:9s
[ 80%] Preparing the environment for test test_ping
[ 80%] Restoring snapshot server_prepare for virtual machine server
[ 80%] Running test test_ping
[ 80%] Executing bash command in virtual machine client with timeout 10m
+ ping 192.168.1.2 -c5
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.032 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.044 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.043 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=0.043 ms

--- 192.168.1.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.032/0.040/0.044/0.008 ms
[ 80%] Executing bash command in virtual machine server with timeout 10m
+ ping 192.168.1.1 -c5
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.039 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.043 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.045 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.044 ms

--- 192.168.1.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.039/0.045/0.055/0.006 ms
[ 80%] Taking snapshot test_ping for flash drive exchange_flash
[ 80%] Taking snapshot test_ping for virtual machine client
[ 80%] Taking snapshot test_ping for virtual machine server
[ 90%] Test test_ping PASSED in 0h:0m:14s
[ 90%] Preparing the environment for test exchange_files_with_flash
[ 90%] Restoring snapshot client_prepare for flash drive exchange_flash
[ 90%] Restoring snapshot client_prepare for virtual machine client
[ 90%] Restoring snapshot server_prepare for virtual machine server
[ 90%] Running test exchange_files_with_flash
[ 90%] Executing bash command in virtual machine client with timeout 10m
+ echo 'Hello from client!'
[ 90%] Plugging flash drive exchange_flash into virtual machine client
[ 90%] Sleeping in virtual machine client for 5s
[ 90%] Executing bash command in virtual machine client with timeout 10m
+ mount /dev/sdb1 /media
+ cp /tmp/copy_me_to_server.txt /media
+ umount /media
[ 90%] Unplugging flash drive exchange_flash from virtual machine client
[ 90%] Plugging flash drive exchange_flash into virtual machine server
[ 90%] Sleeping in virtual machine server for 5s
[ 90%] Executing bash command in virtual machine server with timeout 10m
+ mount /dev/sdb1 /media
+ cp /media/copy_me_to_server.txt /tmp
+ umount /media
+ cat /tmp/copy_me_to_server.txt
Hello from client!
[ 90%] Unplugging flash drive exchange_flash from virtual machine server
[ 90%] Taking snapshot exchange_files_with_flash for flash drive exchange_flash
[ 90%] Taking snapshot exchange_files_with_flash for virtual machine client
[ 90%] Taking snapshot exchange_files_with_flash for virtual machine server
[100%] Test exchange_files_with_flash PASSED in 0h:0m:19s
PROCESSED TOTAL 10 TESTS IN 0h:0m:43s
UP-TO-DATE: 7
RUN SUCCESSFULLY: 3
FAILED: 0
user$

Как мы видим, все тесты успешно отработали, так что передача rename_net.sh внутрь виртуальной машины успешно состоялась.

Можно выделить несколько интересных моментов:

  1. Флешка exchange была создана заново. Это произошло только потому, что мы изменили её конфигурацию (добавили атрибут folder). Если бы целостность конфигурации осталась нетронутой, был бы восстановлен снепшот initial.
  2. Тест test_ping был проведен заново, хотя мы его вовсе не трогали. Это произошло потому что мы изменили тест client_prepare - предшественника теста test_ping.
  3. Целостность файлов, указанных в folder, участвует в целостности теста, в котором участвует флешка. Если поменять содержимое папки folder_to_copy (в том числе просто поменять файл rename_net.sh), то тест client_prepare будет запущен заново. Предлагаем вам убедиться в этом самостоятельно.

Копирование файлов из виртуалки с помощью флешки

Окей, мы разобрались с передачей файлов внутрь виртуальной машины, как с помощью гостевых дополнений, так и с помощью флешек. А что насчёт передачи файлов наружу: из виртуальной машины на хост?

Конечно, если на виртуальной машине установлены гостевые дополнения, то можно применить действие copyfrom (с этим действием предлагаем разобраться читателю самостоятельно), но что, если гостевых дополнений на машине не установлено? В этом случае нам на помощь снова могут придти флешки. Давай разбираться как.

Начиная с версии 2.1.0 в Testo-lang появилась возможность обращаться в тестах к флеш-накопителям как к самостоятельным сущностям, наравне с виртуальными машинами.

В командах с виртуальными флешками можно использовать некоторые действия, которые мы ранее использовали для виртуальных машин. В частности, для флешек тоже можно вызывать действия copyto(скопировать файлы с хоста на виртуальную флешку) и copyfrom(скопировать файлы с виртуальной флешки на хост). Однако если для действий copyto и copyfrom в виртуалках требуется наличие гостевых дополнений, то такие же действия для флешек работают всегда, важно лишь чтобы в момент их вызова флешка не была куда-либо подключена.

Допустим, в конце теста exchange_files_with_flash мы хотим скопировать файл copy_me_to_server.txt к себе на хост. Этот файл уже находится на виртуальной флешке exchange_flash (мы записали его туда в ходе теста), так что нам остаётся только вызывать действие copyfrom для флешки:

test exchange_files_with_flash: client_prepare, server_prepare {
    client {
        # Create a file to be transferred to the server
        exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"

        plug flash exchange_flash
        sleep 5s
        exec bash """
            mount /dev/sdb1 /media
            cp /tmp/copy_me_to_server.txt /media
            umount /media
        """

        unplug flash exchange_flash
    }

    server {
        plug flash exchange_flash
        sleep 5s
        exec bash """
            mount /dev/sdb1 /media
            cp /media/copy_me_to_server.txt /tmp
            umount /media
            cat /tmp/copy_me_to_server.txt
        """

        unplug flash exchange_flash
    }

    exchange_flash {
        copyfrom "/copy_me_to_server.txt" "./copy_me_to_server.txt"
    }
}

Как мы видим, в конце теста добавилась команда, в которой фигурирует не виртуальная машина, а флешка exchange_flash. Действие copyfrom вытаскивает файл copy_me_to_server.txt с флешки на хост. Так что после прогона тестов мы сможем увидеть содержимое этого файла уже на хосте:

user$ sudo testo run ~/testo/hello_world.testo --stop_on_fail --param ISO_DIR /opt/iso
Because of the cache loss, Testo is scheduled to run the following tests:
- exchange_files_with_flash
Do you confirm running them? [y/N]: y
UP-TO-DATE TESTS:
server_install_ubuntu
server_install_guest_additions
server_unplug_nat
server_prepare
client_install_ubuntu
client_install_guest_additions
client_unplug_nat
client_prepare
test_ping
TESTS TO RUN:
exchange_files_with_flash
[ 90%] Preparing the environment for test exchange_files_with_flash
[ 90%] Restoring snapshot server_prepare for virtual machine server
[ 90%] Restoring snapshot client_prepare for virtual machine client
[ 90%] Restoring snapshot client_prepare for flash drive exchange_flash
[ 90%] Running test exchange_files_with_flash
[ 90%] Executing bash command in virtual machine client with timeout 10m
+ echo 'Hello from client!'
[ 90%] Plugging flash drive exchange_flash into virtual machine client
[ 90%] Sleeping in virtual machine client for 5s
[ 90%] Executing bash command in virtual machine client with timeout 10m
+ mount /dev/sdb1 /media
+ cp /tmp/copy_me_to_server.txt /media
+ umount /media
[ 90%] Unplugging flash drive exchange_flash from virtual machine client
[ 90%] Plugging flash drive exchange_flash into virtual machine server
[ 90%] Sleeping in virtual machine server for 5s
[ 90%] Executing bash command in virtual machine server with timeout 10m
+ mount /dev/sdb1 /media
+ cp /media/copy_me_to_server.txt /tmp
+ umount /media
+ cat /tmp/copy_me_to_server.txt
Hello from client!
[ 90%] Unplugging flash drive exchange_flash from virtual machine server
[ 90%] Copying /copy_me_to_server.txt from flash drive exchange_flash to destination /home/alex/work/testo/testo-tutorials/08 - flash/./copy_me_to_server.txt with timeout 10m
[ 90%] Taking snapshot exchange_files_with_flash for virtual machine client
[ 90%] Taking snapshot exchange_files_with_flash for virtual machine server
[ 90%] Taking snapshot exchange_files_with_flash for flash drive exchange_flash
[100%] Test exchange_files_with_flash PASSED in 0h:0m:24s
PROCESSED TOTAL 10 TESTS IN 0h:0m:24s
UP-TO-DATE: 9
RUN SUCCESSFULLY: 1
FAILED: 0
user$ user$ cat copy_me_to_server.txtHello from client!

Здесь нужно обратить внимание на два момента:

  1. Флешка не должна быть подключена к виртуальной машине в момент вызова действия copyfrom (как и copyto);
  2. Путь назначения нужно указывать полностью, то есть вместе с именем конечного файла. То есть так же, как и в действиях copyto/copyfrom в виртуалках.

Предлагаем Вам самостоятельно изучить работу действия copyto для виртуальных флешек. В качестве упражнения попробуйте переделать тесты client_prepare и server_prepare так, чтобы копирование папки ./folder_to_copy с хоста на флешку происходило во время тестов, а не во время создания флешки.

Последний пункт с копированием файла с флешки на хост останется в этой части и не перейдёт в следующие.

Итоги

Виртуальные флешки - последний тип виртуальных сущностей, которые есть в Testo (наряду с виртуальными машинами и сетями). Их можно использовать как для передачи файлов между машинами, так и для передачи файлов с хоста на виртуальную машину в условиях недоступности или нежелательности гостевых дополнений.

Дерево тестов на текущий момент выглядит следующим образом

Готовый скрипт можно найти здесь