-
Notifications
You must be signed in to change notification settings - Fork 262
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
Check trunk support before enabling trunk at port level #1014
Check trunk support before enabling trunk at port level #1014
Conversation
✔️ Deploy Preview for kubernetes-sigs-cluster-api-openstack ready! 🔨 Explore the source changes: c125a4a 🔍 Inspect the deploy log: https://app.netlify.com/sites/kubernetes-sigs-cluster-api-openstack/deploys/617a644bc136ff00071bd2f7 😎 Browse the preview: https://deploy-preview-1014--kubernetes-sigs-cluster-api-openstack.netlify.app |
Hi @Xenwar. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
140bc24
to
ed8a592
Compare
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
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.
Extracting the function will help keep the error messages for trunk support checking consistent in the code, but I think as it stands, instance deletion will be broken by this change. Additionally, I think the function naming could be made clearer.
@@ -582,3 +584,14 @@ func getTimeout(name string, timeout int) time.Duration { | |||
} | |||
return time.Duration(timeout) | |||
} | |||
|
|||
func (s *Service) trunkNotSupported() (notSupported bool, err 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.
This function is named a bit strangely:
- The logic would read more clearly if the name was a positive instead of a negative.
- I can't guess from the function name that it returns a boolean without side effect.
I think I would call this function isTrunkExtSupported
or maybe better: isTrunkExtEnabled
.
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.
+1 to make it positive case
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.
done
func (s *Service) trunkNotSupported() (notSupported bool, err error) { | ||
trunkSupport, err := s.networkingService.GetTrunkSupport() | ||
if err != nil { | ||
return true, fmt.Errorf("there was an issue verifying whether trunk support is available, please disable it: %v", err) |
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 don't think the instruction to 'please disable it' is helpful. We don't know what the error is.
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.
That was the original text. But, changing it based on the next comment.
return true, fmt.Errorf("there was an issue verifying whether trunk support is available, please disable it: %v", err) | ||
} | ||
if !trunkSupport { | ||
return true, fmt.Errorf("there is no trunk support. Please disable it") |
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.
'Please disable it' isn't a clear instruction. The user has two options to proceed with their configuration: either they enable the trunk extension in their OpenStack deployment, or they give up on using trunking. I think a more helpful message would be "Please ensure that the trunk extension is enabled in your OpenStack deployment."
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.
done
trunkNotSupported, err := s.trunkNotSupported() | ||
if trunkNotSupported { | ||
return err |
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 this mean we return an error when trying to delete an instance whenever trunking is not enabled in the environment? I think you only want to return err here if s.trunkNotSupported()
returned an error. If I have understood this code, this is broken and will break instance deletion in all environments without the trunk extension enabled.
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.
yes, I think the delete we don't need check trunk support at all
it's weird that we can create trunk on openstack but not able to delete it ..
so delete the trunk if we enabled it , that's good enough:)
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 haven't added this part. It was already there. see from the master branch
trunkSupport, err := s.networkingService.GetTrunkSupport() |
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.
It would be great to remove the check!
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 think it is being used here
cluster-api-provider-openstack/pkg/cloud/services/compute/instance.go
Lines 457 to 461 in 180f320
if trunkSupport { | |
if err = s.networkingService.DeleteTrunk(eventObject, port.PortID); err != nil { | |
return err | |
} | |
} |
Should I remove both ?
@@ -135,6 +132,13 @@ func (s *Service) constructNetworks(openStackCluster *infrav1.OpenStackCluster, | |||
if pOpts.Trunk == nil { | |||
pOpts.Trunk = &openStackMachine.Spec.Trunk | |||
} | |||
// verify trunk support | |||
if *pOpts.Trunk { |
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.
Since *pOpts.Trunk
defaults to openstackMachine.Spec.Trunk
, do we need to check trunk support for openstackMachine.Spec.Trunk
explicitly in lines 75-79 above? This here looks like the correct place to check.
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.
That assignment is conditional.
if pOpts.Trunk == nil { |
/ok-to-test |
d59ad70
to
aa2648d
Compare
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.
Some unit test coverage would also be really helpful here.
if port.Trunk == nil { | ||
*port.Trunk = openStackMachine.Spec.Trunk | ||
} | ||
if openStackMachine.Spec.Trunk || *port.Trunk { |
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.
Given that you just set this above, you could simplify this to:
if *port.Trunk {
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.
There is nowhere else where openStackMachine.Spec.Trunk
is checked. So, we need both.
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.
What we're saying here is that if Trunk is set on the Machine it will be set on all ports, regardless of the explicit setting for that port. Is that correct?
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 opposite:
- If set@port => take port level and ignore Machine level
- if not set@port => take Machine level
on verifying trunk support:
(a) No matter how trunk was setup via (1) or (2): check at port level (*port.Trunk)
(b) In case no port was supplied => check at instance level (openStackMachine.Spec.Trunk)
trunkSupported, err := s.isTrunkExtSupported() | ||
if err != nil { | ||
return nil, err | ||
} |
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.
Please can you move this outside the loop? This is adding an extra API call per port.
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.
When it was outside, it was checking only instance level before instanceSpec.Trunk = openStackMachine.Spec.Trunk
. Now, in the for loop, it is checking both instance level and port level.
I agree, in the current format, it is making API calls per port. I am trying to make it efficient by stopping at the first occurrence trunk-set port. I have not succeeded so far as combing return
and break
is not possible.
Note that making API calls per port is not avoidable. The other location where the check could be added is here. Both do iterate over the ports.
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 only thing you need to move outside the loop is the code above which sets trunkSupported. The value of trunkSupported will never change during the loop. You can leave the code below, which generates the error, inside the loop.
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.
Thanks. Moving it out.
Thanks, there is an ongoing work by @macaptain on the tests. We needed to make the change on this PR in order to test the check. |
aa2648d
to
06465a5
Compare
if port.Trunk == nil { | ||
*port.Trunk = openStackMachine.Spec.Trunk | ||
} | ||
if openStackMachine.Spec.Trunk || *port.Trunk { |
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.
What we're saying here is that if Trunk is set on the Machine it will be set on all ports, regardless of the explicit setting for that port. Is that correct?
trunkSupported, err := s.isTrunkExtSupported() | ||
if err != nil { | ||
return nil, err | ||
} |
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 only thing you need to move outside the loop is the code above which sets trunkSupported. The value of trunkSupported will never change during the loop. You can leave the code below, which generates the error, inside the loop.
@@ -113,6 +104,25 @@ func (s *Service) CreateInstance(openStackCluster *infrav1.OpenStackCluster, mac | |||
if err != nil { | |||
return nil, err | |||
} | |||
// verify trunk support if trunk is set on at least one Port. | |||
for _, net := range nets { |
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.
Here we're iterating over nets, which is the return value of constructNetworks()
. constructNetworks returns nets generated from both Spec.Networks and Spec.Ports.
I believe this means we're now potentially trunking ports generated for both Spec.Networks and Spec.Ports, where previously we were only trunking Spec.Ports.
I'm not clear on the use case difference between these 2 fields, but I feel like this is a significant change which we should make deliberately. Perhaps @iamemilio or @dulek know?
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 agree. To avoid that, one option is to move the inheriting logic to
cluster-api-provider-openstack/pkg/cloud/services/networking/port.go
Lines 166 to 179 in 1be73ec
if portOpts.Trunk != nil && *portOpts.Trunk { | |
trunk, err := s.getOrCreateTrunk(eventObject, clusterName, port.Name, port.ID) | |
if err != nil { | |
record.Warnf(eventObject, "FailedCreateTrunk", "Failed to create trunk for port %s: %v", portName, err) | |
return nil, err | |
} | |
if err = s.replaceAllAttributesTags(eventObject, trunk.ID, tags); err != nil { | |
record.Warnf(eventObject, "FailedReplaceTags", "Failed to replace trunk tags %s: %v", portName, err) | |
return nil, err | |
} | |
} | |
return port, nil | |
} |
And, pass the openstackmachine resource to it.
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 do think the inheriting logic belongs in constructNetworks()
and we should make a separate PR if we need to address the inconsistency in inheriting the machine's trunk value between ports and networks. This location in CreateInstance
is a good place to check if we need to make an API call to check for trunk support in OpenStack.
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.
Yep, lets leave the inheriting logic in constructNetworks()
. I also think defaulting it there means we don't have to check it here and just look directly at the ports.
Due to the lack of map/reduce in Go, how about something like:
trunkingRequired := func() bool {
for _, port := range ports {
if *port.Trunk != nil && *port.Trunk {
return true
}
}
return false
}()
if trunkingRequired {
if !s.isTrunkExtSupported() {
... err
}
}
Or something more idiomatic if you know what that is 🙂
This means we only check trunk support once, and only if we actually need it.
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.
Thanks, done
06465a5
to
7525e1e
Compare
@@ -113,6 +104,25 @@ func (s *Service) CreateInstance(openStackCluster *infrav1.OpenStackCluster, mac | |||
if err != nil { | |||
return nil, err | |||
} | |||
// verify trunk support if trunk is set on at least one Port. | |||
trunkSupported, err := s.isTrunkExtSupported() |
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 you need to move the error checking (currently lines 117-119) up here, too.
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.
At that point, the second par to the following (i.e. *port.Trunk) is not available outside of the loop. We can only check the instance level outside of the loop.
if openStackMachine.Spec.Trunk || *port.Trunk
As we have it now, the error checking detached from the actual api call, perhaps, we need to move 108 back inside ?
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.
Thanks, done
@@ -113,6 +104,25 @@ func (s *Service) CreateInstance(openStackCluster *infrav1.OpenStackCluster, mac | |||
if err != nil { | |||
return nil, err | |||
} | |||
// verify trunk support if trunk is set on at least one Port. | |||
for _, net := range nets { |
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.
Yep, lets leave the inheriting logic in constructNetworks()
. I also think defaulting it there means we don't have to check it here and just look directly at the ports.
Due to the lack of map/reduce in Go, how about something like:
trunkingRequired := func() bool {
for _, port := range ports {
if *port.Trunk != nil && *port.Trunk {
return true
}
}
return false
}()
if trunkingRequired {
if !s.isTrunkExtSupported() {
... err
}
}
Or something more idiomatic if you know what that is 🙂
This means we only check trunk support once, and only if we actually need it.
7525e1e
to
11048f1
Compare
/pull-cluster-api-provider-openstack-e2e-test |
dc22b42
to
ad1a7d3
Compare
If there are no further comments on this issue, could this PR be approved ? |
/approve |
ad1a7d3
to
b658554
Compare
Made some changes based on a feedback received from slack. |
4b079c6
to
c125a4a
Compare
Now that the /lgtm |
@mdbooth, the PR is now approved and lgtm-ed |
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
func (s *Service) isTrunkExtSupported() (trunknSupported bool, err error) { | ||
trunkSupport, err := s.networkingService.GetTrunkSupport() | ||
if err != nil { | ||
return false, fmt.Errorf("there was an issue verifying whether trunk support is available, please disable trunk on your manifests: %v", err) |
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.
nit: please disable trunk on your manifests
is probably the wrong advice here, as any error returned by this api call is unlikely to be related to trunk support. Please try again later
would be better advice and we'll do that anyway, so probably just log it.
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.
Thanks, fixed.
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: hidekazuna, macaptain, mdbooth, Xenwar The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/hold cancel |
Signed-off-by: Anwar Hassen <[email protected]>
c125a4a
to
74dfbf3
Compare
/lgtm |
This PR adds a check on trunk support before enabling trunk at port level.
Fixes: #1013