runsisi's

technical notes

Nova 到 Qemu 的调用

2019-07-20 runsisiopenstack

Nova 侧

# nova/virt/libvirt/driver.py

class LibvirtDriver(driver.ComputeDriver):
  def power_on
    self._hard_reboot
      self._get_guest_xml
      self._create_domain_and_network
        self._create_domain
          guest = libvirt_guest.Guest.create
          guest.launch
# nova/virt/libvirt/guest.py

class Guest(object):
  def create
    guest = host.write_instance_config(xml)
    return guest

  def launch
    self._domain.createWithFlags

  def attach_device(self, conf, persistent=False, live=False):
    device_xml = conf.to_xml()
    self._domain.attachDeviceFlags(device_xml, flags=flags)
# nova/virt/libvirt/host.py

class Host(object):
  def write_instance_config(self, xml):
    domain = self.get_connection().defineXML(xml)
      conn = self._get_connection()
        self._get_new_connection()
          self._connect
            libvirt.openAuth
    return libvirt_guest.Guest(domain)

libvirt Python 绑定

https://github.com/libvirt/libvirt-python

代码引用以 libvirt-python 构建后的目录结构为例。

# build/libvirt.py
def openAuth(uri, auth, flags=0):
  ret = libvirtmod.virConnectOpenAuth(uri, auth, flags)

// libvirt-override.c
static PyObject *
libvirt_virConnectOpenAuth {
  virConnectOpenAuth
}
# build/libvirt.py
class virConnect(object):
  def defineXML(self, xml):
    ret = libvirtmod.virDomainDefineXML(self._o, xml)
    __tmp = virDomain(self,_obj=ret)
    return __tmp
# build/libvirt.py
class virDomain(object):
  def createWithFlags(self, flags=0):
    libvirtmod.virDomainCreateWithFlags(self._o, flags)

  def attachDeviceFlags(self, xml, flags=0):
    libvirtmod.virDomainAttachDeviceFlags(self._o, xml, flags)
// build/libvirt.c
PyObject *
libvirt_virDomainCreateWithFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
{
  virDomainCreateWithFlags(domain, flags);
}

PyObject *
libvirt_virDomainAttachDeviceFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)
{
  virDomainAttachDeviceFlags(domain, xml, flags);
}

libvirt 侧

https://github.com/libvirt/libvirt

// src/libvirt-domain.c
int
virDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
{
  conn->driver->domainCreateWithFlags(domain, flags);
}

int
virDomainAttachDeviceFlags(virDomainPtr domain,
                           const char *xml, unsigned int flags)
{
  conn->driver->domainAttachDeviceFlags(domain, xml, flags);
}

// src/qemu/qemu_driver.c
static int
qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
{
  qemuDomainObjStart
}

static int
qemuDomainAttachDeviceFlags(virDomainPtr dom,
                            const char *xml,
                            unsigned int flags)
{
  qemuDomainAttachDeviceLiveAndConfig(vm, driver, xml, flags)
}

qemu 侧

https://github.com/qemu/qemu

// hmp.c
void hmp_device_add(Monitor *mon, const QDict *qdict)
{
    Error *err = NULL;

    qmp_device_add((QDict *)qdict, NULL, &err);
    hmp_handle_error(mon, &err);
}

void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
{
    Error *local_err = NULL;
    QemuOpts *opts;
    DeviceState *dev;

    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
        qemu_opts_del(opts);
        return;
    }
    dev = qdev_device_add(opts, &local_err);
    if (!dev) {
        error_propagate(errp, local_err);
        qemu_opts_del(opts);
        return;
    }
    object_unref(OBJECT(dev));
}