54t23 发表于 2014-12-15 08:45:42

saltstack之virt模块创建虚拟机分析

虚拟管理机:kvm/qemu
两种方式创建:
salt 'hypervisor' virt.init vm_name 4 512 salt://path/to/image.raw
salt 'hypervisor' virt.init vm_name 4 512 nic=profile disk=profile

先说第1种,此种方式是将Master上的镜像文件cp到kvm主机(此种方式依赖网络速),
执行命令如下:
salt 'kvm.tiancity.com' virt.init web10 4 512 salt://img/Template_Centos63x64.img

hypervisor = __salt__['config.get']('libvirt:hypervisor', hypervisor)
config.get获取数据的顺序如下:
    - Local minion config (opts)
    - Minion's grains
    - Minion's pillar
    - Master config
因为我没有在grains,pillar处设置libvirt:hypervisor,所以此处的值为hypervisor(默认值:hypervisor=VIRT_DEFAULT_HYPER,VIRT_DEFAULT_HYPER = 'kvm')

假设我在/etc/salt/minion的配置文件处,设置如下

通过salt 'kvm.tiancity.com' config.get libvirt:hypervisor,我们将会获取到zzj这个值。


在这里,我不需要设置,因为我的虚拟管理机用的就是kvm。哇....

nicp = _nic_profile(nic, hypervisor, **kwargs)
此处的函数会获取一个网卡相关属性列表,最后我会提供出来
    # support old location
    config_data = __salt__['config.option']('virt.nic', {}).get(
      profile_name, None
    )
    if config_data is None:
      config_data = __salt__['config.get']('virt:nic', {}).get(
            profile_name, default
      )
这段话的意思是说,如果你没有定义virt.nic变量,那么config_data为None
当config_data为None时,我们再判定有没有设置virt:nic,如果没有设置则取default
那么config_data=default(default = [{'eth0': {}}])

    if isinstance(config_data, dict):
      append_dict_profile_to_interface_list(config_data)

    elif isinstance(config_data, list):
      for interface in config_data:
            if isinstance(interface, dict):
                if len(interface.keys()) == 1:
                  append_dict_profile_to_interface_list(interface)
                else:
                  interfaces.append(interface)

判定config_data是字典,还是列表,此处是列表,并且仅有1个键(如果有两块网卡呢?以后分析测试),执行append_dict_profile_to_interface_list(interface)


    def append_dict_profile_to_interface_list(profile_dict):
      for interface_name, attributes in profile_dict.items():
            attributes['name'] = interface_name
            interfaces.append(attributes)
此处意指:interfaces这个列表追加一个attributes字典.值interfaces=[{'name':'eth0'}]

    for interface in interfaces:
      _normalize_net_types(interface)
      _assign_mac(interface)
      if hypervisor in overlays:
            _apply_default_overlay(interface)

_normalize_net_types(interface)将会为interfaces中的字典增加type和source属性,interfaces=[{'name':'eth0','type':None,'source':None}]
_assign_mac(interface)此处通过salt.utils.gen_mac()生成一个虚拟mac,并且更新interfaces=[{'name':'eth0','type':None,'source':None,'mac':'AC:DE:48:5D:9C:B4'}]

_apply_default_overlay(interface)将会更新interfaces=[{'name':'eth0','type':'bridge','source':'br0','mac':'AC:DE:48:5D:9C:B4','model': 'virtio'}]
并且返回interfaces,那么nicp的值就是interfaces


若指定image,
diskp = _disk_profile('default', hypervisor, **kwargs)
则返回diskp=[{'system':{'size':'8192','format':'qcow2','model':'virtio','pool':'/srv/salt-images'}}]

      disk_name = diskp.keys()
      disk_type = diskp['format']
      disk_file_name = '{0}.{1}'.format(disk_name, disk_type)
则disk_name=system,disk_type=qcow2,disk_file_name=system.qcow2
            img_dir = __salt__['config.option']('virt.images')
            img_dest = os.path.join(
                img_dir,
                name,
                disk_file_name
            )
            img_dir = os.path.dirname(img_dest)
则:img_dest="/srv/salt-image/web10/system.qcow2",img_dir="/srv/salt-image/web10"

sfn = __salt__['cp.cache_file'](image, saltenv)调用cp.cache_file将image通过网络保存到
minion(也是kvm主机的)/var/cache/salt/minion/files/base/web10/system.qcow2

最后通过salt.utils.copyfile(sfn, img_dest)将
/var/cache/salt/minion/files/base/img/Template_Centos63x64.img此处的文件copy到

/srv/salt-image/web10/system.qcow2

xml = _gen_xml(name, cpu, mem, diskp, nicp, hypervisor, **kwargs)
这段很重要,这段生成了一个虚拟机简要的xml,不过,最重要的是构造了一个context的复杂数据,再通过JINJA的模板(libvirt_domain.jinja)渲染成xml.
context={'hypervisor':'kvm','mem':'524288','name':'web10','cpu':'4','controller_model':False,'boot_dev':['hd'],'disks':{'system':{'file_name':'system.qcow2','source_file':'/srv/salt-images/vm_name/system.qcow2','target_dev':'vda','address':False,'driver': True,'disk_bus':'virtio','type': 'qcow2','index': '0'}},'nics':[{'mac':'AC:DE:48:FE:01:BC','model':'virtio','name':'eth0','source':'br0','type':'bridge'}]}
生成的xml:

      web10
      4
      524288
      
                hvm
               
               
               
      
      
               
               
                        
                        
                        
                        
                        
               
                              
               
                  
                  
                  
               
               

               

      
      
               
      


define_xml_str(xml)将以上的xml生成一个/etc/libvirt/qemu/web10.xml
后面那一段要不要安装salt-minion,最后一个create(name),就启动虚拟机喽。

注意:我的镜像文件格式为raw,不是qcow2,所以我将代码中的'format':'qcow2'改为
'format':'raw',注意噢,改的是minion的virt.py代码噢。

你看我的结果:





页: [1]
查看完整版本: saltstack之virt模块创建虚拟机分析