guest_xml.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from jimvc.models import Config, Disk
  4. from jimvc.models import Guest
  5. from jimvc.models import status
  6. __author__ = 'James Iter'
  7. __date__ = '2017/3/25'
  8. __contact__ = 'james.iter.cn@gmail.com'
  9. __copyright__ = '(c) 2017 by James Iter.'
  10. class GuestXML(object):
  11. def __init__(self, host=None, guest=None, disk=None, config=None, os_type=None):
  12. assert isinstance(guest, Guest)
  13. assert isinstance(disk, Disk)
  14. assert isinstance(config, Config)
  15. self.host = host
  16. self.guest = guest
  17. self.disk = disk
  18. self.config = config
  19. self.os_type = os_type
  20. def get_domain(self):
  21. return """<?xml version="1.0" encoding="utf-8"?>
  22. <domain type="{0}">
  23. {1}
  24. {2}
  25. {3}
  26. {4}
  27. {5}
  28. {6}
  29. {7}
  30. {8}
  31. {9}
  32. </domain>
  33. """.format(self.get_hypervisor(), self.get_features(), self.get_cpu_mode(), self.get_clock(), self.get_name(),
  34. self.get_uuid(), self.get_vcpu(), self.get_memory(), self.get_os(), self.get_devices())
  35. def get_hypervisor(self):
  36. hypervisor = 'qemu'
  37. if self.host['cpuinfo'] is not None and 'flags' in self.host['cpuinfo']:
  38. if 'vmx' in self.host['cpuinfo']['flags'] or 'svm' in self.host['cpuinfo']['flags']:
  39. hypervisor = 'kvm'
  40. return hypervisor
  41. @staticmethod
  42. def get_features():
  43. return """
  44. <features>
  45. <acpi/>
  46. <apic/>
  47. </features>
  48. """
  49. def get_cpu_mode(self):
  50. cpu_mode = """"""
  51. if 'kvm' == self.get_hypervisor():
  52. cpu_mode = """<cpu mode='host-passthrough'/>"""
  53. return cpu_mode
  54. def get_clock(self):
  55. # clock 参考链接:https://libvirt.org/formatdomain.html#elementsTime
  56. # Windows Guest 设为 localtime,非 Windows Guest 都设为 utc
  57. offset = 'utc'
  58. if str(self.os_type).lower().find('windows') >= 0:
  59. offset = 'localtime'
  60. return """<clock offset='{0}'/>""".format(offset)
  61. def get_name(self):
  62. return """<name>{0}</name>""".format(self.guest.label)
  63. def get_uuid(self):
  64. return """<uuid>{0}</uuid>""".format(self.guest.uuid)
  65. def get_vcpu(self):
  66. return """<vcpu>{0}</vcpu>""".format(self.guest.cpu.__str__())
  67. def get_memory(self):
  68. return """<memory unit="GiB">{0}</memory>""".format(self.guest.memory.__str__())
  69. @staticmethod
  70. def get_os():
  71. return """
  72. <os>
  73. <boot dev="hd"/>
  74. <type arch="x86_64">hvm</type>
  75. <bootmenu timeout="3000" enable="yes"/>
  76. </os>
  77. """
  78. def get_devices(self):
  79. return """
  80. <devices>
  81. {0}
  82. {1}
  83. {2}
  84. {3}
  85. {4}
  86. </devices>
  87. """.format(self.get_interface(), self.get_disk(), self.get_graphics(), self.get_console(), self.get_channel())
  88. def get_interface(self):
  89. return """
  90. <interface type='network'>
  91. <source network='{0}'/>
  92. <model type='virtio'/>
  93. <bandwidth>
  94. <inbound average='{1}'/>
  95. <outbound average='{1}'/>
  96. </bandwidth>
  97. </interface>
  98. """.format(self.guest.network, self.guest.bandwidth / 1000 / 8)
  99. def get_disk(self):
  100. from initialize import dev_table
  101. if self.config.storage_mode in [status.StorageMode.local.value, status.StorageMode.shared_mount.value]:
  102. disk_xml = """
  103. <disk type='file' device='disk'>
  104. <driver name='qemu' type='{0}' cache='none'/>
  105. <source file='{1}'/>
  106. <target dev='{2}' bus='virtio'/>
  107. </disk>
  108. """.format(self.disk.format, self.disk.path, dev_table[self.disk.sequence])
  109. elif self.config.storage_mode in [status.StorageMode.ceph.value, status.StorageMode.glusterfs.value]:
  110. dfs_protocol = 'ceph'
  111. if self.config.storage_mode == status.StorageMode.glusterfs.value:
  112. dfs_protocol = 'gluster'
  113. disk_xml = """
  114. <disk type='network' device='disk'>
  115. <driver name='qemu' type='{0}' cache='none'/>
  116. <source protocol='{1}' name='{2}/{3}'>
  117. <host name='127.0.0.1' port='24007'/>
  118. </source>
  119. <target dev='{4}' bus='virtio'/>
  120. </disk>
  121. """.format(self.disk.format, dfs_protocol, self.config.dfs_volume, self.disk.path,
  122. dev_table[self.disk.sequence])
  123. else:
  124. disk_xml = ''
  125. return disk_xml
  126. def get_graphics(self):
  127. return """
  128. <graphics passwd="{0}" keymap="en-us" port="{1}" type="vnc">
  129. <listen network="{2}" type="network"/>
  130. </graphics>
  131. """.format(self.guest.vnc_password, self.guest.vnc_port, self.guest.manage_network)
  132. @staticmethod
  133. def get_console():
  134. return """
  135. <serial type='pty'>
  136. <target port='0'/>
  137. </serial>
  138. <console type='pty'>
  139. <target type='serial' port='0'/>
  140. </console>
  141. """
  142. @staticmethod
  143. def get_channel():
  144. return """
  145. <channel type='unix'>
  146. <source mode='bind'/>
  147. <target type='virtio' name='org.qemu.guest_agent.0'/>
  148. </channel>
  149. """