Глава 3. Подключение к домену
Содержание
Как уже упоминалось в предыдущей главе, соединение выступает основой для любого действия и объекта в обсуждаемой нами системе libvirt. Всякий логический элемент, который желает взаимодействовать с libvirt, быдь то virsh, virt-manager или программа, применяющая библиотеку libvirt, вначале должен получить некое соединение к соответствующему демону libvirt в самом узле хоста, к которому у него имеется заинтересованность. Некое соединение описывает не только занчение типа технологии виртуализации, с которой желает взаимодействовать данный агент (QEMU, XEN, UML и так далее), но также все методы аутентификации, которые требуются для подключения к такому ресурсу.
Данная глава подробно описывет сам объект соединения, включая то как открывать и закрывать такой объект, как подключаться к некому определённому драйверу и связанным с ним доменам, те форматы URI, которые описывают данное соединение, необходимые возможности хоста, а также имеющееся физическое оборудование этого хоста.
Самая первая вещь которую следует сделать агенту libvirt, это выполнить вызов функции
virInitialize
или одной из имеющихся функций подключения libvirt Python для
получения некого экземпляра класса virConnect
. Этот экземпляр будет применяться
в последующих действиях. Модуль libvirt Python предоставляет три различных функции для подключения к некому ресурсу.
conn = libvirt.open(name)
conn = libvirt.openAuth(uri, auth, flags)
conn = libvirt.openReadOnly(name)
Во всех трёх случаях имеется параметр name
, который ссылается на значение
URI того гипервизора, к которому требуется подключаться. Глава 2
предоставляет все подробности относительно различных допустимых форматов URI. Если значением URI является
None
, тогда libvirt применит некую эвристику и выставит на пробу какой- то
подходящий драйвер гипервизора. Хотя это и может быть удобным для разработчиков выполнять проверку по месту,
&qout;как есть&qout;, настоятельно рекомендуется чтобы приложения не полагались на подобную пробную логику, ибо она
может измениться в любой момент. Приложения должны всегда в явном виде запрашивать какое именно подключение
гипервизора желательно представлением его в URI.
Основное отличие между этими тремя методами состоит в том способе, которым они осуществляют аутентификацию и получаемый в результате предоставляемый ими уровень авторизации.
Функция open
попытается открыть соединение для полного доступа с чтением- записью.
Она не имеет никаких средств предоставления обратных вызовов аутентификации, а потому она будет успешной лишь для тех
подключений, при которых аутентификация может быть осуществлена на основании прав доступа самого данного приложения.
Листинг 3-1 показывает как подключаться к имеющейся системе
для получения некого обхекта соединения, который будет в дальнейшем применяться для этого подключения.
Листинг 3-1. Применение open
# Listing-1.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
print('Connection successful.')
conn.close()
print('Connection closed.')
exit(0)
Данный пример открывает соединение на чтение- запись к имеющемуся системному драйверу гипервизора QEMU, убеждается что оно успешно и, если это так, закрывает данное подключение. Для получения дополнительных сведений относительно URI libvirt обратитесь к Главе 2.
Функция openReadOnly
попробует открыть некое соединение для доступа только на
чтение (Листинг 3-2). Такое подключение имеет ограниченный
набор допустимых вызовов методов и обычно полезна для отслеживания приложений, которые не должны допускать изменений.
Как и в случае с open
, этод метод не имеет средств для обратных вызовов
аутентификации, а потому он полагается на праметры доступа.
Почти все функции, возвращающие информационные данные могут применяться в редиме с доступом только для чтения. В из состав входит большинство описываемых в данной главе функций. Очевидно, изменение имеющихся доменов внутри подключения невозможно при соединении с доступом только на чтение, причём включая запуск и останов домена.
Листинг 3-2. Применение openReadOnly
# Example-2.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.openReadOnly('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
conn.close()
exit(0)
Этот пример открывает подключение с доступом только для чтения к системноу драйверу гипервизора QEMU, убеждается что оно успешное и, если это так, закрывает данное подключение. Для получения дополнительных сведений относительно URI libvirt обратитесь к Главе 2.
Функция openAuth
является наиболее гибкой и действенной, делая предыдущие
две функции избыточными. Она получает некий дополнительный параметр, который предоставляет некий
list
Python, который содержит параметры доступа аутентификации из вашего прикладного
приложения клиента. Значение параметра flags
позволяет приложению выполнять запросы
на подключения с доступом только для чтения, если это желательно, при помощи установки флага VIR_CONNECT_RO
.
Листинг 3-3 показывает образец программы Python, которая
применяет openAuth
с правами доступа указанных именем пользователя и его паролем.
Как и в случае с open
, этот метод не имеет никаких средств предоставления обратных
вызовов аутентификации, а потому она будет успешной лишь для тех подключений, при которых аутентификация может быть
осуществлена на основании прав доступа самого данного приложения.
Листинг 3-3. Применение openAuth
# Example-3.py
from __future__ import print_function
import sys
import libvirt
SASL_USER = "my-super-user"
SASL_PASS = "my-super-pass"
def request_cred(credentials, user_data):
for credential in credentials:
if credential[0] == libvirt.VIR_CRED_AUTHNAME:
credential[4] = SASL_USER
elif credential[0] == libvirt.VIR_CRED_PASSPHRASE:
credential[4] = SASL_PASS
return 0
auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE], \
request_cred, None]
conn = libvirt.openAuth('qemu+tcp://localhost/system', auth, 0)
if conn == None:
print('Failed to open connection to qemu+tcp://localhost/system', \
file=sys.stderr)
exit(1)
conn.close()
exit(0)
Чтобы проверить эту программу, должны быть представлены все следующие настройки:
-
/etc/libvirt/libvirtd.conf
listen_tls = 0 listen_tcp = 1 auth_tcp = "sasl"
-
/etc/sasl2/libvirt.conf
mech_list: digest-md5
-
Некий пользователь программы virt был добавлен в имеющуюся базу данных SASL. Как правило, это некая реляционная база данных, настроенная под хранение прав доступа SASL.
-
libvirtd
был запущен с--listen
.
Если соблюдены все настройки, Листинг 3-3 может воспользоваться установленными именем пользователя и его паролем и разрешить к libvirtd доступ по чтению- записи.
В отличии от интерфейса C libvirt, Python не предоставляет настраиваемых обратных вызовов для получения прав достопа.
Также следует заметить, что права доступа SASL это не только доступный для данного API метод аутентификации. Также имеется большое число доступных взаимодействий с правами доступа, которые включают PolicyKit (PKI), GSSAPI, SSH, ESX и XEN. Могут быть настроены любые из них.
Некое подключение, когда оно больше не требуется, может быть высвобождено вызовом метода
close
из класса virConnection
.
Соединения являются объектами с подсчётом ссылок, поэтому для каждого вызова функции open
должен иметься соответствующий вызов метода close
(Листинг 3-4).
Как уже упоминалось, соединения подсчитывают число ссылок на них; такой счётчик в явном виде увеличивает своё значение
при первоначальном open
, openAuth
и им подобным.
Он также временно увеличивается прочими методами, которые полагают что данное соединение остаётся рабочим. Вызов функции
open
должен иметь соответствующий ему close
, а все
прочие ссылки высвобожденными по завершению соответствующих операций.
В Python счётчики ссылок могут автоматически уменьшаться когда некий экземпляр класса покидает его зону действия или когда завершается данная программа. Когда же завершается сам процесс, счётчики ссылок также мкидываются в ноль.
Листинг 3-4. Применение close с дополнительными ссылками
# Example-4.py
from __future__ import print_function
import sys
import libvirt
conn1 = libvirt.open('qemu:///system')
if conn1 == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
conn2 = libvirt.open('qemu:///system')
if conn2 == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
conn1.close()
conn2.close()
exit(0)
Обратите также внимание на то, что все прочие экземпляры класса, ассоциированные с неким соединением
(virDomain
, virNetwork
и прочие) будут
удерживать ссылку на это соединение.
Для идентификации подключений к гипервизору libvirt применяет URI (uniform resource identifiers, единообразные идентификаторы ресурсов). Как локальные, так и удалённые гипервизоры адресуются со стороны libvirt при помощи URI. Сама схема URI и путь определяют гипервизор для подключения, в то время как часть хоста в этом URI задаёт его местоположение.
Локальные URI libvirt имеют один из следующих видов:
driver:///system
driver:///session
driver+unix:///system
driver+unix:///session
Все прочие URI libvirt рассматриваются как удалённые и ведут себя именно так, даже если подключаются локально. Для получения дополнительных сведений об удалённых URI обратитесь к разделу с названием Удалённые URI.
В настоящее воемя поддерживаются драйверы, перечисленные в Таблице 3-1.
Драйвер | Описание |
---|---|
|
Для управления гостями qemu и KVM |
|
Для управления гостями Xen старого стиля (Xen 3.1 и старше) |
|
Для управления гостями Xen нового стиля |
|
Для управления гостями UML |
|
Для контейнерами Linux |
|
Для управления гостями VirtualBox |
|
Для управления контейнерами OpenVZ |
|
Для управления гостями VMware ESX |
|
Для управления гостями OpenNebula |
|
Для управления гостями гипревизора Power |
Листинг 3-5 показывает как подключаться к некому локальному гипервизору QEMU с применением локального URI.
Листинг 3-5. Подключение к локальному гипервизору QEMU
# Example-5.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
conn.close()
exit(0)
Удалённые URI имеют общую форму, показанную здесь ([...]
обозначает необязательную
часть):
driver[+transport]://[username@][hostname][:port]/[path][?extraparameters]
Все компоненты данного URI поясняются в Таблице 3-2.
Компонент | Описание |
---|---|
|
Само название того драйвера гипервизора libvirt, к которому выполняется
подключение. Оно в точности то же самое, что применяется и в локальном URI. Некими примерами выступают
|
|
Название одного из описанных ранее в этом разделе видов доставки данных. Возможными
значениями могут быть |
|
Когда для транспортировки данных применяется SSH, данный компонент делает возможным выбор имени пользователя, который отличается от имени текущего зарегистрированного пользователя. |
|
Полностью определённое имя хоста данной удалённой машины. Когда применяются TLS с сертификатами x509 или SASL с подключаемыми модулями GSSAPI/ Keberos, критически важно чтобы это имя хоста соответствовало имени хоста, используемого в соответствующем сертификате x509 сервера/ правиле Kerberos. Отсутствие такого соответствия с гарантией приведёт к отказу в аутентификации. |
|
Редко требуется, только если SSH или libvirtd не были настроены для работы с нестандартным портом TCP. Значением по умолчанию является 22 для транспорта данных SSH, 16509 для транспорта данных TCP и 16514 для транспорта данных TLS. |
|
Значением пути должен быть тот же самый путь, который используется для самого
локального URI драйвера гипервизора. Для Xen это всегда |
|
Парааметры тонкой настройки некоторых аспектов для данного удалённого подключения, которые будут более подробно рассмотрены в нашем следующем разделе. |
На основании предоставленной здесь информации, а также при помощи сведений на приведённые ранее в этой главе URI, специфичные для гипервизоров, у нас имеется возможность предложить некие образцы URI удалённого доступа.
-
Подключение к некому удалённому гипервизору Xen в хосте
node.example.com
с применением транспортировки данных через SSH туннель и имени пользователя SSHroot
:xen+ssh://root@node.example.com/
-
Подключение к некому удалённому гипервизору QEMU в хосте
node.example.com
с применением TLS с сертификатами x509:qemu://node.example.com/system
-
Подключение к некому удалённому гипервизору Xen в хосте
node.example.com
с применением TLS с сертификатами x509 (Обратите внимание: здесь вы допускаете компромисс со своей безопасностью):xen://node.example.com/?no_verify=1
-
Подключение к некому локальному экземпляру QEMU поверх нестандартного сокета Unix (в этом случае в явном виде поддерживается полный путь к такому сокету Unix):
qemu+unix:///system?socket=/opt/libvirt/run/libvirt/libvirt-sock
-
Подключение к некому демону libvirtd, предлагающему незашифрованное соединение TCP/IP по некому альтернативному порту 5000 и применяющему тестовый драйвер с какой- то конфигурацией по умолчанию:
test+tcp://node.example.com:5000/default
Для удалённого URI могут добавляться дополнительные параметры как часть строки запроса (та часть, которая следует за
?
). Удалённые URI распозгают те дополнительные параметры, которые показаны в
Таблице 3-3. Всё прочее передаётся без изменений самому
получателю. Отметим, что значения параметров обязаны быть URI- экранированными. Для получения дополнительных сведений
обратитесь к http://xmlsoft.org/html/libxml-uri.html%2523xmlURIEscapeStr.
Название | Транспорт | Описание |
---|---|---|
|
любой транспорт |
Значение URI локального гипервизора, передаваемое в соответствующий удалённый
метод
|
|
|
Значение внешней команды. Для транспорта
|
|
|
Значение внешней команды. Для транспорта
|
|
|
Значение команды Netcat в соответствующей удалённой машине. Хначением по умолчанию
является
где
|
|
|
Клиенты проверяют что сертификат сервера отключён, когда установлено не нулевое значение. Отметим, что для отклбчения проверок сервером сертификатов клиента или IP адресов вам требуется изменить значения настроек libvirtd. Пример:
|
|
|
Если установлено не нулевое значение, это предотвращает запросы SSH на ввод пароля когда нет возможности зарегистрироваться автоматически в этой удалённой машине (например, при использовании агента SSH). Применяйте когда у вас нет доступа к терминалу, например в программах с графическим интерфейсом, которые применяют libvirt. Пример:
|
Листинг 3-6 показывает как подключаться к некому гипервизору QEMU с применением удалённого URI.
Листинг 3-6. Подключение к удалённому гипервизору QEMU
# Example-6.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu+tls://host2/system')
if conn == None:
print('Failed to open connection to qemu+tls://host2/system', \
file=sys.stderr)
exit(1)
conn.close()
exit(0)
Для получения информации относительно возможностей определённого хоста можно применять метод
getCapabilities
. В случае успеха он возвращает некую строку Python, которая
содержит XML значение возможностей (описываемых нами через мгновение). В случае возникновения ошибки будет возвращено
None
. Листинг 3-7
демонстрирует применение такого метода getCapabilities
.
Листинг 3-7. Применение getCapabilities
# Example-7.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
caps = conn.getCapabilities() # caps will be a string of XML
print('Capabilities:\n'+caps)
conn.close()
exit(0)
Имеющийся формат возможностей XML предоставляет сведения относительно присутствующей технологии виртуализации. В частности, он описывает сами возможности данного хоста виртуализации, его драйвера виртуализации, а также те виды гостей, которые данная технология виртуализации способна запускать. Отметим, что сами возможности XML могут различаться (и на самом деле разнятся) на основе применяемого драйвера libvirt. Листинг 3-8 представляет некий образец полученных возможностей в XML.
Листинг 3-8. Пример возможностей драйвера QEMU
<capabilities>
<host>
<cpu>
<arch>x86_64</arch>
</cpu>
<migration_features>
<live/>
<uri_transports>
<uri_transport>tcp</uri_transport>
</uri_transports>
</migration_features>
<topology>
<cells num="1">
<cell id="0">
<cpus num="2">
<cpu id="0"/>
<cpu id="1"/>
</cpus>
</cell>
</cells>
</topology>
</host>
<guest>
<os_type>hvm</os_type>
<arch name="i686">
<wordsize>32</wordsize>
<emulator>/usr/bin/qemu</emulator>
<machine>pc</machine>
<machine>isapc</machine>
<domain type="qemu">
</domain>
<domain type="kvm">
<emulator>/usr/bin/qemu-kvm</emulator>
</domain>
</arch>
<features>
<pae/>
<nonpae/>
<acpi default="on" toggle="yes"/>
<apic default="on" toggle="no"/>
</features>
</guest>
<guest>
<os_type>hvm</os_type>
<arch name="x86_64">
<wordsize>64</wordsize>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<machine>pc</machine>
<machine>isapc</machine>
<domain type="qemu">
</domain>
<domain type="kvm">
<emulator>/usr/bin/qemu-kvm</emulator>
</domain>
</arch>
<features>
<acpi default="on" toggle="yes"/>
<apic default="on" toggle="no"/>
</features>
</guest>
</capabilities>
Совет | |
---|---|
Остальная часть обсуждения будет посвящена такому XML с применением нотации Xpath. В представляемых XML
возможностях всегда имеется подчинённый документ |
Подчинённый документ <host>
описывает возможности самого хоста.
<host><uuid>
отображает значение UUID данного хоста. Оно проистекает
из значения UUID SMDIOS если таковой доступен и допустим, либо может быть переопределено в
libvirtd.conf
неким персональным значением. Когда не установлено ни одно из этих
свойств, при каждом перезапуске libvirtd будет вырабатываться временный UUID.
Подчинённый документ <host><cpu>
описывает все возможности ЦПУ данного
хоста. Он применяется libvirt при принятии решения может ли надлежащим образом быть запущен некий гость в данной конкретной
машине, а также для консультаций при миграции в реальном масштабе времени для определения того будет ли машина назначения
поддерживать все необходимые флаги для запуска такого гостя.
<host><cpu><arch>
является необходимым узлом XML, который
описывает всю лежащую в основе архитектуру ЦПУ. На момент написания все драйверы libvirt инициализируют из получаемого
вывода uname(2)
.
<host><cpu><features>
является неким не обязательным подчинённым
документом, который описывает дополнительные свойства расположенного в этом хосте ЦПУ. На момент написания используется лишь
в драйвере xen для выдачи отчёта о наличии или отсутствии соответствующего флага svm
или vmx
, а также для получения отчёта о наличии или отсутствии флага
pae
.
<host><cpu><model>
является необязательным элементом, который
описывает ту модель, на который более всего походит ЦПУ данного хоста. Те модели ЦПУ, о которых известно в настоящее время
libvirt имеются в файле cpu_map.xml
.
<host><cpu><feature>
состоит из нуля или более элементов,
который описывает дополнительные свойства ЦПУ имеющегося в этом хосте ЦПУ, которые не содержатся в
/host/cpu/model
.
<host><migration_features>
является необязательным подчинённым
документом, который описывает те свойства миграции, которые этот драйвер поддерживает в данном хосте (если они имеются).
Когда данный подчинённый документ не существует, миграция не поддерживается. На момент написания миграцию поддерживали
драйверы XEN, QEMU и ESX.
Данный узел XML <host><migration_features><live>
существует
если этот драйвер поддерживает миграцию в реальном масштабе времени.
<host><migration_features><uri_transports>
является некий
необязательный подчинённый документ, который описывает альтернативные механизмы соединения миграции. Такие
альтернативные механизмы соединения могут быть полезны в системах виртуализации с несколькими сетевыми контроллерами
(групповых, multihomed). Например, команда virsh migrate
может быть подключена к
своему источнику миграции через 10.0.0.1
и к получателю через
10.0.0.2
. Однако из- за политики безопасности, нашему источнику данной миграции
может быть позволено только для непосредственного общения с получателями этой миграции через
192.168.0.0/24
. В этом случае применение такого альтернативного механизма
подключения успешно допустило бы подобную миграцию. На момент написания драйвер xen поддерживает свой альтернативный
механизм миграции xenmigr
, в то время как драйвер qemu поддерживает свой
альтернативный механизм миграции tcp
. За дополнительными сведениями относительно
миграции обращайтесь к соответствующей документации.
Подчинённый документ <host><topology>
описывает присутствующую
топологию NUMA данной машины хостинга; каждый узел NUMA представлен
<host><topology><cells><cell>
и описывает какие ЦПУ
находятся в этом узле NUMA. Если данная машина хостинга является машиной UMA (не- NUMA), тогда будет иметься лишь одна
ячейка, а все ЦПУ будут помещены в эту ячейку. Это слишком специфично для оборудования, а потому будет разниться для
различных машин.
<host><secmodel>
является необязательным подчинённым документом,
который определяет значение используемой в данном хосте модели безопасности.
<host><secmodel><model>
отображает значение названия данной модели
безопасности, в то время как
<host><secmodel>https://doi.org/10.1007/978-1-4842-4862-1_3
отображает
значение интерпретации. За дополнительными сведениями относительно безопасности обращайтесь к
Главе 14.
Всякий подчинённый документ <guest>
описывает некий вид гостя, который
способен запускать этот драйвер хоста. Данное описание содержит значение архитектуры такого гостя (например, i686) помимо
предоставляемого этому гостю ABI (например, HVM, XEN или UML), как это представлено в
Таблице 3-4.
<guest><os_type>
является обязательным элементом, который задаёт
значение типа гостя.
Драйвер | Тип гостя |
---|---|
|
Всегда |
|
Либо |
|
Всегда |
|
Всегда |
|
Всегда |
|
Всегда |
|
Всегда |
|
В настоящее время не поддерживается |
<guest><arch>
выступает корнем некого подчинённого документа, определяющего
различные стороны виртуального оборудования для данного типа гостя. Он имеет единственный атрибут с названием
name
, который может применяться для ссылки на данный подчинённый документ.
<guest><arch><wordsize>
является необходимым элементом, определяющим сколько
бит применяется в машинном слове данного гостя. Обычно это 32 или 64.
<guest><arch><emulator>
является необчзательным элементом, который
задаёт значение пути по умолчанию для эмулятора данного типа гостя. Обратите внимание, что этот эмулятор может перекрываться
значением элемента <guest><arch><domain><emulator>
для
типов гостей, которым требуются альтернативные исполняемые файлы.
<guest><arch><loader>
является необязательным элементом, который
описывает значение пути по умолчанию необходимого для данного типа гостя загрусчика встроенного программного обеспечения
(firmware). Обратите внимание, что этот загрузчик может перекрываться значением элемента
<guest><arch><domain><loader>
для
типов гостей, которые используют альтернативные загрузчики. В настоящее время применяется драйвером XEN для гостей HVM.
Может присутствовать ноль или более элементов <guest><arch><machine>
,
которые определяют значения типов по умолчанию тех машин, которые способен эмулировать данный эмулятор гостя. Такие
"машины" обычно представляют свой ABI или интерфейс оборудования, с которого способен запускаться некий гость.
Обратите внимание, что этот тип машины может перекрываться значениями элементов
<guest><arch><domain><machine>
для
тех технологий виртуализации, которые предоставляют альтернативные типы машин. Обычными значениями для него являются
pc
и isapc
, что означает, соответственно,
обычный PC на основе PCI или более ранний PC на основе ISA.
Может иметься ноль или более поддеревьев XML <guest><arch><domain>
(хотя при нуле поддеревьев XML <guest><arch><domain>
из этого
драйвера не могут быть запущены никакие гости). Каждое поддерево /guest/arch/domain
имеет необязательные элементы <emulator>
,
<loader>
и <machine>
, которые
перекрывают соответствующие определённые ранее значения по умолчанию. Для всех данных опускаемых элементов применяются
установленные по умолчанию значения.
Необязательный подчинённый документ <guest><machine>
определяет различные
дополнительные свойства гостя, которые могут быть включены или отключены, совместно с их значением состояния по умолчанию
и тем, могут ли они переключаться во включённое или отключённое состояние.
Для получения информации о хосте виртуализации, включая само имя хоста, максимально поддерживаемое число гостевых ЦПУ и т.п.
могут применяться различные методы virConnection
Python.
Метод gethostname
может использоваться для получения самого имени хоста данного
хоста виртуализации, возвращаемое gethostname()
. Он вызывается через экземпляр
virConnection
и, в случае успеха, возвращает некую строку, содержащую название
хоста, возможно расширенное до полностью определённого доменного имени. Если произошла ошибка, вместо этого будет
возвращено None
. Будет обоснованным для самого вызывающего освободить ту память,
которая возвращена данным вызовом метода. Листинг 3-9
демонстрирует применение gethostname
.
Листинг 3-9. Применение getHostname
# Example-9.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
host = conn.getHostname()
print('Hostname:'+host)
conn.close()
exit(0)
Для получения значения максимального числа виртуальных ЦПУ для каждого гостя, которое поддерживается лежащей в основе
технологией виртуализации, может применяться метод getMaxVcpus
. Он получает некий
"тип" виртуализации в качестве входного параметра (которым может быть None
) и,
в случае успеха возвращать значение числа поддерживаемых виртуальных ЦПУ. Если произошла ошибка, вместо этого будет возвращено
-1
. Листинг 3-10
демонстрирует применение getMaxVcpus
.
Листинг 3-10. Применение getMaxVcpus
# Example-10.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
vcpus = conn.getMaxVcpus(None)
print('Maximum support virtual CPUs: '+str(vcpus))
conn.close()
exit(0)
Метод getInfo
может быть применён для получения различной информации относительно
определённого хоста виртуализации. Этот метод возвращает в случае успеха list
Python и None
в том случае, когда произошла ошибка.
Таблица 3-5 перечисляет участников данного
list
Python.
Участник | Описание |
---|---|
|
Указывающая значение модели ЦПУ строка |
|
Размер памяти в MiB |
|
Число активных ЦПУ |
|
Ожидаемая частота ЦПУ (МГц) |
|
Число узлов NUMA, для единообразного доступа к памяти 1. Неоднородный доступ к памяти (NUMA, nonuniform memory access) это метод настройки некого кластера микропроцессоров в системе со множеством процессоров с тем, чтобы они имели возможность разделять память локально. |
|
Число разъёмов (сокетов) ЦПУ на узел |
|
Число ядер на сокет |
|
Число потоков на ядро |
Листинг 3-11
демонстрирует применение getInfo
.
Листинг 3-11. Применение getInfo
# Example-12.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
nodeinfo = conn.getInfo()
print('Model: '+str(nodeinfo[0]))
print('Memory size: '+str(nodeinfo[1])+'MB')
print('Number of CPUs: '+str(nodeinfo[2]))
print('MHz of CPUs: '+str(nodeinfo[3]))
print('Number of NUMA nodes: '+str(nodeinfo[4]))
print('Number of CPU sockets: '+str(nodeinfo[5]))
print('Number of CPU cores per socket: '+str(nodeinfo[6]))
print('Number of CPU threads per core: '+str(nodeinfo[7]))
conn.close()
exit(0)
Для получения объёма свободной памяти (в байтах) в каком- то или во всех узлах NUMA данной системы можно
воспользоваться методом getCellsFreeMemory
. Он получает в качестве параметра
на входе значение начальной ячейки и максимальное число ячеек для получения данных от них. В случае успеха будет возвращён
некий list
Python со значениями объёма свободной памяти для каждого узла.
В случае неудачи возвращается None
.
Листинг 3-12
демонстрирует применение getCellsFreeMemory
.
Листинг 3-12. Применение getCellsFreeMemory
# Example-13.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
nodeinfo = conn.getInfo()
numnodes = nodeinfo[4]
memlist = conn.getCellsFreeMemory(0, numnodes)
cell = 0
for cellfreemem in memlist:
print('Node '+str(cell)+': '+str(cellfreemem)+' bytes free memory')
cell += 1
conn.close()
exit(0)
Данная функция возвратит общий объём доступной памяти для всех узлов в вашей системе. Если эта система не имеет узлов NUMA, тогда она возвратит некий отдельный узел и всю доступную ему память. Вот показан некий пример выдачи от отдельного узла:
Node 0: 13226958848 bytes free memory
Метод getType
можно применять для получения типа виртуализации, рименяемой при
данном подключении. В случае успеха он возврвщает некую строку, предоставляющую значение типа применяемой виртуализации.
В случае возникновения ошибки вместо этого будет возвращено None
.
Листинг 3-13
демонстрирует применение getType
.
Листинг 3-13. Применение getType
# Example-13.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
print('Virtualization type: '+conn.getType())
conn.close()
exit(0)
Если не передаётся никакой параметр name
(либо значением
name
выступает None
),
тогда возвращается в виде целого номер версии применяемой библиотеки libvirt. Если же getVersion
передаётся и оно ссылается на некий подключённый к данной библиотеке libvirt драйвер, тогда этот метод возвратит некий
кортеж (library version
, driver version
).
Значением возвращаемого названия яляется только само название драйвера; например, как KVM, так и QEMU гости обслуживаются
одним драйвером для qemu:// URI
, а потому возврат
QEMU
merely не указывает на то присутствует ли ускорение KVM
(Листинг 3-14).
Если же переданное имя указывает на несуществующий драйвер, тогда будет получена исключительная ситуация
"no support for hypervisor" (нет поддержки гипервизора). Номера версии являются целыми, а именно:
1000000*основная + 1000*вспомогательная + выпуск
.
Листинг 3-14. Применение virConnectGetVersion
Example-14.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
ver = conn.getVersion()
print('Version: '+str(ver))
conn.close()
exit(0)
Метод getLibVersion
может использоваться для получения значения версии того
программного обеспечения libvirt, которое применяется в данном хосте. В случае успеха он возвращает строку Python
с данной версией; в противном случае он возвращает None
. Когда возвращается
номер версии, он имеет формат 1000000*версия
Листинг 3-15
демонстрирует применение getLibVersion
.
Листинг 3-15. Применение getLibVersion
# Example-15.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
ver = conn.getLibVersion();
print('Libvirt Version: '+str(ver));
conn.close()
exit(0)
Для получения значения URI текущего соединения можно воспользоваться методом getURI
.
Хотя обычно это та же самая строка, которая передаётся в вызов open
,
лежащий в основе драйвер может иногда приводить эту строку к каноническому виду. Такой метод выполнит возврат строки в
канонической версии. В случае успеха он возвращает строку URI. При возникновении ошибки вместо этого будет возвращаться
None
. Листинг 3-16
демонстрирует применение getURI
.
Листинг 3-16. Применение getURI
# Example-16.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
uri = conn.getURI()
print('Canonical URI: '+uri)
conn.close()
exit(0)
Для получения того шифруется ли данное соединение, можно применить метод isEncrypted
.
В члучае успеха он возвращает 1
для шифруемого метода и 0
для соединения без шифрации. В случае возникновения ошибки будет возвращаться -1
.
Листинг 3-17
демонстрирует применение isEncrypted
.
Листинг 3-17. Применение isEncrypted
# Example-17.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
print('Connection is encrypted: '+str(conn.isEncrypted()))
conn.close()
exit(0)
Метод isSecure
может применяться для вывода того будет ли шифроваться данное подключение.
Некое соединение будет классифицировано как безопасное либо когда оно шифруется, либо запускается в канале, которое не
является уязвимым для подслущивания (как сокет домена UNIX). В случае успеха будет возвращаться 1
для безопасного подклбчения и 0
для ненадёжного соединения. В случае ошибки
будет возвращаться -1
. Листинг 3-18
демонстрирует применение isSecure
.
Листинг 3-18. Применение isSecure
# Example-18.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
print('Connection is secure: '+str(conn.isSecure()))
conn.close()
exit(0)
Данный метод применяется дл определения того является ли данное подключение к имеющемуся гипервизору всё ещё действующим. Некое соединение будет классифицировано как действующее (alive) если он локальное, либо запкущено в канале (TCP или сокет UNIX), который не закрыт (Листинг 3-19).
Листинг 3-19. Применение isAlive
# Example-19.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
alive = conn.isAlive()
print("Connection is alive = " + str(alive))
conn.close()
exit(0)
Данный метод сравнивает заданное описание ЦПУ со значением ЦПУ хоста. Такое описание XML является тем же самым, что и применяемое для задания домена значение описания XML (Листинг 3-20).
Листинг 3-20. Применение compareCPU
# Example-20.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
xml = '<cpu mode="custom" match="exact">' + \
'<model fallback="forbid">kvm64</model>' + \
'</cpu>'
retc = conn.compareCPU(xml)
if retc == libvirt.VIR_CPU_COMPARE_ERROR:
print("CPUs are not the same or ther was error.")
elif retc == libvirt.VIR_CPU_COMPARE_INCOMPATIBLE:
print("CPUs are incompatible.")
elif retc == libvirt.VIR_CPU_COMPARE_IDENTICAL:
print("CPUs are identical.")
elif retc == libvirt.VIR_CPU_COMPARE_SUPERSET:
print("The host CPU is better than the one specified.")
else:
print("An Unknown return code was emitted.")
conn.close()
exit(0)
Данный метод запрашивает объём свободной памяти (Листинг 3-21). Обратите внимание, что большинство API libvirt предоставляет размер свобоной памяти в байтах, и данная функция возвращает значение в байтах.
Листинг 3-21. Применение getFreeMemory
# Example-21.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
mem = conn.getFreeMemory()
print("Free memory on the node (host) is " + str(mem) + " bytes.")
conn.close()
exit(0)
Данный метод запрашивает у своей системы хостинга свободные страницы с предписанным размером. На входе значением
параметра pages
выступает некий list
Python размеров страниц, в которых заинтересован вызывающий (размер элемента в килобайтах, поэтому, к примеру, для 2MiB
передаётся 2048
), значение параметра start
ссылается на самый первый узел NUMA, с которого следует собирать сведения, а значение пераметра
cellcount
сообщает сколько последовательных узлов следует опросить. Данная
функция возвращает list
Python, содержащий указатель на то будут ли доступны
страницы определяемого на входе размера. В случае когда система хоста не поддерживает страницы памяти запрошенных размеров,
будет отброшена некая ошибка (Листинг 3-22).
Листинг 3-22. Применение getFreePages
# Example-22.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
pages = [2048]
start = 0
cellcount = 4
buf = conn.getFreePages(pages, start, cellcount)
i = 0
for page in buf:
print("Page Size: " + str(pages[i]) + \
" Available pages: " + str(page))
++i
conn.close()
exit(0)
Ниже приводится вывод примера Листинга 3-22.
Page Size: 2048 Available pages: 0
Этот метод в виде строки возвращает все имеющиеся доступными параметры памяти (Листинг 3-23).
Листинг 3-23. Применение getMemoryParameters
# Example-23.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
buf = conn.getMemoryParameters()
print('shm_pages_shared : ' + str(buf['shm_pages_shared']))
print('shm_full_scans : ' + str(buf['shm_full_scans']))
print('shm_merge_across_nodes : ' + str(buf['shm_merge_across_nodes']))
print('shm_pages_to_scan : ' + str(buf['shm_pages_to_scan']))
print('shm_pages_unshared : ' + str(buf['shm_pages_unshared']))
print('shm_sleep_millisecs : ' + str(buf['shm_sleep_millisecs']))
print('shm_pages_sharing : ' + str(buf['shm_pages_sharing']))
print('shm_pages_volatile : ' + str(buf['shm_pages_volatile']))
conn.close()
exit(0)
Данный метод возвращает статистические данные памяти для отдельного узла (хоста). Он возвращает некий
list
строк Python
(Листинг 3-24).
Листинг 3-24. Применение getMemoryStats
# Example-24.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
buf = conn.getMemoryStats(libvirt.VIR_NODE_MEMORY_STATS_ALL_CELLS)
print('cached : ' + str(buf['cached']))
print('total : ' + str(buf['total']))
print('buffers: ' + str(buf['buffers']))
print('total : ' + str(buf['total']))
conn.close()
exit(0)
В Листинге 3-25 этот метод возвращает значение модели
безопасности (в виде некого list
) применяемой в настоящее время (если она имеется).
Листинг 3-25. Применение getSecurityModel
# Example-25.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
model = conn.getSecurityModel()
print(model[0] + " " + model[1])
conn.close()
exit(0)
Для большинства систем Дштгч x86_64 это будет SELinux
. Для прочих архитектур
это значение может быть иным.
Данный метод возвращает всю информацию о системе в виде некого определения XML. Его формат тот же самый, что и для определения домена XML (Листинг 3-26).
Листинг 3-26. Применение getSysinfo
# Example-26.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
xmlInfo = conn.getSysinfo()
print(xmlInfo)
conn.close()
exit(0)
Данный метод применяется для получения карты ЦПУ процессоров узда хостинга (Листинг 3-27).
Листинг 3-27. Применение getCPUMap
# Example-27.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
map = conn.getCPUMap()
print("CPUs: " + str(map[0]))
print("Available: " + str(map[1]))
conn.close()
exit(0)
Данный метод применяется для получения статистических сведений для одного или всех ЦПУ. Этот метод требует некого
отдельного параметра, который представляет номер опрашиваемого на статистику ЦПУ для отдельного ЦПУ либо значение
VIR_NODE_CPU_STATS_ALL_CPUS
для опроса списка Python статистических данных
от всех ЦПУ (Листинг 3-28).
Листинг 3-28. Применение getCPUStats
# Example-28.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
stats = conn.getCPUStats(0)
print("kernel: " + str(stats['kernel']))
print("idle: " + str(stats['idle']))
print("user: " + str(stats['user']))
print("iowait: " + str(stats['iowait']))
conn.close()
exit(0)
Этот метод применяется для получения значения списка имён ЦПУ, которые соответствуют некому типу архитектуры (Листинг 3-29).
Листинг 3-29. Применение getCPUModelNames
# Example-29.py
from __future__ import print_function
import sys
import libvirt
conn = libvirt.open('qemu:///system')
if conn == None:
print('Failed to open connection to qemu:///system', \
file=sys.stderr)
exit(1)
models = conn.getCPUModelNames('x86_64')
for model in models:
print(model)
conn.close()
exit(0)
Данная глава представила собственно функции соединения и обсудила как подключаться и как возвращать информацию из основной системы хостинга. Функции соединения включают в свой состав открытие и закрытие соединений. Все информационные функции содержат информацию относительно своего хоста, включая ЦПУ, память, безопасность и прочую относящуюся к оборудованию хоста информацию.