由于该文件大于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 p_w_picpaths.  
  4.    
  5.        A rescue is normally performed when something goes wrong with the  
  6.        primary p_w_picpaths and data needs to be corrected/recovered. Rescuing  
  7.        should not edit or over-ride the original p_w_picpath, 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_p_w_picpaths = {  
  23.            'p_w_picpath_id': FLAGS.rescue_p_w_picpath_id or instance['p_w_picpath_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_p_w_picpath(context, instance, xml, '.rescue', rescue_p_w_picpaths,  
  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 p_w_picpaths.  
  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_p_w_picpath(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_p_w_picpath(fn, target, fname, cow=False, *args, **kwargs):  
  204.        #封装一个方法是他能够创建一个可以缓存镜像的镜像  
  205.        """Wrapper for a method that creates an p_w_picpath that caches the p_w_picpath.  
  206.  
  207.        This wrapper will save the p_w_picpath 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 p_w_picpath will be saved.  
  212.  
  213.        fname is used as the filename of the base p_w_picpath.  The filename needs  
  214.        to be unique to a given p_w_picpath.  
  215.  
  216.        If cow is True, it will make a CoW p_w_picpath 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_p_w_picpath(self, context, target, p_w_picpath_id, user_id, project_id,  
  240.                     size=None):  
  241.        """Grab p_w_picpath and optionally attempt to resize it""" 
  242.        #GRAB 镜像和可选地试图调整他  
  243.        p_w_picpaths.fetch_to_raw(context, p_w_picpath_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 p_w_picpath 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_p_w_picpath(self, context, inst, libvirt_xml, suffix='',  
  269.                      disk_p_w_picpaths=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 p_w_picpath'), 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_p_w_picpaths:  
  299.            disk_p_w_picpaths = {'p_w_picpath_id': inst['p_w_picpath_ref'],  
  300.                           'kernel_id': inst['kernel_id'],  
  301.                           'ramdisk_id': inst['ramdisk_id']}  
  302.  
  303.        if disk_p_w_picpaths['kernel_id']:  
  304.            fname = '%08x' % int(disk_p_w_picpaths['kernel_id'])  
  305.            self._cache_p_w_picpath(fn=self._fetch_p_w_picpath,  
  306.                              context=context,  
  307.                              target=basepath('kernel'),  
  308.                              fname=fname,  
  309.                              p_w_picpath_id=disk_p_w_picpaths['kernel_id'],  
  310.                              user_id=inst['user_id'],  
  311.                              project_id=inst['project_id'])  
  312.            if disk_p_w_picpaths['ramdisk_id']:  
  313.                fname = '%08x' % int(disk_p_w_picpaths['ramdisk_id'])  
  314.                self._cache_p_w_picpath(fn=self._fetch_p_w_picpath,  
  315.                                  context=context,  
  316.                                  target=basepath('ramdisk'),  
  317.                                  fname=fname,  
  318.                                  p_w_picpath_id=disk_p_w_picpaths['ramdisk_id'],  
  319.                                  user_id=inst['user_id'],  
  320.                                  project_id=inst['project_id'])  
  321.  
  322.        root_fname = hashlib.sha1(disk_p_w_picpaths['p_w_picpath_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_p_w_picpath(fn=self._fetch_p_w_picpath,  
  334.                              context=context,  
  335.                              target=basepath('disk'),  
  336.                              fname=root_fname,  
  337.                              cow=FLAGS.use_cow_p_w_picpaths,  
  338.                              p_w_picpath_id=disk_p_w_picpaths['p_w_picpath_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_p_w_picpath(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_p_w_picpaths,  
  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_p_w_picpath(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_p_w_picpaths,  
  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_p_w_picpath(fn=self._create_swap,  
  379.                              target=basepath('disk.swap'),  
  380.                              fname="swap_%s" % swap_mb,  
  381.                              cow=FLAGS.use_cow_p_w_picpaths,  
  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 p_w_picpath 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_p_w_picpath(fn=self._fetch_p_w_picpath,  
  400.                              target=basepath('disk.config'),  
  401.                              fname=fname,  
  402.                              p_w_picpath_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.p_w_picpath_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 p_w_picpath %(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_p_w_picpaths,  
  474.                                 tune2fs=tune2fs)  
  475.  
  476.            except Exception as e:  
  477.                # This could be a windows p_w_picpath, or a vmdk format disk  
  478.                LOG.warn(_('instance %(inst_name)s: ignoring error injecting' 
  479.                        ' data into p_w_picpath %(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_p_w_picpaths)  
  485.  
  486.        if FLAGS.libvirt_type == 'uml':  
  487.            utils.execute('chown''root', basepath('disk'), run_as_root=True