+9
main.ts
+9
main.ts
···
1
1
#!/usr/bin/env -S deno run --allow-run --allow-read --allow-env
2
2
3
3
import { Command } from "@cliffy/command";
4
+
import { createBridgeNetworkIfNeeded } from "./network.ts";
4
5
import {
5
6
createDriveImageIfNeeded,
6
7
downloadIso,
···
43
44
default: "20G",
44
45
},
45
46
)
47
+
.option(
48
+
"-b, --bridge <name:string>",
49
+
"Name of the network bridge to use for networking (e.g., br0)",
50
+
)
46
51
.example(
47
52
"Default usage",
48
53
"openindiana-up",
···
76
81
77
82
if (!input && options.drive && !await emptyDiskImage(options.drive)) {
78
83
isoPath = null;
84
+
}
85
+
86
+
if (options.bridge) {
87
+
await createBridgeNetworkIfNeeded(options.bridge);
79
88
}
80
89
81
90
await runQemu(isoPath, options);
+104
network.ts
+104
network.ts
···
1
+
import chalk from "chalk";
2
+
3
+
export async function setupQemuBridge(bridgeName: string): Promise<void> {
4
+
const bridgeConfPath = "/etc/qemu/bridge.conf";
5
+
const bridgeConfContent = await Deno.readTextFile(bridgeConfPath).catch(
6
+
() => "",
7
+
);
8
+
if (bridgeConfContent.includes(`allow ${bridgeName}`)) {
9
+
console.log(
10
+
chalk.greenBright(
11
+
`QEMU bridge configuration for ${bridgeName} already exists.`,
12
+
),
13
+
);
14
+
return;
15
+
}
16
+
17
+
console.log(
18
+
chalk.blueBright(
19
+
`Adding QEMU bridge configuration for ${bridgeName}...`,
20
+
),
21
+
);
22
+
23
+
const cmd = new Deno.Command("sudo", {
24
+
args: [
25
+
"sh",
26
+
"-c",
27
+
`mkdir -p /etc/qemu && echo "allow ${bridgeName}" >> ${bridgeConfPath}`,
28
+
],
29
+
stdin: "inherit",
30
+
stdout: "inherit",
31
+
stderr: "inherit",
32
+
});
33
+
const status = await cmd.spawn().status;
34
+
35
+
if (!status.success) {
36
+
console.error(
37
+
chalk.redBright(
38
+
`Failed to add QEMU bridge configuration for ${bridgeName}.`,
39
+
),
40
+
);
41
+
Deno.exit(status.code);
42
+
}
43
+
44
+
console.log(
45
+
chalk.greenBright(
46
+
`QEMU bridge configuration for ${bridgeName} added successfully.`,
47
+
),
48
+
);
49
+
}
50
+
51
+
export async function createBridgeNetworkIfNeeded(
52
+
bridgeName: string,
53
+
): Promise<void> {
54
+
const bridgeExistsCmd = new Deno.Command("ip", {
55
+
args: ["link", "show", bridgeName],
56
+
stdout: "null",
57
+
stderr: "null",
58
+
});
59
+
60
+
const bridgeExistsStatus = await bridgeExistsCmd.spawn().status;
61
+
if (bridgeExistsStatus.success) {
62
+
console.log(
63
+
chalk.greenBright(`Network bridge ${bridgeName} already exists.`),
64
+
);
65
+
await setupQemuBridge(bridgeName);
66
+
return;
67
+
}
68
+
69
+
console.log(chalk.blueBright(`Creating network bridge ${bridgeName}...`));
70
+
const createBridgeCmd = new Deno.Command("sudo", {
71
+
args: ["ip", "link", "add", bridgeName, "type", "bridge"],
72
+
stdin: "inherit",
73
+
stdout: "inherit",
74
+
stderr: "inherit",
75
+
});
76
+
77
+
let status = await createBridgeCmd.spawn().status;
78
+
if (!status.success) {
79
+
console.error(
80
+
chalk.redBright(`Failed to create network bridge ${bridgeName}.`),
81
+
);
82
+
Deno.exit(status.code);
83
+
}
84
+
85
+
const bringUpBridgeCmd = new Deno.Command("sudo", {
86
+
args: ["ip", "link", "set", "dev", bridgeName, "up"],
87
+
stdin: "inherit",
88
+
stdout: "inherit",
89
+
stderr: "inherit",
90
+
});
91
+
status = await bringUpBridgeCmd.spawn().status;
92
+
if (!status.success) {
93
+
console.error(
94
+
chalk.redBright(`Failed to bring up network bridge ${bridgeName}.`),
95
+
);
96
+
Deno.exit(status.code);
97
+
}
98
+
99
+
console.log(
100
+
chalk.greenBright(`Network bridge ${bridgeName} created and up.`),
101
+
);
102
+
103
+
await setupQemuBridge(bridgeName);
104
+
}
+6
-2
utils.ts
+6
-2
utils.ts
···
11
11
drive?: string;
12
12
diskFormat: string;
13
13
size: string;
14
+
bridge?: string;
14
15
}
15
16
16
17
async function du(path: string): Promise<number> {
···
88
89
isoPath: string | null,
89
90
options: Options,
90
91
): Promise<void> {
91
-
const cmd = new Deno.Command("qemu-system-x86_64", {
92
+
const cmd = new Deno.Command(options.bridge ? "sudo" : "qemu-system-x86_64", {
92
93
args: [
94
+
..._.compact([options.bridge && "qemu-system-x86_64"]),
93
95
"-enable-kvm",
94
96
"-cpu",
95
97
options.cpu,
···
99
101
options.cpus.toString(),
100
102
..._.compact([isoPath && "-cdrom", isoPath]),
101
103
"-netdev",
102
-
"user,id=net0,hostfwd=tcp::2222-:22",
104
+
options.bridge
105
+
? `bridge,id=net0,br=${options.bridge}`
106
+
: "user,id=net0,hostfwd=tcp::2222-:22",
103
107
"-device",
104
108
"e1000,netdev=net0",
105
109
"-nographic",