初步代码

  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. suricata 命令行解释【转】

    suricata命令行 转载地址:http://blog.sina.com.cn/s/blog_6f8edcde0101gcha.html suricata命令行选项说明 你能两种方式使用命令行选项, ...

  2. IT技术需求建立时需考虑的因素

      2012-11-13 内容存档在evernote,笔记名"IT技术需求建立时需考虑的因素"

  3. Swift 扩展

    前言 扩展就是给一个现存类.结构体.枚举或者协议添加新的属性或者方法,无需修改目标的源代码,就可以把想要的代码加到目标上面. 扩展可以用来扩展现有类型的计算属性.构造器.方法和下标. 不能添加一个已经 ...

  4. Smarty标签 for运算

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

  5. Android Notification 的声音和震动

    我们在Android系统发送一条Notification的时候,经常需要通过震动或声音来提醒用户.如何为Notification设置声音和震动了.大致思路有: - AndroidNotificatio ...

  6. 你的应用是怎样被替换的,App劫持病毒剖析

    一.App劫持病毒介绍 App劫持是指运行流程被重定向,又可分为Activity劫持.安装劫持.流量劫持.函数运行劫持等. 本文将对最近利用Acticity劫持和安装劫持的病毒进行分析. 二.Acti ...

  7. Eclipse配置SQL Explorer插件和数据库

    1.下载SQL Explore插件,地址:http://www.sqlexplorer.org/,下载第三个.复制到eclipse插件相应文件夹重新启动,下载RCP插件能够直接使用exe 2.下载JD ...

  8. 跟我学SharePoint 2013视频培训课程——排序、过滤在列表、库中的使用(10)

    课程简介 第10天,SharePoint 2013排序.过滤在列表.库中的使用. 视频 SharePoint 2013 交流群 41032413

  9. 设计模式之策略模式&amp;简单工厂模式

    学习设计模式已经有非常长一段时间了,事实上先前已经敲过一遍了.可是老认为没有学到什么,认识也不够深刻.如今趁着重构机房,再又一次来过,也不晚. 事实上在敲了机房之后,看看模式,事实上,曾经非常难理解. ...

  10. 例说Linux内核链表(一)

    介绍 众所周知,Linux内核大部分是使用GNU C语言写的.C不同于其它的语言,它不具备一个好的数据结构对象或者标准对象库的支持. 所以能够借用Linux内核源代码树的循环双链表是一件非常值得让人高 ...