openstack关于libvirt相关代码的分析(一)

这段时间研究openstack+xen可惜资料太少,决定看一下源代码得了。

如果看过一篇关于启动Openstack中启动一个虚拟机的过程的文章的话,就一定知道有一个叫做Spawn instance的过程。

我使用的代码是nova-2012.2的版本。

下面我们看一下nova/virt/libvirt/connection.py文件。

"""
A connection to a hypervisor through libvirt.

Supports KVM, LXC, QEMU, UML, and XEN.

**Related Flags**

:libvirt_type:  Libvirt domain type.  Can be kvm, qemu, uml, xen
                (default: kvm).
:libvirt_uri:  Override for the default libvirt URI (depends on libvirt_type).
:libvirt_disk_prefix:  Override the default disk prefix for the devices
                       attached to a server.
:rescue_image_id:  Rescue ami image (None = original image).
:rescue_kernel_id:  Rescue aki image (None = original image).
:rescue_ramdisk_id:  Rescue ari image (None = original image).
:injected_network_template:  Template file for injected network
:allow_same_net_traffic:  Whether to allow in project network traffic

我们需要创建以个libvirt xml去新建一个实例。这将会涉及到其中的to_xml函数。

   def to_xml(self, instance, network_info, image_meta=None, rescue=False,
               block_device_info=None):
        LOG.debug(_('Starting toXML method'), instance=instance)
        conf = self.get_guest_config(instance, network_info, image_meta,
                                     rescue, block_device_info)
        xml = conf.to_xml()
        LOG.debug(_('Finished toXML method'), instance=instance)
        return xml

可以看到,它调用了一个叫get_guest_config的函数

    def get_guest_config(self, instance, network_info, image_meta, rescue,
                         block_device_info=None):
        block_device_mapping = driver.block_device_info_get_mapping(
            block_device_info)

        devs = []

        # FIXME(vish): stick this in db
        inst_type_id = instance['instance_type_id']
        inst_type = instance_types.get_instance_type(inst_type_id)

        guest = config.LibvirtConfigGuest()
        guest.virt_type = FLAGS.libvirt_type
        guest.name = instance['name']
        guest.uuid = instance['uuid']
        guest.memory = inst_type['memory_mb'] * 1024
        guest.vcpus = inst_type['vcpus']

        root_device_name = driver.block_device_info_get_root(block_device_info)
        if root_device_name:
            root_device = block_device.strip_dev(root_device_name)
        else:
            # NOTE(yamahata):
            # for nova.api.ec2.cloud.CloudController.get_metadata()
            root_device = self.default_root_device
            db.instance_update(
                nova_context.get_admin_context(), instance['id'],
                {'root_device_name': '/dev/' + self.default_root_device})

        if FLAGS.libvirt_type == "lxc":
            guest.os_type = "exe"
            guest.os_init_path = "/sbin/init"
            guest.os_cmdline = "console=ttyS0"
        elif FLAGS.libvirt_type == "uml":
            guest.os_type = "uml"
            guest.os_kernel = "/usr/bin/linux"
            guest.os_root = root_device_name or "/dev/ubda"
        else:
            if FLAGS.libvirt_type == "xen":
                guest.os_type = "linux"
                guest.os_root = root_device_name or "/dev/xvda"
            else:
                guest.os_type = "hvm"

            if rescue:
                guest.os_kernel = os.path.join(FLAGS.instances_path,
                                               instance['name'],
                                               "kernel.rescue")
                guest.os_initrd = os.path.join(FLAGS.instances_path,
                                               instance['name'],
                                               "ramdisk.rescue")
            elif instance['kernel_id']:
                guest.os_kernel = os.path.join(FLAGS.instances_path,
                                               instance['name'],
                                               "kernel")
                if FLAGS.libvirt_type == "xen":
                    guest.os_cmdline = "ro"
                else:
                    guest.os_cmdline = "root=%s console=ttyS0" % (
                        root_device_name or "/dev/vda",)
                if instance['ramdisk_id']:
                    guest.os_initrd = os.path.join(FLAGS.instances_path,
                                                   instance['name'],
                                                   "ramdisk")
            else:
                guest.os_boot_dev = "hd"

        if FLAGS.libvirt_type != "lxc" and FLAGS.libvirt_type != "uml":
            guest.acpi = True

        if FLAGS.libvirt_type == "lxc":
            fs = config.LibvirtConfigGuestFilesys()
            fs.type = "mount"
            fs.source_dir = os.path.join(FLAGS.instances_path,
                                         instance['name'],
                                         "rootfs")
            guest.add_device(fs)
        else:
            if FLAGS.use_cow_images:
                driver_type = 'qcow2'
            else:
                driver_type = 'raw'

            if image_meta and image_meta.get('disk_format') == 'iso':
                root_device_type = 'cdrom'
            else:
                root_device_type = 'disk'

            if FLAGS.libvirt_type == "uml":
                ephemeral_disk_bus = "uml"
            elif FLAGS.libvirt_type == "xen":
                ephemeral_disk_bus = "xen"
            else:
                ephemeral_disk_bus = "virtio"

            if rescue:
                diskrescue = config.LibvirtConfigGuestDisk()
                diskrescue.source_type = "file"
                diskrescue.source_path = os.path.join(FLAGS.instances_path,
                                                      instance['name'],
                                                      "disk.rescue")
                diskrescue.driver_format = driver_type
                diskrescue.driver_cache = self.disk_cachemode
                diskrescue.target_dev = self.default_root_device
                diskrescue.target_bus = ephemeral_disk_bus
                guest.add_device(diskrescue)

                diskos = config.LibvirtConfigGuestDisk()
                diskos.source_type = "file"
                diskos.source_path = os.path.join(FLAGS.instances_path,
                                                  instance['name'],
                                                  "disk")
                diskos.driver_format = driver_type
                diskos.driver_cache = self.disk_cachemode
                diskos.target_dev = self.default_second_device
                diskos.target_bus = ephemeral_disk_bus
                guest.add_device(diskos)
            else:
                ebs_root = self._volume_in_mapping(self.default_root_device,
                                                   block_device_info)

                if not ebs_root:
                    diskos = config.LibvirtConfigGuestDisk()
                    diskos.source_type = "file"
                    diskos.source_device = root_device_type
                    diskos.driver_format = driver_type
                    diskos.driver_cache = self.disk_cachemode
                    diskos.source_path = os.path.join(FLAGS.instances_path,
                                                      instance['name'],
                                                      "disk")
                    diskos.target_dev = root_device
                    if root_device_type == "cdrom":
                        diskos.target_bus = "ide"
                    else:
                        diskos.target_bus = "virtio"
                    guest.add_device(diskos)

                ephemeral_device = None
                if not (self._volume_in_mapping(self.default_second_device,
                                                block_device_info) or
                        0 in [eph['num'] for eph in
                              driver.block_device_info_get_ephemerals(
                            block_device_info)]):
                    if instance['ephemeral_gb'] > 0:
                        ephemeral_device = self.default_second_device

                if ephemeral_device is not None:
                    disklocal = config.LibvirtConfigGuestDisk()
                    disklocal.source_type = "file"
                    disklocal.source_device = root_device_type
                    disklocal.driver_format = driver_type
                    disklocal.driver_cache = self.disk_cachemode
                    disklocal.source_path = os.path.join(FLAGS.instances_path,
                                                         instance['name'],
                                                         "disk.local")
                    disklocal.target_dev = ephemeral_device
                    disklocal.target_bus = ephemeral_disk_bus
                    guest.add_device(disklocal)

                if ephemeral_device is not None:
                    swap_device = self.default_third_device
                    db.instance_update(
                        nova_context.get_admin_context(), instance['id'],
                        {'default_ephemeral_device':
                             '/dev/' + self.default_second_device})
                else:
                    swap_device = self.default_second_device

                for eph in driver.block_device_info_get_ephemerals(
                    block_device_info):
                    diskeph = config.LibvirtConfigGuestDisk()
                    diskeph.source_type = "block"
                    diskeph.source_device = root_device_type
                    diskeph.driver_format = driver_type
                    diskeph.driver_cache = self.disk_cachemode
                    diskeph.source_path = os.path.join(FLAGS.instances_path,
                                                       instance['name'],
                                                       _get_eph_disk(eph))
                    diskeph.target_dev = block_device.strip_dev(
                        eph['device_name'])
                    diskeph.target_bus = ephemeral_disk_bus
                    guest.add_device(diskeph)

                swap = driver.block_device_info_get_swap(block_device_info)
                if driver.swap_is_usable(swap):
                    diskswap = config.LibvirtConfigGuestDisk()
                    diskswap.disk_type = "file"
                    diskswap.driver_format = driver_type
                    diskswap.driver_cache = self.disk_cachemode
                    diskswap.source_path = os.path.join(FLAGS.instances_path,
                                                        instance['name'],
                                                        "disk.swap")
                    diskswap.target_dev = block_device.strip_dev(
                        swap['device_name'])
                    diskswap.target_bus = ephemeral_disk_bus
                    guest.add_device(diskswap)
                elif (inst_type['swap'] > 0 and
                      not self._volume_in_mapping(swap_device,
                                                  block_device_info)):
                    diskswap = config.LibvirtConfigGuestDisk()
                    diskswap.disk_type = "file"
                    diskswap.driver_format = driver_type
                    diskswap.driver_cache = self.disk_cachemode
                    diskswap.source_path = os.path.join(FLAGS.instances_path,
                                                        instance['name'],
                                                        "disk.swap")
                    diskswap.target_dev = swap_device
                    diskswap.target_bus = ephemeral_disk_bus
                    guest.add_device(diskswap)
                    db.instance_update(
                        nova_context.get_admin_context(), instance['id'],
                        {'default_swap_device': '/dev/' + swap_device})

                for vol in block_device_mapping:
                    connection_info = vol['connection_info']
                    mountpoint = vol['mount_device']
                    cfg = self.volume_driver_method('connect_volume',
                                                    connection_info,
                                                    mountpoint)
                    guest.add_device(cfg)

            if self._has_config_drive(instance):
                diskconfig = config.LibvirtConfigGuestDisk()
                diskconfig.source_type = "file"
                diskconfig.driver_format = "raw"
                diskconfig.driver_cache = self.disk_cachemode
                diskconfig.source_path = os.path.join(FLAGS.instances_path,
                                                      instance['name'],
                                                      "disk.config")
                diskconfig.target_dev = self.default_last_device
                diskconfig.target_bus = ephemeral_disk_bus
                guest.add_device(diskconfig)

        for (network, mapping) in network_info:
            cfg = self.vif_driver.plug(instance, network, mapping)
            guest.add_device(cfg)

        if FLAGS.libvirt_type == "qemu" or FLAGS.libvirt_type == "kvm":
            # The QEMU 'pty' driver throws away any data if no
            # client app is connected. Thus we can't get away
            # with a single type=pty console. Instead we have
            # to configure two separate consoles.
            consolelog = config.LibvirtConfigGuestSerial()
            consolelog.type = "file"
            consolelog.source_path = os.path.join(FLAGS.instances_path,
                                                  instance['name'],
                                                  "console.log")
            guest.add_device(consolelog)

            consolepty = config.LibvirtConfigGuestSerial()
            consolepty.type = "pty"
            guest.add_device(consolepty)
        else:
            consolepty = config.LibvirtConfigGuestConsole()
            consolepty.type = "pty"
            guest.add_device(consolepty)

        if FLAGS.vnc_enabled and FLAGS.libvirt_type not in ('lxc', 'uml'):
            if FLAGS.use_usb_tablet:
                tablet = config.LibvirtConfigGuestInput()
                tablet.type = "tablet"
                tablet.bus = "usb"
                guest.add_device(tablet)

            graphics = config.LibvirtConfigGuestGraphics()
            graphics.type = "vnc"
            graphics.keymap = FLAGS.vnc_keymap
            graphics.listen = FLAGS.vncserver_listen
            guest.add_device(graphics)

        return guest

你可能感兴趣的:(openstack关于libvirt相关代码的分析(一))