Merge lp:~javier.collado/utah/sshmixin_destroy_fixes into lp:utah
Status: | Merged |
---|---|
Merged at revision: | 491 |
Proposed branch: | lp:~javier.collado/utah/sshmixin_destroy_fixes |
Merge into: | lp:utah |
Diff against target: |
58 lines (+15/-7) 3 files modified
utah/config.py (+2/-0) utah/provisioning/provisioning.py (+10/-7) utah/provisioning/vm/vm.py (+3/-0) |
To merge this branch: | bzr merge lp:~javier.collado/utah/sshmixin_destroy_fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Max Brustkern (community) | Approve | ||
Review via email: mp+115959@code.launchpad.net |
Description of the change
Fixes to make SSHMixin.destroy work.
When running some tests I got this error message:
Failed to destroy machine: Method destroy not defined for machine type CustomVM
This is a misleading error because CustomVM has a destroy method already. However, since it calls `super` there's a whole chain to take into account. According to the MRO this would be as follows:
(utah.provision
utah.provision
utah.provision
utah.provision
utah.provision
utah.provision
object)
The problem happened in SSHMixin when calling `super` and that when through `LibvirtVM`, `VM` and, finally, `Machine` which is the method that raised the error. I already fixed it with an empty implementation in `VM`, but I still don't like this solution, so I'd like to further discuss this to know what do you think about this.
In my opinion, here there are two problems:
- The error is misleading because it doesn't really points out what's the class that is causing the problem
- Mixins shouldn't be involved in all this chained `super` calls.
My proposal would be to change the inheritance order. For example from this:
class CustomVM(
to this:
class CustomVM(LibvirtVM, CustomInstallMixin, SSHMixin)
to keep MRO use classes in the hierarchy tree (hopefully single inheritance is still used and there's always a final class that doesn't call `super` to avoid calling the mixin methods).
Also if some mixin code has to be called, then it should be explicitly called like:
super(LibvirtVM, self).destroy(self) # Destroy calling parent class methods
CustomInstallMi
SSHMixin.
When I originally implemented the exception-raising destroy in Machine, I wasn't thinking that destroy would be something we'd need much inheritance on. I think moving that to an empty implementation in Machine (or one that just returns False) might be a good way to go.
As far as the exceptions go, I didn't really take inheritance into account well when setting up all those methods. Perhaps a clearer exception would be something like "{class} has called the {method} method of the base Machine class, which is not implemented."
I think changing the inheritance order is going to cause problems with all those exception-creating base methods. We can remove those, but if we do that, I'd like to see some way of reporting that we've called a method that a Machine does not implement that's more readable than the default python exception. Maybe we just need to be catching that and raising something else.
Finally, a note on the config file. Anything that uses a directory or information on the system on which the package is installed currently needs to go through a special routine to prevent the config info from being written when the package is built. It's this function that does that: build=False) : 'sshprivatekey' ] 'sshpublickey' ] DEFAULTS, sort_keys=True, indent=4)
def dumpdefaults(
if build:
del DEFAULTS['bridge']
del DEFAULTS['logfile']
del DEFAULTS[
del DEFAULTS[
del DEFAULTS['user']
del DEFAULTS['vmpath']
return json.dumps(
The reason I do that is so that we can ship a config file that's based on config.py, but still goes in /etc/utah and takes advantage of the debian packaging facilities for tracking user changes to config files. This may not be the best approach in the long run. If you've got ideas on that, we can discuss them. For now I'm going to make the system-specific options a separate dict which gets added the defaults, and then we can remove it if we need to.