@@ -160,86 +160,96 @@ func Validate(y LimaYAML) error {
160
160
// processed sequentially and the first matching rule for a guest port determines forwarding behavior.
161
161
}
162
162
163
- if err := validateNetwork (y . Network ); err != nil {
163
+ if err := validateNetwork (y ); err != nil {
164
164
return err
165
165
}
166
166
167
167
return nil
168
168
}
169
169
170
- func validateNetwork (yNetwork Network ) error {
171
- networkName := make ( map [ string ] int )
172
- for i , vde := range yNetwork . VDE {
173
- field := fmt . Sprintf ( " network.vde[%d]" , i )
174
- if vde . VNL == "" {
175
- return fmt .Errorf ("field `%s.vnl` must not be empty" , field )
170
+ func validateNetwork (y LimaYAML ) error {
171
+ if len ( y . Network . VDEDeprecated ) > 0 {
172
+ if y . Network . migrated {
173
+ logrus . Warnf ( "field ` network.VDE` is deprecated; please use `networks` instead" )
174
+ } else {
175
+ return fmt .Errorf ("you cannot use deprecated field `network.VDE` together with replacement field `networks`" )
176
176
}
177
- // The field is called VDE.VNL in anticipation of QEMU upgrading VDE2 to VDEplug4,
178
- // but right now the only valid value on macOS is a path to the vde_switch socket directory,
179
- // optionally with vde:// prefix.
180
- // TODO: use networks.LimaSchema after solving circular dependency
181
- if strings .HasPrefix (vde .VNL , "lima://" ) {
182
- // TODO: validate network names? Problem is we can't use "networks" or "store" packages here...
183
- //name := strings.TrimPrefix(vde.VNL, networks.LimaScheme)
184
- //if _, ok := networkConfig.Networks[name]; !ok {
185
- // return fmt.Errorf("field `%s.vnl` references undefined network %q", field, name)
186
- //}
187
- } else if ! strings .Contains (vde .VNL , "://" ) || strings .HasPrefix (vde .VNL , "vde://" ) {
188
- vdeSwitch := strings .TrimPrefix (vde .VNL , "vde://" )
189
- if fi , err := os .Stat (vdeSwitch ); err != nil {
190
- // negligible when the instance is stopped
191
- logrus .WithError (err ).Debugf ("field `%s.vnl` %q failed stat" , field , vdeSwitch )
192
- } else {
193
- if fi .IsDir () {
194
- /* Switch mode (vdeSwitch is dir, port != 65535) */
195
- ctlSocket := filepath .Join (vdeSwitch , "ctl" )
196
- // ErrNotExist during os.Stat(ctlSocket) can be ignored. ctlSocket does not need to exist until actually starting the VM
197
- if fi , err = os .Stat (ctlSocket ); err == nil {
177
+ }
178
+ interfaceName := make (map [string ]int )
179
+ for i , nw := range y .Networks {
180
+ field := fmt .Sprintf ("networks[%d]" , i )
181
+ if nw .Lima != "" {
182
+ if nw .VNL != "" {
183
+ return fmt .Errorf ("field `%s.lima` and field `%s.vnl` are mutually exclusive" , field , field )
184
+ }
185
+ if nw .SwitchPort != 0 {
186
+ return fmt .Errorf ("field `%s.switchPort` cannot be used with field `%s.lima`" , field , field )
187
+ }
188
+ // TODO: validate network name (we can't use networks and store packages right now)
189
+ } else {
190
+ if nw .VNL == "" {
191
+ return fmt .Errorf ("field `%s.lima` or field `%s.vnl` must be set" , field , field )
192
+ }
193
+ // The field is called VDE.VNL in anticipation of QEMU upgrading VDE2 to VDEplug4,
194
+ // but right now the only valid value on macOS is a path to the vde_switch socket directory,
195
+ // optionally with vde:// prefix.
196
+ if ! strings .Contains (nw .VNL , "://" ) || strings .HasPrefix (nw .VNL , "vde://" ) {
197
+ vdeSwitch := strings .TrimPrefix (nw .VNL , "vde://" )
198
+ if fi , err := os .Stat (vdeSwitch ); err != nil {
199
+ // negligible when the instance is stopped
200
+ logrus .WithError (err ).Debugf ("field `%s.vnl` %q failed stat" , field , vdeSwitch )
201
+ } else {
202
+ if fi .IsDir () {
203
+ /* Switch mode (vdeSwitch is dir, port != 65535) */
204
+ ctlSocket := filepath .Join (vdeSwitch , "ctl" )
205
+ // ErrNotExist during os.Stat(ctlSocket) can be ignored. ctlSocket does not need to exist until actually starting the VM
206
+ if fi , err = os .Stat (ctlSocket ); err == nil {
207
+ if fi .Mode ()& os .ModeSocket == 0 {
208
+ return fmt .Errorf ("field `%s.vnl` file %q is not a UNIX socket" , field , ctlSocket )
209
+ }
210
+ }
211
+ if nw .SwitchPort == 65535 {
212
+ return fmt .Errorf ("field `%s.vnl` points to a non-PTP switch, so the port number must not be 65535" , field )
213
+ }
214
+ } else {
215
+ /* PTP mode (vdeSwitch is socket, port == 65535) */
198
216
if fi .Mode ()& os .ModeSocket == 0 {
199
- return fmt .Errorf ("field `%s.vnl` file %q is not a UNIX socket" , field , ctlSocket )
217
+ return fmt .Errorf ("field `%s.vnl` %q is not a directory nor a UNIX socket" , field , vdeSwitch )
218
+ }
219
+ if nw .SwitchPort != 65535 {
220
+ return fmt .Errorf ("field `%s.vnl` points to a PTP (switchless) socket %q, so the port number has to be 65535 (got %d)" ,
221
+ field , vdeSwitch , nw .SwitchPort )
200
222
}
201
- }
202
- if vde .SwitchPort == 65535 {
203
- return fmt .Errorf ("field `%s.vnl` points to a non-PTP switch, so the port number must not be 65535" , field )
204
- }
205
- } else {
206
- /* PTP mode (vdeSwitch is socket, port == 65535) */
207
- if fi .Mode ()& os .ModeSocket == 0 {
208
- return fmt .Errorf ("field `%s.vnl` %q is not a directory nor a UNIX socket" , field , vdeSwitch )
209
- }
210
- if vde .SwitchPort != 65535 {
211
- return fmt .Errorf ("field `%s.vnl` points to a PTP (switchless) socket %q, so the port number has to be 65535 (got %d)" ,
212
- field , vdeSwitch , vde .SwitchPort )
213
223
}
214
224
}
225
+ } else if runtime .GOOS != "linux" {
226
+ logrus .Warnf ("field `%s.vnl` is unlikely to work for %s (unless libvdeplug4 has been ported to %s and is installed)" ,
227
+ field , runtime .GOOS , runtime .GOOS )
215
228
}
216
- } else if runtime .GOOS != "linux" {
217
- logrus .Warnf ("field `%s.vnl` is unlikely to work for %s (unless libvdeplug4 has been ported to %s and is installed)" ,
218
- field , runtime .GOOS , runtime .GOOS )
219
229
}
220
- if vde .MACAddress != "" {
221
- hw , err := net .ParseMAC (vde .MACAddress )
230
+ if nw .MACAddress != "" {
231
+ hw , err := net .ParseMAC (nw .MACAddress )
222
232
if err != nil {
223
233
return fmt .Errorf ("field `vmnet.mac` invalid: %w" , err )
224
234
}
225
235
if len (hw ) != 6 {
226
- return fmt .Errorf ("field `%s.macAddress` must be a 48 bit (6 bytes) MAC address; actual length of %q is %d bytes" , field , vde .MACAddress , len (hw ))
236
+ return fmt .Errorf ("field `%s.macAddress` must be a 48 bit (6 bytes) MAC address; actual length of %q is %d bytes" , field , nw .MACAddress , len (hw ))
227
237
}
228
238
}
229
- // FillDefault() will make sure that vde.Name is not the empty string
230
- if len (vde . Name ) >= 16 {
231
- return fmt .Errorf ("field `%s.name ` must be less than 16 bytes, but is %d bytes: %q" , field , len (vde . Name ), vde . Name )
239
+ // FillDefault() will make sure that nw.Interface is not the empty string
240
+ if len (nw . Interface ) >= 16 {
241
+ return fmt .Errorf ("field `%s.interface ` must be less than 16 bytes, but is %d bytes: %q" , field , len (nw . Interface ), nw . Interface )
232
242
}
233
- if strings .ContainsAny (vde . Name , " \t \n /" ) {
234
- return fmt .Errorf ("field `%s.name ` must not contain whitespace or slashes" , field )
243
+ if strings .ContainsAny (nw . Interface , " \t \n /" ) {
244
+ return fmt .Errorf ("field `%s.interface ` must not contain whitespace or slashes" , field )
235
245
}
236
- if vde . Name == qemuconst .SlirpNICName {
237
- return fmt .Errorf ("field `%s.name ` must not be set to %q because it is reserved for slirp" , field , qemuconst .SlirpNICName )
246
+ if nw . Interface == qemuconst .SlirpNICName {
247
+ return fmt .Errorf ("field `%s.interface ` must not be set to %q because it is reserved for slirp" , field , qemuconst .SlirpNICName )
238
248
}
239
- if prev , ok := networkName [ vde . Name ]; ok {
240
- return fmt .Errorf ("field `%s.name ` value %q has already been used by field `network.vde[%d].name`" , field , vde . Name , prev )
249
+ if prev , ok := interfaceName [ nw . Interface ]; ok {
250
+ return fmt .Errorf ("field `%s.interface ` value %q has already been used by field `network.vde[%d].name`" , field , nw . Interface , prev )
241
251
}
242
- networkName [ vde . Name ] = i
252
+ interfaceName [ nw . Interface ] = i
243
253
}
244
254
return nil
245
255
}
0 commit comments