Skip to content

Commit c1adfa9

Browse files
jeckersbcgwalters
authored andcommitted
libvirt: Add opt-in --graphical-console flag for SPICE display
Add a --graphical-console flag to 'bcvk libvirt run' that enables a SPICE graphics console for virt-manager access. When enabled, the domain XML includes a SPICE display with autoport, a virtio GPU, and a spicevmc channel for clipboard and display resize support. This also removes unused VNC support code. Closes: #237 Assisted-by: OpenCode (claude-opus-4-6) Signed-off-by: John Eckersberg <jeckersb@redhat.com>
1 parent e953294 commit c1adfa9

2 files changed

Lines changed: 43 additions & 20 deletions

File tree

crates/kit/src/libvirt/domain.rs

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct DomainBuilder {
4343
disk_path: Option<String>,
4444
transient_disk: bool, // Use transient disk with temporary overlay
4545
network: Option<String>,
46-
vnc_port: Option<u16>,
46+
graphical_console: bool,
4747
kernel_args: Option<String>,
4848
metadata: HashMap<String, String>,
4949
qemu_args: Vec<String>,
@@ -78,7 +78,7 @@ impl DomainBuilder {
7878
disk_path: None,
7979
transient_disk: false,
8080
network: None,
81-
vnc_port: None,
81+
graphical_console: false,
8282
kernel_args: None,
8383
metadata: HashMap::new(),
8484
qemu_args: Vec::new(),
@@ -133,10 +133,9 @@ impl DomainBuilder {
133133
self
134134
}
135135

136-
/// Enable VNC on specified port
137-
#[allow(dead_code)]
138-
pub fn with_vnc(mut self, port: u16) -> Self {
139-
self.vnc_port = Some(port);
136+
/// Enable graphical console (SPICE) for virt-manager access
137+
pub fn with_graphical_console(mut self) -> Self {
138+
self.graphical_console = true;
140139
self
141140
}
142141

@@ -498,19 +497,23 @@ impl DomainBuilder {
498497
}
499498
}
500499

501-
// VNC graphics if enabled
502-
if let Some(vnc_port) = self.vnc_port {
500+
// Graphical console (SPICE) for virt-manager access
501+
if self.graphical_console {
502+
writer.start_element("graphics", &[("type", "spice"), ("autoport", "yes")])?;
503+
writer.write_empty_element("listen", &[("type", "address")])?;
504+
writer.end_element("graphics")?;
505+
writer.start_element("video", &[])?;
503506
writer.write_empty_element(
504-
"graphics",
505-
&[
506-
("type", "vnc"),
507-
("port", &vnc_port.to_string()),
508-
("listen", "127.0.0.1"),
509-
],
507+
"model",
508+
&[("type", "virtio"), ("heads", "1"), ("primary", "yes")],
510509
)?;
511-
writer.start_element("video", &[])?;
512-
writer.write_empty_element("model", &[("type", "vga")])?;
513510
writer.end_element("video")?;
511+
writer.start_element("channel", &[("type", "spicevmc")])?;
512+
writer.write_empty_element(
513+
"target",
514+
&[("type", "virtio"), ("name", "com.redhat.spice.0")],
515+
)?;
516+
writer.end_element("channel")?;
514517
}
515518

516519
// Virtiofs filesystems
@@ -657,15 +660,28 @@ mod tests {
657660
}
658661

659662
#[test]
660-
fn test_vnc_configuration() {
663+
fn test_graphical_console_configuration() {
664+
// Test with graphical console enabled
661665
let xml = DomainBuilder::new()
662666
.with_name("test")
663-
.with_vnc(5901)
667+
.with_graphical_console()
668+
.build_xml()
669+
.unwrap();
670+
671+
assert!(xml.contains("graphics type=\"spice\" autoport=\"yes\""));
672+
assert!(xml.contains("model type=\"virtio\" heads=\"1\" primary=\"yes\""));
673+
assert!(xml.contains("channel type=\"spicevmc\""));
674+
assert!(xml.contains("target type=\"virtio\" name=\"com.redhat.spice.0\""));
675+
676+
// Test without graphical console (default)
677+
let xml_no_graphics = DomainBuilder::new()
678+
.with_name("test-no-graphics")
664679
.build_xml()
665680
.unwrap();
666681

667-
assert!(xml.contains("graphics type=\"vnc\" port=\"5901\""));
668-
assert!(xml.contains("model type=\"vga\""));
682+
assert!(!xml_no_graphics.contains("<graphics"));
683+
assert!(!xml_no_graphics.contains("<video"));
684+
assert!(!xml_no_graphics.contains("spicevmc"));
669685
}
670686

671687
#[test]

crates/kit/src/libvirt/run.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ pub struct LibvirtRunOpts {
297297
#[clap(long)]
298298
pub label: Vec<String>,
299299

300+
/// Enable graphical console (SPICE) for virt-manager access
301+
#[clap(long)]
302+
pub graphical_console: bool,
303+
300304
/// Create a transient VM that disappears on shutdown/reboot
301305
#[clap(long)]
302306
pub transient: bool,
@@ -1209,6 +1213,9 @@ fn create_libvirt_domain_from_disk(
12091213
domain_builder =
12101214
domain_builder.with_firmware_log(crate::libvirt::domain::FirmwareLogOutput::Console);
12111215
}
1216+
if opts.graphical_console {
1217+
domain_builder = domain_builder.with_graphical_console();
1218+
}
12121219
domain_builder = domain_builder
12131220
.with_metadata("bootc:source-image", &opts.image)
12141221
.with_metadata("bootc:memory-mb", &memory.to_string())

0 commit comments

Comments
 (0)