openstack nova 源码分析5-2 -nova/virt/libvirt目录下的connection.py

   由于该文件大于8万字符 所以我分4次挂载(2)

   该文件位于nova/virt/libvirt目录下的connection.py!我只是浅浅的分析了一下类中函数的方法 细节并没有多看,肯定有很多地方是错的 或者不好!希望大家能够帮忙指出错误!

    接下来 看源代码如下:中文部分是我加的注释 !或许大家会问 为什么要看这个connection.py呢 因为我发现该文件外部virt目录下有个connection.py 其中引用了 这个文件 所以觉得这个应该很重要 而且发现 好多方法都是重写的底层的driver的方法

 

  
  
  
  
  1. def rescue(self, context, instance, callback, network_info):  
  2.        #使用恢复镜像 加载一个vM  
  3.        """Loads a VM using rescue images.  
  4.    
  5.        A rescue is normally performed when something goes wrong with the  
  6.        primary images and data needs to be corrected/recovered. Rescuing  
  7.        should not edit or over-ride the original image, only allow for  
  8.        data recovery.  
  9.  
  10.        """ 
  11.  
  12.        virt_dom = self._conn.lookupByName(instance['name'])  
  13.        unrescue_xml = virt_dom.XMLDesc(0)  
  14.        unrescue_xml_path = os.path.join(FLAGS.instances_path,  
  15.                                         instance['name'],  
  16.                                         'unrescue.xml')  
  17.        f = open(unrescue_xml_path, 'w')  
  18.        f.write(unrescue_xml)  
  19.        f.close()  
  20.  
  21.        xml = self.to_xml(instance, network_info, rescue=True)  
  22.        rescue_images = {  
  23.            'image_id': FLAGS.rescue_image_id or instance['image_ref'],  
  24.            'kernel_id': FLAGS.rescue_kernel_id or instance['kernel_id'],  
  25.            'ramdisk_id': FLAGS.rescue_ramdisk_id or instance['ramdisk_id'],  
  26.        }  
  27.        self._create_image(context, instance, xml, '.rescue', rescue_images,  
  28.                           network_info=network_info)  
  29.        self.reboot(instance, network_info, xml=xml)  
  30.  
  31.    @exception.wrap_exception()  
  32.    def unrescue(self, instance, callback, network_info):  
  33.        """Reboot the VM which is being rescued back into primary images.  
  34.  
  35.        Because reboot destroys and re-creates instances, unresue should  
  36.        simply call reboot.  
  37.  
  38.        """ 
  39.        unrescue_xml_path = os.path.join(FLAGS.instances_path,  
  40.                                         instance['name'],  
  41.                                         'unrescue.xml')  
  42.        f = open(unrescue_xml_path)  
  43.        unrescue_xml = f.read()  
  44.        f.close()  
  45.        os.remove(unrescue_xml_path)  
  46.        self.reboot(instance, network_info, xml=unrescue_xml)  
  47.  
  48.    @exception.wrap_exception()  
  49.    def poll_rescued_instances(self, timeout):  
  50.        #轮询已经恢复的实例  
  51.        pass 
  52.  
  53.    # NOTE(ilyaalekseyev): Implementation like in multinics  
  54.    # for xenapi(tr3buchet)  
  55.    @exception.wrap_exception()  
  56.    def spawn(self, context, instance, network_info,  
  57.              block_device_info=None):  
  58.        #感觉像是防火墙的过滤  
  59.        xml = self.to_xml(instance, network_info, False,  
  60.                          block_device_info=block_device_info)  
  61.        self.firewall_driver.setup_basic_filtering(instance, network_info)  
  62.        self.firewall_driver.prepare_instance_filter(instance, network_info)  
  63.        self._create_image(context, instance, xml, network_info=network_info,  
  64.                           block_device_info=block_device_info)  
  65.  
  66.        domain = self._create_new_domain(xml)  
  67.        LOG.debug(_("instance %s: is running"), instance['name'])  
  68.        self.firewall_driver.apply_instance_filter(instance, network_info)  
  69.  
  70.        def _wait_for_boot():  
  71.            """Called at an interval until the VM is running.""" 
  72.            instance_name = instance['name']  
  73.  
  74.            try:  
  75.                state = self.get_info(instance_name)['state']  
  76.            except exception.NotFound:  
  77.                msg = _("During reboot, %s disappeared.") % instance_name  
  78.                LOG.error(msg)  
  79.                raise utils.LoopingCallDone  
  80.  
  81.            if state == power_state.RUNNING:  
  82.                msg = _("Instance %s spawned successfully.") % instance_name  
  83.                LOG.info(msg)  
  84.                raise utils.LoopingCallDone  
  85.  
  86.        timer = utils.LoopingCall(_wait_for_boot)  
  87.        return timer.start(interval=0.5, now=True)  
  88.  
  89.    def _flush_xen_console(self, virsh_output):  
  90.        #清除??  
  91.        LOG.info(_('virsh said: %r'), virsh_output)  
  92.        virsh_output = virsh_output[0].strip()  
  93.  
  94.        if virsh_output.startswith('/dev/'):  
  95.            LOG.info(_("cool, it's a device"))  
  96.            out, err = utils.execute('dd',  
  97.                                     "if=%s" % virsh_output,  
  98.                                     'iflag=nonblock',  
  99.                                     run_as_root=True,  
  100.                                     check_exit_code=False)  
  101.            return out  
  102.        else:  
  103.            return '' 
  104.  
  105.    def _append_to_file(self, data, fpath):  
  106.        #写入fp中 返回fpath  
  107.        LOG.info(_('data: %(data)r, fpath: %(fpath)r') % locals())  
  108.        fp = open(fpath, 'a+')  
  109.        fp.write(data)  
  110.        return fpath  
  111.  
  112.    def _dump_file(self, fpath):  
  113.        #返回读出来的contents  
  114.        fp = open(fpath, 'r+')  
  115.        contents = fp.read()  
  116.        LOG.info(_('Contents of file %(fpath)s: %(contents)r') % locals())  
  117.        return contents  
  118.  
  119.    @exception.wrap_exception()  
  120.    def get_console_output(self, instance):  
  121.        #得到控制台的outPut 最后返回的是fpath里面的contents  
  122.        console_log = os.path.join(FLAGS.instances_path, instance['name'],  
  123.                                   'console.log')  
  124.  
  125.        utils.execute('chown', os.getuid(), console_log, run_as_root=True)  
  126.  
  127.        if FLAGS.libvirt_type == 'xen':  
  128.            # Xen is special  
  129.            virsh_output = utils.execute('virsh''ttyconsole',  
  130.                                         instance['name'])  
  131.            data = self._flush_xen_console(virsh_output)  
  132.            fpath = self._append_to_file(data, console_log)  
  133.        elif FLAGS.libvirt_type == 'lxc':  
  134.            # LXC is also special  
  135.            LOG.info(_("Unable to read LXC console"))  
  136.        else:  
  137.            fpath = console_log  
  138.  
  139.        return self._dump_file(fpath)  
  140.  
  141.    @exception.wrap_exception()  
  142.    def get_ajax_console(self, instance):  
  143.        def get_open_port():  
  144.            start_port, end_port = FLAGS.ajaxterm_portrange.split("-")  
  145.            for i in xrange(0100):  # don't loop forever  
  146.                port = random.randint(int(start_port), int(end_port))  
  147.                # netcat will exit with 0 only if the port is in use,  
  148.                # so a nonzero return value implies it is unused  
  149.                cmd = 'netcat''0.0.0.0', port, '-w''1' 
  150.                try:  
  151.                    stdout, stderr = utils.execute(*cmd, process_input='')  
  152.                except exception.ProcessExecutionError:  
  153.                    return port  
  154.            raise Exception(_('Unable to find an open port'))  
  155.  
  156.        def get_pty_for_instance(instance_name):  
  157.            virt_dom = self._lookup_by_name(instance_name)  
  158.            xml = virt_dom.XMLDesc(0)  
  159.            dom = minidom.parseString(xml)  
  160.  
  161.            for serial in dom.getElementsByTagName('serial'):  
  162.                if serial.getAttribute('type') == 'pty':  
  163.                    source = serial.getElementsByTagName('source')[0]  
  164.                    return source.getAttribute('path')  
  165.  
  166.        port = get_open_port()  
  167.        token = str(uuid.uuid4())  
  168.        host = instance['host']  
  169.  
  170.        ajaxterm_cmd = 'sudo socat - %s' \  
  171.                       % get_pty_for_instance(instance['name'])  
  172.  
  173.        cmd = ['%s/tools/ajaxterm/ajaxterm.py' % utils.novadir(),  
  174.               '--command', ajaxterm_cmd, '-t', token, '-p', port]  
  175.  
  176.        utils.execute(cmd)  
  177.        return {'token': token, 'host': host, 'port': port}  
  178.  
  179.    def get_host_ip_addr(self):  
  180.        # Retrieves the IP address of the dom0得到主机ip地址  
  181.        return FLAGS.my_ip  
  182.  
  183.    @exception.wrap_exception()  
  184.    def get_vnc_console(self, instance):  
  185.        #取得虚拟网络计算机的控制 最后返回 token,host,port  
  186.        def get_vnc_port_for_instance(instance_name):  
  187.            virt_dom = self._lookup_by_name(instance_name)  
  188.            xml = virt_dom.XMLDesc(0)  
  189.            # TODO: use etree instead of minidom  
  190.            dom = minidom.parseString(xml)  
  191.  
  192.            for graphic in dom.getElementsByTagName('graphics'):  
  193.                if graphic.getAttribute('type') == 'vnc':  
  194.                    return graphic.getAttribute('port')  
  195.  
  196.        port = get_vnc_port_for_instance(instance['name'])  
  197.        token = str(uuid.uuid4())  
  198.        host = instance['host']  
  199.  
  200.        return {'token': token, 'host': host, 'port': port}  
  201.  
  202.    @staticmethod 
  203.    def _cache_image(fn, target, fname, cow=False, *args, **kwargs):  
  204.        #封装一个方法是他能够创建一个可以缓存镜像的镜像  
  205.        """Wrapper for a method that creates an image that caches the image.  
  206.  
  207.        This wrapper will save the image into a common store and create a  
  208.        copy for use by the hypervisor.  
  209.  
  210.        The underlying method should specify a kwarg of target representing  
  211.        where the image will be saved.  
  212.  
  213.        fname is used as the filename of the base image.  The filename needs  
  214.        to be unique to a given image.  
  215.  
  216.        If cow is True, it will make a CoW image instead of a copy.  
  217.        """ 
  218.  
  219.        if not os.path.exists(target):  
  220.            base_dir = os.path.join(FLAGS.instances_path, '_base')  
  221.            if not os.path.exists(base_dir):  
  222.                os.mkdir(base_dir)  
  223.            base = os.path.join(base_dir, fname)  
  224.  
  225.            @utils.synchronized(fname)  
  226.            def call_if_not_exists(base, fn, *args, **kwargs):  
  227.                if not os.path.exists(base):  
  228.                    fn(target=base, *args, **kwargs)  
  229.  
  230.            call_if_not_exists(base, fn, *args, **kwargs)  
  231.  
  232.            if cow:  
  233.                utils.execute('qemu-img''create''-f''qcow2''-o',  
  234.                              'cluster_size=2M,backing_file=%s' % base,  
  235.                              target)  
  236.            else:  
  237.                utils.execute('cp', base, target)  
  238.  
  239.    def _fetch_image(self, context, target, image_id, user_id, project_id,  
  240.                     size=None):  
  241.        """Grab image and optionally attempt to resize it""" 
  242.        #GRAB 镜像和可选地试图调整他  
  243.        images.fetch_to_raw(context, image_id, target, user_id, project_id)  
  244.        if size:  
  245.            disk.extend(target, size)  
  246.  
  247.    def _create_local(self, target, local_size, unit='G', fs_format=None):  
  248.        """Create a blank image of specified size""" 
  249.        #创建一个空的指定size的镜像  
  250.  
  251.        if not fs_format:  
  252.            fs_format = FLAGS.default_local_format  
  253.  
  254.        utils.execute('truncate', target, '-s'"%d%c" % (local_size, unit))  
  255.        if fs_format:  
  256.            utils.execute('mkfs''-t', fs_format, target)  
  257.  
  258.    def _create_ephemeral(self, target, local_size, fs_label, os_type):  
  259.        self._create_local(target, local_size)  
  260.        disk.mkfs(os_type, fs_label, target)  
  261.  
  262.    def _create_swap(self, target, swap_mb):  
  263.        """Create a swap file of specified size""" 
  264.        #创建一个指定size的swap file  
  265.        self._create_local(target, swap_mb, unit='M')  
  266.        utils.execute('mkswap', target)  
  267.  
  268.    def _create_image(self, context, inst, libvirt_xml, suffix='',  
  269.                      disk_images=None, network_info=None,  
  270.                      block_device_info=None):  
  271.        if not suffix:  
  272.            suffix = '' 
  273.  
  274.        # syntactic nicety  
  275.        def basepath(fname='', suffix=suffix):  
  276.            return os.path.join(FLAGS.instances_path,  
  277.                                inst['name'],  
  278.                                fname + suffix)  
  279.  
  280.        # ensure directories exist and are writable  
  281.        utils.execute('mkdir''-p', basepath(suffix=''))  
  282.  
  283.        LOG.info(_('instance %s: Creating image'), inst['name'])  
  284.        f = open(basepath('libvirt.xml'), 'w')  
  285.        f.write(libvirt_xml)  
  286.        f.close()  
  287.  
  288.        if FLAGS.libvirt_type == 'lxc':  
  289.            container_dir = '%s/rootfs' % basepath(suffix='')  
  290.            utils.execute('mkdir''-p', container_dir)  
  291.  
  292.        # NOTE(vish): No need add the suffix to console.log  
  293.        console_log = basepath('console.log''')  
  294.        if os.path.exists(console_log):  
  295.            utils.execute('chown', os.getuid(), console_log, run_as_root=True)  
  296.        os.close(os.open(console_log, os.O_CREAT | os.O_WRONLY, 0660))  
  297.  
  298.        if not disk_images:  
  299.            disk_images = {'image_id': inst['image_ref'],  
  300.                           'kernel_id': inst['kernel_id'],  
  301.                           'ramdisk_id': inst['ramdisk_id']}  
  302.  
  303.        if disk_images['kernel_id']:  
  304.            fname = '%08x' % int(disk_images['kernel_id'])  
  305.            self._cache_image(fn=self._fetch_image,  
  306.                              context=context,  
  307.                              target=basepath('kernel'),  
  308.                              fname=fname,  
  309.                              image_id=disk_images['kernel_id'],  
  310.                              user_id=inst['user_id'],  
  311.                              project_id=inst['project_id'])  
  312.            if disk_images['ramdisk_id']:  
  313.                fname = '%08x' % int(disk_images['ramdisk_id'])  
  314.                self._cache_image(fn=self._fetch_image,  
  315.                                  context=context,  
  316.                                  target=basepath('ramdisk'),  
  317.                                  fname=fname,  
  318.                                  image_id=disk_images['ramdisk_id'],  
  319.                                  user_id=inst['user_id'],  
  320.                                  project_id=inst['project_id'])  
  321.  
  322.        root_fname = hashlib.sha1(disk_images['image_id']).hexdigest()  
  323.        size = FLAGS.minimum_root_size  
  324.  
  325.        inst_type_id = inst['instance_type_id']  
  326.        inst_type = instance_types.get_instance_type(inst_type_id)  
  327.        if inst_type['name'] == 'm1.tiny' or suffix == '.rescue':  
  328.            size = None 
  329.            root_fname += "_sm" 
  330.  
  331.        if not self._volume_in_mapping(self.default_root_device,  
  332.                                       block_device_info):  
  333.            self._cache_image(fn=self._fetch_image,  
  334.                              context=context,  
  335.                              target=basepath('disk'),  
  336.                              fname=root_fname,  
  337.                              cow=FLAGS.use_cow_images,  
  338.                              image_id=disk_images['image_id'],  
  339.                              user_id=inst['user_id'],  
  340.                              project_id=inst['project_id'],  
  341.                              size=size)  
  342.  
  343.        local_gb = inst['local_gb']  
  344.        if local_gb and not self._volume_in_mapping(  
  345.            self.default_local_device, block_device_info):  
  346.            fn = functools.partial(self._create_ephemeral,  
  347.                                   fs_label='ephemeral0',  
  348.                                   os_type=inst.os_type)  
  349.            self._cache_image(fn=fn,  
  350.                              target=basepath('disk.local'),  
  351.                              fname="ephemeral_%s_%s_%s" %  
  352.                              ("0", local_gb, inst.os_type),  
  353.                              cow=FLAGS.use_cow_images,  
  354.                              local_size=local_gb)  
  355.  
  356.        for eph in driver.block_device_info_get_ephemerals(block_device_info):  
  357.            fn = functools.partial(self._create_ephemeral,  
  358.                                   fs_label='ephemeral%d' % eph['num'],  
  359.                                   os_type=inst.os_type)  
  360.            self._cache_image(fn=fn,  
  361.                              target=basepath(_get_eph_disk(eph)),  
  362.                              fname="ephemeral_%s_%s_%s" %  
  363.                              (eph['num'], eph['size'], inst.os_type),  
  364.                              cow=FLAGS.use_cow_images,  
  365.                              local_size=eph['size'])  
  366.  
  367.        swap_mb = 0 
  368.  
  369.        swap = driver.block_device_info_get_swap(block_device_info)  
  370.        if driver.swap_is_usable(swap):  
  371.            swap_mb = swap['swap_size']  
  372.        elif (inst_type['swap'] > 0 and 
  373.              not self._volume_in_mapping(self.default_swap_device,  
  374.                                          block_device_info)):  
  375.            swap_mb = inst_type['swap']  
  376.  
  377.        if swap_mb > 0:  
  378.            self._cache_image(fn=self._create_swap,  
  379.                              target=basepath('disk.swap'),  
  380.                              fname="swap_%s" % swap_mb,  
  381.                              cow=FLAGS.use_cow_images,  
  382.                              swap_mb=swap_mb)  
  383.  
  384.        # For now, we assume that if we're not using a kernel, we're using a  
  385.        # partitioned disk image where the target partition is the first  
  386.        # partition  
  387.        target_partition = None 
  388.        if not inst['kernel_id']:  
  389.            target_partition = "1" 
  390.  
  391.        config_drive_id = inst.get('config_drive_id')  
  392.        config_drive = inst.get('config_drive')  
  393.  
  394.        if any((FLAGS.libvirt_type == 'lxc', config_drive, config_drive_id)):  
  395.            target_partition = None 
  396.  
  397.        if config_drive_id:  
  398.            fname = '%08x' % int(config_drive_id)  
  399.            self._cache_image(fn=self._fetch_image,  
  400.                              target=basepath('disk.config'),  
  401.                              fname=fname,  
  402.                              image_id=config_drive_id,  
  403.                              user_id=inst['user_id'],  
  404.                              project_id=inst['project_id'],)  
  405.        elif config_drive:  
  406.            self._create_local(basepath('disk.config'), 64, unit='M',  
  407.                               fs_format='msdos')  # 64MB  
  408.  
  409.        if inst['key_data']:  
  410.            key = str(inst['key_data'])  
  411.        else:  
  412.            key = None 
  413.        net = None 
  414.  
  415.        nets = []  
  416.        ifc_template = open(FLAGS.injected_network_template).read()  
  417.        ifc_num = -1 
  418.        have_injected_networks = False 
  419.        admin_context = nova_context.get_admin_context()  
  420.        for (network_ref, mapping) in network_info:  
  421.            ifc_num += 1 
  422.  
  423.            if not network_ref['injected']:  
  424.                continue 
  425.  
  426.            have_injected_networks = True 
  427.            address = mapping['ips'][0]['ip']  
  428.            netmask = mapping['ips'][0]['netmask']  
  429.            address_v6 = None 
  430.            gateway_v6 = None 
  431.            netmask_v6 = None 
  432.            if FLAGS.use_ipv6:  
  433.                address_v6 = mapping['ip6s'][0]['ip']  
  434.                netmask_v6 = mapping['ip6s'][0]['netmask']  
  435.                gateway_v6 = mapping['gateway6']  
  436.            net_info = {'name''eth%d' % ifc_num,  
  437.                   'address': address,  
  438.                   'netmask': netmask,  
  439.                   'gateway': mapping['gateway'],  
  440.                   'broadcast': mapping['broadcast'],  
  441.                   'dns'' '.join(mapping['dns']),  
  442.                   'address_v6': address_v6,  
  443.                   'gateway6': gateway_v6,  
  444.                   'netmask_v6': netmask_v6}  
  445.            nets.append(net_info)  
  446.  
  447.        if have_injected_networks:  
  448.            net = str(Template(ifc_template,  
  449.                               searchList=[{'interfaces': nets,  
  450.                                            'use_ipv6': FLAGS.use_ipv6}]))  
  451.  
  452.        metadata = inst.get('metadata')  
  453.        if any((key, net, metadata)):  
  454.            inst_name = inst['name']  
  455.  
  456.            if config_drive:  # Should be True or None by now.  
  457.                injection_path = basepath('disk.config')  
  458.                img_id = 'config-drive' 
  459.                tune2fs = False 
  460.            else:  
  461.                injection_path = basepath('disk')  
  462.                img_id = inst.image_ref  
  463.                tune2fs = True 
  464.  
  465.            for injection in ('metadata''key''net'):  
  466.                if locals()[injection]:  
  467.                    LOG.info(_('instance %(inst_name)s: injecting ' 
  468.                               '%(injection)s into image %(img_id)s' 
  469.                               % locals()))  
  470.            try:  
  471.                disk.inject_data(injection_path, key, net, metadata,  
  472.                                 partition=target_partition,  
  473.                                 nbd=FLAGS.use_cow_images,  
  474.                                 tune2fs=tune2fs)  
  475.  
  476.            except Exception as e:  
  477.                # This could be a windows image, or a vmdk format disk  
  478.                LOG.warn(_('instance %(inst_name)s: ignoring error injecting' 
  479.                        ' data into image %(img_id)s (%(e)s)') % locals())  
  480.  
  481.        if FLAGS.libvirt_type == 'lxc':  
  482.            disk.setup_container(basepath('disk'),  
  483.                                container_dir=container_dir,  
  484.                                nbd=FLAGS.use_cow_images)  
  485.  
  486.        if FLAGS.libvirt_type == 'uml':  
  487.            utils.execute('chown''root', basepath('disk'), run_as_root=True

 

你可能感兴趣的:(openstack,openstack,openstack,源码分析,nova,nova源码分析)