son30 发表于 2018-8-1 09:30:40

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:
  <domain type='kvm'>
  <name>web10</name>
  <vcpu>4</vcpu>
  <memory unit='KiB'>524288</memory>
  <os>
  <type>hvm</type>
  <boot dev='hd' />
  </os>
  <devices>
  <disk type='file' device='disk'>
  <source file='/srv/salt-images/vm_name/system.qcow2' />
  <target dev='vda' bus='virtio' />
  <driver name='qemu' type='qcow2' cache='none' io='native'/>
  </disk>
  <interface type='bridge'>
  <source bridge='br0'/>
  <mac address='AC:DE:48:FE:01:BC'/>
  <model type='virtio'/>
  </interface>
  <graphics type='vnc' listen='0.0.0.0' autoport='yes' />
  </devices>
  <features>
  <acpi />
  </features>
  </domain>
  define_xml_str(xml)将以上的xml生成一个/etc/libvirt/qemu/web10.xml
  后面那一段要不要安装salt-minion,最后一个create(name),就启动虚拟机喽。
  注意:我的镜像文件格式为raw,不是qcow2,所以我将代码中的'format':'qcow2'改为
  'format':'raw',注意噢,改的是minion的virt.py代码噢。
  你看我的结果:


  如果想了解更多,请关注我们的公众号
  公众号ID:opdevos
  扫码关注
页: [1]
查看完整版本: saltstack之virt模块创建虚拟机分析