qubes/vm/dispvm: Add methods for creating and destroying
fixes QubesOS/qubes-issues#866
This commit is contained in:
		
							parent
							
								
									a719e0d93d
								
							
						
					
					
						commit
						5a76d0b03b
					
				
							
								
								
									
										12
									
								
								qubes/app.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								qubes/app.py
									
									
									
									
									
								
							| @ -30,9 +30,11 @@ import functools | |||||||
| import grp | import grp | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
|  | import random | ||||||
| import sys | import sys | ||||||
| import tempfile | import tempfile | ||||||
| import time | import time | ||||||
|  | import uuid | ||||||
| 
 | 
 | ||||||
| import jinja2 | import jinja2 | ||||||
| import libvirt | import libvirt | ||||||
| @ -485,6 +487,16 @@ class VMCollection(object): | |||||||
|         raise LookupError("Cannot find unused netid!") |         raise LookupError("Cannot find unused netid!") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def get_new_unused_dispid(self): | ||||||
|  |         for i in range(qubes.config.max_dispid ** 0.5): | ||||||
|  |             dispid = random.SystemRandom().randrange(qubes.config.max_dispid) | ||||||
|  |             if not any(getattr(vm, 'dispid', None) == dispid for vm in self): | ||||||
|  |                 return dispid | ||||||
|  |         raise LookupError(( | ||||||
|  |             'https://xkcd.com/221/', | ||||||
|  |             'http://dilbert.com/strip/2001-10-25')[random.randint(0, 1)]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class Qubes(qubes.PropertyHolder): | class Qubes(qubes.PropertyHolder): | ||||||
|     '''Main Qubes application |     '''Main Qubes application | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -111,3 +111,4 @@ defaults = { | |||||||
| 
 | 
 | ||||||
| max_qid = 254 | max_qid = 254 | ||||||
| max_netid = 254 | max_netid = 254 | ||||||
|  | max_dispid = 10000 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| 
 | 
 | ||||||
| import qubes.events | import qubes.events | ||||||
| import qubes.vm.qubesvm | import qubes.vm.qubesvm | ||||||
|  | 
 | ||||||
| from qubes.config import defaults | from qubes.config import defaults | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| #!/usr/bin/python2 -O | #!/usr/bin/python2 -O | ||||||
| # vim: fileencoding=utf-8 | # vim: fileencoding=utf-8 | ||||||
| 
 | 
 | ||||||
|  | import random | ||||||
|  | 
 | ||||||
| import qubes.vm.qubesvm | import qubes.vm.qubesvm | ||||||
| import qubes.vm.appvm | import qubes.vm.appvm | ||||||
| import qubes.config | import qubes.config | ||||||
| @ -44,6 +46,7 @@ class DispVM(qubes.vm.qubesvm.QubesVM): | |||||||
|                 'volume_type': 'read-only', |                 'volume_type': 'read-only', | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         super(DispVM, self).__init__(*args, **kwargs) |         super(DispVM, self).__init__(*args, **kwargs) | ||||||
| 
 | 
 | ||||||
|     @qubes.events.handler('domain-load') |     @qubes.events.handler('domain-load') | ||||||
| @ -52,3 +55,49 @@ class DispVM(qubes.vm.qubesvm.QubesVM): | |||||||
|         # Some additional checks for template based VM |         # Some additional checks for template based VM | ||||||
|         assert self.template |         assert self.template | ||||||
|         # self.template.appvms.add(self) # XXX |         # self.template.appvms.add(self) # XXX | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def from_appvm(cls, appvm, **kwargs): | ||||||
|  |         '''Create a new instance from given AppVM | ||||||
|  | 
 | ||||||
|  |         :param qubes.vm.appvm.AppVM appvm: template from which the VM should \ | ||||||
|  |             be created (could also be name or qid) | ||||||
|  |         :returns: new disposable vm | ||||||
|  | 
 | ||||||
|  |         *kwargs* are passed to the newly created VM | ||||||
|  | 
 | ||||||
|  |         >>> import qubes.vm.dispvm.DispVM | ||||||
|  |         >>> dispvm = qubes.vm.dispvm.DispVM.from_appvm(appvm).start() | ||||||
|  |         >>> dispvm.run_service('qubes.VMShell', input='firefox') | ||||||
|  |         >>> dispvm.cleanup() | ||||||
|  | 
 | ||||||
|  |         This method modifies :file:`qubes.xml` file. In fact, the newly created | ||||||
|  |         vm belongs to other :py:class:`qubes.Qubes` instance than the *app*. | ||||||
|  |         The qube returned is not started. | ||||||
|  |         ''' | ||||||
|  |         store = appvm.app.store if isinstance(appvm, qubes.vm.BaseVM) else None | ||||||
|  |         app = qubes.Qubes(store) | ||||||
|  |         dispvm = app.add_new_vm( | ||||||
|  |             cls, | ||||||
|  |             dispid=app.domains.get_new_unused_dispid(), | ||||||
|  |             template=app.domains[appvm], | ||||||
|  |             **kwargs) | ||||||
|  |         dispvm.create_on_disk() | ||||||
|  |         app.save() | ||||||
|  |         return dispvm | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def cleanup(self): | ||||||
|  |         '''Clean up after the DispVM | ||||||
|  | 
 | ||||||
|  |         This stops the disposable qube and removes it from the store. | ||||||
|  | 
 | ||||||
|  |         This method modifies :file:`qubes.xml` file. | ||||||
|  |         ''' | ||||||
|  |         app = qubes.Qubes(self.app.store) | ||||||
|  |         self = app.domains[self.uuid] | ||||||
|  |         self.force_shutdown() | ||||||
|  |         self.remove_from_disk() | ||||||
|  |         del app.domains[self] | ||||||
|  |         app.save() | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Wojtek Porczyk
						Wojtek Porczyk