@@ -13,12 +13,11 @@ import (
1313 "syscall"
1414 "time"
1515
16- "gitlab.com/bootc-org/podman-bootc/pkg/config"
16+ "gitlab.com/bootc-org/podman-bootc/pkg/cache"
17+ "gitlab.com/bootc-org/podman-bootc/pkg/container"
1718 "gitlab.com/bootc-org/podman-bootc/pkg/user"
18- "gitlab.com/bootc-org/podman-bootc/pkg/utils"
1919
2020 "github.com/containers/podman/v5/pkg/bindings/containers"
21- "github.com/containers/podman/v5/pkg/bindings/images"
2221 "github.com/containers/podman/v5/pkg/domain/entities/types"
2322 "github.com/containers/podman/v5/pkg/specgen"
2423 "github.com/docker/go-units"
@@ -62,14 +61,11 @@ type diskFromContainerMeta struct {
6261}
6362
6463type BootcDisk struct {
65- ImageNameOrId string
64+ ContainerImage container.ContainerImage
65+ Cache cache.Cache
6666 User user.User
6767 Ctx context.Context
68- ImageId string
69- imageData * types.ImageInspectReport
70- RepoTag string
7168 CreatedAt time.Time
72- Directory string
7369 file * os.File
7470 bootcInstallContainerId string
7571}
@@ -80,40 +76,34 @@ var (
8076 instanceOnce sync.Once
8177)
8278
83- func NewBootcDisk (imageNameOrId string , ctx context.Context , user user.User ) * BootcDisk {
79+ // NewBootcDisk creates a new BootcDisk instance
80+ //
81+ // Parameters:
82+ // - imageNameOrId: the name or id of the container image
83+ // - ctx: context for the podman machine connection
84+ // - user: the user who is running the command, determines where the disk image is stored
85+ func NewBootcDisk (containerImage container.ContainerImage , ctx context.Context , user user.User , cache cache.Cache ) * BootcDisk {
8486 instanceOnce .Do (func () {
8587 instance = & BootcDisk {
86- ImageNameOrId : imageNameOrId ,
87- Ctx : ctx ,
88- User : user ,
88+ ContainerImage : containerImage ,
89+ Ctx : ctx ,
90+ User : user ,
91+ Cache : cache ,
8992 }
9093 })
9194 return instance
9295}
9396
94- func (p * BootcDisk ) GetDirectory () string {
95- return p .Directory
96- }
97-
98- func (p * BootcDisk ) GetImageId () string {
99- return p .ImageId
100- }
101-
10297// GetSize returns the virtual size of the disk in bytes;
10398// this may be larger than the actual disk usage
10499func (p * BootcDisk ) GetSize () (int64 , error ) {
105- st , err := os .Stat (filepath . Join ( p . Directory , config . DiskImage ))
100+ st , err := os .Stat (p . Cache . GetDiskPath ( ))
106101 if err != nil {
107102 return 0 , err
108103 }
109104 return st .Size (), nil
110105}
111106
112- // GetRepoTag returns the repository of the container image
113- func (p * BootcDisk ) GetRepoTag () string {
114- return p .RepoTag
115- }
116-
117107// GetCreatedAt returns the creation time of the disk image
118108func (p * BootcDisk ) GetCreatedAt () time.Time {
119109 return p .CreatedAt
@@ -122,32 +112,6 @@ func (p *BootcDisk) GetCreatedAt() time.Time {
122112func (p * BootcDisk ) Install (quiet bool , config DiskImageConfig ) (err error ) {
123113 p .CreatedAt = time .Now ()
124114
125- err = p .pullImage ()
126- if err != nil {
127- return
128- }
129-
130- // Create VM cache dir; one per oci bootc image
131- p .Directory = filepath .Join (p .User .CacheDir (), p .ImageId )
132- lock := utils .NewCacheLock (p .User .RunDir (), p .Directory )
133- locked , err := lock .TryLock (utils .Exclusive )
134- if err != nil {
135- return fmt .Errorf ("error locking the VM cache path: %w" , err )
136- }
137- if ! locked {
138- return fmt .Errorf ("unable to lock the VM cache path" )
139- }
140-
141- defer func () {
142- if err := lock .Unlock (); err != nil {
143- logrus .Errorf ("unable to unlock VM %s: %v" , p .ImageId , err )
144- }
145- }()
146-
147- if err := os .MkdirAll (p .Directory , os .ModePerm ); err != nil {
148- return fmt .Errorf ("error while making bootc disk directory: %w" , err )
149- }
150-
151115 err = p .getOrInstallImageToDisk (quiet , config )
152116 if err != nil {
153117 return
@@ -173,7 +137,7 @@ func (p *BootcDisk) Cleanup() (err error) {
173137
174138// getOrInstallImageToDisk checks if the disk is present and if not, installs the image to a new disk
175139func (p * BootcDisk ) getOrInstallImageToDisk (quiet bool , diskConfig DiskImageConfig ) error {
176- diskPath := filepath . Join ( p . Directory , config . DiskImage )
140+ diskPath := p . Cache . GetDiskPath ( )
177141 f , err := os .Open (diskPath )
178142 if err != nil {
179143 if ! errors .Is (err , os .ErrNotExist ) {
@@ -199,8 +163,8 @@ func (p *BootcDisk) getOrInstallImageToDisk(quiet bool, diskConfig DiskImageConf
199163 return p .bootcInstallImageToDisk (quiet , diskConfig )
200164 }
201165
202- logrus .Debugf ("previous disk digest: %s current digest: %s" , serializedMeta .ImageDigest , p .ImageId )
203- if serializedMeta .ImageDigest == p .ImageId {
166+ logrus .Debugf ("previous disk digest: %s current digest: %s" , serializedMeta .ImageDigest , p .ContainerImage . GetId () )
167+ if serializedMeta .ImageDigest == p .ContainerImage . GetId () {
204168 return nil
205169 }
206170
@@ -217,12 +181,12 @@ func align(size int64, align int64) int64 {
217181
218182// bootcInstallImageToDisk creates a disk image from a bootc container
219183func (p * BootcDisk ) bootcInstallImageToDisk (quiet bool , diskConfig DiskImageConfig ) (err error ) {
220- fmt .Printf ("Executing `bootc install to-disk` from container image %s to create disk image\n " , p .RepoTag )
221- p .file , err = os .CreateTemp (p .Directory , "podman-bootc-tempdisk" )
184+ fmt .Printf ("Executing `bootc install to-disk` from container image %s to create disk image\n " , p .ContainerImage . GetRepoTag () )
185+ p .file , err = os .CreateTemp (p .Cache . GetDirectory () , "podman-bootc-tempdisk" )
222186 if err != nil {
223187 return err
224188 }
225- size := p .imageData . Size * containerSizeToDiskSizeMultiplier
189+ size := p .ContainerImage . GetSize () * containerSizeToDiskSizeMultiplier
226190 if size < diskSizeMinimum {
227191 size = diskSizeMinimum
228192 }
@@ -237,7 +201,7 @@ func (p *BootcDisk) bootcInstallImageToDisk(quiet bool, diskConfig DiskImageConf
237201 }
238202 // Round up to 4k; loopback wants at least 512b alignment
239203 size = align (size , 4096 )
240- humanContainerSize := units .HumanSize (float64 (p .imageData . Size ))
204+ humanContainerSize := units .HumanSize (float64 (p .ContainerImage . GetSize () ))
241205 humanSize := units .HumanSize (float64 (size ))
242206 logrus .Infof ("container size: %s, disk size: %s" , humanContainerSize , humanSize )
243207
@@ -257,7 +221,7 @@ func (p *BootcDisk) bootcInstallImageToDisk(quiet bool, diskConfig DiskImageConf
257221 return fmt .Errorf ("failed to create disk image: %w" , err )
258222 }
259223 serializedMeta := diskFromContainerMeta {
260- ImageDigest : p .ImageId ,
224+ ImageDigest : p .ContainerImage . GetId () ,
261225 }
262226 buf , err := json .Marshal (serializedMeta )
263227 if err != nil {
@@ -266,8 +230,8 @@ func (p *BootcDisk) bootcInstallImageToDisk(quiet bool, diskConfig DiskImageConf
266230 if err := unix .Fsetxattr (int (p .file .Fd ()), imageMetaXattr , buf , 0 ); err != nil {
267231 return fmt .Errorf ("failed to set xattr: %w" , err )
268232 }
269- diskPath := filepath .Join (p .Directory , config .DiskImage )
270233
234+ diskPath := p .Cache .GetDiskPath ()
271235 if err := os .Rename (p .file .Name (), diskPath ); err != nil {
272236 return fmt .Errorf ("failed to rename to %s: %w" , diskPath , err )
273237 }
@@ -276,39 +240,10 @@ func (p *BootcDisk) bootcInstallImageToDisk(quiet bool, diskConfig DiskImageConf
276240 return nil
277241}
278242
279- // pullImage fetches the container image if not present
280- func (p * BootcDisk ) pullImage () (err error ) {
281- pullPolicy := "missing"
282- ids , err := images .Pull (p .Ctx , p .ImageNameOrId , & images.PullOptions {Policy : & pullPolicy })
283- if err != nil {
284- return fmt .Errorf ("failed to pull image: %w" , err )
285- }
286-
287- if len (ids ) == 0 {
288- return fmt .Errorf ("no ids returned from image pull" )
289- }
290-
291- if len (ids ) > 1 {
292- return fmt .Errorf ("multiple ids returned from image pull" )
293- }
294-
295- image , err := images .GetImage (p .Ctx , p .ImageNameOrId , & images.GetOptions {})
296- if err != nil {
297- return fmt .Errorf ("failed to get image: %w" , err )
298- }
299- p .imageData = image
300-
301- imageId := ids [0 ]
302- p .ImageId = imageId
303- p .RepoTag = image .RepoTags [0 ]
304-
305- return
306- }
307-
308243// runInstallContainer runs the bootc installer in a container to create a disk image
309244func (p * BootcDisk ) runInstallContainer (quiet bool , config DiskImageConfig ) (err error ) {
310245 // Create a temporary external shell script with the contents of our losetup wrapper
311- losetupTemp , err := os .CreateTemp (p .Directory , "losetup-wrapper" )
246+ losetupTemp , err := os .CreateTemp (p .Cache . GetDirectory () , "losetup-wrapper" )
312247 if err != nil {
313248 return fmt .Errorf ("temp losetup wrapper: %w" , err )
314249 }
@@ -393,7 +328,7 @@ func (p *BootcDisk) createInstallContainer(config DiskImageConfig, tempLosetup s
393328 Terminal : & trueDat ,
394329 },
395330 ContainerStorageConfig : specgen.ContainerStorageConfig {
396- Image : p .ImageNameOrId ,
331+ Image : p .ContainerImage . ImageNameOrId ,
397332 Mounts : []specs.Mount {
398333 {
399334 Source : "/var/lib/containers" ,
@@ -406,7 +341,7 @@ func (p *BootcDisk) createInstallContainer(config DiskImageConfig, tempLosetup s
406341 Type : "bind" ,
407342 },
408343 {
409- Source : p .Directory ,
344+ Source : p .Cache . GetDirectory () ,
410345 Destination : "/output" ,
411346 Type : "bind" ,
412347 },
0 commit comments