@@ -109,25 +109,40 @@ func doRun(flags *cobra.Command, args []string) error {
109109 return fmt .Errorf ("unable to pull container image: %w" , err )
110110 }
111111
112- // create the cache directory
113- cache := cache .NewCache (containerImage .GetId (), user )
114- err = cache .Create ()
112+ // create the cacheDir directory
113+ cacheDir , err := cache .NewCache (containerImage .GetId (), user )
114+ if err != nil {
115+ return fmt .Errorf ("unable to create cache: %w" , err )
116+ }
117+ err = cacheDir .Create ()
115118 if err != nil {
116119 return fmt .Errorf ("unable to create cache: %w" , err )
117120 }
118121
122+ err = cacheDir .Lock (cache .Exclusive )
123+ if err != nil {
124+ return err
125+ }
126+
119127 // check if the vm is already running
120128 bootcVM , err := vm .NewVM (vm.NewVMParameters {
121129 ImageID : containerImage .GetId (),
122130 User : user ,
123131 LibvirtUri : config .LibvirtUri ,
124- Locking : utils .Shared ,
125132 })
126133
127134 if err != nil {
128135 return fmt .Errorf ("unable to initialize VM: %w" , err )
129136 }
130137
138+ defer func () {
139+ // Let's be explicit instead of relying on the defer exec order
140+ bootcVM .CloseConnection ()
141+ if err := cacheDir .Unlock (); err != nil {
142+ logrus .Errorf ("unable to unlock cache %s: %v" , cacheDir .ImageId , err )
143+ }
144+ }()
145+
131146 isRunning , err := bootcVM .IsRunning ()
132147 if err != nil {
133148 return fmt .Errorf ("unable to check if VM is running: %w" , err )
@@ -145,7 +160,7 @@ func doRun(flags *cobra.Command, args []string) error {
145160 }
146161
147162 // create the disk image
148- bootcDisk := bootc .NewBootcDisk (containerImage , ctx , user , cache , bustCache )
163+ bootcDisk := bootc .NewBootcDisk (containerImage , ctx , user , cacheDir , bustCache )
149164 err = bootcDisk .Install (vmConfig .Quiet , diskImageConfigInstance )
150165
151166 if err != nil {
@@ -159,14 +174,6 @@ func doRun(flags *cobra.Command, args []string) error {
159174 return fmt .Errorf ("unable to get free port for SSH: %w" , err )
160175 }
161176
162- // Let's be explicit instead of relying on the defer exec order
163- defer func () {
164- bootcVM .CloseConnection ()
165- if err := bootcVM .Unlock (); err != nil {
166- logrus .Warningf ("unable to unlock VM %s: %v" , containerImage .GetId (), err )
167- }
168- }()
169-
170177 cmd := args [1 :]
171178 err = bootcVM .Run (vm.RunVMParameters {
172179 Cmd : cmd ,
@@ -189,6 +196,14 @@ func doRun(flags *cobra.Command, args []string) error {
189196 return err
190197 }
191198
199+ // done modifying the cache, so remove the Exclusive lock
200+ cacheDir .Unlock ()
201+
202+ // take a RO lock for the SSH connection
203+ // it will be unlocked at the end of this function
204+ // by the previous defer()
205+ cacheDir .Lock (cache .Shared )
206+
192207 if ! vmConfig .Background {
193208 if ! vmConfig .Quiet {
194209 var vmConsoleWg sync.WaitGroup
@@ -227,6 +242,14 @@ func doRun(flags *cobra.Command, args []string) error {
227242
228243 // Always remove when executing a command
229244 if vmConfig .RemoveVm || len (cmd ) > 0 {
245+ // remove the RO lock
246+ cacheDir .Unlock ()
247+
248+ // take an exclusive lock to remove the VM
249+ // it will be unlocked at the end of this function
250+ // by the previous defer()
251+ cacheDir .Lock (cache .Exclusive )
252+
230253 err = bootcVM .Delete () //delete the VM, but keep the disk image
231254 if err != nil {
232255 return fmt .Errorf ("unable to remove VM from cache: %w" , err )
0 commit comments