-
Notifications
You must be signed in to change notification settings - Fork 837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
introduce an upgrade framework and related testing #659
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good. One question inline and will approve.
""" | ||
|
||
def __getstate__(self): | ||
return self.__dict__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth an assert "_ci_pkl_version" not in self.dict ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ci_pkl_version
will never be in __dict__
unless it's explicitly added to instance state: I don't think we'd ever trigger that assert
here without modifying this test subclass to set such instance state. Am I missing a case this could cover?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently not triggered, but if we didn't pop the _ci_pkl_version off of the state dict in __setstate__
we also don't cause any tests to fail either.
diff --git a/cloudinit/persistence.py b/cloudinit/persistence.py
index 85aa79df3..543af4da2 100644
--- a/cloudinit/persistence.py
+++ b/cloudinit/persistence.py
@@ -49,7 +49,7 @@ class CloudInitPickleMixin:
See https://docs.python.org/3/library/pickle.html#object.__setstate__
for further background.
"""
- version = state.pop("_ci_pkl_version", 0)
+ version = state.get("_ci_pkl_version", 0)
self.__dict__.update(state)
self._unpickle(version)
Thanks for working on this. It looks quite straight forward. Do we have any obj.pkl upgrade items in debian/* that could be dropped with this framework? Azure has a systemd dropin config to rm the obj.pkl to ensure networking is regenerated on every boot; and I thought there was an issue around ec2-classic VMs and networking; I know I tried at one time to update existing obj.pkl with the EventType.BOOT flag to regenerate network-config on each boot there (when shutting down ec2-classic instances, the MAC of the nic is lost and changes on startup). |
A quick look around the {post,pre}inst doesn't reveal anything immediately obvious: there is some handling of
I would expect this to be replaceable with the new framework:
This issue certainly sounds familiar, and I think we'd be able to do something similar to the Azure case too. Thanks for the review! |
This introduces a utility mixin class, ``CloudInitPickleMixin`` which implements the pickling magic methods (``__getstate__`` and ``__setstate__``) to add a version to the state persisted for classes to which it is added.
Updated description with the manual testing I have performed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! address my final testing assert nit if you feel it is needed.
Thanks again for the responses, I do agree that any pickle upgrade path testing uncovered by this framework will be much more accessible with our simpler integration tests.
""" | ||
|
||
def __getstate__(self): | ||
return self.__dict__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently not triggered, but if we didn't pop the _ci_pkl_version off of the state dict in __setstate__
we also don't cause any tests to fail either.
diff --git a/cloudinit/persistence.py b/cloudinit/persistence.py
index 85aa79df3..543af4da2 100644
--- a/cloudinit/persistence.py
+++ b/cloudinit/persistence.py
@@ -49,7 +49,7 @@ class CloudInitPickleMixin:
See https://docs.python.org/3/library/pickle.html#object.__setstate__
for further background.
"""
- version = state.pop("_ci_pkl_version", 0)
+ version = state.get("_ci_pkl_version", 0)
self.__dict__.update(state)
self._unpickle(version)
Proposed Commit Message
Additional Context
This work was started in #609, and a lot of design discussion happened over there.
Test Steps
Upgrade from pre-refactor cloud-init
ubuntu:ffae848ee5a0
is a focal image containing a pre-networking-refactor cloud-init (which will exhibit this bug); it is launched asreproducer
:reproducer2
is launched from the same image, and has a deb built from this branch (instead of the archive) installed into it:Upgrade from post-refactor cloud-init
Following the same steps as for
reproducer2
above, we can see that both.networking_cls
and.networking
remain available:Checklist: