Skip to content

Commit df8c8d2

Browse files
committed
Added Backup Infrastructure
Including Backup Proxies,, and an entire new and redesigned Backup Proxies view
1 parent 8035eae commit df8c8d2

File tree

19 files changed

+1861
-93
lines changed

19 files changed

+1861
-93
lines changed

README.md

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,18 @@ A Next.js 15 application providing a unified monitoring dashboard for Veeam Data
2929
- **Session Status**: Success, Warning, Failed, and Running session tracking
3030
- **Time-based Filtering**: Filter sessions by time range
3131

32-
#### Managed Servers
33-
- **Infrastructure Overview**: View all managed backup infrastructure servers
34-
- **Server Details**: Name, type, description, and version information
35-
- **Server Types**: Backup servers, proxies, repositories, and more
32+
#### Backup Infrastructure
33+
- **Backup Proxies**:
34+
- **Performance Monitoring**: Track CPU/Memory usage and task slot utilization (concurrent tasks)
35+
- **Configuration**: View transport modes, OS type, and details
36+
- **Status**: Visual health indicators (Online/Offline) and maintenance mode status
37+
- **Backup Repositories**:
38+
- **Capacity Planning**: Visual capacity bars showing Used vs Free space
39+
- **Type Support**: Windows, Linux, NFS, SMB, and Object Storage repository support
40+
- **Properties**: Monitor immutability settings, task limits, and overall health
41+
- **Managed Servers**:
42+
- **Infrastructure Overview**: View all managed backup infrastructure servers
43+
- **Server Details**: Name, type, description, and version information
3644

3745
#### Inventory Management
3846
- **Virtual Infrastructure**:
@@ -156,7 +164,9 @@ See [CONTAINER.md](./CONTAINER.md) for detailed instructions on building and run
156164
- `/api/v1/jobs/states` - Advanced job monitoring
157165
- `/api/v1/backupInfrastructure/jobs/{id}/sessions` - Job sessions
158166
- `/api/v1/backupInfrastructure/backupServers` - Managed servers
159-
- `/api/v1/backupInfrastructure/backupServers/{id}/backupRepositories` - Repositories
167+
- `/api/v1/backupInfrastructure/backupProxies` - Backup proxies
168+
- `/api/v1/backupInfrastructure/backupRepositories` - Backup repositories
169+
- `/api/v1/backupInfrastructure/repositories/states` - Repository states
160170
- `/api/v1/license` - License information
161171
- `/api/v1/malware-detection` - Malware events
162172
- `/api/v1/security/best-practices` - Security best practices
@@ -197,6 +207,8 @@ See [CONTAINER.md](./CONTAINER.md) for detailed instructions on building and run
197207
│ │ │ ├── jobs/ # Backup jobs endpoint
198208
│ │ │ ├── sessions/ # Job sessions endpoint
199209
│ │ │ ├── backupInfrastructure/ # Infrastructure endpoints
210+
│ │ │ │ ├── proxies/ # Backup proxies
211+
│ │ │ │ └── repositories/ # Backup repositories
200212
│ │ │ ├── license/ # License information
201213
│ │ │ ├── malware-detection/ # Malware events
202214
│ │ │ └── security/ # Security best practices
@@ -216,7 +228,10 @@ See [CONTAINER.md](./CONTAINER.md) for detailed instructions on building and run
216228
│ │ │ ├── virtual/ # Virtual infrastructure (VMware/Hyper-V)
217229
│ │ │ ├── protection-groups/ # Physical & Cloud infrastructure
218230
│ │ │ └── unstructured/ # Unstructured data (NAS/Object)
219-
│ │ └── managed-servers/ # Managed servers view
231+
│ │ └── infrastructure/ # Infrastructure management
232+
│ │ ├── proxies/ # Backup proxies view
233+
│ │ ├── repositories/ # Backup repositories view
234+
│ │ └── managed-servers/ # Managed servers view
220235
│ ├── vro/ # VRO monitoring page
221236
│ ├── vbm/ # VBM monitoring page
222237
│ ├── k10/ # K10 placeholder page
@@ -232,6 +247,8 @@ See [CONTAINER.md](./CONTAINER.md) for detailed instructions on building and run
232247
│ ├── sessions-overview.tsx # Recent sessions widget
233248
│ ├── session-tasks-table.tsx # Session tasks breakdown
234249
│ ├── job-details-header.tsx # Job details header component
250+
│ ├── backup-proxies-table.tsx # Backup proxies table
251+
│ ├── backup-repositories-table.tsx # Backup repositories table
235252
│ ├── managed-servers-table.tsx # Managed servers table
236253
│ ├── virtual-infrastructure-table.tsx # Virtual inventory with protection status
237254
│ ├── protection-groups-table.tsx # Protection groups inventory
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
const API_BASE_URL = process.env.VEEAM_API_URL;
4+
5+
async function proxy(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
6+
try {
7+
if (!API_BASE_URL) {
8+
return NextResponse.json(
9+
{ error: 'Server configuration error: Missing VEEAM_API_URL' },
10+
{ status: 500 }
11+
);
12+
}
13+
14+
const authHeader = request.headers.get('authorization');
15+
if (!authHeader) {
16+
return NextResponse.json(
17+
{ error: 'Authorization header required' },
18+
{ status: 401 }
19+
);
20+
}
21+
22+
const { id } = await params;
23+
const fullUrl = `${API_BASE_URL}/api/v1/backupInfrastructure/proxies/${id}/disable`;
24+
25+
const options: RequestInit = {
26+
method: 'POST',
27+
headers: {
28+
'Authorization': authHeader,
29+
'Content-Type': 'application/json',
30+
'Accept': 'application/json',
31+
'x-api-version': '1.3-rev1',
32+
},
33+
body: '{}' // Empty body for action
34+
};
35+
36+
const response = await fetch(fullUrl, options);
37+
38+
if (response.status === 204) {
39+
return new NextResponse(null, { status: 204 });
40+
}
41+
42+
const responseText = await response.text();
43+
let data;
44+
try {
45+
data = responseText ? JSON.parse(responseText) : {};
46+
} catch {
47+
data = { error: responseText };
48+
}
49+
50+
if (!response.ok) {
51+
return NextResponse.json(data, { status: response.status });
52+
}
53+
54+
return NextResponse.json(data);
55+
56+
} catch (error) {
57+
console.error('[PROXY DISABLE PROXY] Internal Error:', error);
58+
return NextResponse.json(
59+
{ error: error instanceof Error ? error.message : 'Internal Server Error' },
60+
{ status: 500 }
61+
);
62+
}
63+
}
64+
65+
export { proxy as POST };
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
const API_BASE_URL = process.env.VEEAM_API_URL;
4+
5+
async function proxy(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
6+
try {
7+
if (!API_BASE_URL) {
8+
return NextResponse.json(
9+
{ error: 'Server configuration error: Missing VEEAM_API_URL' },
10+
{ status: 500 }
11+
);
12+
}
13+
14+
const authHeader = request.headers.get('authorization');
15+
if (!authHeader) {
16+
return NextResponse.json(
17+
{ error: 'Authorization header required' },
18+
{ status: 401 }
19+
);
20+
}
21+
22+
const { id } = await params;
23+
const fullUrl = `${API_BASE_URL}/api/v1/backupInfrastructure/proxies/${id}/enable`;
24+
25+
const options: RequestInit = {
26+
method: 'POST',
27+
headers: {
28+
'Authorization': authHeader,
29+
'Content-Type': 'application/json',
30+
'Accept': 'application/json',
31+
'x-api-version': '1.3-rev1',
32+
},
33+
body: '{}' // Empty body for action
34+
};
35+
36+
const response = await fetch(fullUrl, options);
37+
38+
if (response.status === 204) {
39+
return new NextResponse(null, { status: 204 });
40+
}
41+
42+
const responseText = await response.text();
43+
let data;
44+
try {
45+
data = responseText ? JSON.parse(responseText) : {};
46+
} catch {
47+
data = { error: responseText };
48+
}
49+
50+
if (!response.ok) {
51+
return NextResponse.json(data, { status: response.status });
52+
}
53+
54+
return NextResponse.json(data);
55+
56+
} catch (error) {
57+
console.error('[PROXY ENABLE PROXY] Internal Error:', error);
58+
return NextResponse.json(
59+
{ error: error instanceof Error ? error.message : 'Internal Server Error' },
60+
{ status: 500 }
61+
);
62+
}
63+
}
64+
65+
export { proxy as POST };
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
const API_BASE_URL = process.env.VEEAM_API_URL;
4+
5+
async function proxy(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
6+
try {
7+
if (!API_BASE_URL) {
8+
return NextResponse.json(
9+
{ error: 'Server configuration error: Missing VEEAM_API_URL' },
10+
{ status: 500 }
11+
);
12+
}
13+
14+
const authHeader = request.headers.get('authorization');
15+
if (!authHeader) {
16+
return NextResponse.json(
17+
{ error: 'Authorization header required' },
18+
{ status: 401 }
19+
);
20+
}
21+
22+
const { id } = await params;
23+
const fullUrl = `${API_BASE_URL}/api/v1/backupInfrastructure/proxies/${id}`;
24+
25+
const options: RequestInit = {
26+
method: request.method,
27+
headers: {
28+
'Authorization': authHeader,
29+
'Content-Type': 'application/json',
30+
'Accept': 'application/json',
31+
'x-api-version': '1.3-rev1',
32+
},
33+
};
34+
35+
if (request.method !== 'GET' && request.method !== 'HEAD' && request.method !== 'DELETE') {
36+
const text = await request.text();
37+
if (text) {
38+
options.body = text;
39+
}
40+
}
41+
42+
const response = await fetch(fullUrl, options);
43+
44+
if (response.status === 204) {
45+
return new NextResponse(null, { status: 204 });
46+
}
47+
48+
const responseText = await response.text();
49+
let data;
50+
try {
51+
data = responseText ? JSON.parse(responseText) : {};
52+
} catch {
53+
data = { error: responseText };
54+
}
55+
56+
if (!response.ok) {
57+
return NextResponse.json(data, { status: response.status });
58+
}
59+
60+
return NextResponse.json(data);
61+
62+
} catch (error) {
63+
console.error('[PROXY ID PROXY] Internal Error:', error);
64+
return NextResponse.json(
65+
{ error: error instanceof Error ? error.message : 'Internal Server Error' },
66+
{ status: 500 }
67+
);
68+
}
69+
}
70+
71+
export { proxy as GET, proxy as PUT, proxy as DELETE };
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
3+
const API_BASE_URL = process.env.VEEAM_API_URL;
4+
5+
async function proxy(request: NextRequest) {
6+
try {
7+
if (!API_BASE_URL) {
8+
return NextResponse.json(
9+
{ error: 'Server configuration error: Missing VEEAM_API_URL' },
10+
{ status: 500 }
11+
);
12+
}
13+
14+
const authHeader = request.headers.get('authorization');
15+
if (!authHeader) {
16+
return NextResponse.json(
17+
{ error: 'Authorization header required' },
18+
{ status: 401 }
19+
);
20+
}
21+
22+
const { searchParams } = new URL(request.url);
23+
const queryString = searchParams.toString();
24+
const endpoint = queryString ? `/api/v1/backupInfrastructure/proxies?${queryString}` : `/api/v1/backupInfrastructure/proxies`;
25+
const fullUrl = `${API_BASE_URL}${endpoint}`;
26+
27+
const options: RequestInit = {
28+
method: request.method,
29+
headers: {
30+
'Authorization': authHeader,
31+
'Content-Type': 'application/json',
32+
'Accept': 'application/json',
33+
'x-api-version': '1.3-rev1',
34+
},
35+
};
36+
37+
if (request.method !== 'GET' && request.method !== 'HEAD') {
38+
const text = await request.text();
39+
if (text) {
40+
options.body = text;
41+
}
42+
}
43+
44+
const response = await fetch(fullUrl, options);
45+
46+
if (response.status === 204) {
47+
return new NextResponse(null, { status: 204 });
48+
}
49+
50+
const responseText = await response.text();
51+
let data;
52+
try {
53+
data = responseText ? JSON.parse(responseText) : {};
54+
} catch {
55+
data = { error: responseText };
56+
}
57+
58+
if (!response.ok) {
59+
return NextResponse.json(data, { status: response.status });
60+
}
61+
62+
return NextResponse.json(data);
63+
64+
} catch (error) {
65+
console.error('[PROXIES PROXY] Internal Error:', error);
66+
return NextResponse.json(
67+
{ error: error instanceof Error ? error.message : 'Internal Server Error' },
68+
{ status: 500 }
69+
);
70+
}
71+
}
72+
73+
export { proxy as GET, proxy as POST };

0 commit comments

Comments
 (0)