Хочу разобрать для себя, как посредством инструмента единой конфигурации Ansible
приспособить его для взаимодействия с телефонными аппаратами Yealink
, у меня в парке устройств встречаются: Yealink T21_E2, T21P_E2, T31G.
К примеру, если телефонные аппараты настраиваются через AutoProvision
или вручную кому как нравится, то последующие действия можно явно для каждого аппарата с учетом тегирования задач выполнять средствами Ansible.
Ниже я покажу, каким образом я приспособил Ubuntu 22.04 + Ansible
к управлению аппаратами Yealink
, опробовано на моем парке устройств.
Вот об этом будет текущая пошаговая заметка.
Шаг №1:
Опираясь на заметку "Через Ansible с доменными Windows системами на Ubuntu 22.04 Server"
устанавливаю инструмент Ansible.
Шаг №2:
Опираюсь на заметку "Удаленное управление Yealink аппаратами"
указываю IP
адрес системы с которой можно будет взаимодействовать с телефонным аппаратом Yealink
через Action URI
. Так проделываем для каждого аппарата.
Шаг №3:
Проверяю, что с хоста Ansible
я могу взаимодействовать с аппаратом (ами) Yealink
, к примеру, включить DND
режим на аппарате, а затем выключить DND
режим:
ekzorchik@srv-ansible:~$ curl -X POST --ciphers 'DEFAULT:!DH' -d "" --user admin:Aa1234567aA https://192.168.10.10/cgi-bin/ConfigManApp.com?key=DNDOn -k -s -v * Trying 192.168.10.10:443... * Connected to 192.168.10.10 (192.168.10.10) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * Cipher selection: DEFAULT:!DH * TLSv1.0 (OUT), TLS header, Certificate Status (22): * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS header, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.2 (OUT), TLS header, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS header, Certificate Status (22): * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS header, Finished (20): * TLSv1.2 (IN), TLS header, Certificate Status (22): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.2 (OUT), TLS header, Supplemental data (23): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server did not agree to a protocol * Server certificate: * subject: C=CN; ST=Fujian; L=Xiamen; O=Yealink Network Technology Co.,Ltd.; OU=Yealink Equipment; CN=249ad847fe20; serialNumber=ffffffff-ffff-ffff-fff0-249ad847fe20; emailAddress=support@yealink.com * start date: Mar 20 00:31:35 2023 GMT * expire date: Mar 17 00:31:35 2033 GMT * issuer: C=CN; ST=Fujian; L=Xiamen; O=Yealink Network Technology Co.,Ltd.; OU=yealink.com; CN=Yealink Manufacturing CA; emailAddress=support@yealink.com * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. * Server auth using Basic with user 'admin' * TLSv1.2 (OUT), TLS header, Supplemental data (23): > POST /cgi-bin/ConfigManApp.com?key=DNDOn HTTP/1.1 > Host: 192.168.10.10 > Authorization: Basic YWRtaW46a2s1NTQ1NGx0 > User-Agent: curl/7.81.0 > Accept: */* > Content-Length: 0 > Content-Type: application/x-www-form-urlencoded > * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.2 (IN), TLS header, Supplemental data (23): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing * TLSv1.2 (IN), TLS header, Supplemental data (23): * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < X-Frame-Options: SAMEORIGIN < X-Content-Type-Options: nosniff < X-XSS-Protection: 1; mode=block < Strict-Transport-Security: max-age=31536000; includeSubDomains < Cache-Control: private, max-age=0, no-cache < Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; img-src * data:; frame-ancestors 'self' < Content-Type: text/html < Content-Length: 58 < Date: Thu, 07 Sep 2023 05:32:13 GMT < * TLSv1.2 (IN), TLS header, Supplemental data (23): <html> <body> <div id="_RES_INFO_"></div> </body> * Connection #0 to host 192.168.10.10 left intact </html>ekzorchik@srv-ansible:~$
Команда выше отработала успешно.
ekzorchik@srv-ansible:~$ curl -X POST --ciphers 'DEFAULT:!DH' -d "" --user admin:Aa1234567aA https://192.168.10.10/cgi-bin/ConfigManApp.com?key=DNDOff -k -s -v
Команда выше отработала успешно.
Шаг №4:
А теперь разберем, как сделать Playbook
и через него взаимодействовать с аппаратом(ами) Yealink
, но из общего Playbook
мне нужно будет запускать конкретный Task (Задачу):
ekzorchik@srv-ansible:~$ sudo nano /etc/ansible/playbook/voipyealink.yml --- - name: Enable/disable DND on Yealink phones via rest API hosts: localhost gather_facts: false vars: # set enable_dnd to 1 to enable it on the phone and set it to 0 to disable it on the phone #enable_dnd: '0' url_u: admin url_p: Aa1234567aA phone_ip: 192.168.10.10 tasks: - name: Enable DND delegate_to: localhost #when: "enable_dnd == '1'" uri: url: "https://{{ phone_ip }}/cgi-bin/ConfigManApp.com?key=DNDOn" url_username: "{{ url_u }}" url_password: "{{ url_p }}" method: POST body: "" force_basic_auth: yes status_code: 200 validate_certs: No register: _result #Для запуска конкретной задачи используем tag (тег) tags: - dndon - name: Disable DND delegate_to: localhost #when: "enable_dnd != '1'" uri: url: "https://{{ phone_ip }}/cgi-bin/ConfigManApp.com?key=DNDOff" url_username: "{{ url_u }}" url_password: "{{ url_p }}" method: POST body: "" force_basic_auth: yes status_code: 200 validate_certs: No register: _result #Для запуска конкретной задачи используем tag (тег) tags: - dndoff
На заметку: Во многих примерах имена переменных я видел что заключают значение в {{ }}
, но я так понял что на моей версии Ansible
данное не работает поэтому никак не обрамлял переменные: имя пользователя, пароль, IP-адрес; у меня:
ekzorchik@srv-ansible:~$ ansible --version ansible [core 2.15.2] config file = /etc/ansible/ansible.cfg configured module search path = ['/home/ekzorchik/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3/dist-packages/ansible ansible collection location = /home/ekzorchik/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] (/usr/bin/python3) jinja version = 3.0.3 libyaml = True ekzorchik@srv-ansible:~$
Шаг №5:
Отобразить какие задачи описаны в Playbook:
ekzorchik@srv-ansible:~$ sudo ansible-playbook /etc/ansible/playbook/voipyealink.yml --list-tags [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' playbook: /etc/ansible/playbook/voipyealink.yml play #1 (localhost): Enable/disable DND on Yealink phones via rest API TAGS: [] TASK TAGS: [dndoff, dndon] ekzorchik@srv-ansible:~$
Шаг №6:
Запускаю Playbook
где из него выполняю только конкретную задачу, для этого опираюсь на указанный атрибут в виде тега:
(включаю DND режим)
— отрабатывает успешно.
ekzorchik@srv-ansible:~$ sudo ansible-playbook /etc/ansible/playbook/voipyealink.yml --tags="dndon" [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [Enable/disable DND on Yealink phones via rest API] *************************************************************** TASK [Enable DND] ****************************************************************************************************** ok: [localhost] PLAY RECAP ************************************************************************************************************* localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(выключаю DND режим)
— отрабатывает успешно.
ekzorchik@srv-ansible:~$ sudo ansible-playbook /etc/ansible/playbook/voipyealink.yml --tags="dndoff" [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' PLAY [Enable/disable DND on Yealink phones via rest API] *************************************************************** TASK [Disable DND] ***************************************************************************************************** ok: [localhost] PLAY RECAP ************************************************************************************************************* localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ekzorchik@srv-ansible:~$
Шаг №7:
Дополняю Playbook
следующими задачами: перезагрузка:
ekzorchik@srv-ansible:~$ sudo nano /etc/ansible/playbook/voipyealink.yml - name: Reboot delegate_to: localhost #when: "enable_dnd != '1'" uri: url: "https://{{ phone_ip }}/cgi-bin/ConfigManApp.com?key=Reboot" url_username: "{{ url_u }}" url_password: "{{ url_p }}" method: POST body: "" force_basic_auth: yes status_code: 200 validate_certs: No register: _result #Для запуска конкретной задачи используем tag (тег) tags: - reboot ekzorchik@srv-ansible:~$ sudo ansible-playbook /etc/ansible/playbook/voipyealink.yml --tags="reboot"
По аналогии делаем для доступных команд строки в Playbook
, к примеру:
key=MUTE – включить режим без звука
key=X – завершить текущий вызов
key=OK/ENTER - отобразить на экране если выбрать меню "Статус"
какие команды еще доступы можно посмотреть также у меня в заметке: "Удаленное управление Yealink аппаратами"
В таком случае, не о какой предварительной настройки речь не идет, получается, что используем AutoProvision
, а для выполнения задач: DNDON & DNDOFF & Reboot
инструмент Ansible.
Ну пусть будет так. На этом я прощаюсь, буду в работе замечания, замечания будут отражены в виде пошаговых заметок на блоге, с уважением автор блога Олло Александр aka ekzorchik.