初步代码

  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. 【struts2】预定义拦截器

    1)预定义拦截器 Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器.由于Struts2的默认拦截器声明和引用都在这个St ...

  2. SQL如何获得本季度第一天、一年的第一天、本月的最后一天

    nterval 参数,具有以下设定值: 设置 描述 Year yy, yyyy 年 quarter qq, q 季 Month mm, m 月 dayofyear dy, y 一年的日数 Day dd ...

  3. 为什么你学不会递归?告别递归,谈谈我的一些经验 关于集合中一些常考的知识点总结 .net辗转java系列(一)视野 彻底理解cookie,session,token

    为什么你学不会递归?告别递归,谈谈我的一些经验   可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了! ...

  4. SharePoint下在Feature中动态Register/Remove HttpModule

    在SharePoint开发时,你会遇到这样一个问题,Global.asax去哪儿?怎样添加一个Global.asax?怎样在Application_Start这个事件处理程序里设置初始化?似乎在Vis ...

  5. Elasticsearch初探(一)

    一.安装(Linux篇) 现在的开源软件越来越成熟,都打好包了,下载后直接解压就可以测试了. curl -L -O https://artifacts.elastic.co/downloads/ela ...

  6. Cross compiling coreutils and generate the manpages

    When we cross compiling coreutils, there is an problem of generating man pages, because the source s ...

  7. Mac下 如何配置虚拟机软件Parallel Desktop--超详细

    Mac下 如何配置虚拟机软件Pparallel Desktop--超详细 Mac 的双系统解决方案有两种,一种是使用Boot Camp分区安装独立的Windows,一种是通过安装Parallels D ...

  8. python 取整的两种方法

    问题简介: 要把一个浮点数(float)整数部分提取出来.比如把“2.1”变成“2”的这一过程:现在我们给这个过程起一个名字叫“取整”.那么它 在python中大致可以有两种写法 写法1)类型转换: ...

  9. shell编程入门(一)

    运行Linux程序有三种方法: (1).使文件具有可执行权限,直接运行文件. (2).直接调用命令解释器执行程序(Linux shell是一种解释型语言). (3).使用source执行文件 第一种: ...

  10. Flume 相关

    在CentOS 7上安装配置Flume https://mos.meituan.com/library/41/how-to-install-flume-on-centos7/ Flume NG 学习笔 ...