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
refactor: virtwrap: remove/improve some code #11548
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Hi @EdDev, not urgent but because you are familiar with the code, when you have the time please take a look if I'm not mistaken or missing anything with this changes. Cheers! |
on 1.29-sig-compute
Seems to be similar to the fix 125f4a1 |
/cc |
Also breaks the arguments per line, just to reduce the line length. Signed-off-by: Victor Toso <victortoso@redhat.com>
This simplify the logic around withNetworkIfacesResources() as on appendPlaceholderInterfacesToTheDomain(), in this two conditionals, we would return domainSpec which would make the follow up check of len() of Interfaces to be always true. Now we return early and appendPlaceholderInterfacesToTheDomain() is called only when we need to add placeholder interfaces. Signed-off-by: Victor Toso <victortoso@redhat.com>
No real need for DeepCopy as we can keep using domainSpec. Signed-off-by: Victor Toso <victortoso@redhat.com>
The api.Domain is passed by reference and set by the function. In SyncVMI() we ignore the return value and we can do the same with prepareMigrationTarget(), making better usage of the `domain` variable already existing. Signed-off-by: Victor Toso <victortoso@redhat.com>
This is just calling hooks OnDefineDomain without doing anything with the resulting Domain XML. If this was really needed, it should be using SetDomainSpecStrWithHooks() instead, which is what SyncVMI() does. Note that this happens later, when SyncVirtualMachine() from Launcher is called. Signed-off-by: Victor Toso <victortoso@redhat.com>
e606835
to
ebbfa47
Compare
From #11548 (comment)
The mistake I had was removing |
/retest |
|
/test pull-kubevirt-e2e-k8s-1.29-sig-compute |
@@ -172,12 +172,18 @@ func indexedDomainInterfaces(domain *api.Domain) map[string]api.Interface { | |||
return domainInterfaces | |||
} | |||
|
|||
type SetDomainFunc func(*v1.VirtualMachineInstance, *api.DomainSpec) (cli.VirDomain, error) |
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.
Does it need to be exposed?
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.
No, I'll change it
func withNetworkIfacesResources( | ||
vmi *v1.VirtualMachineInstance, | ||
domainSpec *api.DomainSpec, | ||
f SetDomainFunc, | ||
) (cli.VirDomain, error) { |
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.
The linter is configured to allow line lengths up to 140 [1]. Now that the function type is used, do we exceed it?
[1] https://github.com/kubevirt/kubevirt/blob/main/.golangci.yml#L50
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.
Ah! We do have an agreed line length limit! That's great, I can point it out to people now! :)
To your question, I don't think we exceed after using function type but I'll double check and revert the change if it is still <= 140 chars per line. Thanks!
@@ -184,6 +184,11 @@ func withNetworkIfacesResources( | |||
domainSpec *api.DomainSpec, | |||
f SetDomainFunc, | |||
) (cli.VirDomain, error) { | |||
onRootComplex := vmi.Annotations[v1.PlacePCIDevicesOnRootComplex] | |||
if len(vmi.Spec.Domain.Devices.Interfaces) == 0 || onRootComplex == "true" { | |||
return f(vmi, domainSpec) |
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.
I'm contemplating about this one for a while now.
First, I want to admit that I seem to have came up with this terrible function. It does not look good at all, hiding the domain object creation.
The change here results in a logic change, where we will not always call the hook twice.
On one hand this makes sense, but at the same time I am a bit concern someone (sidecar logic authors) may assume we call it only once and depend on it.
In the past it was called many times, on each change to the libvirt metadata (which carried information we wanted to preserve), but now the only place we still call it more than once is here.
I feel we need to do something to compensate to balance this now. Perhaps adding text on the hook package and relevant methods to warn about this. Even making sure it appears on the documentation/examples.
Lastly, I think we should add this "filter" outside and never call withNetworkIfacesResources
if this is the case. The whole point of this function was to process the logic of calling things twice, but now it has a condition that it does not and makes it less focused.
WDYT?
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.
I am a bit concern someone (sidecar logic authors) may assume we call it only once and depend on it.
We will document kubevirt/community#252 about calling the sidecar multiple times.
Lastly, I think we should add this "filter" outside and never call withNetworkIfacesResources if this is the case. The whole point of this function was to process the logic of calling things twice, but now it has a condition that it does not and makes it less focused.
WDYT?
I like it. I'll change it.
interfacePlaceholderCount := ReservedInterfaces - len(vmi.Spec.Domain.Devices.Interfaces) | ||
for i := 0; i < interfacePlaceholderCount; i++ { | ||
domainSpecWithIfacesResource.Devices.Interfaces = append( | ||
domainSpecWithIfacesResource.Devices.Interfaces, | ||
domainSpec.Devices.Interfaces = append( |
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 change causes the function to be mutable, having the side-effect of changing the inputted domain spec. I think we should avoid doing things like this as much as possible.
I prefer the input not to mutate and only the return value to have new values.
This is what I would expect from other objects/functions to behave like.
@@ -678,7 +678,12 @@ func (l *LibvirtDomainManager) generateCloudInitEmptyISO(vmi *v1.VirtualMachineI | |||
// | |||
// The Domain.Spec can be alterned in this function and any changes | |||
// made to the domain will get set in libvirt after this function exits. | |||
func (l *LibvirtDomainManager) preStartHook(vmi *v1.VirtualMachineInstance, domain *api.Domain, generateEmptyIsos bool, options *cmdv1.VirtualMachineOptions) (*api.Domain, error) { | |||
func (l *LibvirtDomainManager) preStartHook( |
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.
You may be right that the method mutates the inputted domain, but it is very hard to be sure really.
From a caller perspective, before this change, I understood that it is suppose to change as it returned the object, but now a common reader would be surprised.
The problem is that it does mutate it and I would really prefer to fix that instead of making it hidden.
On the other hand, you could claim that you just express the reality here and it is better to see the problem over hiding it. I do not know what is better. :/
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.
On the other hand, you could claim that you just express the reality here and it is better to see the problem over hiding it. I do not know what is better. :/
I'm fine either way, but we should come up with a clear way to define when input is being changed (e.g: documentation, variable prefix/suffix).
If we think about functions like append
, because the slice might be nil, it'll do the allocation and return the pointer to the new slice. The same should happen when slice's cap
is reached and append
will allocate a new bigger chunk of memory.
I don't think that would ever happen for most functions that will do changes api.DomainSpec
, that is, the initial pointer will be kept unchanged. For that reason, I think it is somewhat safe to do what I did. preStartHook
will do what it advertises and any related changes will be propagated to internals of api.DomainSpec
.
Again, either way is fine for me, I'm just in favour of team consistency
overall ;)
// Right now we need to call OnDefineDomain, so that additional setup, which might be done | ||
// by the hook can also be done for the new target pod | ||
hooksManager := hooks.GetManager() | ||
_, err = hooksManager.OnDefineDomain(&domain.Spec, vmi) |
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.
You basically remove a hook point where a preparation on the pod could have been done to accept the new domain.
The hook point is not only about changing the domain-xml, it is also about doing other preparations based on the VMI and domain.
This may break backward compatibility.
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.
But this is still to be called later on, as I mentioned in the commit log. I'm not sure we are breaking compatibility either, no migration tests have failed so far... which it doesn't mean I haven't broken something with this patch.
I'm not sure. By just reading the code, this looks out of place.
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.
I'll revert it, just to be safe. Sadly, this was one of the changes I really wanted in because I plan to change OnDefineDomain
later on and I'll need to replicate it here.... but let's do what is right.
Thanks again for the review.
@victortoso: The following tests failed, say
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
I'll change the approach for this, so: |
@victortoso: Closed this PR. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
What this PR does
Before this PR:
The logic was fine but not easy to rework it in a way a could try to fix the issue mentioned in pull #11324 so I'm trying to improve it as I go. This is a continuation from #11384, hopefully the next one is what I'm actually trying to fix :)
After this PR:
Why we need it and why it was done in this way
The following tradeoffs were made:
The following alternatives were considered:
Links to places where the discussion took place:
Special notes for your reviewer
Checklist
This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR.
Approvers are expected to review this list.
Release note