初步代码

  1. <span style="font-size:18px;">'''''
  2. Work with virtual machines managed by libvirt
  3. :depends: libvirt Python module
  4. '''
  5. # Special Thanks to Michael Dehann, many of the concepts, and a few structures
  6. # of his in the virt func module have been used
  7. # Import python libs
  8. import os
  9. import re
  10. import shutil
  11. import subprocess
  12. from xml.dom import minidom
  13. # Import third party libs
  14. try:
  15. import libvirt
  16. HAS_LIBVIRT = True
  17. except ImportError:
  18. HAS_LIBVIRT = False
  19. import yaml
  20. # Import salt libs
  21. import salt.utils
  22. from salt._compat import StringIO as _StringIO
  23. from salt.exceptions import CommandExecutionError
  24. VIRT_STATE_NAME_MAP = {0: 'running',
  25. 1: 'running',
  26. 2: 'running',
  27. 3: 'paused',
  28. 4: 'shutdown',
  29. 5: 'shutdown',
  30. 6: 'crashed'}
  31. def __virtual__():
  32. if not HAS_LIBVIRT:
  33. return False
  34. return 'virt'
  35. def __get_conn():
  36. '''''
  37. Detects what type of dom this node is and attempts to connect to the
  38. correct hypervisor via libvirt.
  39. '''
  40. # This has only been tested on kvm and xen, it needs to be expanded to
  41. # support all vm layers supported by libvirt
  42. try:
  43. conn = libvirt.open('qemu:///system')
  44. except Exception:
  45. raise CommandExecutionError(
  46. 'Sorry, {0} failed to open a connection to the hypervisor '
  47. 'software'.format(
  48. __grains__['fqdn']
  49. )
  50. )
  51. return conn
  52. def _get_dom(vm_):
  53. '''''
  54. Return a domain object for the named vm
  55. '''
  56. conn = __get_conn()
  57. if vm_ not in list_vms():
  58. raise CommandExecutionError('The specified vm is not present')
  59. return conn.lookupByName(vm_)
  60. def _libvirt_creds():
  61. '''''
  62. Returns the user and group that the disk images should be owned by
  63. '''
  64. g_cmd = 'grep ^\s*group /etc/libvirt/qemu.conf'
  65. u_cmd = 'grep ^\s*user /etc/libvirt/qemu.conf'
  66. try:
  67. group = subprocess.Popen(g_cmd,
  68. shell=True,
  69. stdout=subprocess.PIPE).communicate()[0].split('"''"')[1]
  70. except IndexError:
  71. group = 'root'
  72. try:
  73. user = subprocess.Popen(u_cmd,
  74. shell=True,
  75. stdout=subprocess.PIPE).communicate()[0].split('"')[1]
  76. except IndexError:
  77. user = 'root'
  78. return {'user': user, 'group': group}
  79. def _get_migrate_command():
  80. '''''
  81. Returns the command shared by the differnt migration types
  82. '''
  83. return 'virsh migrate --live --persistent --undefinesource '
  84. def _get_target(target, ssh):
  85. proto = 'qemu'
  86. if ssh:
  87. proto += '+ssh'
  88. return ' %s://%s/%s' %(proto, target, 'system')
  89. def list_vms():
  90. '''''
  91. Return a list of virtual machine names on the minion
  92. CLI Example::
  93. salt '*' virt.list_vms
  94. '''
  95. vms = []
  96. vms.extend(list_active_vms())
  97. vms.extend(list_inactive_vms())
  98. return vms
  99. def list_active_vms():
  100. '''''
  101. Return a list of names for active virtual machine on the minion
  102. CLI Example::
  103. salt '*' virt.list_active_vms
  104. '''
  105. conn = __get_conn()
  106. vms = []
  107. for id_ in conn.listDomainsID():
  108. vms.append(conn.lookupByID(id_).name())
  109. return vms
  110. def list_inactive_vms():
  111. '''''
  112. Return a list of names for inactive virtual machine on the minion
  113. CLI Example::
  114. salt '*' virt.list_inactive_vms
  115. '''
  116. conn = __get_conn()
  117. vms = []
  118. for id_ in conn.listDefinedDomains():
  119. vms.append(id_)
  120. return vms
  121. def vm_info(vm_=None):
  122. '''''
  123. Return detailed information about the vms on this hyper in a
  124. list of dicts::
  125. [
  126. 'your-vm': {
  127. 'cpu': <int>,
  128. 'maxMem': <int>,
  129. 'mem': <int>,
  130. 'state': '<state>',
  131. 'cputime' <int>
  132. },
  133. ...
  134. ]
  135. If you pass a VM name in as an argument then it will return info
  136. for just the named VM, otherwise it will return all VMs.
  137. CLI Example::
  138. salt '*' virt.vm_info
  139. '''
  140. def _info(vm_):
  141. dom = _get_dom(vm_)
  142. raw = dom.info()
  143. return {'cpu': raw[3],
  144. 'cputime': int(raw[4]),
  145. 'disks': get_disks(vm_),
  146. 'graphics': get_graphics(vm_),
  147. 'nics': get_nics(vm_),
  148. 'maxMem': int(raw[1]),
  149. 'mem': int(raw[2]),
  150. 'state': VIRT_STATE_NAME_MAP.get(raw[0], 'unknown')}
  151. info = {}
  152. if vm_:
  153. info[vm_] = _info(vm_)
  154. else:
  155. for vm_ in list_vms():
  156. info[vm_] = _info(vm_)
  157. return info
  158. def vm_state(vm_=None):
  159. '''''
  160. Return list of all the vms and their state.
  161. If you pass a VM name in as an argument then it will return info
  162. for just the named VM, otherwise it will return all VMs.
  163. CLI Example::
  164. salt '*' virt.vm_state <vm name>
  165. '''
  166. def _info(vm_):
  167. state = ''
  168. dom = _get_dom(vm_)
  169. raw = dom.info()
  170. state = VIRT_STATE_NAME_MAP.get(raw[0], 'unknown')
  171. return state
  172. info = {}
  173. if vm_:
  174. info[vm_] = _info(vm_)
  175. else:
  176. for vm_ in list_vms():
  177. info[vm_] = _info(vm_)
  178. return info
  179. def node_info():
  180. '''''
  181. Return a dict with information about this node
  182. CLI Example::
  183. salt '*' virt.node_info
  184. '''
  185. conn = __get_conn()
  186. raw = conn.getInfo()
  187. info = {'cpucores': raw[6],
  188. 'cpumhz': raw[3],
  189. 'cpumodel': str(raw[0]),
  190. 'cpus': raw[2],
  191. 'cputhreads': raw[7],
  192. 'numanodes': raw[4],
  193. 'phymemory': raw[1],
  194. 'sockets': raw[5]}
  195. return info
  196. def get_nics(vm_):
  197. '''''
  198. Return info about the network interfaces of a named vm
  199. CLI Example::
  200. salt '*' virt.get_nics <vm name>
  201. '''
  202. nics = {}
  203. doc = minidom.parse(_StringIO(get_xml(vm_)))
  204. for node in doc.getElementsByTagName('devices'):
  205. i_nodes = node.getElementsByTagName('interface')
  206. for i_node in i_nodes:
  207. nic = {}
  208. nic['type'] = i_node.getAttribute('type')
  209. for v_node in i_node.getElementsByTagName('*'):
  210. if v_node.tagName == 'mac':
  211. nic['mac'] = v_node.getAttribute('address')
  212. if v_node.tagName == 'model':
  213. nic['model'] = v_node.getAttribute('type')
  214. if v_node.tagName == 'target':
  215. nic['target'] = v_node.getAttribute('dev')
  216. # driver, source, and match can all have optional attributes
  217. if re.match('(driver|source|address)', v_node.tagName):
  218. temp = {}
  219. for key in v_node.attributes.keys():
  220. temp[key] = v_node.getAttribute(key)
  221. nic[str(v_node.tagName)] = temp
  222. # virtualport needs to be handled separately, to pick up the
  223. # type attribute of the virtualport itself
  224. if v_node.tagName == 'virtualport':
  225. temp = {}
  226. temp['type'] = v_node.getAttribute('type')
  227. for key in v_node.attributes.keys():
  228. temp[key] = v_node.getAttribute(key)
  229. nic['virtualport'] = temp
  230. if 'mac' not in nic:
  231. continue
  232. nics[nic['mac']] = nic
  233. return nics
  234. def get_macs(vm_):
  235. '''''
  236. Return a list off MAC addresses from the named vm
  237. CLI Example::
  238. salt '*' virt.get_macs <vm name>
  239. '''
  240. macs = []
  241. doc = minidom.parse(_StringIO(get_xml(vm_)))
  242. for node in doc.getElementsByTagName('devices'):
  243. i_nodes = node.getElementsByTagName('interface')
  244. for i_node in i_nodes:
  245. for v_node in i_node.getElementsByTagName('mac'):
  246. macs.append(v_node.getAttribute('address'))
  247. return macs
  248. def get_graphics(vm_):
  249. '''''
  250. Returns the information on vnc for a given vm
  251. CLI Example::
  252. salt '*' virt.get_graphics <vm name>
  253. '''
  254. out = {'autoport': 'None',
  255. 'keymap': 'None',
  256. 'listen': 'None',
  257. 'port': 'None',
  258. 'type': 'vnc'}
  259. xml = get_xml(vm_)
  260. ssock = _StringIO(xml)
  261. doc = minidom.parse(ssock)
  262. for node in doc.getElementsByTagName('domain'):
  263. g_nodes = node.getElementsByTagName('graphics')
  264. for g_node in g_nodes:
  265. for key in g_node.attributes.keys():
  266. out[key] = g_node.getAttribute(key)
  267. return out
  268. def get_disks(vm_):
  269. '''''
  270. Return the disks of a named vm
  271. CLI Example::
  272. salt '*' virt.get_disks <vm name>
  273. '''
  274. disks = {}
  275. doc = minidom.parse(_StringIO(get_xml(vm_)))
  276. for elem in doc.getElementsByTagName('disk'):
  277. sources = elem.getElementsByTagName('source')
  278. targets = elem.getElementsByTagName('target')
  279. if len(sources) > 0:
  280. source = sources[0]
  281. else:
  282. continue
  283. if len(targets) > 0:
  284. target = targets[0]
  285. else:
  286. continue
  287. if target.hasAttribute('dev'):
  288. qemu_target = ''
  289. if source.hasAttribute('file'):
  290. qemu_target = source.getAttribute('file')
  291. elif source.hasAttribute('dev'):
  292. qemu_target = source.getAttribute('dev')
  293. elif source.hasAttribute('protocol') and \
  294. source.hasAttribute('name'): # For rbd network
  295. qemu_target = '%s:%s' %(
  296. source.getAttribute('protocol'),
  297. source.getAttribute('name'))
  298. if qemu_target:
  299. disks[target.getAttribute('dev')] = {\
  300. 'file': qemu_target}
  301. for dev in disks:
  302. try:
  303. output = []
  304. qemu_output = subprocess.Popen(['qemu-img', 'info',
  305. disks[dev]['file']],
  306. shell=False,
  307. stdout=subprocess.PIPE).communicate()[0]
  308. snapshots = False
  309. columns = None
  310. lines = qemu_output.strip().split('\n')
  311. for line in lines:
  312. if line.startswith('Snapshot list:'):
  313. snapshots = True
  314. continue
  315. elif snapshots:
  316. if line.startswith('ID'):  # Do not parse table headers
  317. line = line.replace('VM SIZE', 'VMSIZE')
  318. line = line.replace('VM CLOCK', 'TIME VMCLOCK')
  319. columns = re.split('\s+', line)
  320. columns = [c.lower() for c in columns]
  321. output.append('snapshots:')
  322. continue
  323. fields = re.split('\s+', line)
  324. for i, field in enumerate(fields):
  325. sep = ' '
  326. if i == 0:
  327. sep = '-'
  328. output.append(
  329. '{0} {1}: "{2}"'.format(
  330. sep, columns[i], field
  331. )
  332. )
  333. continue
  334. output.append(line)
  335. output = '\n'.join(output)
  336. disks[dev].update(yaml.safe_load(output))
  337. except TypeError:
  338. disks[dev].update(yaml.safe_load('image: Does not exist'))
  339. return disks
  340. def setmem(vm_, memory, config=False):
  341. '''''
  342. Changes the amount of memory allocated to VM. The VM must be shutdown
  343. for this to work.
  344. memory is to be specified in MB
  345. If config is True then we ask libvirt to modify the config as well
  346. CLI Example::
  347. salt '*' virt.setmem myvm 768
  348. '''
  349. if vm_state(vm_) != 'shutdown':
  350. return False
  351. dom = _get_dom(vm_)
  352. # libvirt has a funny bitwise system for the flags in that the flag
  353. # to affect the "current" setting is 0, which means that to set the
  354. # current setting we have to call it a second time with just 0 set
  355. flags = libvirt.VIR_DOMAIN_MEM_MAXIMUM
  356. if config:
  357. flags = flags | libvirt.VIR_DOMAIN_AFFECT_CONFIG
  358. ret1 = dom.setMemoryFlags(memory * 1024, flags)
  359. ret2 = dom.setMemoryFlags(memory * 1024, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
  360. # return True if both calls succeeded
  361. return ret1 == ret2 == 0
  362. def setvcpus(vm_, vcpus, config=False):
  363. '''''
  364. Changes the amount of vcpus allocated to VM. The VM must be shutdown
  365. for this to work.
  366. vcpus is an int representing the number to be assigned
  367. If config is True then we ask libvirt to modify the config as well
  368. CLI Example::
  369. salt '*' virt.setvcpus myvm 2
  370. '''
  371. if vm_state(vm_) != 'shutdown':
  372. return False
  373. dom = _get_dom(vm_)
  374. # see notes in setmem
  375. flags = libvirt.VIR_DOMAIN_VCPU_MAXIMUM
  376. if config:
  377. flags = flags | libvirt.VIR_DOMAIN_AFFECT_CONFIG
  378. ret1 = dom.setVcpusFlags(vcpus, flags)
  379. ret2 = dom.setVcpusFlags(vcpus, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
  380. return ret1 == ret2 == 0
  381. def freemem():
  382. '''''
  383. Return an int representing the amount of memory that has not been given
  384. to virtual machines on this node
  385. CLI Example::
  386. salt '*' virt.freemem
  387. '''
  388. conn = __get_conn()
  389. mem = conn.getInfo()[1]
  390. # Take off just enough to sustain the hypervisor
  391. mem -= 256
  392. for vm_ in list_vms():
  393. dom = _get_dom(vm_)
  394. if dom.ID() > 0:
  395. mem -= dom.info()[2] / 1024
  396. return mem
  397. def freecpu():
  398. '''''
  399. Return an int representing the number of unallocated cpus on this
  400. hypervisor
  401. CLI Example::
  402. salt '*' virt.freecpu
  403. '''
  404. conn = __get_conn()
  405. cpus = conn.getInfo()[2]
  406. for vm_ in list_vms():
  407. dom = _get_dom(vm_)
  408. if dom.ID() > 0:
  409. cpus -= dom.info()[3]
  410. return cpus
  411. def full_info():
  412. '''''
  413. Return the node_info, vm_info and freemem
  414. CLI Example::
  415. salt '*' virt.full_info
  416. '''
  417. return {'freecpu': freecpu(),
  418. 'freemem': freemem(),
  419. 'node_info': node_info(),
  420. 'vm_info': vm_info()}
  421. def get_xml(vm_):
  422. '''''
  423. Returns the xml for a given vm
  424. CLI Example::
  425. salt '*' virt.get_xml <vm name>
  426. '''
  427. dom = _get_dom(vm_)
  428. return dom.XMLDesc(0)
  429. def shutdown(vm_):
  430. '''''
  431. Send a soft shutdown signal to the named vm
  432. CLI Example::
  433. salt '*' virt.shutdown <vm name>
  434. '''
  435. dom = _get_dom(vm_)
  436. return dom.shutdown() == 0
  437. def pause(vm_):
  438. '''''
  439. Pause the named vm
  440. CLI Example::
  441. salt '*' virt.pause <vm name>
  442. '''
  443. dom = _get_dom(vm_)
  444. return dom.suspend() == 0
  445. def resume(vm_):
  446. '''''
  447. Resume the named vm
  448. CLI Example::
  449. salt '*' virt.resume <vm name>
  450. '''
  451. dom = _get_dom(vm_)
  452. return dom.resume() == 0
  453. def create(vm_):
  454. '''''
  455. Start a defined domain
  456. CLI Example::
  457. salt '*' virt.create <vm name>
  458. '''
  459. dom = _get_dom(vm_)
  460. return dom.create() == 0
  461. def start(vm_):
  462. '''''
  463. Alias for the obscurely named 'create' function
  464. CLI Example::
  465. salt '*' virt.start <vm name>
  466. '''
  467. return create(vm_)
  468. def reboot(vm_):
  469. '''''
  470. Reboot a domain via ACPI request
  471. CLI Example::
  472. salt '*' virt.reboot <vm name>
  473. '''
  474. dom = _get_dom(vm_)
  475. # reboot has a few modes of operation, passing 0 in means the
  476. # hypervisor will pick the best method for rebooting
  477. return dom.reboot(0) == 0
  478. def reset(vm_):
  479. '''''
  480. Reset a VM by emulating the reset button on a physical machine
  481. CLI Example::
  482. salt '*' virt.reset <vm name>
  483. '''
  484. dom = _get_dom(vm_)
  485. # reset takes a flag, like reboot, but it is not yet used
  486. # so we just pass in 0
  487. # see: http://libvirt.org/html/libvirt-libvirt.html#virDomainReset
  488. return dom.reset(0) == 0
  489. def ctrl_alt_del(vm_):
  490. '''''
  491. Sends CTRL+ALT+DEL to a VM
  492. CLI Example::
  493. salt '*' virt.ctrl_alt_del <vm name>
  494. '''
  495. dom = _get_dom(vm_)
  496. return dom.sendKey(0, 0, [29, 56, 111], 3, 0) == 0
  497. def create_xml_str(xml):
  498. '''''
  499. Start a domain based on the xml passed to the function
  500. CLI Example::
  501. salt '*' virt.create_xml_str <xml in string format>
  502. '''
  503. conn = __get_conn()
  504. return conn.createXML(xml, 0) is not None
  505. def create_xml_path(path):
  506. '''''
  507. Start a defined domain
  508. CLI Example::
  509. salt '*' virt.create_xml_path <path to xml file on the node>
  510. '''
  511. if not os.path.isfile(path):
  512. return False
  513. return create_xml_str(salt.utils.fopen(path, 'r').read())
  514. def define_xml_str(xml):
  515. '''''
  516. Define a domain based on the xml passed to the function
  517. CLI Example::
  518. salt '*' virt.define_xml_str <xml in string format>
  519. '''
  520. conn = __get_conn()
  521. return conn.defineXML(xml) is not None
  522. def migrate_non_shared(vm_, target, ssh=False):
  523. '''''
  524. Attempt to execute non-shared storage "all" migration
  525. CLI Example::
  526. salt '*' virt.migrate_non_shared <vm name> <target hypervisor>
  527. '''
  528. cmd = _get_migrate_command() + ' --copy-storage-all ' + vm_\
  529. + _get_target(target, ssh)
  530. return subprocess.Popen(cmd,
  531. shell=True,
  532. stdout=subprocess.PIPE).communicate()[0]
  533. def migrate_non_shared_inc(vm_, target, ssh=False):
  534. '''''
  535. Attempt to execute non-shared storage "all" migration
  536. CLI Example::
  537. salt '*' virt.migrate_non_shared_inc <vm name> <target hypervisor>
  538. '''
  539. cmd = _get_migrate_command() + ' --copy-storage-inc ' + vm_\
  540. + _get_target(target, ssh)
  541. return subprocess.Popen(cmd,
  542. shell=True,
  543. stdout=subprocess.PIPE).communicate()[0]
  544. def migrate(vm_, target, ssh=False):
  545. '''''
  546. Shared storage migration
  547. CLI Example::
  548. salt '*' virt.migrate <vm name> <target hypervisor>
  549. '''
  550. cmd = _get_migrate_command() + ' ' + vm_\
  551. + _get_target(target, ssh)
  552. return subprocess.Popen(cmd,
  553. shell=True,
  554. stdout=subprocess.PIPE).communicate()[0]
  555. def seed_non_shared_migrate(disks, force=False):
  556. '''''
  557. Non shared migration requires that the disks be present on the migration
  558. destination, pass the disks information via this function, to the
  559. migration destination before executing the migration.
  560. CLI Example::
  561. salt '*' virt.seed_non_shared_migrate <disks>
  562. '''
  563. for _, data in disks.items():
  564. fn_ = data['file']
  565. form = data['file format']
  566. size = data['virtual size'].split()[1][1:]
  567. if os.path.isfile(fn_) and not force:
  568. # the target exists, check to see if is is compatible
  569. pre = yaml.safe_load(subprocess.Popen('qemu-img info arch',
  570. shell=True,
  571. stdout=subprocess.PIPE).communicate()[0])
  572. if not pre['file format'] == data['file format']\
  573. and not pre['virtual size'] == data['virtual size']:
  574. return False
  575. if not os.path.isdir(os.path.dirname(fn_)):
  576. os.makedirs(os.path.dirname(fn_))
  577. if os.path.isfile(fn_):
  578. os.remove(fn_)
  579. cmd = 'qemu-img create -f ' + form + ' ' + fn_ + ' ' + size
  580. subprocess.call(cmd, shell=True)
  581. creds = _libvirt_creds()
  582. cmd = 'chown ' + creds['user'] + ':' + creds['group'] + ' ' + fn_
  583. subprocess.call(cmd, shell=True)
  584. return True
  585. def set_autostart(vm_, state='on'):
  586. '''''
  587. Set the autostart flag on a VM so that the VM will start with the host
  588. system on reboot.
  589. CLI Example::
  590. salt "*" virt.set_autostart <vm name> <on | off>
  591. '''
  592. dom = _get_dom(vm_)
  593. if state == 'on':
  594. return dom.setAutostart(1) == 0
  595. elif state == 'off':
  596. return dom.setAutostart(0) == 0
  597. else:
  598. # return False if state is set to something other then on or off
  599. return False
  600. def destroy(vm_):
  601. '''''
  602. Hard power down the virtual machine, this is equivalent to pulling the
  603. power
  604. CLI Example::
  605. salt '*' virt.destroy <vm name>
  606. '''
  607. dom = _get_dom(vm_)
  608. return dom.destroy() == 0
  609. def undefine(vm_):
  610. '''''
  611. Remove a defined vm, this does not purge the virtual machine image, and
  612. this only works if the vm is powered down
  613. CLI Example::
  614. salt '*' virt.undefine <vm name>
  615. '''
  616. dom = _get_dom(vm_)
  617. return dom.undefine() == 0
  618. def purge(vm_, dirs=False):
  619. '''''
  620. Recursively destroy and delete a virtual machine, pass True for dir's to
  621. also delete the directories containing the virtual machine disk images -
  622. USE WITH EXTREME CAUTION!
  623. CLI Example::
  624. salt '*' virt.purge <vm name>
  625. '''
  626. disks = get_disks(vm_)
  627. if not destroy(vm_):
  628. return False
  629. directories = set()
  630. for disk in disks:
  631. os.remove(disks[disk]['file'])
  632. directories.add(os.path.dirname(disks[disk]['file']))
  633. if dirs:
  634. for dir_ in directories:
  635. shutil.rmtree(dir_)
  636. return True
  637. def virt_type():
  638. '''''
  639. Returns the virtual machine type as a string
  640. CLI Example::
  641. salt '*' virt.virt_type
  642. '''
  643. return __grains__['virtual']
  644. def is_kvm_hyper():
  645. '''''
  646. Returns a bool whether or not this node is a KVM hypervisor
  647. CLI Example::
  648. salt '*' virt.is_kvm_hyper
  649. '''
  650. if __grains__['virtual'] != 'physical':
  651. return False
  652. try:
  653. if 'kvm_' not in salt.utils.fopen('/proc/modules').read():
  654. return False
  655. except IOError:
  656. # No /proc/modules? Are we on Windows? Or Solaris?
  657. return False
  658. return 'libvirtd' in __salt__['cmd.run'](__grains__['ps'])
  659. def is_xen_hyper():
  660. '''''
  661. Returns a bool whether or not this node is a XEN hypervisor
  662. CLI Example::
  663. salt '*' virt.is_xen_hyper
  664. '''
  665. try:
  666. if __grains__['virtual_subtype'] != 'Xen Dom0':
  667. return False
  668. except KeyError:
  669. # virtual_subtype isn't set everywhere.
  670. return False
  671. try:
  672. if 'xen_' not in salt.utils.fopen('/proc/modules').read():
  673. return False
  674. except IOError:
  675. # No /proc/modules? Are we on Windows? Or Solaris?
  676. return False
  677. return 'libvirtd' in __salt__['cmd.run'](__grains__['ps'])
  678. def is_hyper():
  679. '''''
  680. Returns a bool whether or not this node is a hypervisor of any kind
  681. CLI Example::
  682. salt '*' virt.is_hyper
  683. '''
  684. return is_xen_hyper() or is_kvm_hyper()
  685. def vm_cputime(vm_=None):
  686. '''''
  687. Return cputime used by the vms on this hyper in a
  688. list of dicts::
  689. [
  690. 'your-vm': {
  691. 'cputime' <int>
  692. 'cputime_percent' <int>
  693. },
  694. ...
  695. ]
  696. If you pass a VM name in as an argument then it will return info
  697. for just the named VM, otherwise it will return all VMs.
  698. CLI Example::
  699. salt '*' virt.vm_cputime
  700. '''
  701. host_cpus = __get_conn().getInfo()[2]
  702. def _info(vm_):
  703. dom = _get_dom(vm_)
  704. raw = dom.info()
  705. vcpus = int(raw[3])
  706. cputime = int(raw[4])
  707. cputime_percent = 0
  708. if cputime:
  709. # Divide by vcpus to always return a number between 0 and 100
  710. cputime_percent = (1.0e-7 * cputime / host_cpus) / vcpus
  711. return {
  712. 'cputime': int(raw[4]),
  713. 'cputime_percent': int('%.0f' %cputime_percent)
  714. }
  715. info = {}
  716. if vm_:
  717. info[vm_] = _info(vm_)
  718. else:
  719. for vm_ in list_vms():
  720. info[vm_] = _info(vm_)
  721. return info
  722. def vm_netstats(vm_=None):
  723. '''''
  724. Return combined network counters used by the vms on this hyper in a
  725. list of dicts::
  726. [
  727. 'your-vm': {
  728. 'rx_bytes'   : 0,
  729. 'rx_packets' : 0,
  730. 'rx_errs'    : 0,
  731. 'rx_drop'    : 0,
  732. 'tx_bytes'   : 0,
  733. 'tx_packets' : 0,
  734. 'tx_errs'    : 0,
  735. 'tx_drop'    : 0
  736. },
  737. ...
  738. ]
  739. If you pass a VM name in as an argument then it will return info
  740. for just the named VM, otherwise it will return all VMs.
  741. CLI Example::
  742. salt '*' virt.vm_netstats
  743. '''
  744. def _info(vm_):
  745. dom = _get_dom(vm_)
  746. nics = get_nics(vm_)
  747. ret = {
  748. 'rx_bytes'   : 0,
  749. 'rx_packets' : 0,
  750. 'rx_errs'    : 0,
  751. 'rx_drop'    : 0,
  752. 'tx_bytes'   : 0,
  753. 'tx_packets' : 0,
  754. 'tx_errs'    : 0,
  755. 'tx_drop'    : 0
  756. }
  757. for mac, attrs in nics.items():
  758. if 'target' in attrs:
  759. dev = attrs['target']
  760. stats = dom.interfaceStats(dev)
  761. ret['rx_bytes'] += stats[0]
  762. ret['rx_packets'] += stats[1]
  763. ret['rx_errs'] += stats[2]
  764. ret['rx_drop'] += stats[3]
  765. ret['tx_bytes'] += stats[4]
  766. ret['tx_packets'] += stats[5]
  767. ret['tx_errs'] += stats[6]
  768. ret['tx_drop'] += stats[7]
  769. return ret
  770. info = {}
  771. if vm_:
  772. info[vm_] = _info(vm_)
  773. else:
  774. for vm_ in list_vms():
  775. info[vm_] = _info(vm_)
  776. return info
  777. def vm_diskstats(vm_=None):
  778. '''''
  779. Return disk usage counters used by the vms on this hyper in a
  780. list of dicts::
  781. [
  782. 'your-vm': {
  783. 'rd_req'   : 0,
  784. 'rd_bytes' : 0,
  785. 'wr_req'   : 0,
  786. 'wr_bytes' : 0,
  787. 'errs'     : 0
  788. },
  789. ...
  790. ]
  791. If you pass a VM name in as an argument then it will return info
  792. for just the named VM, otherwise it will return all VMs.
  793. CLI Example::
  794. salt '*' virt.vm_blockstats
  795. '''
  796. def get_disk_devs(vm_):
  797. doc = minidom.parse(_StringIO(get_xml(vm_)))
  798. disks = []
  799. for elem in doc.getElementsByTagName('disk'):
  800. targets = elem.getElementsByTagName('target')
  801. target = targets[0]
  802. disks.append(target.getAttribute('dev'))
  803. return disks
  804. def _info(vm_):
  805. dom = _get_dom(vm_)
  806. # Do not use get_disks, since it uses qemu-img and is very slow
  807. # and unsuitable for any sort of real time statistics
  808. disks = get_disk_devs(vm_)
  809. ret = {
  810. 'rd_req'   : 0,
  811. 'rd_bytes' : 0,
  812. 'wr_req'   : 0,
  813. 'wr_bytes' : 0,
  814. 'errs'     : 0
  815. }
  816. for disk in disks:
  817. stats = dom.blockStats(disk)
  818. ret['rd_req']   += stats[0]
  819. ret['rd_bytes'] += stats[1]
  820. ret['wr_req']   += stats[2]
  821. ret['wr_bytes'] += stats[3]
  822. ret['errs']     += stats[4]
  823. return ret
  824. info = {}
  825. if vm_:
  826. info[vm_] = _info(vm_)
  827. else:
  828. # Can not run function blockStats on inactive VMs
  829. for vm_ in list_active_vms():
  830. info[vm_] = _info(vm_)
  831. return info
  832. </span>
 

通过python-libvirt管理KVM虚拟机 代码实现的更多相关文章

  1. 使用 libvirt创建和管理KVM虚拟机

      1. libvirt介绍    Libvirt是一个软件集合,便于使用者管理虚拟机和其他虚拟化功能,比如存储和网络接口管理等等.Libvirt概括起来包括一个API库.一个 daemon(libv ...

  2. 管理KVM虚拟机(二)

    管理KVM虚拟机 工具:libvirt 官网:http://libvirt.org/ 介绍:Libvirt 库是一种实现 Linux 虚拟化功能的 Linux® API,它支持各种虚拟机监控程序,包括 ...

  3. 关于Linux虚拟化技术KVM的科普 科普二(KVM虚拟机代码揭秘)

    代码分析文章<KVM虚拟机代码揭秘--QEMU代码结构分析>.<KVM虚拟机代码揭秘--中断虚拟化>.<KVM虚拟机代码揭秘--设备IO虚拟化>.<KVM虚拟 ...

  4. Linux 中使用 virsh 管理 KVM 虚拟机 (转)

    术语 虚拟化指的是:在相同的物理(硬件)系统上,同时运行多个操作系统,且这几个系统相互隔离的可能性,而那个硬件在虚拟化架构中被称作宿主机(host).虚拟机监视器(也被称为虚拟机管理程序(hyperv ...

  5. 使用Wok管理kvm虚拟机

    [Centos7.4] !!!测试环境我们首关闭防火墙和selinux [root@localhost ~]# systemctl stop firewalld [root@localhost ~]# ...

  6. 使用libvirt管理KVM(一)

    一. 安装和配置libvirt,源码下载http://www.qemu-project.org/download/#source. 二. 从包和源码包进行安装libvirt. 1. 在ubuntu系统 ...

  7. 安装libvirt管理套件(C/S架构模式,用户管理kvm虚拟机)

    # 1:安装程序包 yum install -y libvirt virt-manager virt-viewer virt-install qemu-kvm   # 2:启动libvirtd守护进程 ...

  8. 使用cockpit管理kvm虚拟机

    在Centos8.2主机上部署kvm,使用cockpit管理 首先检测cpu是否支持虚拟化 [root@localhost ~]# cat /proc/cpuinfo | grep vmx flags ...

  9. 通过python-libvirt管理KVM虚拟机 源码

    版本:0.9.13 libvirt库可真是大,先看看该版本里面都有哪些类和方法,验证过的方法我会用O开头,|开头的标示还没亲自验证过. <span style="font-size:1 ...

随机推荐

  1. 高并发分布式系统中生成全局唯一(订单号)Id js返回上一页并刷新、返回上一页、自动刷新页面 父页面操作嵌套iframe子页面的HTML标签元素 .net判断System.Data.DataRow中是否包含某列 .Net使用system.Security.Cryptography.RNGCryptoServiceProvider类与System.Random类生成随机数

    高并发分布式系统中生成全局唯一(订单号)Id   1.GUID数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么通过组合的方式,保留GUID的10个字节,用另6个字节表示GUID生成的时间(D ...

  2. OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

  3. Smarty标签 for运算

    $select="SELECT {$col_name} FROM woke_order where deleted=0 ".$where.$orderby ; // 取出数组 $r ...

  4. 【转】DRY原则的误区

    很多编程的人,喜欢鼓吹各种各样的“原则”,比如KISS原则,DRY原则…… 总有人把这些所谓原则奉为教条或者秘方,以为兢兢业业地遵循这些,空喊几个口号,就可以写出好的代码.同时,他们对违反这些原则的人 ...

  5. iOS Terminating app due to uncaught exception &#39;NSInternalInconsistencyException&#39;, reason: &#39;unable to

    刚接触iOS,依照教程操作执行出现错误 Terminating app due to uncaught exception 'NSInternalInconsistencyException', re ...

  6. Database Vault Administrator的使用

    第一次安装Database Vault的时候,先安装好了Database Vault.然后才安装的EM.发现,根本无法訪问<span><span>Database Vault ...

  7. DrawItem

    原文链接: http://blog.csdn.net/jiftlixu/article/details/4893505 今天从CButton派生了一个类CUIButton,主要用于自绘,按照基本的流程 ...

  8. [转]什么是C++虚函数、虚函数的作用和使用方法

    我们知道,在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是“重复定义”.但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能不同的函数.例如在例 ...

  9. Appium 点击屏幕

    由于版本变更,appium 点击屏幕方法已经改变, TouchAction action = new TouchAction(driver); Duration duration = Duration ...

  10. php分享十一:PHP实现异步调用方法研究

    浏览器和服务器之间是通过 HTTP 协议进行连接通讯的.这是一种基于请求和响应模型的协议.浏览器通过 URL 向服务器发起请求,Web 服务器接收到请求,执行一段程序,然后做出响应,发送相应的html ...