Refactor subnet discovery logic to allow auto-detection and improve error handling

This commit is contained in:
2025-11-04 17:17:01 +00:00
parent 2469acbc88
commit dfc7694fb9
4 changed files with 14 additions and 29 deletions

View File

@@ -47,7 +47,7 @@ export function ClusterNodesComponent() {
status: clusterStatus status: clusterStatus
} = useCluster(currentInstance); } = useCluster(currentInstance);
const [discoverSubnet, setDiscoverSubnet] = useState('192.168.8.0/24'); const [discoverSubnet, setDiscoverSubnet] = useState('');
const [addNodeIp, setAddNodeIp] = useState(''); const [addNodeIp, setAddNodeIp] = useState('');
const [discoverError, setDiscoverError] = useState<string | null>(null); const [discoverError, setDiscoverError] = useState<string | null>(null);
const [detectError, setDetectError] = useState<string | null>(null); const [detectError, setDetectError] = useState<string | null>(null);
@@ -92,9 +92,9 @@ export function ClusterNodesComponent() {
if (prevDiscoveryActive === true && isActive === false && discoveryStatus) { if (prevDiscoveryActive === true && isActive === false && discoveryStatus) {
const count = discoveryStatus.nodes_found?.length || 0; const count = discoveryStatus.nodes_found?.length || 0;
if (count === 0) { if (count === 0) {
setDiscoverSuccess(`Discovery complete! No nodes were found in the subnet.`); setDiscoverSuccess(`Discovery complete! No nodes were found.`);
} else { } else {
setDiscoverSuccess(`Discovery complete! Found ${count} node${count !== 1 ? 's' : ''} in subnet.`); setDiscoverSuccess(`Discovery complete! Found ${count} node${count !== 1 ? 's' : ''}.`);
} }
setDiscoverError(null); setDiscoverError(null);
refetch(); refetch();
@@ -224,7 +224,8 @@ export function ClusterNodesComponent() {
const handleDiscover = () => { const handleDiscover = () => {
setDiscoverError(null); setDiscoverError(null);
setDiscoverSuccess(null); setDiscoverSuccess(null);
discover(discoverSubnet); // Pass subnet only if it's not empty, otherwise auto-detect
discover(discoverSubnet || undefined);
}; };
@@ -421,7 +422,7 @@ export function ClusterNodesComponent() {
Discover Nodes on Network Discover Nodes on Network
</h3> </h3>
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4"> <p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
Scan a subnet to find nodes in maintenance mode Scan a specific subnet or leave empty to auto-detect all local networks
</p> </p>
<div className="flex gap-3 mb-4"> <div className="flex gap-3 mb-4">
@@ -429,7 +430,7 @@ export function ClusterNodesComponent() {
type="text" type="text"
value={discoverSubnet} value={discoverSubnet}
onChange={(e) => setDiscoverSubnet(e.target.value)} onChange={(e) => setDiscoverSubnet(e.target.value)}
placeholder="192.168.8.0/24" placeholder="192.168.1.0/24 (optional - leave empty to auto-detect)"
className="flex-1" className="flex-1"
/> />
<Button <Button

View File

@@ -12,18 +12,14 @@ export function useNodes(instanceName: string | null | undefined) {
}); });
const discoverMutation = useMutation({ const discoverMutation = useMutation({
mutationFn: (subnet: string) => nodesApi.discover(instanceName!, subnet), mutationFn: (subnet?: string) => nodesApi.discover(instanceName!, subnet),
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['instances', instanceName, 'discovery'] }); queryClient.invalidateQueries({ queryKey: ['instances', instanceName, 'discovery'] });
}, },
}); });
const detectMutation = useMutation({ const detectMutation = useMutation({
mutationFn: (ip?: string) => nodesApi.detect(instanceName!, ip), mutationFn: (ip: string) => nodesApi.detect(instanceName!, ip),
});
const autoDetectMutation = useMutation({
mutationFn: () => nodesApi.autoDetect(instanceName!),
}); });
const addMutation = useMutation({ const addMutation = useMutation({
@@ -88,10 +84,6 @@ export function useNodes(instanceName: string | null | undefined) {
isDetecting: detectMutation.isPending, isDetecting: detectMutation.isPending,
detectResult: detectMutation.data, detectResult: detectMutation.data,
detectError: detectMutation.error, detectError: detectMutation.error,
autoDetect: autoDetectMutation.mutate,
isAutoDetecting: autoDetectMutation.isPending,
autoDetectResult: autoDetectMutation.data,
autoDetectError: autoDetectMutation.error,
getHardware: getHardwareMutation.mutateAsync, getHardware: getHardwareMutation.mutateAsync,
isGettingHardware: getHardwareMutation.isPending, isGettingHardware: getHardwareMutation.isPending,
getHardwareError: getHardwareMutation.error, getHardwareError: getHardwareMutation.error,

View File

@@ -35,17 +35,13 @@ export const nodesApi = {
}, },
// Discovery // Discovery
async discover(instanceName: string, subnet: string): Promise<OperationResponse> { async discover(instanceName: string, subnet?: string): Promise<OperationResponse> {
return apiClient.post(`/api/v1/instances/${instanceName}/nodes/discover`, { subnet }); const body = subnet ? { subnet } : {};
return apiClient.post(`/api/v1/instances/${instanceName}/nodes/discover`, body);
}, },
async detect(instanceName: string, ip?: string): Promise<OperationResponse> { async detect(instanceName: string, ip: string): Promise<HardwareInfo> {
const body = ip ? { ip } : {}; return apiClient.post(`/api/v1/instances/${instanceName}/nodes/detect`, { ip });
return apiClient.post(`/api/v1/instances/${instanceName}/nodes/detect`, body);
},
async autoDetect(instanceName: string): Promise<{ networks: string[]; nodes: any[]; count: number }> {
return apiClient.post(`/api/v1/instances/${instanceName}/nodes/auto-detect`);
}, },
async discoveryStatus(instanceName: string): Promise<DiscoveryStatus> { async discoveryStatus(instanceName: string): Promise<DiscoveryStatus> {

View File

@@ -108,10 +108,6 @@ export function mockUseNodes(nodes: Node[] = []) {
isDetecting: false, isDetecting: false,
detectResult: undefined, detectResult: undefined,
detectError: null, detectError: null,
autoDetect: vi.fn(),
isAutoDetecting: false,
autoDetectResult: undefined,
autoDetectError: null,
getHardware: vi.fn(), getHardware: vi.fn(),
isGettingHardware: false, isGettingHardware: false,
getHardwareError: null, getHardwareError: null,