@@ -57,10 +57,6 @@ pub struct LibvirtCreateOpts {
5757 #[ clap( long) ]
5858 pub vnc : bool ,
5959
60- /// Hypervisor connection URI (e.g., qemu:///system, qemu+ssh://host/system)
61- #[ clap( short = 'c' , long = "connect" ) ]
62- pub connect : Option < String > ,
63-
6460 /// VNC port (default: auto-assign)
6561 #[ clap( long) ]
6662 pub vnc_port : Option < u16 > ,
@@ -123,12 +119,8 @@ pub struct SshConfig {
123119
124120impl LibvirtCreateOpts {
125121 /// Build a virsh command with optional connection URI
126- fn virsh_command ( & self ) -> Command {
127- let mut cmd = Command :: new ( "virsh" ) ;
128- if let Some ( ref connect) = self . connect {
129- cmd. arg ( "-c" ) . arg ( connect) ;
130- }
131- cmd
122+ fn virsh_command ( & self , global_opts : & crate :: libvirt:: LibvirtOptions ) -> Command {
123+ global_opts. virsh_command ( )
132124 }
133125
134126 /// Check if the input appears to be a container image (vs volume name)
@@ -161,7 +153,11 @@ impl LibvirtCreateOpts {
161153 }
162154
163155 /// Find existing volume by container image digest using name-based lookup
164- fn find_cached_volume ( & self , image_digest : & str ) -> Result < Option < String > > {
156+ fn find_cached_volume (
157+ & self ,
158+ global_opts : & crate :: libvirt:: LibvirtOptions ,
159+ image_digest : & str ,
160+ ) -> Result < Option < String > > {
165161 debug ! ( "Looking for cached volume with digest: {}" , image_digest) ;
166162
167163 // Create a temporary upload opts to get the expected cached volume name
@@ -176,14 +172,13 @@ impl LibvirtCreateOpts {
176172 } ,
177173 vcpus : Some ( default_vcpus ( ) ) ,
178174 karg : vec ! [ ] ,
179- connect : self . connect . clone ( ) ,
180175 } ;
181176
182177 let expected_volume_name = temp_upload_opts. get_cached_volume_name ( image_digest) ;
183178 let expected_volume_path = format ! ( "{}.raw" , expected_volume_name) ;
184179
185180 // Check if this specific volume exists
186- let output = self
181+ let output = global_opts
187182 . virsh_command ( )
188183 . args ( & [ "vol-info" , & expected_volume_path, "--pool" , & self . pool ] )
189184 . output ( ) ?;
@@ -198,7 +193,7 @@ impl LibvirtCreateOpts {
198193 }
199194
200195 /// Automatically upload container image if no cached volume exists
201- fn ensure_volume_exists ( & self ) -> Result < String > {
196+ fn ensure_volume_exists ( & self , global_opts : & crate :: libvirt :: LibvirtOptions ) -> Result < String > {
202197 if !self . is_container_image ( ) {
203198 // If it's already a volume name, just return it
204199 return Ok ( self . volume_name_or_image . clone ( ) ) ;
@@ -207,7 +202,7 @@ impl LibvirtCreateOpts {
207202 // It's a container image, check for cached volume
208203 let image_digest = images:: get_image_digest ( & self . volume_name_or_image ) ?;
209204
210- if let Some ( cached_volume) = self . find_cached_volume ( & image_digest) ? {
205+ if let Some ( cached_volume) = self . find_cached_volume ( global_opts , & image_digest) ? {
211206 debug ! ( "Using cached volume: {}" , cached_volume) ;
212207 return Ok ( cached_volume) ;
213208 }
@@ -227,11 +222,10 @@ impl LibvirtCreateOpts {
227222 memory : self . install_memory . clone ( ) ,
228223 vcpus : self . install_vcpus ,
229224 karg : self . karg . clone ( ) ,
230- connect : self . connect . clone ( ) ,
231225 } ;
232226
233227 // Run the upload
234- crate :: libvirt:: upload:: run ( upload_opts. clone ( ) ) ?;
228+ crate :: libvirt:: upload:: run ( global_opts , upload_opts. clone ( ) ) ?;
235229
236230 // Return the generated volume name (with digest)
237231 Ok ( upload_opts. get_cached_volume_name ( & image_digest) )
@@ -243,15 +237,19 @@ impl LibvirtCreateOpts {
243237 }
244238
245239 /// Check if volume exists in the specified pool
246- fn check_volume_exists ( & self , volume_name : & str ) -> Result < String > {
240+ fn check_volume_exists (
241+ & self ,
242+ global_opts : & crate :: libvirt:: LibvirtOptions ,
243+ volume_name : & str ,
244+ ) -> Result < String > {
247245 let volume_path = if volume_name. ends_with ( ".raw" ) {
248246 volume_name. to_string ( )
249247 } else {
250248 format ! ( "{}.raw" , volume_name)
251249 } ;
252250
253251 let output = self
254- . virsh_command ( )
252+ . virsh_command ( global_opts )
255253 . args ( & [ "vol-info" , & volume_path, "--pool" , & self . pool ] )
256254 . output ( ) ?;
257255
@@ -267,7 +265,7 @@ impl LibvirtCreateOpts {
267265
268266 // Get the full volume path
269267 let vol_path_output = self
270- . virsh_command ( )
268+ . virsh_command ( global_opts )
271269 . args ( & [ "vol-path" , & volume_path, "--pool" , & self . pool ] )
272270 . output ( ) ?;
273271
@@ -280,15 +278,19 @@ impl LibvirtCreateOpts {
280278 }
281279
282280 /// Extract metadata from bootc volume
283- fn get_volume_metadata ( & self , volume_name : & str ) -> Result < BootcVolumeMetadata > {
281+ fn get_volume_metadata (
282+ & self ,
283+ global_opts : & crate :: libvirt:: LibvirtOptions ,
284+ volume_name : & str ,
285+ ) -> Result < BootcVolumeMetadata > {
284286 let volume_path = if volume_name. ends_with ( ".raw" ) {
285287 volume_name. to_string ( )
286288 } else {
287289 format ! ( "{}.raw" , volume_name)
288290 } ;
289291
290292 let output = self
291- . virsh_command ( )
293+ . virsh_command ( global_opts )
292294 . args ( & [ "vol-dumpxml" , & volume_path, "--pool" , & self . pool ] )
293295 . output ( ) ?;
294296 if !output. status . success ( ) {
@@ -311,9 +313,13 @@ impl LibvirtCreateOpts {
311313 }
312314
313315 /// Check if domain already exists
314- fn check_domain_exists ( & self , domain_name : & str ) -> bool {
316+ fn check_domain_exists (
317+ & self ,
318+ global_opts : & crate :: libvirt:: LibvirtOptions ,
319+ domain_name : & str ,
320+ ) -> bool {
315321 let output = self
316- . virsh_command ( )
322+ . virsh_command ( global_opts )
317323 . args ( & [ "dominfo" , domain_name] )
318324 . output ( ) ;
319325
@@ -324,22 +330,27 @@ impl LibvirtCreateOpts {
324330 }
325331
326332 /// Create a domain-specific copy of the volume
327- fn create_domain_volume ( & self , source_volume_name : & str , domain_name : & str ) -> Result < String > {
333+ fn create_domain_volume (
334+ & self ,
335+ global_opts : & crate :: libvirt:: LibvirtOptions ,
336+ source_volume_name : & str ,
337+ domain_name : & str ,
338+ ) -> Result < String > {
328339 let domain_volume_name = format ! ( "{}-{}" , source_volume_name, domain_name) ;
329340 let domain_volume_path = format ! ( "{}.raw" , domain_volume_name) ;
330341 let source_volume_path = format ! ( "{}.raw" , source_volume_name) ;
331342
332343 // Check if domain volume already exists
333344 let check_output = self
334- . virsh_command ( )
345+ . virsh_command ( global_opts )
335346 . args ( & [ "vol-info" , & domain_volume_path, "--pool" , & self . pool ] )
336347 . output ( ) ?;
337348
338349 if check_output. status . success ( ) {
339350 if self . force {
340351 debug ! ( "Removing existing domain volume: {}" , domain_volume_name) ;
341352 let _ = self
342- . virsh_command ( )
353+ . virsh_command ( global_opts )
343354 . args ( & [ "vol-delete" , & domain_volume_path, "--pool" , & self . pool ] )
344355 . output ( ) ;
345356 } else {
@@ -357,7 +368,7 @@ impl LibvirtCreateOpts {
357368
358369 // Clone the source volume to create a domain-specific copy
359370 let output = self
360- . virsh_command ( )
371+ . virsh_command ( global_opts )
361372 . args ( & [
362373 "vol-clone" ,
363374 & source_volume_path,
@@ -374,7 +385,7 @@ impl LibvirtCreateOpts {
374385
375386 // Get the path to the new domain volume
376387 let vol_path_output = self
377- . virsh_command ( )
388+ . virsh_command ( global_opts )
378389 . args ( & [ "vol-path" , & domain_volume_path, "--pool" , & self . pool ] )
379390 . output ( ) ?;
380391
@@ -389,6 +400,7 @@ impl LibvirtCreateOpts {
389400 /// Create the libvirt domain
390401 fn create_domain (
391402 & self ,
403+ global_opts : & crate :: libvirt:: LibvirtOptions ,
392404 _volume_path : & str ,
393405 metadata : & BootcVolumeMetadata ,
394406 volume_name : & str ,
@@ -397,7 +409,8 @@ impl LibvirtCreateOpts {
397409 let memory_mb = self . parse_memory ( ) ?;
398410
399411 // Create a domain-specific volume copy to avoid file locking issues
400- let domain_volume_path = self . create_domain_volume ( volume_name, & domain_name) ?;
412+ let domain_volume_path =
413+ self . create_domain_volume ( global_opts, volume_name, & domain_name) ?;
401414 debug ! ( "Using domain-specific volume: {}" , domain_volume_path) ;
402415
403416 // Setup SSH configuration
@@ -408,22 +421,22 @@ impl LibvirtCreateOpts {
408421 domain_name, volume_name, self . pool
409422 ) ;
410423
411- if self . check_domain_exists ( & domain_name) && !self . force {
424+ if self . check_domain_exists ( global_opts , & domain_name) && !self . force {
412425 return Err ( eyre ! (
413426 "Domain '{}' already exists. Use --force to recreate." ,
414427 domain_name
415428 ) ) ;
416429 }
417430
418431 // If domain exists and force is specified, undefine it first
419- if self . check_domain_exists ( & domain_name) && self . force {
432+ if self . check_domain_exists ( global_opts , & domain_name) && self . force {
420433 debug ! ( "Domain exists, removing it first (--force specified)" ) ;
421434 let _ = self
422- . virsh_command ( )
435+ . virsh_command ( global_opts )
423436 . args ( & [ "destroy" , & domain_name] )
424437 . output ( ) ;
425438 let _ = self
426- . virsh_command ( )
439+ . virsh_command ( global_opts )
427440 . args ( & [ "undefine" , & domain_name] )
428441 . output ( ) ;
429442 }
@@ -514,7 +527,7 @@ impl LibvirtCreateOpts {
514527
515528 // Define the domain
516529 let output = self
517- . virsh_command ( )
530+ . virsh_command ( global_opts )
518531 . args ( & [ "define" , "/dev/stdin" ] )
519532 . stdin ( std:: process:: Stdio :: piped ( ) )
520533 . stdout ( std:: process:: Stdio :: piped ( ) )
@@ -539,7 +552,7 @@ impl LibvirtCreateOpts {
539552 if self . start {
540553 debug ! ( "Starting domain '{}'" , domain_name) ;
541554 let output = self
542- . virsh_command ( )
555+ . virsh_command ( global_opts )
543556 . args ( & [ "start" , & domain_name] )
544557 . output ( ) ?;
545558
@@ -676,27 +689,27 @@ impl LibvirtCreateOpts {
676689}
677690
678691/// Execute the libvirt domain creation process
679- pub fn run ( opts : LibvirtCreateOpts ) -> Result < ( ) > {
692+ pub fn run ( global_opts : & crate :: libvirt :: LibvirtOptions , opts : LibvirtCreateOpts ) -> Result < ( ) > {
680693 debug ! (
681694 "Creating libvirt domain from: {}" ,
682695 opts. volume_name_or_image
683696 ) ;
684697
685698 // Phase 1: Ensure volume exists (auto-upload if needed)
686- let volume_name = opts. ensure_volume_exists ( ) ?;
699+ let volume_name = opts. ensure_volume_exists ( global_opts ) ?;
687700
688701 // Phase 2: Validate volume exists and get path
689- let volume_path = opts. check_volume_exists ( & volume_name) ?;
702+ let volume_path = opts. check_volume_exists ( global_opts , & volume_name) ?;
690703 debug ! ( "Found volume at: {}" , volume_path) ;
691704
692705 // Phase 3: Extract volume metadata
693- let metadata = opts. get_volume_metadata ( & volume_name) ?;
706+ let metadata = opts. get_volume_metadata ( global_opts , & volume_name) ?;
694707 if let Some ( ref source_image) = metadata. source_image {
695708 debug ! ( "Volume contains bootc image: {}" , source_image) ;
696709 }
697710
698711 // Phase 4: Create and optionally start domain
699- opts. create_domain ( & volume_path, & metadata, & volume_name) ?;
712+ opts. create_domain ( global_opts , & volume_path, & metadata, & volume_name) ?;
700713
701714 Ok ( ( ) )
702715}
0 commit comments