-
Notifications
You must be signed in to change notification settings - Fork 36
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
Network clustering #1053
base: main
Are you sure you want to change the base?
Network clustering #1053
Conversation
54c1afa
to
e2e4075
Compare
add1260
to
2379d77
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 interim code comments. The network list with filtering looks pretty good (cluster and non-cluster conditions) from QA perspective. Will go through the other QA items as well.
src/pages/networks/NetworkList.tsx
Outdated
isLoading: isClusterNetworksLoading, | ||
} = useQuery({ | ||
queryKey: [queryKeys.networks, "default", queryKeys.cluster], | ||
queryFn: () => fetchClusterMemberNetworks("default", clusterMembers), |
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 there is a specific scenario we need to take into consideration here. It is possible to create OVN networks for specific restricted projects (even with ip ranges that overlaps other exisitng ovn networks), not sure if fetching networks from the default
project will surface those?
See this video ref, watch from around 17:00
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, good point. We should use the current project here and not "default". We want to fetch all real interfaces for each cluster member. Those are either available on the current project (if has features.networks set to false) or not available. In the later case, we should not show them.
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 is a pretty niche case though, afaik this only applies to OVN networks due to their virtual nature
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 uplink network for OVN needs to be in the default project. In the uplink selector we do fetch networks from the default project regardless of which project the user is currently in. I think we should not show those in the network list, though. So I think we are doing the right thing even for all cases.
8f766bf
to
b0927a5
Compare
Resolved issues 1-3 and 5.
This sounds like the expected behaviour. Wdyt?
This shows up, because the uplink config of the OVN network doesn't change when deleting the uplink network. It might be that LXD should refuse to delete the uplink, but that should be in the API then, not in the UI itself.
This needs future work. |
016a2d5
to
5b8158b
Compare
My main concern is that the network gets created even when it's not valid. Would it be possible to check upon parent selection if it is already used by another network and reflect that as an error message on the creation / edit form? If that's too complex I think the current behaviour is also fine.
Noted, perhaps we should raise this with the core team?
|
5b8158b
to
9c42ee6
Compare
Improved the error handling, that should resolve 7.
I am not 100% sure we can never reuse an interface as parent. Reported this edge case to lxd: canonical/lxd#14810
I tried to reproduce it, but was getting an error. I couldn't delete the uplink in use by the OVN network. So this might not be an issue after all. |
bf5ade3
to
fb1b4e9
Compare
…stered backend Signed-off-by: David Edler <[email protected]>
fb1b4e9
to
b52956e
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.
This is looking really good! Couldn't actually find that many issues QA wise, left some code comments
export const fetchNetworksFromClusterMembers = ( | ||
project: string, | ||
clusterMembers: LxdClusterMember[], | ||
): Promise<LXDNetworkOnClusterMember[]> => { |
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.
love how simple things look now with the latest type update! 👍
project: string, | ||
parentsPerClusterMember?: ClusterSpecificValues, | ||
): Promise<void> => { | ||
if (!parentsPerClusterMember) { |
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.
not quite sure why we need this here, for this scenario, can't we just use updateNetwork
directly where ever we are calling updateClusterNetwork
? The handling of undefined parentsPerClusterMember
perhaps should be in the component instead?
if (error) { | ||
notify.failure("Loading networks failed", error); | ||
} | ||
useEffect(() => { |
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.
why does this need to be in an useEffect
?
export const intersection = (lists: string[][]): string[] => { | ||
const result = []; | ||
|
||
for (let i = 0; i < lists.length; i++) { |
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.
a potential way to improve the efficiency and readability of this could be to hold an object with keys being unique strings from lists, and values indicate the count of occurrence for each unique string. As we iterate the lists, we convert each list into a set, then increment the count for each unique string. At the end, all unique string items with a count that equates to the length of the input lists would have appeared in all.
networkOnMembers?: LXDNetworkOnClusterMember[], | ||
): NetworkFormValues => { | ||
const parentPerClusterMember: ClusterSpecificValues = {}; | ||
networkOnMembers?.map( |
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.
networkOnMembers?.map( | |
networkOnMembers?.forEach( |
|
||
const setValueForAllMembers = (value: string) => { | ||
const update: ClusterSpecificValues = {}; | ||
options.map((item) => (update[item.memberName] = value)); |
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.
options.map((item) => (update[item.memberName] = value)); | |
options.forEach((item) => (update[item.memberName] = value)); |
label="Same for all cluster members" | ||
checked={!isSpecific} | ||
onChange={() => { | ||
if (isSpecific) { |
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.
shouldn't we place the setValueForAllMembers
logic inside a useEffect
?
<ResourceLink | ||
type="cluster-member" | ||
value={item.memberName} | ||
to={`/ui/project/${project}/networks?member=${item.memberName}`} |
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.
do we always want to redirect to the networks page with member filter? This feels a little strange, not sure what's the best way to approach it though, maybe expose this as a function prop?
onChange={(value) => { | ||
void formik.setFieldValue("parentPerClusterMember", value); | ||
}} |
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.
onChange={(value) => { | |
void formik.setFieldValue("parentPerClusterMember", value); | |
}} | |
onChange={(value) => void formik.setFieldValue("parentPerClusterMember", value)} |
network: LXDNetworkOnClusterMember; | ||
} | ||
|
||
const NetworkClusterMemberChip: FC<Props> = ({ network }) => { |
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.
nice extraction!
Done
QA