+5
.vscode/extensions.json
+5
.vscode/extensions.json
+17
.vscode/settings.json
+17
.vscode/settings.json
···
1
+
{
2
+
"deno.enable": true,
3
+
"deno.lint": true,
4
+
"editor.defaultFormatter": "denoland.vscode-deno",
5
+
"[typescriptreact]": {
6
+
"editor.defaultFormatter": "denoland.vscode-deno"
7
+
},
8
+
"[typescript]": {
9
+
"editor.defaultFormatter": "denoland.vscode-deno"
10
+
},
11
+
"[javascriptreact]": {
12
+
"editor.defaultFormatter": "denoland.vscode-deno"
13
+
},
14
+
"[javascript]": {
15
+
"editor.defaultFormatter": "denoland.vscode-deno"
16
+
}
17
+
}
+364
LICENSE
+364
LICENSE
···
1
+
Copyright (c) 2025 Tsiry Sandratraina <tsiry.sndr@rocksky.app>
2
+
3
+
Mozilla Public License, version 2.0
4
+
5
+
1. Definitions
6
+
7
+
1.1. "Contributor"
8
+
9
+
means each individual or legal entity that creates, contributes to the
10
+
creation of, or owns Covered Software.
11
+
12
+
1.2. "Contributor Version"
13
+
14
+
means the combination of the Contributions of others (if any) used by a
15
+
Contributor and that particular Contributor's Contribution.
16
+
17
+
1.3. "Contribution"
18
+
19
+
means Covered Software of a particular Contributor.
20
+
21
+
1.4. "Covered Software"
22
+
23
+
means Source Code Form to which the initial Contributor has attached the
24
+
notice in Exhibit A, the Executable Form of such Source Code Form, and
25
+
Modifications of such Source Code Form, in each case including portions
26
+
thereof.
27
+
28
+
1.5. "Incompatible With Secondary Licenses"
29
+
means
30
+
31
+
a. that the initial Contributor has attached the notice described in
32
+
Exhibit B to the Covered Software; or
33
+
34
+
b. that the Covered Software was made available under the terms of
35
+
version 1.1 or earlier of the License, but not also under the terms of
36
+
a Secondary License.
37
+
38
+
1.6. "Executable Form"
39
+
40
+
means any form of the work other than Source Code Form.
41
+
42
+
1.7. "Larger Work"
43
+
44
+
means a work that combines Covered Software with other material, in a
45
+
separate file or files, that is not Covered Software.
46
+
47
+
1.8. "License"
48
+
49
+
means this document.
50
+
51
+
1.9. "Licensable"
52
+
53
+
means having the right to grant, to the maximum extent possible, whether
54
+
at the time of the initial grant or subsequently, any and all of the
55
+
rights conveyed by this License.
56
+
57
+
1.10. "Modifications"
58
+
59
+
means any of the following:
60
+
61
+
a. any file in Source Code Form that results from an addition to,
62
+
deletion from, or modification of the contents of Covered Software; or
63
+
64
+
b. any new file in Source Code Form that contains any Covered Software.
65
+
66
+
1.11. "Patent Claims" of a Contributor
67
+
68
+
means any patent claim(s), including without limitation, method,
69
+
process, and apparatus claims, in any patent Licensable by such
70
+
Contributor that would be infringed, but for the grant of the License,
71
+
by the making, using, selling, offering for sale, having made, import,
72
+
or transfer of either its Contributions or its Contributor Version.
73
+
74
+
1.12. "Secondary License"
75
+
76
+
means either the GNU General Public License, Version 2.0, the GNU Lesser
77
+
General Public License, Version 2.1, the GNU Affero General Public
78
+
License, Version 3.0, or any later versions of those licenses.
79
+
80
+
1.13. "Source Code Form"
81
+
82
+
means the form of the work preferred for making modifications.
83
+
84
+
1.14. "You" (or "Your")
85
+
86
+
means an individual or a legal entity exercising rights under this
87
+
License. For legal entities, "You" includes any entity that controls, is
88
+
controlled by, or is under common control with You. For purposes of this
89
+
definition, "control" means (a) the power, direct or indirect, to cause
90
+
the direction or management of such entity, whether by contract or
91
+
otherwise, or (b) ownership of more than fifty percent (50%) of the
92
+
outstanding shares or beneficial ownership of such entity.
93
+
94
+
95
+
2. License Grants and Conditions
96
+
97
+
2.1. Grants
98
+
99
+
Each Contributor hereby grants You a world-wide, royalty-free,
100
+
non-exclusive license:
101
+
102
+
a. under intellectual property rights (other than patent or trademark)
103
+
Licensable by such Contributor to use, reproduce, make available,
104
+
modify, display, perform, distribute, and otherwise exploit its
105
+
Contributions, either on an unmodified basis, with Modifications, or
106
+
as part of a Larger Work; and
107
+
108
+
b. under Patent Claims of such Contributor to make, use, sell, offer for
109
+
sale, have made, import, and otherwise transfer either its
110
+
Contributions or its Contributor Version.
111
+
112
+
2.2. Effective Date
113
+
114
+
The licenses granted in Section 2.1 with respect to any Contribution
115
+
become effective for each Contribution on the date the Contributor first
116
+
distributes such Contribution.
117
+
118
+
2.3. Limitations on Grant Scope
119
+
120
+
The licenses granted in this Section 2 are the only rights granted under
121
+
this License. No additional rights or licenses will be implied from the
122
+
distribution or licensing of Covered Software under this License.
123
+
Notwithstanding Section 2.1(b) above, no patent license is granted by a
124
+
Contributor:
125
+
126
+
a. for any code that a Contributor has removed from Covered Software; or
127
+
128
+
b. for infringements caused by: (i) Your and any other third party's
129
+
modifications of Covered Software, or (ii) the combination of its
130
+
Contributions with other software (except as part of its Contributor
131
+
Version); or
132
+
133
+
c. under Patent Claims infringed by Covered Software in the absence of
134
+
its Contributions.
135
+
136
+
This License does not grant any rights in the trademarks, service marks,
137
+
or logos of any Contributor (except as may be necessary to comply with
138
+
the notice requirements in Section 3.4).
139
+
140
+
2.4. Subsequent Licenses
141
+
142
+
No Contributor makes additional grants as a result of Your choice to
143
+
distribute the Covered Software under a subsequent version of this
144
+
License (see Section 10.2) or under the terms of a Secondary License (if
145
+
permitted under the terms of Section 3.3).
146
+
147
+
2.5. Representation
148
+
149
+
Each Contributor represents that the Contributor believes its
150
+
Contributions are its original creation(s) or it has sufficient rights to
151
+
grant the rights to its Contributions conveyed by this License.
152
+
153
+
2.6. Fair Use
154
+
155
+
This License is not intended to limit any rights You have under
156
+
applicable copyright doctrines of fair use, fair dealing, or other
157
+
equivalents.
158
+
159
+
2.7. Conditions
160
+
161
+
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
162
+
Section 2.1.
163
+
164
+
165
+
3. Responsibilities
166
+
167
+
3.1. Distribution of Source Form
168
+
169
+
All distribution of Covered Software in Source Code Form, including any
170
+
Modifications that You create or to which You contribute, must be under
171
+
the terms of this License. You must inform recipients that the Source
172
+
Code Form of the Covered Software is governed by the terms of this
173
+
License, and how they can obtain a copy of this License. You may not
174
+
attempt to alter or restrict the recipients' rights in the Source Code
175
+
Form.
176
+
177
+
3.2. Distribution of Executable Form
178
+
179
+
If You distribute Covered Software in Executable Form then:
180
+
181
+
a. such Covered Software must also be made available in Source Code Form,
182
+
as described in Section 3.1, and You must inform recipients of the
183
+
Executable Form how they can obtain a copy of such Source Code Form by
184
+
reasonable means in a timely manner, at a charge no more than the cost
185
+
of distribution to the recipient; and
186
+
187
+
b. You may distribute such Executable Form under the terms of this
188
+
License, or sublicense it under different terms, provided that the
189
+
license for the Executable Form does not attempt to limit or alter the
190
+
recipients' rights in the Source Code Form under this License.
191
+
192
+
3.3. Distribution of a Larger Work
193
+
194
+
You may create and distribute a Larger Work under terms of Your choice,
195
+
provided that You also comply with the requirements of this License for
196
+
the Covered Software. If the Larger Work is a combination of Covered
197
+
Software with a work governed by one or more Secondary Licenses, and the
198
+
Covered Software is not Incompatible With Secondary Licenses, this
199
+
License permits You to additionally distribute such Covered Software
200
+
under the terms of such Secondary License(s), so that the recipient of
201
+
the Larger Work may, at their option, further distribute the Covered
202
+
Software under the terms of either this License or such Secondary
203
+
License(s).
204
+
205
+
3.4. Notices
206
+
207
+
You may not remove or alter the substance of any license notices
208
+
(including copyright notices, patent notices, disclaimers of warranty, or
209
+
limitations of liability) contained within the Source Code Form of the
210
+
Covered Software, except that You may alter any license notices to the
211
+
extent required to remedy known factual inaccuracies.
212
+
213
+
3.5. Application of Additional Terms
214
+
215
+
You may choose to offer, and to charge a fee for, warranty, support,
216
+
indemnity or liability obligations to one or more recipients of Covered
217
+
Software. However, You may do so only on Your own behalf, and not on
218
+
behalf of any Contributor. You must make it absolutely clear that any
219
+
such warranty, support, indemnity, or liability obligation is offered by
220
+
You alone, and You hereby agree to indemnify every Contributor for any
221
+
liability incurred by such Contributor as a result of warranty, support,
222
+
indemnity or liability terms You offer. You may include additional
223
+
disclaimers of warranty and limitations of liability specific to any
224
+
jurisdiction.
225
+
226
+
4. Inability to Comply Due to Statute or Regulation
227
+
228
+
If it is impossible for You to comply with any of the terms of this License
229
+
with respect to some or all of the Covered Software due to statute,
230
+
judicial order, or regulation then You must: (a) comply with the terms of
231
+
this License to the maximum extent possible; and (b) describe the
232
+
limitations and the code they affect. Such description must be placed in a
233
+
text file included with all distributions of the Covered Software under
234
+
this License. Except to the extent prohibited by statute or regulation,
235
+
such description must be sufficiently detailed for a recipient of ordinary
236
+
skill to be able to understand it.
237
+
238
+
5. Termination
239
+
240
+
5.1. The rights granted under this License will terminate automatically if You
241
+
fail to comply with any of its terms. However, if You become compliant,
242
+
then the rights granted under this License from a particular Contributor
243
+
are reinstated (a) provisionally, unless and until such Contributor
244
+
explicitly and finally terminates Your grants, and (b) on an ongoing
245
+
basis, if such Contributor fails to notify You of the non-compliance by
246
+
some reasonable means prior to 60 days after You have come back into
247
+
compliance. Moreover, Your grants from a particular Contributor are
248
+
reinstated on an ongoing basis if such Contributor notifies You of the
249
+
non-compliance by some reasonable means, this is the first time You have
250
+
received notice of non-compliance with this License from such
251
+
Contributor, and You become compliant prior to 30 days after Your receipt
252
+
of the notice.
253
+
254
+
5.2. If You initiate litigation against any entity by asserting a patent
255
+
infringement claim (excluding declaratory judgment actions,
256
+
counter-claims, and cross-claims) alleging that a Contributor Version
257
+
directly or indirectly infringes any patent, then the rights granted to
258
+
You by any and all Contributors for the Covered Software under Section
259
+
2.1 of this License shall terminate.
260
+
261
+
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
262
+
license agreements (excluding distributors and resellers) which have been
263
+
validly granted by You or Your distributors under this License prior to
264
+
termination shall survive termination.
265
+
266
+
6. Disclaimer of Warranty
267
+
268
+
Covered Software is provided under this License on an "as is" basis,
269
+
without warranty of any kind, either expressed, implied, or statutory,
270
+
including, without limitation, warranties that the Covered Software is free
271
+
of defects, merchantable, fit for a particular purpose or non-infringing.
272
+
The entire risk as to the quality and performance of the Covered Software
273
+
is with You. Should any Covered Software prove defective in any respect,
274
+
You (not any Contributor) assume the cost of any necessary servicing,
275
+
repair, or correction. This disclaimer of warranty constitutes an essential
276
+
part of this License. No use of any Covered Software is authorized under
277
+
this License except under this disclaimer.
278
+
279
+
7. Limitation of Liability
280
+
281
+
Under no circumstances and under no legal theory, whether tort (including
282
+
negligence), contract, or otherwise, shall any Contributor, or anyone who
283
+
distributes Covered Software as permitted above, be liable to You for any
284
+
direct, indirect, special, incidental, or consequential damages of any
285
+
character including, without limitation, damages for lost profits, loss of
286
+
goodwill, work stoppage, computer failure or malfunction, or any and all
287
+
other commercial damages or losses, even if such party shall have been
288
+
informed of the possibility of such damages. This limitation of liability
289
+
shall not apply to liability for death or personal injury resulting from
290
+
such party's negligence to the extent applicable law prohibits such
291
+
limitation. Some jurisdictions do not allow the exclusion or limitation of
292
+
incidental or consequential damages, so this exclusion and limitation may
293
+
not apply to You.
294
+
295
+
8. Litigation
296
+
297
+
Any litigation relating to this License may be brought only in the courts
298
+
of a jurisdiction where the defendant maintains its principal place of
299
+
business and such litigation shall be governed by laws of that
300
+
jurisdiction, without reference to its conflict-of-law provisions. Nothing
301
+
in this Section shall prevent a party's ability to bring cross-claims or
302
+
counter-claims.
303
+
304
+
9. Miscellaneous
305
+
306
+
This License represents the complete agreement concerning the subject
307
+
matter hereof. If any provision of this License is held to be
308
+
unenforceable, such provision shall be reformed only to the extent
309
+
necessary to make it enforceable. Any law or regulation which provides that
310
+
the language of a contract shall be construed against the drafter shall not
311
+
be used to construe this License against a Contributor.
312
+
313
+
314
+
10. Versions of the License
315
+
316
+
10.1. New Versions
317
+
318
+
Mozilla Foundation is the license steward. Except as provided in Section
319
+
10.3, no one other than the license steward has the right to modify or
320
+
publish new versions of this License. Each version will be given a
321
+
distinguishing version number.
322
+
323
+
10.2. Effect of New Versions
324
+
325
+
You may distribute the Covered Software under the terms of the version
326
+
of the License under which You originally received the Covered Software,
327
+
or under the terms of any subsequent version published by the license
328
+
steward.
329
+
330
+
10.3. Modified Versions
331
+
332
+
If you create software not governed by this License, and you want to
333
+
create a new license for such software, you may create and use a
334
+
modified version of this License if you rename the license and remove
335
+
any references to the name of the license steward (except to note that
336
+
such modified license differs from this License).
337
+
338
+
10.4. Distributing Source Code Form that is Incompatible With Secondary
339
+
Licenses If You choose to distribute Source Code Form that is
340
+
Incompatible With Secondary Licenses under the terms of this version of
341
+
the License, the notice described in Exhibit B of this License must be
342
+
attached.
343
+
344
+
Exhibit A - Source Code Form License Notice
345
+
346
+
This Source Code Form is subject to the
347
+
terms of the Mozilla Public License, v.
348
+
2.0. If a copy of the MPL was not
349
+
distributed with this file, You can
350
+
obtain one at
351
+
http://mozilla.org/MPL/2.0/.
352
+
353
+
If it is not possible or desirable to put the notice in a particular file,
354
+
then You may include the notice in a location (such as a LICENSE file in a
355
+
relevant directory) where a recipient would be likely to look for such a
356
+
notice.
357
+
358
+
You may add additional accurate notices of copyright ownership.
359
+
360
+
Exhibit B - "Incompatible With Secondary Licenses" Notice
361
+
362
+
This Source Code Form is "Incompatible
363
+
With Secondary Licenses", as defined by
364
+
the Mozilla Public License, v. 2.0.
+171
README.md
+171
README.md
···
1
+
# 🌅 OpenIndiana Up
2
+
3
+
> A simple, powerful CLI tool to spin up OpenIndiana virtual machines with QEMU
4
+
5
+

6
+
7
+
## ✨ Features
8
+
9
+
- 🚀 **Quick Start** - Launch OpenIndiana VMs with a single command
10
+
- 📦 **Auto-Download** - Automatically downloads ISO images from official
11
+
sources
12
+
- 🎯 **Version Support** - Specify exact OpenIndiana versions or use the latest
13
+
default
14
+
- 💾 **Persistent Storage** - Attach virtual disk drives for data persistence
15
+
- ⚡ **KVM Acceleration** - Native hardware acceleration for better performance
16
+
- 🌐 **SSH Ready** - Pre-configured port forwarding (host:2222 → guest:22)
17
+
- 🎛️ **Customizable** - Configure CPU, memory, cores, and disk options
18
+
- 📥 **Smart Caching** - Skips re-downloading existing ISO files
19
+
20
+
## 📋 Requirements
21
+
22
+
- [Deno](https://deno.land/) runtime
23
+
- QEMU with KVM support
24
+
- Linux host with KVM enabled
25
+
26
+
## 🛠️ Installation
27
+
28
+
Run the following command to install the CLI:
29
+
30
+
```bash
31
+
deno install -A -g -r -f --config deno.json ./main.ts -n openindiana-up
32
+
```
33
+
34
+
## 🚀 Quick Start
35
+
36
+
```bash
37
+
# Use default OpenIndiana version (20251026)
38
+
openindiana-up
39
+
40
+
# Specify a version
41
+
openindiana-up 20251026
42
+
43
+
# Use a local ISO file
44
+
openindiana-up /path/to/openindiana.iso
45
+
46
+
# Download from a custom URL
47
+
openindiana-up https://dlc.openindiana.org/isos/hipster/20251026/OI-hipster-text-20251026.iso
48
+
```
49
+
50
+
## 🎮 Usage
51
+
52
+
```bash
53
+
openindiana-up [path-or-url-to-iso-or-version] [options]
54
+
```
55
+
56
+
### Options
57
+
58
+
| Option | Description | Default |
59
+
| ------------------------ | ------------------------------ | ------------ |
60
+
| `-o, --output <path>` | Output path for downloaded ISO | ISO filename |
61
+
| `-c, --cpu <type>` | CPU type to emulate | `host` |
62
+
| `-C, --cpus <number>` | Number of CPU cores | `2` |
63
+
| `-m, --memory <size>` | RAM allocation | `2G` |
64
+
| `-d, --drive <path>` | Path to virtual disk image | None |
65
+
| `--disk-format <format>` | Disk format (qcow2, raw, etc.) | `raw` |
66
+
67
+
## 💡 Examples
68
+
69
+
### Basic VM with defaults
70
+
71
+
```bash
72
+
openindiana-up
73
+
```
74
+
75
+
### VM with custom resources
76
+
77
+
```bash
78
+
openindiana-up -C 4 -m 4G
79
+
```
80
+
81
+
### VM with persistent storage
82
+
83
+
```bash
84
+
# Create a disk image first
85
+
qemu-img create -f qcow2 openindiana-disk.qcow2 20G
86
+
87
+
# Launch with the disk attached
88
+
openindiana-up -d openindiana-disk.qcow2 --disk-format qcow2
89
+
```
90
+
91
+
### Download to specific location
92
+
93
+
```bash
94
+
openindiana-up -o ~/isos/openindiana.iso
95
+
```
96
+
97
+
## 🖥️ Console Setup
98
+
99
+
When FreeBSD boots, you'll see the boot menu. For the best experience with the
100
+
serial console:
101
+
102
+
1. **Select option `3. Escape to loader prompt`**
103
+
2. **Configure console output:**
104
+
```
105
+
set console=ttya
106
+
set osconsole=ttya
107
+
set ttya-mode=115200,8,n,1,-
108
+
boot
109
+
```
110
+
111
+
This enables proper console redirection to your terminal.
112
+
113
+
## ⚙️ VM Configuration
114
+
115
+
The script creates a VM with the following default specifications:
116
+
117
+
- **CPU**: Host CPU with KVM acceleration (configurable with `--cpu`)
118
+
- **Memory**: 2GB RAM (configurable with `--memory`)
119
+
- **Cores**: 2 virtual CPUs (configurable with `--cpus`)
120
+
- **Storage**: ISO-only by default; optional persistent disk (configurable with
121
+
`--drive`)
122
+
- **Network**: User mode networking with SSH forwarding
123
+
- **Console**: Enhanced serial console via stdio with proper signal handling
124
+
- **Default Version**: FreeBSD 14.3-RELEASE (when no arguments provided)
125
+
126
+
### Available CPU Types
127
+
128
+
Common CPU types you can specify with `--cpu`:
129
+
130
+
- `host` (default) - Use host CPU features for best performance
131
+
- `qemu64` - Generic 64-bit CPU for maximum compatibility
132
+
- `Broadwell` - Intel Broadwell CPU
133
+
- `Skylake-Client` - Intel Skylake CPU
134
+
- `max` - Enable all supported CPU features
135
+
136
+
### Available Disk Formats
137
+
138
+
Common disk formats you can specify with `--disk-format`:
139
+
140
+
- `raw` (default) - Raw disk image format for maximum compatibility
141
+
- `qcow2` - QEMU Copy On Write format with compression and snapshots
142
+
- `vmdk` - VMware disk format
143
+
- `vdi` - VirtualBox disk format
144
+
145
+
## 🔌 SSH Access
146
+
147
+
The VM is configured with port forwarding for SSH access:
148
+
149
+
```bash
150
+
# After OpenIndiana is installed and SSH is configured
151
+
ssh -p 2222 user@localhost
152
+
```
153
+
154
+
## 📝 Notes
155
+
156
+
- The script uses text-based installer ISOs for better headless compatibility
157
+
- Downloaded ISOs are cached and won't be re-downloaded if they exist
158
+
- KVM acceleration requires `/dev/kvm` access on your host system
159
+
- Serial console is connected to stdio for direct interaction
160
+
161
+
## 📜 License
162
+
163
+
See [LICENSE](LICENSE) file for details.
164
+
165
+
## 🤝 Contributing
166
+
167
+
Contributions, issues, and feature requests are welcome!
168
+
169
+
---
170
+
171
+
Made with ☀️ for OpenIndiana enthusiasts
+10
deno.json
+10
deno.json
+68
deno.lock
+68
deno.lock
···
1
+
{
2
+
"version": "5",
3
+
"specifiers": {
4
+
"jsr:@cliffy/command@^1.0.0-rc.8": "1.0.0-rc.8",
5
+
"jsr:@cliffy/flags@1.0.0-rc.8": "1.0.0-rc.8",
6
+
"jsr:@cliffy/internal@1.0.0-rc.8": "1.0.0-rc.8",
7
+
"jsr:@cliffy/table@1.0.0-rc.8": "1.0.0-rc.8",
8
+
"jsr:@std/assert@1": "1.0.15",
9
+
"jsr:@std/fmt@~1.0.2": "1.0.8",
10
+
"jsr:@std/internal@^1.0.12": "1.0.12",
11
+
"jsr:@std/text@~1.0.7": "1.0.16",
12
+
"npm:chalk@^5.6.2": "5.6.2"
13
+
},
14
+
"jsr": {
15
+
"@cliffy/command@1.0.0-rc.8": {
16
+
"integrity": "758147790797c74a707e5294cc7285df665422a13d2a483437092ffce40b5557",
17
+
"dependencies": [
18
+
"jsr:@cliffy/flags",
19
+
"jsr:@cliffy/internal",
20
+
"jsr:@cliffy/table",
21
+
"jsr:@std/fmt",
22
+
"jsr:@std/text"
23
+
]
24
+
},
25
+
"@cliffy/flags@1.0.0-rc.8": {
26
+
"integrity": "0f1043ce6ef037ba1cb5fe6b1bcecb25dc2f29371a1c17f278ab0f45e4b6f46c",
27
+
"dependencies": [
28
+
"jsr:@std/text"
29
+
]
30
+
},
31
+
"@cliffy/internal@1.0.0-rc.8": {
32
+
"integrity": "34cdf2fad9b084b5aed493b138d573f52d4e988767215f7460daf0b918ff43d8"
33
+
},
34
+
"@cliffy/table@1.0.0-rc.8": {
35
+
"integrity": "8bbcdc2ba5e0061b4b13810a24e6f5c6ab19c09f0cce9eb691ccd76c7c6c9db5",
36
+
"dependencies": [
37
+
"jsr:@std/fmt"
38
+
]
39
+
},
40
+
"@std/assert@1.0.15": {
41
+
"integrity": "d64018e951dbdfab9777335ecdb000c0b4e3df036984083be219ce5941e4703b",
42
+
"dependencies": [
43
+
"jsr:@std/internal"
44
+
]
45
+
},
46
+
"@std/fmt@1.0.8": {
47
+
"integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7"
48
+
},
49
+
"@std/internal@1.0.12": {
50
+
"integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027"
51
+
},
52
+
"@std/text@1.0.16": {
53
+
"integrity": "ddb9853b75119a2473857d691cf1ec02ad90793a2e8b4a4ac49d7354281a0cf8"
54
+
}
55
+
},
56
+
"npm": {
57
+
"chalk@5.6.2": {
58
+
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="
59
+
}
60
+
},
61
+
"workspace": {
62
+
"dependencies": [
63
+
"jsr:@cliffy/command@^1.0.0-rc.8",
64
+
"jsr:@std/assert@1",
65
+
"npm:chalk@^5.6.2"
66
+
]
67
+
}
68
+
}
+177
main.ts
+177
main.ts
···
1
+
#!/usr/bin/env -S deno run --allow-run --allow-read --allow-env
2
+
3
+
import { Command } from "@cliffy/command";
4
+
import chalk from "chalk";
5
+
6
+
const DEFAULT_VERSION = "20251026";
7
+
8
+
interface Options {
9
+
output?: string;
10
+
cpu: string;
11
+
cpus: number;
12
+
memory: string;
13
+
drive?: string;
14
+
diskFormat: string;
15
+
}
16
+
17
+
async function downloadIso(url: string, outputPath?: string): Promise<string> {
18
+
const filename = url.split("/").pop()!;
19
+
outputPath = outputPath ?? filename;
20
+
21
+
if (await Deno.stat(outputPath).catch(() => false)) {
22
+
console.log(
23
+
chalk.yellowBright(
24
+
`File ${outputPath} already exists, skipping download.`,
25
+
),
26
+
);
27
+
return outputPath;
28
+
}
29
+
30
+
const cmd = new Deno.Command("curl", {
31
+
args: ["-L", "-o", outputPath, url],
32
+
stdin: "inherit",
33
+
stdout: "inherit",
34
+
stderr: "inherit",
35
+
});
36
+
37
+
const status = await cmd.spawn().status;
38
+
if (!status.success) {
39
+
console.error(chalk.redBright("Failed to download ISO image."));
40
+
Deno.exit(status.code);
41
+
}
42
+
43
+
console.log(chalk.greenBright(`Downloaded ISO to ${outputPath}`));
44
+
return outputPath;
45
+
}
46
+
47
+
function constructDownloadUrl(version: string): string {
48
+
return `https://dlc.openindiana.org/isos/hipster/${version}/OI-hipster-text-${version}.iso`;
49
+
}
50
+
51
+
async function runQemu(isoPath: string, options: Options): Promise<void> {
52
+
const cmd = new Deno.Command("qemu-system-x86_64", {
53
+
args: [
54
+
"-enable-kvm",
55
+
"-cpu",
56
+
options.cpu,
57
+
"-m",
58
+
options.memory,
59
+
"-smp",
60
+
options.cpus.toString(),
61
+
"-cdrom",
62
+
isoPath,
63
+
"-netdev",
64
+
"user,id=net0,hostfwd=tcp::2222-:22",
65
+
"-device",
66
+
"e1000,netdev=net0",
67
+
"-nographic",
68
+
"-monitor",
69
+
"none",
70
+
"-chardev",
71
+
"stdio,id=con0,signal=off",
72
+
"-serial",
73
+
"chardev:con0",
74
+
...(options.drive
75
+
? [
76
+
"-drive",
77
+
`file=${options.drive},format=${options.diskFormat},if=virtio`,
78
+
]
79
+
: []),
80
+
],
81
+
stdin: "inherit",
82
+
stdout: "inherit",
83
+
stderr: "inherit",
84
+
});
85
+
86
+
const status = await cmd.spawn().status;
87
+
88
+
if (!status.success) {
89
+
Deno.exit(status.code);
90
+
}
91
+
}
92
+
93
+
function handleInput(input?: string): string {
94
+
if (!input) {
95
+
console.log(
96
+
`No ISO path provided, defaulting to ${chalk.cyan("OpenIndiana")} ${
97
+
chalk.cyan(DEFAULT_VERSION)
98
+
}...`,
99
+
);
100
+
return constructDownloadUrl(DEFAULT_VERSION);
101
+
}
102
+
103
+
const versionRegex = /^\d{8}$/;
104
+
105
+
if (versionRegex.test(input)) {
106
+
console.log(
107
+
`Detected version ${chalk.cyan(input)}, constructing download URL...`,
108
+
);
109
+
return constructDownloadUrl(input);
110
+
}
111
+
112
+
return input;
113
+
}
114
+
115
+
if (import.meta.main) {
116
+
await new Command()
117
+
.name("openindiana-up")
118
+
.version("0.1.0")
119
+
.description("Start a OpenIndiana virtual machine using QEMU")
120
+
.arguments(
121
+
"[path-or-url-to-iso-or-version:string]",
122
+
)
123
+
.option("-o, --output <path:string>", "Output path for downloaded ISO")
124
+
.option("-c, --cpu <type:string>", "Type of CPU to emulate", {
125
+
default: "host",
126
+
})
127
+
.option("-C, --cpus <number:number>", "Number of CPU cores", {
128
+
default: 2,
129
+
})
130
+
.option("-m, --memory <size:string>", "Amount of memory for the VM", {
131
+
default: "2G",
132
+
})
133
+
.option("-d, --drive <path:string>", "Path to VM disk image")
134
+
.option(
135
+
"--disk-format <format:string>",
136
+
"Disk image format (e.g., qcow2, raw)",
137
+
{
138
+
default: "raw",
139
+
},
140
+
)
141
+
.example(
142
+
"Default usage",
143
+
"openindiana-up",
144
+
)
145
+
.example(
146
+
"Specific version",
147
+
"openindiana-up 20251026",
148
+
)
149
+
.example(
150
+
"Local ISO file",
151
+
"openindiana-up /path/to/openindiana.iso",
152
+
)
153
+
.example(
154
+
"Download URL",
155
+
"openindiana-up https://dlc.openindiana.org/isos/hipster/20251026/OI-hipster-text-20251026.iso",
156
+
)
157
+
.action(async (options: Options, input?: string) => {
158
+
const resolvedInput = handleInput(input);
159
+
let isoPath = resolvedInput;
160
+
161
+
if (
162
+
resolvedInput.startsWith("https://") ||
163
+
resolvedInput.startsWith("http://")
164
+
) {
165
+
isoPath = await downloadIso(resolvedInput, options.output);
166
+
}
167
+
168
+
await runQemu(isoPath, {
169
+
cpu: options.cpu,
170
+
memory: options.memory,
171
+
cpus: options.cpus,
172
+
drive: options.drive,
173
+
diskFormat: options.diskFormat,
174
+
});
175
+
})
176
+
.parse(Deno.args);
177
+
}
preview.png
preview.png
This is a binary file and will not be displayed.