@@ -19,9 +19,13 @@ import (
19
19
"fmt"
20
20
"io"
21
21
"os/exec"
22
+ "regexp"
23
+ "strconv"
24
+ "strings"
22
25
26
+ sharedErrors "github.com/coreos/ignition/v2/config/shared/errors"
23
27
"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 "
25
29
"github.com/coreos/ignition/v2/internal/distro"
26
30
"github.com/coreos/ignition/v2/internal/log"
27
31
)
@@ -30,30 +34,18 @@ type Operation struct {
30
34
logger * log.Logger
31
35
dev string
32
36
wipe bool
33
- parts []Partition
37
+ parts []device_managers. Partition
34
38
deletions []int
35
39
infos []int
36
40
}
37
41
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
-
50
42
// Begin begins an sfdisk operation
51
43
func Begin (logger * log.Logger , dev string ) * Operation {
52
44
return & Operation {logger : logger , dev : dev }
53
45
}
54
46
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 ) {
57
49
op .parts = append (op .parts , p )
58
50
}
59
51
@@ -81,7 +73,7 @@ func (op *Operation) Pretend() (string, error) {
81
73
return "" , err
82
74
}
83
75
84
- script := op .sfdiskBuildOptions ()
76
+ script := op .buildOptions ()
85
77
cmd := exec .Command ("sh" , "-c" , fmt .Sprintf ("echo -e \" %s\" | sudo %s --no-act %s" , script , distro .SfdiskCmd (), op .dev ))
86
78
stdout , err := cmd .StdoutPipe ()
87
79
@@ -114,35 +106,108 @@ func (op *Operation) Pretend() (string, error) {
114
106
}
115
107
116
108
// Commit commits an partitioning operation.
117
- func (op * Operation ) SfdiskCommit () error {
118
- script := op .sfdiskBuildOptions ()
109
+ func (op * Operation ) Commit () error {
110
+ println ("Commit: HERE" )
111
+ fmt .Println (op .parts )
112
+ script := op .buildOptions ()
119
113
if len (script ) == 0 {
120
114
return nil
121
115
}
122
116
123
117
// If wipe we need to reset the partition table
124
118
if op .wipe {
125
119
// Erase the existing partition tables
126
- cmd := exec .Command ("sudo" , distro .WipefsCmd (), "-a" , op .dev )
120
+ cmd := exec .Command (distro .WipefsCmd (), "-a" , op .dev )
127
121
if _ , err := op .logger .LogCmd (cmd , "option wipe selected, and failed to execute on %q" , op .dev ); err != nil {
128
122
return fmt .Errorf ("wipe partition table failed: %v" , err )
129
123
}
130
124
}
131
125
132
- op .logger .Info ("running sfdisk with script: %v" , script )
133
- exec .Command ("sh" , "-c" , fmt .Sprintf ("echo label: gpt | sudo %s %s" , distro .SfdiskCmd (), op .dev ))
134
- cmd := exec .Command ("sh" , "-c" , fmt .Sprintf ("echo \" %s\" | sudo %s %s" , script , distro .SfdiskCmd (), op .dev ))
126
+ op .runSfdisk (true )
127
+
128
+ return nil
129
+ }
130
+
131
+ func (op * Operation ) runSfdisk (shouldWrite bool ) error {
132
+ var opts []string
133
+ if ! shouldWrite {
134
+ opts = append (opts , "--no-act" )
135
+ }
136
+ opts = append (opts , "-X" , "gpt" , op .dev )
137
+ fmt .Printf ("The options are %v" , opts )
138
+ cmd := exec .Command (distro .SfdiskCmd (), opts ... )
139
+ cmd .Stdin = strings .NewReader (op .buildOptions ())
135
140
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 {
136
141
return fmt .Errorf ("create partitions failed: %v" , err )
137
142
}
138
143
139
144
return nil
140
145
}
141
146
142
- func (op Operation ) sfdiskBuildOptions () string {
147
+ // ParseOutput takes the output from sfdisk. Similarly to sgdisk
148
+ // it then uses regex to parse the output into understood values like 'start' 'size' and attempts
149
+ // to catch any failures and wrap them to return to the caller.
150
+ func (op * Operation ) ParseOutput (sfdiskOutput string , partitionNumbers []int ) (map [int ]device_managers.Output , error ) {
151
+ if len (partitionNumbers ) == 0 {
152
+ return nil , nil
153
+ }
154
+
155
+ // Look for new lines starting with /dev/ and the following string it
156
+ // Additionally Group on Start sector, and End sector
157
+ // Example output match would be "/dev/vda1 2048 2057 10 5K 83 Linux"
158
+ partitionRegex := regexp .MustCompile (`^/dev/\S+\s+\S*\s+(\d+)\s+(\d+)\s+\d+\s+\S+\s+\S+\s+\S+.*$` )
159
+ output := map [int ]device_managers.Output {}
160
+ current := device_managers.Output {}
161
+ i := 0
162
+ lines := strings .Split (sfdiskOutput , "\n " )
163
+ for _ , line := range lines {
164
+ matches := partitionRegex .FindStringSubmatch (line )
165
+
166
+ // Sanity check number of partition entries
167
+ if i > len (partitionNumbers ) {
168
+ return nil , sharedErrors .ErrBadSfdiskPretend
169
+ }
170
+
171
+ // Verify that we are not reading a 'failed' or 'error'
172
+ errorRegex := regexp .MustCompile (`(?i)(failed|error)` )
173
+ if errorRegex .MatchString (line ) {
174
+ return nil , fmt .Errorf ("%w: sfdisk returned :%v" , sharedErrors .ErrBadSfdiskPretend , line )
175
+ }
176
+
177
+ // When we get a match it should be
178
+ // Whole line at [0]
179
+ // Start at [1]
180
+ // End at [2]
181
+ if len (matches ) > 2 {
182
+ start , err := strconv .Atoi (matches [1 ])
183
+ if err != nil {
184
+ return nil , err
185
+ }
186
+ end , err := strconv .Atoi (matches [2 ])
187
+ if err != nil {
188
+ return nil , err
189
+ }
190
+
191
+ current .Start = int64 (start )
192
+ // Add one due to overlap
193
+ current .Size = int64 (end - start + 1 )
194
+ output [partitionNumbers [i ]] = current
195
+ i ++
196
+ }
197
+ }
198
+
199
+ return output , nil
200
+ }
201
+
202
+ func (op Operation ) buildOptions () string {
143
203
var script bytes.Buffer
144
204
145
205
for _ , p := range op .parts {
206
+ println ("Starting Build Options Script Building" )
207
+
208
+ fmt .Println (p )
209
+ println (script .String ())
210
+
146
211
if p .Number != 0 {
147
212
script .WriteString (fmt .Sprintf ("%d : " , p .Number ))
148
213
}
@@ -170,7 +235,9 @@ func (op Operation) sfdiskBuildOptions() string {
170
235
171
236
// Add escaped new line to allow for 1 or more partitions
172
237
// i.e "1: size=50 \\n size=10" will result in part 1, and 2
173
- script .WriteString ("\\ n " )
238
+ script .WriteString ("\n " )
239
+ println ("here!" )
240
+ println (script .String ())
174
241
175
242
}
176
243
@@ -202,75 +269,3 @@ func (op *Operation) handleInfo() error {
202
269
}
203
270
return nil
204
271
}
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