@@ -19,9 +19,13 @@ import (
1919 "fmt"
2020 "io"
2121 "os/exec"
22+ "regexp"
23+ "strconv"
24+ "strings"
2225
26+ sharedErrors "github.com/coreos/ignition/v2/config/shared/errors"
2327 "github.com/coreos/ignition/v2/config/util"
24- "github.com/coreos/ignition/v2/config/v3_5_experimental/types "
28+ "github.com/coreos/ignition/v2/internal/device_managers "
2529 "github.com/coreos/ignition/v2/internal/distro"
2630 "github.com/coreos/ignition/v2/internal/log"
2731)
@@ -30,30 +34,18 @@ type Operation struct {
3034 logger * log.Logger
3135 dev string
3236 wipe bool
33- parts []Partition
37+ parts []device_managers. Partition
3438 deletions []int
3539 infos []int
3640}
3741
38- // We ignore types.Partition.StartMiB/SizeMiB in favor of
39- // StartSector/SizeInSectors. The caller is expected to do the conversion.
40- type Partition struct {
41- types.Partition
42- StartSector * int64
43- SizeInSectors * int64
44-
45- // shadow StartMiB/SizeMiB so they're not accidentally used
46- StartMiB string
47- SizeMiB string
48- }
49-
5042// Begin begins an sfdisk operation
5143func Begin (logger * log.Logger , dev string ) * Operation {
5244 return & Operation {logger : logger , dev : dev }
5345}
5446
55- // CreatePartition adds the supplied partition to the list of partitions to be created as part of an operation.
56- func (op * Operation ) CreatePartition (p Partition ) {
47+ // CreatePartition adds the supplied partition to the list of partitions to be created as part of an operation
48+ func (op * Operation ) CreatePartition (p device_managers. Partition ) {
5749 op .parts = append (op .parts , p )
5850}
5951
@@ -81,7 +73,7 @@ func (op *Operation) Pretend() (string, error) {
8173 return "" , err
8274 }
8375
84- script := op .sfdiskBuildOptions ()
76+ script := op .buildOptions ()
8577 cmd := exec .Command ("sh" , "-c" , fmt .Sprintf ("echo -e \" %s\" | sudo %s --no-act %s" , script , distro .SfdiskCmd (), op .dev ))
8678 stdout , err := cmd .StdoutPipe ()
8779
@@ -114,8 +106,8 @@ func (op *Operation) Pretend() (string, error) {
114106}
115107
116108// Commit commits an partitioning operation.
117- func (op * Operation ) SfdiskCommit () error {
118- script := op .sfdiskBuildOptions ()
109+ func (op * Operation ) Commit () error {
110+ script := op .buildOptions ()
119111 if len (script ) == 0 {
120112 return nil
121113 }
@@ -139,7 +131,60 @@ func (op *Operation) SfdiskCommit() error {
139131 return nil
140132}
141133
142- func (op Operation ) sfdiskBuildOptions () string {
134+ // ParseOutput takes the output from sfdisk. Similarly to sgdisk
135+ // it then uses regex to parse the output into understood values like 'start' 'size' and attempts
136+ // to catch any failures and wrap them to return to the caller.
137+ func (op * Operation ) ParseOutput (sfdiskOutput string , partitionNumbers []int ) (map [int ]device_managers.Output , error ) {
138+ if len (partitionNumbers ) == 0 {
139+ return nil , nil
140+ }
141+
142+ // Prepare the data, and a regex for matching on partitions
143+ partitionRegex := regexp .MustCompile (`^/dev/\S+\s+\S*\s+(\d+)\s+(\d+)\s+\d+\s+\S+\s+\S+\s+\S+.*$` )
144+ output := map [int ]device_managers.Output {}
145+ current := device_managers.Output {}
146+ i := 0
147+ lines := strings .Split (sfdiskOutput , "\n " )
148+ for _ , line := range lines {
149+ matches := partitionRegex .FindStringSubmatch (line )
150+
151+ // Sanity check number of partition entries
152+ if i > len (partitionNumbers ) {
153+ return nil , sharedErrors .ErrBadSfdiskPretend
154+ }
155+
156+ // Verify that we are not reading a 'failed' or 'error'
157+ errorRegex := regexp .MustCompile (`(?i)(failed|error)` )
158+ if errorRegex .MatchString (line ) {
159+ return nil , fmt .Errorf ("%w: sfdisk returned :%v" , sharedErrors .ErrBadSfdiskPretend , line )
160+ }
161+
162+ // When we get a match it should be
163+ // Whole line at [0]
164+ // Start at [1]
165+ // Size at [2]
166+ if len (matches ) > 2 {
167+ start , err := strconv .Atoi (matches [1 ])
168+ if err != nil {
169+ return nil , err
170+ }
171+ end , err := strconv .Atoi (matches [2 ])
172+ if err != nil {
173+ return nil , err
174+ }
175+
176+ current .Start = int64 (start )
177+ // Add one due to overlap
178+ current .Size = int64 (end - start + 1 )
179+ output [partitionNumbers [i ]] = current
180+ i ++
181+ }
182+ }
183+
184+ return output , nil
185+ }
186+
187+ func (op Operation ) buildOptions () string {
143188 var script bytes.Buffer
144189
145190 for _ , p := range op .parts {
@@ -202,75 +247,3 @@ func (op *Operation) handleInfo() error {
202247 }
203248 return nil
204249}
205-
206- // Copy old functionality from sgdisk to switch between the two during testing.
207- // Will be removed.
208- func (op * Operation ) SgdiskCommit () error {
209- opts := op .sgdiskBuildOptions ()
210- if len (opts ) == 0 {
211- return nil
212- }
213- op .logger .Info ("running sgdisk with options: %v" , opts )
214- cmd := exec .Command (distro .SgdiskCmd (), opts ... )
215-
216- if _ , err := op .logger .LogCmd (cmd , "deleting %d partitions and creating %d partitions on %q" , len (op .deletions ), len (op .parts ), op .dev ); err != nil {
217- return fmt .Errorf ("create partitions failed: %v" , err )
218- }
219-
220- return nil
221- }
222-
223- // Copy old functionality from sgdisk to switch between the two during testing.
224- // Will be removed.
225- func (op Operation ) sgdiskBuildOptions () []string {
226- opts := []string {}
227-
228- if op .wipe {
229- opts = append (opts , "--zap-all" )
230- }
231-
232- // Do all deletions before creations
233- for _ , partition := range op .deletions {
234- opts = append (opts , fmt .Sprintf ("--delete=%d" , partition ))
235- }
236-
237- for _ , p := range op .parts {
238- opts = append (opts , fmt .Sprintf ("--new=%d:%s:+%s" , p .Number , partitionGetStart (p ), partitionGetSize (p )))
239- if p .Label != nil {
240- opts = append (opts , fmt .Sprintf ("--change-name=%d:%s" , p .Number , * p .Label ))
241- }
242- if util .NotEmpty (p .TypeGUID ) {
243- opts = append (opts , fmt .Sprintf ("--typecode=%d:%s" , p .Number , * p .TypeGUID ))
244- }
245- if util .NotEmpty (p .GUID ) {
246- opts = append (opts , fmt .Sprintf ("--partition-guid=%d:%s" , p .Number , * p .GUID ))
247- }
248- }
249-
250- for _ , partition := range op .infos {
251- opts = append (opts , fmt .Sprintf ("--info=%d" , partition ))
252- }
253-
254- if len (opts ) == 0 {
255- return nil
256- }
257-
258- opts = append (opts , op .dev )
259- return opts
260- }
261-
262- // Copy old functionality from sgdisk to switch between the two during testing.
263- // Will be removed.
264- func partitionGetStart (p Partition ) string {
265- if p .StartSector != nil {
266- return fmt .Sprintf ("%d" , * p .StartSector )
267- }
268- return "0"
269- }
270-
271- func partitionGetSize (p Partition ) string {
272- if p .SizeInSectors != nil {
273- return fmt .Sprintf ("%d" , * p .SizeInSectors )
274- }
275- return "0"
276- }
0 commit comments