XEN: Простой скрипт для быстрого открытия vnc-консолей

в 8:57, , рубрики: xen, виртуализация, системное администрирование, скрипты, метки: , ,

Постановка задачи

Описание проблемы

В работе активно используется Xen с HVM виртуализацией. Часто бывает нужно получить доступ к консоли виртуальных машин, причем в том числе и тем, у кого доступа на севера с Xenом нет. У Xenа для этого есть возможность создавать для каждой виртуальной машины VNC-консоль, но каждый раз подключаться через VNC вручную неудобно.

Задача

Сделать веб-страницу со списком запущенных виртуальных машин и внедренным в нее VNC-апплетом, который можно открыть по нажатию ссылки. По пути разобраться с тем, как можно работать с Xenом из Питона.

Что получилось

Список запущенных domU

XEN: Простой скрипт для быстрого открытия vnc консолей

Сама VNC-консоль

XEN: Простой скрипт для быстрого открытия vnc консолей

Как получилось

Я использовал Питон и легкий веб-фреймворк CherrPy.

Из чего состоит

vm_console.py                # сам скрипт
static                       # директория со статическими файлами
static/table.htm             # шаблон для списка domU, в который потом подставляется сам список с помощью интерполяции
static/vnc.js                # javascript для открытия нового окна с VNC-апплетом и подстаивания размеров окна под апплет
static/vnc.htm               # шаблон для нового окна с VNC-апплетом, в который нужные данные подставляются с помощью интерполяции
static/tightvnc-jviewer.jar  # java-апплет для подключения к VNC, взят с http://www.tightvnc.com/
static/styles.css            # стили для таблицы со списком domU, взяты с http://veerle-v2.duoh.com/blog/comments/a_css_styled_table/
static/images                # картинки для стилей таблицы
static/images/bg_header.jpg
static/images/bullet1.gif

Сам скрпит

Логика работы скрипта следующая:

По запросу веб-страницы
    Получить список запущенных domU и портов их VNC-консолей
    Отобразить этот список
По нажатию на соответвующий порт
    Открыть новую страницу с внедренным в нее java VNC-апплетом
    Передать этому апплету нужный адрес и порт

Импортируем нужные модули: сам cherrypy, модуль для взаимодействия с XEN-сервером и модуль для регулярных выражений чтобы правильно заматчить адрес и порт VNC-сервера:

import cherrypy
from xen.util.xmlrpcclient import ServerProxy
import re

Класс для получения списка запущенных domU и формирования таблицы:

class xen():
    """Communicates with xen via rpc"""
    @staticmethod
    def get_domains():
        """Gets a dictionary with 'Domain Name':'VNC host:port' structure"""
        server = ServerProxy('httpu:///var/run/xend/xmlrpc.sock')
        domains = server.xend.domains_with_state(True, 'all', 1)
        domain_list = {}
        for first_level in domains:                             # iterate through first level parameters
            for second_level in first_level:                    # iterate through second level parameters
                if second_level[0] == "name" and second_level[1] != "Domain-0":
                    domain_list_current = second_level[1]
                if second_level[0] == "device":
                    for third_level in second_level[1]:         # iterate through third level subparameters
                        if third_level[0] == "location" and re.match("d+.d+.d+.d+:dddd", third_level[1]):
                            domain_list[domain_list_current] = str(third_level[1])
        return domain_list

    @staticmethod
    def create_domain_table():
        """Creates table from domain list"""        
        table = """<table id='mytable' cellspacing='0'><caption>List of active domUs</caption>
                   <th scope="col" class="nobg">domU</th>
                   <th scope="col">VNC host:port</th>
            """
        domain_list = xen.get_domains()
        for k, v in domain_list.iteritems():
            link = v.split(':', 1)[1]
            table += """
                <tr>
                <th class="spec" scope="row">%s</th>
                <td><a href="javascript:vnc_console('/vnc/%s')" target='_blank'>%s</a></td>
                </tr>
                """ % (k, link, v)

        table += "</table>"
        return table

Он подключается к XEN-серверу через сокет, и вытаскивает из него спикок запущенных domU со множеством атрибутов. Затем из этих атрибутов вытаскиваются нужные: имя domU и адрес: порт VNC-сервера. После этого формируется таблица со списком запущенных domU.

Метод подключения я подстмотрел в идущей в поставке с ксеном утилите xm, у меня она лежит в

/usr/lib64/python2.7/site-packages/xen/util/xmlrpcclient.pyc

Возможно в будем, если будет время, я передалю подключение ко XEN-серверу через XenApi, что более правильно.

Класс для отображения веб-страницы:

class listvm(object):
    def index(self, port=None):
        """Just a stub"""
        return """<h1><a href="/vnc/">vnc</a></h1>"""
    index.exposed = True
    def vnc(self, port=None):
        """Show running vm's or open vnc applet"""
        if port:
            template = open("static/vnc.htm", 'r').read() 
            return template % port 
        else:
            template = open("static/table.htm", 'r').read()
            return template % xen.create_domain_table()
    vnc.exposed = True

Нас интересует функция vnc. Eсли перейти на

<адрес сервера>/vnc

она отобразит список запущенных domU, если же передать ей нужный порт через слеш, например

<адрес сервера>/vnc/5900

она запустит нужную консоль. Консоли запускаются с помощюь выдранной из Proxmox VE функции на javascript. После открытия апплета еще одна функция из Proxmox VE подстраивает размеры нового окна под необходимые.

Конфиг вебсервера cherrypy, здесь все тривиально:

server_config = {
                  'server.socket_host': '127.0.0.1',
                  'server.socket_port': 80,
                  'tools.staticdir.root': "/usr/local/vm_console",
                  'tools.staticdir.debug': True,
                }
cherrypy.config.update(server_config)

listvm_config = {
                '/static':
                    {'tools.staticdir.on': True,
                     'tools.staticdir.dir': "static",
                    }
                }
cherrypy.tree.mount(listvm(), '/', config=listvm_config)

cherrypy.engine.start()
cherrypy.engine.block()

Хочу потыкать

Я выложил все на github, взять можно здесь: github.com/sistemshik/vm_console

Автор: sistemshik

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js