Skip to content
This repository has been archived by the owner on Apr 20, 2024. It is now read-only.

Commit

Permalink
Refactor network device handling
Browse files Browse the repository at this point in the history
This refactors network device handling to guarantee that the host and
guest sides of a network device are assigned different MAC addresses.
This required replacing the --backend parameter to the command line
with a set of parameters. The information involved is too complex to
specify with a single command-line parameter.

This also updates the schema to enforce unique MAC addresses within
a virtual machine.

Fix: #36
  • Loading branch information
io7m committed Aug 1, 2020
1 parent ff63faa commit fd2e708
Show file tree
Hide file tree
Showing 72 changed files with 1,440 additions and 940 deletions.
Expand Up @@ -305,7 +305,7 @@ private static String configureBhyveNetworkVMNet(
return String.format(
"%s,mac=%s",
backend.name().value(),
backend.address().value()
backend.guestMAC().value()
);
}

Expand All @@ -315,7 +315,7 @@ private static String configureBhyveNetworkTAP(
return String.format(
"%s,mac=%s",
backend.name().value(),
backend.address().value()
backend.guestMAC().value()
);
}

Expand Down Expand Up @@ -434,7 +434,7 @@ private void networkDeviceBackendCommands(
.setExecutable(ifconfig)
.addArguments(tapName)
.addArguments("ether")
.addArguments(tap.address().value())
.addArguments(tap.hostMAC().value())
.build()
);

Expand Down Expand Up @@ -468,7 +468,7 @@ private void networkDeviceBackendCommands(
.setExecutable(ifconfig)
.addArguments(vmNetName)
.addArguments("ether")
.addArguments(vmNet.address().value())
.addArguments(vmNet.hostMAC().value())
.build()
);

Expand Down
Expand Up @@ -23,6 +23,7 @@
import com.io7m.waxmill.client.api.WXMClientType;
import com.io7m.waxmill.database.api.WXMVirtualMachineDatabaseType;
import com.io7m.waxmill.exceptions.WXMException;
import com.io7m.waxmill.exceptions.WXMExceptionNonexistent;
import com.io7m.waxmill.machines.WXMBootConfigurationName;
import com.io7m.waxmill.machines.WXMConsoles;
import com.io7m.waxmill.machines.WXMDeviceLPC;
Expand Down Expand Up @@ -92,7 +93,7 @@ public WXMVirtualMachine vmFind(
Objects.requireNonNull(id, "id");

return this.database.vmGet(id)
.orElseThrow(() -> new WXMException(
.orElseThrow(() -> new WXMExceptionNonexistent(
String.format("No such virtual machine: %s", id))
);
}
Expand Down
10 changes: 10 additions & 0 deletions com.io7m.waxmill.cmdline/pom.xml
Expand Up @@ -115,6 +115,16 @@
<artifactId>org.osgi.annotation.versioning</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.io7m.immutables.style</groupId>
<artifactId>com.io7m.immutables.style</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -52,6 +52,7 @@
import java.net.URI;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.SortedMap;
import java.util.stream.Stream;

Expand Down Expand Up @@ -169,4 +170,13 @@ public String toString()
Long.toUnsignedString(System.identityHashCode(this), 16)
);
}

/**
* @return The exception that caused the exit
*/

public Optional<Exception> exitCause()
{
return this.claypot.exitCause();
}
}
Expand Up @@ -48,7 +48,10 @@ public static void main(

final int exitCode = cm.exitCode();
if (exitCode != 0) {
throw new IOException("Returned exit code " + exitCode);
throw new IOException(
String.format("Returned exit code %d", Integer.valueOf(exitCode)),
cm.exitCause().orElse(null)
);
}
}

Expand Down
Expand Up @@ -21,6 +21,8 @@
import com.io7m.claypot.core.CLPCommandContextType;
import com.io7m.waxmill.machines.WXMDeviceE1000;
import com.io7m.waxmill.machines.WXMDeviceSlot;
import com.io7m.waxmill.machines.WXMInterfaceGroupName;
import com.io7m.waxmill.machines.WXMMACAddress;
import com.io7m.waxmill.machines.WXMMachineMessages;
import com.io7m.waxmill.machines.WXMNetworkDeviceBackendType;
import com.io7m.waxmill.machines.WXMTap;
Expand All @@ -30,6 +32,7 @@
import org.slf4j.LoggerFactory;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

Expand All @@ -52,8 +55,7 @@ public final class WXMCommandVMAddE1000NetworkDevice

@Parameter(
names = "--comment",
description = "A comment describing the new device",
required = false
description = "A comment describing the new device"
)
private String comment = "";

Expand All @@ -65,22 +67,50 @@ public final class WXMCommandVMAddE1000NetworkDevice
)
private WXMDeviceSlot deviceSlot;

@Parameter(
names = "--backend",
description = "A specification of the network device backend to add",
required = true,
converter = WXMNetworkBackendConverter.class
)
private WXMNetworkDeviceBackendType backend;

@Parameter(
names = "--replace",
description = "Replace an existing device, if one exists",
required = false,
arity = 1
)
private boolean replace;

@Parameter(
names = "--type",
description = "The type of network backend",
required = true,
converter = WXMNetworkDeviceKindConverter.class
)
private WXMNetworkDeviceBackendType.Kind type;

@Parameter(
names = "--host-mac",
description = "The MAC address on the host device",
required = true,
converter = WXMMACAddressConverter.class
)
private WXMMACAddress hostMAC;

@Parameter(
names = "--guest-mac",
description = "The MAC address on the guest device",
required = true,
converter = WXMMACAddressConverter.class
)
private WXMMACAddress guestMAC;

@Parameter(
names = "--name",
description = "The name of the device"
)
private String deviceName;

@Parameter(
names = "--interface-group",
description = "The group to which the device will belong on the host",
converter = WXMInterfaceGroupNameConverter.class
)
private List<WXMInterfaceGroupName> groups = new ArrayList<>();

/**
* Construct a command.
*
Expand All @@ -102,11 +132,7 @@ public String name()
@Override
public String extendedHelp()
{
final var messages = this.messages();
return String.join("", List.of(
messages.format("vmAddE1000NetworkDeviceHelp"),
messages.format("networkBackendSpec")
));
return this.messages().format("vmAddE1000NetworkDeviceHelp");
}

@Override
Expand All @@ -117,10 +143,21 @@ protected Status executeActualWithConfiguration(
try (var client = WXMServices.clients().open(configurationPath)) {
final var machine = client.vmFind(this.id);

final var backend =
new WXMNetworkBackendArguments()
.parse(
WXMNamedParameter.of("--type", this.type),
WXMNamedParameter.of("--comment", this.comment),
WXMNamedParameters.optional("--name", this.deviceName),
WXMNamedParameters.optional("--host-mac", this.hostMAC),
WXMNamedParameters.optional("--guest-mac", this.guestMAC),
WXMNamedParameter.of("--interface-group", this.groups)
);

final var virtio =
WXMDeviceE1000.builder()
.setDeviceSlot(this.deviceSlot)
.setBackend(this.backend)
.setBackend(backend)
.setComment(this.comment)
.build();

Expand All @@ -135,21 +172,23 @@ protected Status executeActualWithConfiguration(
client.vmUpdate(updatedMachine);

this.info("infoAddedE1000Net", this.deviceSlot);
switch (this.backend.kind()) {
switch (this.type) {
case WXM_TAP:
final var tap = (WXMTap) this.backend;
final var tap = (WXMTap) backend;
this.info(
"infoBackendTAP",
tap.name().value(),
tap.address().value()
tap.hostMAC().value(),
tap.guestMAC().value()
);
break;
case WXM_VMNET:
final var vmnet = (WXMVMNet) this.backend;
final var vmnet = (WXMVMNet) backend;
this.info(
"infoBackendVMNet",
vmnet.name().value(),
vmnet.address().value()
vmnet.hostMAC().value(),
vmnet.guestMAC().value()
);
break;
}
Expand Down
Expand Up @@ -21,6 +21,8 @@
import com.io7m.claypot.core.CLPCommandContextType;
import com.io7m.waxmill.machines.WXMDeviceSlot;
import com.io7m.waxmill.machines.WXMDeviceVirtioNetwork;
import com.io7m.waxmill.machines.WXMInterfaceGroupName;
import com.io7m.waxmill.machines.WXMMACAddress;
import com.io7m.waxmill.machines.WXMMachineMessages;
import com.io7m.waxmill.machines.WXMNetworkDeviceBackendType;
import com.io7m.waxmill.machines.WXMTap;
Expand All @@ -30,6 +32,7 @@
import org.slf4j.LoggerFactory;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

Expand Down Expand Up @@ -65,14 +68,6 @@ public final class WXMCommandVMAddVirtioNetworkDevice
)
private WXMDeviceSlot deviceSlot;

@Parameter(
names = "--backend",
description = "A specification of the Virtio network device backend to add",
required = true,
converter = WXMNetworkBackendConverter.class
)
private WXMNetworkDeviceBackendType backend;

@Parameter(
names = "--replace",
description = "Replace an existing device, if one exists",
Expand All @@ -81,6 +76,43 @@ public final class WXMCommandVMAddVirtioNetworkDevice
)
private boolean replace;

@Parameter(
names = "--type",
description = "The type of network backend",
required = true,
converter = WXMNetworkDeviceKindConverter.class
)
private WXMNetworkDeviceBackendType.Kind type;

@Parameter(
names = "--host-mac",
description = "The MAC address on the host device",
required = true,
converter = WXMMACAddressConverter.class
)
private WXMMACAddress hostMAC;

@Parameter(
names = "--guest-mac",
description = "The MAC address on the guest device",
required = true,
converter = WXMMACAddressConverter.class
)
private WXMMACAddress guestMAC;

@Parameter(
names = "--name",
description = "The name of the device"
)
private String deviceName;

@Parameter(
names = "--interface-group",
description = "The group to which the device will belong on the host",
converter = WXMInterfaceGroupNameConverter.class
)
private List<WXMInterfaceGroupName> groups = new ArrayList<>();

/**
* Construct a command.
*
Expand All @@ -102,11 +134,7 @@ public String name()
@Override
public String extendedHelp()
{
final var messages = this.messages();
return String.join("", List.of(
messages.format("vmAddVirtioNetworkDeviceHelp"),
messages.format("networkBackendSpec")
));
return this.messages().format("vmAddVirtioNetworkDeviceHelp");
}

@Override
Expand All @@ -117,10 +145,21 @@ protected Status executeActualWithConfiguration(
try (var client = WXMServices.clients().open(configurationPath)) {
final var machine = client.vmFind(this.id);

final var backend =
new WXMNetworkBackendArguments()
.parse(
WXMNamedParameter.of("--type", this.type),
WXMNamedParameter.of("--comment", this.comment),
WXMNamedParameters.optional("--name", this.deviceName),
WXMNamedParameters.optional("--host-mac", this.hostMAC),
WXMNamedParameters.optional("--guest-mac", this.guestMAC),
WXMNamedParameter.of("--interface-group", this.groups)
);

final var virtio =
WXMDeviceVirtioNetwork.builder()
.setDeviceSlot(this.deviceSlot)
.setBackend(this.backend)
.setBackend(backend)
.setComment(this.comment)
.build();

Expand All @@ -135,21 +174,23 @@ protected Status executeActualWithConfiguration(
client.vmUpdate(updatedMachine);

this.info("infoAddedVirtioNet", this.deviceSlot);
switch (this.backend.kind()) {
switch (this.type) {
case WXM_TAP:
final var tap = (WXMTap) this.backend;
final var tap = (WXMTap) backend;
this.info(
"infoBackendTAP",
tap.name().value(),
tap.address().value()
tap.hostMAC().value(),
tap.guestMAC().value()
);
break;
case WXM_VMNET:
final var vmnet = (WXMVMNet) this.backend;
final var vmnet = (WXMVMNet) backend;
this.info(
"infoBackendVMNet",
vmnet.name().value(),
vmnet.address().value()
vmnet.hostMAC().value(),
vmnet.guestMAC().value()
);
break;
}
Expand Down

0 comments on commit fd2e708

Please sign in to comment.