2626from craft_providers .const import TIMEOUT_COMPLEX , TIMEOUT_SIMPLE
2727from craft_providers .util import env_cmd
2828
29- from .. import Executor
29+ from ..executor import Executor , get_instance_name
3030from .errors import MultipassError
3131from .multipass import Multipass
3232
@@ -59,9 +59,10 @@ def _rootify_multipass_command(
5959
6060
6161class MultipassInstance (Executor ):
62- """Multipass Instance Lifecycle .
62+ """Wrapper for a Multipass instance .
6363
64- :param name: Name of multipass instance.
64+ :ivar name: The provided name for the instance.
65+ :ivar instance_name: The normalized name actually used for the instance.
6566 """
6667
6768 def __init__ (
@@ -70,9 +71,17 @@ def __init__(
7071 name : str ,
7172 multipass : Optional [Multipass ] = None ,
7273 ) -> None :
74+ """Set up the wrapper class.
75+
76+ :param name: The name of the MultipassInstance.
77+ :param multipass: The Multipass wrapper to use.
78+
79+ :raises MultipassError: If the name is invalid.
80+ """
7381 super ().__init__ ()
7482
7583 self .name = name
84+ self .instance_name = get_instance_name (name , MultipassError )
7685
7786 if multipass is not None :
7887 self ._multipass = multipass
@@ -146,7 +155,7 @@ def push_file_io(
146155 tmp_file_path = self ._create_temp_file ()
147156
148157 self ._multipass .transfer_source_io (
149- source = content , destination = f"{ self .name } :{ tmp_file_path } "
158+ source = content , destination = f"{ self .instance_name } :{ tmp_file_path } "
150159 )
151160
152161 # now that the file has been transferred, its ownership can be set
@@ -174,15 +183,15 @@ def push_file_io(
174183 raise MultipassError (
175184 brief = (
176185 f"Failed to create file { destination .as_posix ()!r} "
177- f" in Multipass instance { self .name !r} ."
186+ f" in Multipass instance { self .instance_name !r} ."
178187 ),
179188 details = errors .details_from_called_process_error (error ),
180189 ) from error
181190
182191 def delete (self ) -> None :
183192 """Delete instance and purge."""
184193 return self ._multipass .delete (
185- instance_name = self .name ,
194+ instance_name = self .instance_name ,
186195 purge = True ,
187196 )
188197
@@ -215,7 +224,7 @@ def execute_popen(
215224 :returns: Popen instance.
216225 """
217226 return self ._multipass .exec (
218- instance_name = self .name ,
227+ instance_name = self .instance_name ,
219228 command = _rootify_multipass_command (command , cwd = cwd , env = env ),
220229 runner = subprocess .Popen ,
221230 timeout = timeout ,
@@ -255,7 +264,7 @@ def execute_run(
255264 :raises subprocess.CalledProcessError: if command fails and check is True.
256265 """
257266 return self ._multipass .exec (
258- instance_name = self .name ,
267+ instance_name = self .instance_name ,
259268 command = _rootify_multipass_command (command , cwd = cwd , env = env ),
260269 runner = subprocess .run ,
261270 timeout = timeout ,
@@ -272,7 +281,7 @@ def exists(self) -> bool:
272281 """
273282 vm_list = self ._multipass .list ()
274283
275- return self .name in vm_list
284+ return self .instance_name in vm_list
276285
277286 def _get_info (self ) -> Dict [str , Any ]:
278287 """Get configuration and state for instance.
@@ -282,15 +291,15 @@ def _get_info(self) -> Dict[str, Any]:
282291
283292 :raises MultipassError: If unable to parse VM info.
284293 """
285- info_data = self ._multipass .info (instance_name = self .name ).get ("info" )
294+ info_data = self ._multipass .info (instance_name = self .instance_name ).get ("info" )
286295
287- if info_data is None or self .name not in info_data :
296+ if info_data is None or self .instance_name not in info_data :
288297 raise MultipassError (
289298 brief = "Malformed multipass info" ,
290299 details = f"Returned data: { info_data !r} " ,
291300 )
292301
293- return info_data [self .name ]
302+ return info_data [self .instance_name ]
294303
295304 def is_mounted (
296305 self , * , host_source : pathlib .Path , target : pathlib .PurePath
@@ -349,7 +358,7 @@ def launch(
349358 :raises MultipassError: On unexpected failure.
350359 """
351360 self ._multipass .launch (
352- instance_name = self .name ,
361+ instance_name = self .instance_name ,
353362 image = image ,
354363 cpus = str (cpus ),
355364 disk = f"{ disk_gb !s} G" ,
@@ -376,7 +385,7 @@ def mount(
376385
377386 self ._multipass .mount (
378387 source = host_source ,
379- target = f"{ self .name } :{ target .as_posix ()} " ,
388+ target = f"{ self .instance_name } :{ target .as_posix ()} " ,
380389 )
381390
382391 def pull_file (self , * , source : pathlib .PurePath , destination : pathlib .Path ) -> None :
@@ -402,7 +411,8 @@ def pull_file(self, *, source: pathlib.PurePath, destination: pathlib.Path) -> N
402411 raise FileNotFoundError (f"Directory not found: { str (destination .parent )!r} " )
403412
404413 self ._multipass .transfer (
405- source = f"{ self .name } :{ source .as_posix ()} " , destination = str (destination )
414+ source = f"{ self .instance_name } :{ source .as_posix ()} " ,
415+ destination = str (destination ),
406416 )
407417
408418 def push_file (self , * , source : pathlib .Path , destination : pathlib .PurePath ) -> None :
@@ -441,7 +451,7 @@ def push_file(self, *, source: pathlib.Path, destination: pathlib.PurePath) -> N
441451
442452 # push the file to a location where the `ubuntu` user has access
443453 self ._multipass .transfer (
444- source = str (source ), destination = f"{ self .name } :{ tmp_file_path } "
454+ source = str (source ), destination = f"{ self .instance_name } :{ tmp_file_path } "
445455 )
446456
447457 # if the destination was a directory, then we need to specify the filename
@@ -461,7 +471,7 @@ def push_file(self, *, source: pathlib.Path, destination: pathlib.PurePath) -> N
461471 raise MultipassError (
462472 brief = (
463473 f"Failed to push file { destination .as_posix ()!r} "
464- f" into Multipass instance { self .name !r} ."
474+ f" into Multipass instance { self .instance_name !r} ."
465475 ),
466476 details = errors .details_from_called_process_error (error ),
467477 ) from error
@@ -471,7 +481,7 @@ def start(self) -> None:
471481
472482 :raises MultipassError: On unexpected failure.
473483 """
474- self ._multipass .start (instance_name = self .name )
484+ self ._multipass .start (instance_name = self .instance_name )
475485
476486 def stop (self , * , delay_mins : int = 0 ) -> None :
477487 """Stop instance.
@@ -480,7 +490,7 @@ def stop(self, *, delay_mins: int = 0) -> None:
480490
481491 :raises MultipassError: On unexpected failure.
482492 """
483- self ._multipass .stop (instance_name = self .name , delay_mins = delay_mins )
493+ self ._multipass .stop (instance_name = self .instance_name , delay_mins = delay_mins )
484494
485495 def unmount (self , target : pathlib .Path ) -> None :
486496 """Unmount mount target shared with host.
@@ -489,7 +499,7 @@ def unmount(self, target: pathlib.Path) -> None:
489499
490500 :raises MultipassError: On failure to unmount target.
491501 """
492- mount = f"{ self .name } :{ target .as_posix ()} "
502+ mount = f"{ self .instance_name } :{ target .as_posix ()} "
493503
494504 self ._multipass .umount (mount = mount )
495505
@@ -498,4 +508,4 @@ def unmount_all(self) -> None:
498508
499509 :raises MultipassError: On failure to unmount target.
500510 """
501- self ._multipass .umount (mount = self .name )
511+ self ._multipass .umount (mount = self .instance_name )
0 commit comments