aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src
diff options
context:
space:
mode:
Diffstat (limited to 'node-repository/src')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java106
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java2
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java29
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java1
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java10
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java11
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java17
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java14
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java15
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/WireguardResponse.java19
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java9
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java102
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java53
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java36
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/AwsNodeTypes.java73
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/VespaFlavor.java18
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java5
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/wireguard.json6
25 files changed, 355 insertions, 199 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
index 24159b88a9b..d5e891a33c7 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java
@@ -10,7 +10,7 @@ import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
-import com.yahoo.config.provision.WireguardKey;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.hosted.provision.lb.LoadBalancers;
import com.yahoo.vespa.hosted.provision.node.Agent;
@@ -64,8 +64,7 @@ public final class Node implements Nodelike {
private final CloudAccount cloudAccount;
/** Only set for configservers and exclave nodes */
- private final Optional<WireguardKey> wireguardPubKey;
- private final Optional<Instant> wireguardKeyTimestamp;
+ private final Optional<WireguardKeyWithTimestamp> wireguardPubKey;
/** Record of the last event of each type happening to this node */
private final History history;
@@ -96,8 +95,8 @@ public final class Node implements Nodelike {
NodeType type, Reports reports, Optional<String> modelName, Optional<TenantName> reservedTo,
Optional<ApplicationId> exclusiveToApplicationId, Optional<Duration> hostTTL, Optional<Instant> hostEmptyAt,
Optional<ClusterSpec.Type> exclusiveToClusterType, Optional<String> switchHostname,
- List<TrustStoreItem> trustStoreItems, CloudAccount cloudAccount, Optional<WireguardKey> wireguardPubKey,
- Optional<Instant> wireguardKeyTimestamp) {
+ List<TrustStoreItem> trustStoreItems, CloudAccount cloudAccount,
+ Optional<WireguardKeyWithTimestamp> wireguardPubKey) {
this.id = Objects.requireNonNull(id, "A node must have an ID");
this.extraId = Objects.requireNonNull(extraId, "Extra ID cannot be null");
this.hostname = requireNonEmptyString(hostname, "A node must have a hostname");
@@ -120,7 +119,6 @@ public final class Node implements Nodelike {
this.trustStoreItems = Objects.requireNonNull(trustStoreItems).stream().distinct().toList();
this.cloudAccount = Objects.requireNonNull(cloudAccount);
this.wireguardPubKey = Objects.requireNonNull(wireguardPubKey);
- this.wireguardKeyTimestamp = Objects.requireNonNull(wireguardKeyTimestamp);
if (state == State.active)
requireNonEmpty(ipConfig.primary(), "Active node " + hostname + " must have at least one valid IP address");
@@ -264,15 +262,10 @@ public final class Node implements Nodelike {
}
/** Returns the wireguard public key of this node. Only relevant for enclave nodes. */
- public Optional<WireguardKey> wireguardPubKey() {
+ public Optional<WireguardKeyWithTimestamp> wireguardPubKey() {
return wireguardPubKey;
}
- /** Returns the timestamp of the wireguard key of this node. Only relevant for enclave nodes. */
- public Optional<Instant> wireguardKeyTimestamp() {
- return wireguardKeyTimestamp;
- }
-
/**
* Returns a copy of this where wantToFail is set to true and history is updated to reflect this.
*/
@@ -367,16 +360,14 @@ public final class Node implements Nodelike {
public Node with(Status status) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a node with the type assigned to the given value */
public Node with(NodeType type) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history, type,
reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a node with the flavor assigned to the given value */
@@ -385,40 +376,35 @@ public final class Node implements Nodelike {
History updateHistory = history.with(new History.Event(History.Event.Type.resized, agent, instant));
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, updateHistory, type,
reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this with the reboot generation set to generation */
public Node withReboot(Generation generation) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status.withReboot(generation), state, allocation,
history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this with given id set */
public Node withId(String id) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation,
history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this with model name set to given value */
public Node withModelName(String modelName) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, Optional.of(modelName), reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this with model name cleared */
public Node withoutModelName() {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, Optional.empty(), reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this with a history record saying it was detected to be down at this instant */
@@ -460,24 +446,21 @@ public final class Node implements Nodelike {
public Node with(Allocation allocation) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, Optional.of(allocation), history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this node with IP config set to the given value. */
public Node with(IP.Config ipConfig) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this node with the parent hostname assigned to the given value. */
public Node withParentHostname(String parentHostname) {
return new Node(id, extraId, ipConfig, hostname, Optional.of(parentHostname), flavor, status, state, allocation,
history, type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withReservedTo(TenantName tenant) {
@@ -485,73 +468,59 @@ public final class Node implements Nodelike {
throw new IllegalArgumentException("Only host nodes can be reserved, " + hostname + " has type " + type);
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, Optional.of(tenant), exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
/** Returns a copy of this node which is not reserved to a tenant */
public Node withoutReservedTo() {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, Optional.empty(), exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withExclusiveToApplicationId(ApplicationId exclusiveTo) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, Optional.ofNullable(exclusiveTo), hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withExtraId(Optional<String> extraId) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withHostTTL(Duration hostTTL) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, Optional.ofNullable(hostTTL), hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withHostEmptyAt(Instant hostEmptyAt) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, Optional.ofNullable(hostEmptyAt),
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node withExclusiveToClusterType(ClusterSpec.Type exclusiveTo) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- Optional.ofNullable(exclusiveTo), switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ Optional.ofNullable(exclusiveTo), switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
- public Node withWireguardPubkey(WireguardKey wireguardPubkey) {
+ public Node withWireguardPubkey(WireguardKeyWithTimestamp wireguardPubkey) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, Optional.ofNullable(wireguardPubkey),
- wireguardKeyTimestamp);
- }
-
- public Node withWireguardKeyTimestamp(Instant wireguardKeyTimestamp) {
- return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
- type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- Optional.ofNullable(wireguardKeyTimestamp));
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount,
+ Optional.ofNullable(wireguardPubkey));
}
/** Returns a copy of this node with switch hostname set to given value */
public Node withSwitchHostname(String switchHostname) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, Optional.ofNullable(switchHostname), trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, Optional.ofNullable(switchHostname), trustStoreItems, cloudAccount,
+ wireguardPubKey);
}
/** Returns a copy of this node with switch hostname unset */
@@ -604,22 +573,19 @@ public final class Node implements Nodelike {
public Node with(History history) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node with(Reports reports) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
public Node with(List<TrustStoreItem> trustStoreItems) {
return new Node(id, extraId, ipConfig, hostname, parentHostname, flavor, status, state, allocation, history,
type, reports, modelName, reservedTo, exclusiveToApplicationId, hostTTL, hostEmptyAt,
- exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey,
- wireguardKeyTimestamp);
+ exclusiveToClusterType, switchHostname, trustStoreItems, cloudAccount, wireguardPubKey);
}
private static Optional<String> requireNonEmptyString(Optional<String> value, String message) {
@@ -767,8 +733,7 @@ public final class Node implements Nodelike {
private History history;
private List<TrustStoreItem> trustStoreItems;
private CloudAccount cloudAccount = CloudAccount.empty;
- private WireguardKey wireguardPubKey;
- private Instant wireguardKeyTimestamp;
+ private WireguardKeyWithTimestamp wireguardPubKey;
private Builder(String id, String hostname, Flavor flavor, State state, NodeType type) {
this.id = id;
@@ -858,16 +823,11 @@ public final class Node implements Nodelike {
return this;
}
- public Builder wireguardPubKey(WireguardKey wireguardPubKey) {
+ public Builder wireguardKey(WireguardKeyWithTimestamp wireguardPubKey) {
this.wireguardPubKey = wireguardPubKey;
return this;
}
- public Builder wireguardKeyTimestamp(Instant wireguardKeyTimestamp) {
- this.wireguardKeyTimestamp = wireguardKeyTimestamp;
- return this;
- }
-
public Node build() {
return new Node(id, Optional.empty(), Optional.ofNullable(ipConfig).orElse(IP.Config.EMPTY), hostname, Optional.ofNullable(parentHostname),
flavor, Optional.ofNullable(status).orElseGet(Status::initial), state, Optional.ofNullable(allocation),
@@ -875,7 +835,7 @@ public final class Node implements Nodelike {
Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveToApplicationId),
Optional.ofNullable(hostTTL), Optional.ofNullable(hostEmptyAt), Optional.ofNullable(exclusiveToClusterType),
Optional.ofNullable(switchHostname), Optional.ofNullable(trustStoreItems).orElseGet(List::of), cloudAccount,
- Optional.ofNullable(wireguardPubKey), Optional.ofNullable(wireguardKeyTimestamp));
+ Optional.ofNullable(wireguardPubKey));
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
index 8069c9c089b..286ec2451f8 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableResources.java
@@ -160,7 +160,7 @@ public class AllocatableResources {
for (Node node : nodes) {
sum = sum.add(nodeRepository.resourcesCalculator().realResourcesOf(node, nodeRepository).justNumbers());
}
- return nodes.get(0).allocation().get().requestedResources().justNonNumbers()
+ return nodes.get(0).allocation().get().requestedResources()
.withVcpu(sum.vcpu() / nodes.size())
.withMemoryGb(sum.memoryGb() / nodes.size())
.withDiskGb(sum.diskGb() / nodes.size())
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
index e228d31384c..f42d1ce9bd3 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerInstance.java
@@ -21,7 +21,8 @@ import java.util.Set;
public class LoadBalancerInstance {
private final Optional<DomainName> hostname;
- private final Optional<String> ipAddress;
+ private final Optional<String> ip4Address;
+ private final Optional<String> ip6Address;
private final Optional<DnsZone> dnsZone;
private final Set<Integer> ports;
private final Set<String> networks;
@@ -30,11 +31,12 @@ public class LoadBalancerInstance {
private final List<PrivateServiceId> serviceIds;
private final CloudAccount cloudAccount;
- public LoadBalancerInstance(Optional<DomainName> hostname, Optional<String> ipAddress,
+ public LoadBalancerInstance(Optional<DomainName> hostname, Optional<String> ip4Address, Optional<String> ip6Address,
Optional<DnsZone> dnsZone, Set<Integer> ports, Set<String> networks, Set<Real> reals,
ZoneEndpoint settings, List<PrivateServiceId> serviceIds, CloudAccount cloudAccount) {
this.hostname = Objects.requireNonNull(hostname, "hostname must be non-null");
- this.ipAddress = Objects.requireNonNull(ipAddress, "ip must be non-null");
+ this.ip4Address = Objects.requireNonNull(ip4Address, "ip4Address must be non-null");
+ this.ip6Address = Objects.requireNonNull(ip6Address, "ip6Address must be non-null");
this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null");
this.ports = ImmutableSortedSet.copyOf(requirePorts(ports));
this.networks = ImmutableSortedSet.copyOf(Objects.requireNonNull(networks, "networks must be non-null"));
@@ -43,9 +45,9 @@ public class LoadBalancerInstance {
this.serviceIds = List.copyOf(Objects.requireNonNull(serviceIds, "private service id must be non-null"));
this.cloudAccount = Objects.requireNonNull(cloudAccount, "cloudAccount must be non-null");
- if (hostname.isEmpty() == ipAddress.isEmpty()) {
- throw new IllegalArgumentException("Exactly 1 of hostname=%s and ipAddress=%s must be set".formatted(
- hostname.map(DomainName::value).orElse("<empty>"), ipAddress.orElse("<empty>")));
+ if (hostname.isEmpty() == ip4Address.isEmpty()) {
+ throw new IllegalArgumentException("Exactly 1 of hostname=%s and ip4Address=%s must be set".formatted(
+ hostname.map(DomainName::value).orElse("<empty>"), ip4Address.orElse("<empty>")));
}
}
@@ -54,9 +56,14 @@ public class LoadBalancerInstance {
return hostname;
}
- /** IP address of this (public) load balancer */
- public Optional<String> ipAddress() {
- return ipAddress;
+ /** IPv4 address of this (public) load balancer */
+ public Optional<String> ip4Address() {
+ return ip4Address;
+ }
+
+ /** IPv6 address of this (public) load balancer */
+ public Optional<String> ip6Address() {
+ return ip6Address;
}
/** ID of the DNS zone associated with this */
@@ -114,7 +121,7 @@ public class LoadBalancerInstance {
public LoadBalancerInstance with(Set<Real> reals, ZoneEndpoint settings, Optional<PrivateServiceId> serviceId) {
List<PrivateServiceId> ids = new ArrayList<>(serviceIds);
serviceId.filter(id -> ! ids.contains(id)).ifPresent(ids::add);
- return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks,
+ return new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks,
reals, settings, ids,
cloudAccount);
}
@@ -123,7 +130,7 @@ public class LoadBalancerInstance {
public LoadBalancerInstance withServiceIds(List<PrivateServiceId> serviceIds) {
List<PrivateServiceId> ids = new ArrayList<>(serviceIds);
for (PrivateServiceId id : this.serviceIds) if ( ! ids.contains(id)) ids.add(id);
- return new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, ids, cloudAccount);
+ return new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks, reals, settings, ids, cloudAccount);
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
index a79766a577d..c79ccc2aece 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/LoadBalancerServiceMock.java
@@ -57,6 +57,7 @@ public class LoadBalancerServiceMock implements LoadBalancerService {
var instance = new LoadBalancerInstance(
Optional.of(DomainName.of("lb-" + spec.application().toShortString() + "-" + spec.cluster().value())),
Optional.empty(),
+ Optional.empty(),
Optional.of(new DnsZone("zone-id-1")),
Collections.singleton(4443),
ImmutableSet.of("10.2.3.0/24", "10.4.5.0/24"),
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
index e49d1b302cf..073662b39fe 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/lb/SharedLoadBalancerService.java
@@ -45,6 +45,7 @@ public class SharedLoadBalancerService implements LoadBalancerService {
return new LoadBalancerInstance(Optional.of(DomainName.of(vipHostname)),
Optional.empty(),
Optional.empty(),
+ Optional.empty(),
Set.of(4443),
Set.of(),
spec.reals(),
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
index 3c3868bfeb8..e4e08e5a15c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/CuratorDb.java
@@ -47,6 +47,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
import static com.yahoo.stream.CustomCollectors.toLinkedMap;
import static java.util.stream.Collectors.collectingAndThen;
@@ -222,7 +223,7 @@ public class CuratorDb {
node.type(), node.reports(), node.modelName(), node.reservedTo(),
node.exclusiveToApplicationId(), node.hostTTL(), node.hostEmptyAt(),
node.exclusiveToClusterType(), node.switchHostname(), node.trustedCertificates(),
- node.cloudAccount(), node.wireguardPubKey(), node.wireguardKeyTimestamp());
+ node.cloudAccount(), node.wireguardPubKey());
curatorTransaction.add(createOrSet(nodePath(newNode), nodeSerializer.toJson(newNode)));
writtenNodes.add(newNode);
}
@@ -456,7 +457,12 @@ public class CuratorDb {
transaction.onCommitted(() -> {
for (var lb : loadBalancers) {
if (lb.state() == fromState) continue;
- Optional<String> target = lb.instance().flatMap(instance -> instance.hostname().map(DomainName::value).or(instance::ipAddress));
+ Optional<String> target = lb.instance()
+ .flatMap(instance -> instance.hostname()
+ .map(DomainName::value)
+ .or(() -> Optional.of(Stream.concat(instance.ip4Address().stream(),
+ instance.ip6Address().stream())
+ .collect(Collectors.joining(",")))));
if (fromState == null) {
log.log(Level.INFO, () -> "Creating " + lb.id() + target.map(t -> " (" + t + ")").orElse("") +
" in " + lb.state());
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
index b85d96c6b54..d329676f842 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializer.java
@@ -45,6 +45,7 @@ public class LoadBalancerSerializer {
private static final String idField = "id";
private static final String hostnameField = "hostname";
private static final String lbIpAddressField = "ipAddress";
+ private static final String lbIp6AddressField = "ip6Address";
private static final String stateField = "state";
private static final String changedAtField = "changedAt";
private static final String dnsZoneField = "dnsZone";
@@ -69,7 +70,8 @@ public class LoadBalancerSerializer {
root.setString(idField, loadBalancer.id().serializedForm());
loadBalancer.instance().flatMap(LoadBalancerInstance::hostname).ifPresent(hostname -> root.setString(hostnameField, hostname.value()));
- loadBalancer.instance().flatMap(LoadBalancerInstance::ipAddress).ifPresent(ip -> root.setString(lbIpAddressField, ip));
+ loadBalancer.instance().flatMap(LoadBalancerInstance::ip4Address).ifPresent(ip -> root.setString(lbIpAddressField, ip));
+ loadBalancer.instance().flatMap(LoadBalancerInstance::ip6Address).ifPresent(ip -> root.setString(lbIp6AddressField, ip));
root.setString(stateField, asString(loadBalancer.state()));
root.setLong(changedAtField, loadBalancer.changedAt().toEpochMilli());
loadBalancer.instance().flatMap(LoadBalancerInstance::dnsZone).ifPresent(dnsZone -> root.setString(dnsZoneField, dnsZone.id()));
@@ -123,7 +125,8 @@ public class LoadBalancerSerializer {
object.field(networksField).traverse((ArrayTraverser) (i, network) -> networks.add(network.asString()));
Optional<DomainName> hostname = optionalString(object.field(hostnameField), Function.identity()).filter(s -> !s.isEmpty()).map(DomainName::of);
- Optional<String> ipAddress = optionalString(object.field(lbIpAddressField), Function.identity()).filter(s -> !s.isEmpty());
+ Optional<String> ip4Address = optionalString(object.field(lbIpAddressField), Function.identity()).filter(s -> !s.isEmpty());
+ Optional<String> ip6Address = optionalString(object.field(lbIp6AddressField), Function.identity()).filter(s -> !s.isEmpty());
Optional<DnsZone> dnsZone = optionalString(object.field(dnsZoneField), DnsZone::new);
ZoneEndpoint settings = zoneEndpoint(object.field(settingsField));
Optional<PrivateServiceId> serviceId = optionalString(object.field(serviceIdField), PrivateServiceId::of);
@@ -131,9 +134,9 @@ public class LoadBalancerSerializer {
object.field(serviceIdsField).traverse((ArrayTraverser) (__, serviceIdObject) -> serviceIds.add(PrivateServiceId.of(serviceIdObject.asString())));
if (serviceIds.isEmpty()) serviceId.ifPresent(serviceIds::add); // TODO: remove after winter vacation '23
CloudAccount cloudAccount = optionalString(object.field(cloudAccountField), CloudAccount::from).orElse(CloudAccount.empty);
- Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ipAddress.isEmpty()
+ Optional<LoadBalancerInstance> instance = hostname.isEmpty() && ip4Address.isEmpty() && ip6Address.isEmpty()
? Optional.empty()
- : Optional.of(new LoadBalancerInstance(hostname, ipAddress, dnsZone, ports, networks, reals, settings, serviceIds, cloudAccount));
+ : Optional.of(new LoadBalancerInstance(hostname, ip4Address, ip6Address, dnsZone, ports, networks, reals, settings, serviceIds, cloudAccount));
return new LoadBalancer(LoadBalancerId.fromSerializedForm(object.field(idField).asString()),
instance,
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
index 870e678a250..73531d650d5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/persistence/NodeSerializer.java
@@ -16,6 +16,7 @@ import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.WireguardKey;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.config.provision.host.FlavorOverrides;
import com.yahoo.config.provision.serialization.NetworkPortsSerializer;
import com.yahoo.slime.ArrayTraverser;
@@ -188,8 +189,10 @@ public class NodeSerializer {
if (!node.cloudAccount().isUnspecified()) {
object.setString(cloudAccountKey, node.cloudAccount().value());
}
- node.wireguardPubKey().ifPresent(pubKey -> object.setString(wireguardPubKeyKey, pubKey.value()));
- node.wireguardKeyTimestamp().ifPresent(timestamp -> object.setLong(wireguardKeyTimestampKey, timestamp.toEpochMilli()));
+ node.wireguardPubKey().ifPresent(pubKey -> {
+ object.setString(wireguardPubKeyKey, pubKey.key().value());
+ object.setLong(wireguardKeyTimestampKey, pubKey.timestamp().toEpochMilli());
+ });
}
private void toSlime(Flavor flavor, Cursor object) {
@@ -284,8 +287,7 @@ public class NodeSerializer {
SlimeUtils.optionalString(object.field(switchHostnameKey)),
trustedCertificatesFromSlime(object),
SlimeUtils.optionalString(object.field(cloudAccountKey)).map(CloudAccount::from).orElse(CloudAccount.empty),
- SlimeUtils.optionalString(object.field(wireguardPubKeyKey)).map(WireguardKey::from),
- SlimeUtils.optionalInstant(object.field(wireguardKeyTimestampKey)));
+ wireguardKeyWithTimestampFromSlime(object.field(wireguardPubKeyKey), object.field(wireguardKeyTimestampKey)));
}
private Status statusFromSlime(Inspector object) {
@@ -397,6 +399,13 @@ public class NodeSerializer {
.toList();
}
+ private Optional<WireguardKeyWithTimestamp> wireguardKeyWithTimestampFromSlime(Inspector keyObject, Inspector timestampObject) {
+ if ( ! keyObject.valid()) return Optional.empty();
+ return SlimeUtils.optionalString(keyObject).map(
+ key -> new WireguardKeyWithTimestamp(WireguardKey.from(key),
+ SlimeUtils.optionalInstant(timestampObject).orElse(null)));
+ }
+
// ----------------- Enum <-> string mappings ----------------------------------------
/** Returns the event type, or null if this event type should be ignored */
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
index 09f947503f6..20aa7d8181e 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/LoadBalancersResponse.java
@@ -57,7 +57,8 @@ public class LoadBalancersResponse extends SlimeJsonResponse {
lbObject.setString("instance", lb.id().application().instance().value());
lbObject.setString("cluster", lb.id().cluster().value());
lb.instance().flatMap(LoadBalancerInstance::hostname).ifPresent(hostname -> lbObject.setString("hostname", hostname.value()));
- lb.instance().flatMap(LoadBalancerInstance::ipAddress).ifPresent(ipAddress -> lbObject.setString("ipAddress", ipAddress));
+ lb.instance().flatMap(LoadBalancerInstance::ip4Address).ifPresent(ip -> lbObject.setString("ipAddress", ip));
+ lb.instance().flatMap(LoadBalancerInstance::ip6Address).ifPresent(ip -> lbObject.setString("ip6Address", ip));
lb.instance().flatMap(LoadBalancerInstance::dnsZone).ifPresent(dnsZone -> lbObject.setString("dnsZone", dnsZone.id()));
Cursor networkArray = lbObject.setArray("networks");
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
index 9f1ab3dc3d5..cad034e01aa 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodePatcher.java
@@ -11,6 +11,7 @@ import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.WireguardKey;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.slime.Cursor;
import com.yahoo.slime.Inspector;
import com.yahoo.slime.ObjectTraverser;
@@ -108,7 +109,8 @@ public class NodePatcher {
"reports",
"trustStore",
"vespaVersion",
- "wireguardPubkey"));
+ "wireguardPubkey", // TODO wg: remove when all nodes use new key+timestamp format
+ "wireguard"));
if (!disallowedFields.isEmpty()) {
throw new IllegalArgumentException("Patching fields not supported: " + disallowedFields);
}
@@ -271,9 +273,13 @@ public class NodePatcher {
return value.type() == Type.NIX ? node.withoutSwitchHostname() : node.withSwitchHostname(value.asString());
case "trustStore":
return nodeWithTrustStore(node, value);
- case "wireguardPubkey":
- return node.withWireguardPubkey(SlimeUtils.optionalString(value).map(WireguardKey::new).orElse(null))
- .withWireguardKeyTimestamp(clock.instant());
+ case "wireguard":
+ // This is where we set the key timestamp.
+ var key = SlimeUtils.optionalString(value.field("key")).map(WireguardKey::new).orElse(null);
+ return node.withWireguardPubkey(new WireguardKeyWithTimestamp(key, clock.instant()));
+ case "wireguardPubkey": // TODO wg: remove when all nodes use new key+timestamp format
+ var oldKey = SlimeUtils.optionalString(value).map(WireguardKey::new).orElse(null);
+ return node.withWireguardPubkey(new WireguardKeyWithTimestamp(oldKey, clock.instant()));
default:
throw new IllegalArgumentException("Could not apply field '" + name + "' on a node: No such modifiable field");
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
index a8f526544d7..05bb0a27d69 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesResponse.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.ClusterMembership;
import com.yahoo.config.provision.DockerImage;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.NodeResources;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.config.provision.serialization.NetworkPortsSerializer;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.restapi.SlimeJsonResponse;
@@ -192,8 +193,13 @@ class NodesResponse extends SlimeJsonResponse {
if (!node.cloudAccount().isUnspecified()) {
object.setString("cloudAccount", node.cloudAccount().value());
}
- node.wireguardPubKey().ifPresent(key -> object.setString("wireguardPubkey", key.value()));
- node.wireguardKeyTimestamp().ifPresent(timestamp -> object.setLong("wireguardKeyTimestamp", timestamp.toEpochMilli()));
+ node.wireguardPubKey().ifPresent(key -> toSlime(key, object.setObject("wireguard")));
+
+ // TODO wg: remove when all nodes have upgraded to new key+timestamp format
+ node.wireguardPubKey().ifPresent(key -> {
+ object.setString("wireguardPubkey", key.key().value());
+ object.setLong("wireguardKeyTimestamp", key.timestamp().toEpochMilli());
+ });
}
private Version resolveVersionFlag(StringFlag flag, Node node, Allocation allocation) {
@@ -237,6 +243,11 @@ class NodesResponse extends SlimeJsonResponse {
}
}
+ static void toSlime(WireguardKeyWithTimestamp keyWithTimestamp, Cursor object) {
+ object.setString("key", keyWithTimestamp.key().value());
+ object.setLong("timestamp", keyWithTimestamp.timestamp().toEpochMilli());
+ }
+
private Optional<DockerImage> currentContainerImage(Node node) {
if (node.status().containerImage().isPresent()) {
return node.status().containerImage();
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/WireguardResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/WireguardResponse.java
index 16e85dfa48a..e29c4f1b87a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/WireguardResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/WireguardResponse.java
@@ -1,7 +1,7 @@
package com.yahoo.vespa.hosted.provision.restapi;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.WireguardKey;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.restapi.SlimeJsonResponse;
import com.yahoo.slime.Cursor;
import com.yahoo.vespa.hosted.provision.Node;
@@ -10,9 +10,9 @@ import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.IP;
import java.net.InetAddress;
-import java.time.Instant;
import java.util.List;
-import java.util.Optional;
+
+import static com.yahoo.vespa.hosted.provision.restapi.NodesResponse.toSlime;
/**
* A response containing the wireguard peer config for each configserver that has a public key.
@@ -36,17 +36,20 @@ public class WireguardResponse extends SlimeJsonResponse {
.toList();
if (ipAddresses.isEmpty()) continue;
- addConfigserver(cfgArray.addObject(), cfg.hostname(), cfg.wireguardPubKey().get(),
- cfg.wireguardKeyTimestamp(), ipAddresses);
+ addConfigserver(cfgArray.addObject(), cfg.hostname(), cfg.wireguardPubKey().get(), ipAddresses);
}
}
- private void addConfigserver(Cursor cfgEntry, String hostname, WireguardKey key, Optional<Instant> keyTimestamp,
+ private void addConfigserver(Cursor cfgEntry, String hostname, WireguardKeyWithTimestamp keyWithTimestamp,
List<String> ipAddresses) {
cfgEntry.setString("hostname", hostname);
- cfgEntry.setString("wireguardPubkey", key.value());
- cfgEntry.setLong("wireguardKeyTimestamp", keyTimestamp.orElse(Instant.EPOCH).toEpochMilli());
+
+ // TODO wg: remove when all nodes are using new key+timestamp format
+ cfgEntry.setString("wireguardPubkey", keyWithTimestamp.key().value());
+ cfgEntry.setLong("wireguardKeyTimestamp", keyWithTimestamp.timestamp().toEpochMilli());
+
NodesResponse.ipAddressesToSlime(ipAddresses, cfgEntry.setArray("ipAddresses"));
+ toSlime(keyWithTimestamp, cfgEntry.setObject("wireguard"));
}
private static boolean isPublicIp(String ipAddress) {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
index 5cdb08d6fc6..a72c2fb0b9c 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockHostProvisioner.java
@@ -79,7 +79,7 @@ public class MockHostProvisioner implements HostProvisioner {
if (hostFlavor == null)
hostFlavor = flavors.stream()
.filter(f -> request.sharing() == HostSharing.exclusive ? compatible(f, request.resources())
- : f.resources().satisfies(request.resources()))
+ : satisfies(f, request.resources()))
.filter(f -> realHostResourcesWithinLimits.test(f.resources()))
.findFirst()
.orElseThrow(() -> new NodeAllocationException("No host flavor matches " + request.resources(), true));
@@ -223,6 +223,10 @@ public class MockHostProvisioner implements HostProvisioner {
return flavor.resources().compatibleWith(resourcesToVerify);
}
+ public boolean satisfies(Flavor flavor, NodeResources resources) {
+ return flavor.resources().satisfies(resources);
+ }
+
private List<HostName> createHostnames(NodeType hostType, Flavor flavor, int hostIndex) {
long numAddresses = Math.max(2, Math.round(flavor.resources().bandwidthGbps()));
return IntStream.range(1, (int) numAddresses)
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
index 72225763381..2fb549acc11 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockNodeRepository.java
@@ -21,6 +21,7 @@ import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.WireguardKey;
+import com.yahoo.config.provision.WireguardKeyWithTimestamp;
import com.yahoo.config.provision.Zone;
import com.yahoo.config.provision.ZoneEndpoint;
import com.yahoo.config.provision.ZoneEndpoint.AccessType;
@@ -161,8 +162,8 @@ public class MockNodeRepository extends NodeRepository {
// Emulate host in tenant account
nodes.add(Node.create("dockerhost2", ipConfig(101, 1, 3), "dockerhost2.yahoo.com",
flavors.getFlavorOrThrow("large"), NodeType.host)
- .wireguardPubKey(WireguardKey.from("000011112222333344445555666677778888999900c="))
- .wireguardKeyTimestamp(Instant.ofEpochMilli(123L))
+ .wireguardKey(new WireguardKeyWithTimestamp(WireguardKey.from("000011112222333344445555666677778888999900c="),
+ Instant.ofEpochMilli(123L)))
.cloudAccount(tenantAccount).build());
nodes.add(Node.create("dockerhost3", ipConfig(102, 1, 3), "dockerhost3.yahoo.com",
flavors.getFlavorOrThrow("large"), NodeType.host).cloudAccount(defaultCloudAccount).build());
@@ -176,8 +177,8 @@ public class MockNodeRepository extends NodeRepository {
// Config servers
nodes.add(Node.create("cfg1", ipConfig(201), "cfg1.yahoo.com", flavors.getFlavorOrThrow("default"), NodeType.config)
.cloudAccount(defaultCloudAccount)
- .wireguardPubKey(WireguardKey.from("lololololololololololololololololololololoo="))
- .wireguardKeyTimestamp(Instant.ofEpochMilli(456L))
+ .wireguardKey(new WireguardKeyWithTimestamp(WireguardKey.from("lololololololololololololololololololololoo="),
+ Instant.ofEpochMilli(456L)))
.build());
nodes.add(Node.create("cfg2", ipConfig(202), "cfg2.yahoo.com", flavors.getFlavorOrThrow("default"), NodeType.config)
.cloudAccount(defaultCloudAccount)
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
index f64e50310bb..3f66b2c94d8 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationTransaction;
import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.Cloud;
+import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
@@ -25,6 +26,7 @@ import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.config.ConfigPayload;
import com.yahoo.vespa.hosted.provision.maintenance.SwitchRebalancer;
import com.yahoo.vespa.hosted.provision.node.Agent;
+import com.yahoo.vespa.hosted.provision.persistence.ApplicationSerializer;
import com.yahoo.vespa.hosted.provision.persistence.DnsNameResolver;
import com.yahoo.vespa.hosted.provision.persistence.NameResolver;
import com.yahoo.vespa.hosted.provision.persistence.NodeSerializer;
@@ -45,9 +47,10 @@ import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
+import java.util.Map;
+import java.util.function.BiConsumer;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
@@ -75,8 +78,8 @@ public class RealDataScenarioTest {
@Ignore
@Test
- public void test() {
- ProvisioningTester tester = tester(SystemName.Public, CloudName.AWS, Environment.prod, parseFlavors(Path.of("/tmp/node-flavors.xml")));
+ public void test() throws Exception {
+ ProvisioningTester tester = tester(SystemName.Public, CloudName.AWS, Environment.prod, CloudAccount.empty, parseFlavors(Path.of("/tmp/node-flavors.xml")));
initFromZk(tester.nodeRepository(), Path.of("/tmp/snapshot"));
ApplicationId app = ApplicationId.from("tenant", "app", "default");
@@ -132,41 +135,34 @@ public class RealDataScenarioTest {
}
}
- private static void initFromZk(NodeRepository nodeRepository, Path pathToZkSnapshot) {
+ private static void initFromZk(NodeRepository nodeRepository, Path pathToZkSnapshot) throws Exception {
NodeSerializer nodeSerializer = new NodeSerializer(nodeRepository.flavors());
- AtomicBoolean nodeNext = new AtomicBoolean(false);
- Pattern zkNodePathPattern = Pattern.compile(".?/provision/v1/nodes/[a-z0-9.-]+\\.(com|cloud).?");
- Consumer<String> consumer = input -> {
- if (nodeNext.get()) {
- String json = input.substring(input.indexOf("{\""), input.lastIndexOf('}') + 1);
- Node node = nodeSerializer.fromJson(json.getBytes(UTF_8));
- nodeRepository.database().addNodesInState(new LockedNodeList(List.of(node), () -> { }), node.state(), Agent.system);
- nodeNext.set(false);
- } else {
- if (!zkNodePathPattern.matcher(input).matches()) return;
- if (nodeNext.getAndSet(true))
- throw new IllegalStateException("Expected to find node JSON, but found another node path: " + input);
+ Map<Pattern, BiConsumer<byte[], NestedTransaction>> jsonConsumerByPathPattern = Map.of(
+ Pattern.compile(".?/provision/v1/nodes/[a-z0-9.-]+\\.(com|cloud).?"), (json, transaction) -> {
+ Node node = nodeSerializer.fromJson(json);
+ nodeRepository.database().addNodesInState(new LockedNodeList(List.of(node), () -> { }), node.state(), Agent.system, transaction);
+ },
+ Pattern.compile(".?/provision/v1/applications/[a-z0-9:-]+.?"), (json, transaction) ->
+ nodeRepository.database().writeApplication(ApplicationSerializer.fromJson(json), transaction));
+
+ try (StringsIterator iterator = new StringsIterator(pathToZkSnapshot); NestedTransaction transaction = new NestedTransaction()) {
+ while (iterator.hasNext()) {
+ String s1 = iterator.next();
+ if (!iterator.hasNext()) break;
+ for (var entry : jsonConsumerByPathPattern.entrySet()) {
+ if (!entry.getKey().matcher(s1).matches()) continue;
+ String s2 = iterator.next();
+ byte[] json = s2.substring(s2.indexOf("{\""), s2.lastIndexOf('}') + 1).getBytes(UTF_8);
+ entry.getValue().accept(json, transaction);
+ break;
+ }
}
- };
-
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(Files.newInputStream(pathToZkSnapshot), UTF_8))) {
- StringBuilder sb = new StringBuilder(1000);
- for (int r; (r = reader.read()) != -1; ) {
- if (r < 0x20 || r >= 0x7F) {
- if (sb.length() > 0) {
- consumer.accept(sb.toString());
- sb.setLength(0);
- }
- } else sb.append((char) r);
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
+ transaction.commit();
}
}
- private static ProvisioningTester tester(SystemName systemName, CloudName cloudName, Environment environment, List<Flavor> flavors) {
- Cloud cloud = Cloud.builder().name(cloudName).dynamicProvisioning(cloudName != CloudName.YAHOO).build();
+ private static ProvisioningTester tester(SystemName systemName, CloudName cloudName, Environment environment, CloudAccount cloudAccount, List<Flavor> flavors) {
+ Cloud cloud = Cloud.builder().name(cloudName).dynamicProvisioning(cloudName != CloudName.YAHOO).account(cloudAccount).build();
NameResolver nameResolver = cloudName == CloudName.YAHOO ? new DnsNameResolver() : new MockNameResolver().mockAnyLookup();
ProvisioningTester.Builder builder = new ProvisioningTester.Builder()
.zone(new Zone(cloud, systemName, environment, RegionName.defaultName()))
@@ -179,4 +175,42 @@ public class RealDataScenarioTest {
return builder.build();
}
+ /** Extracts sequences longer than 5 printable characters from a binary file, similar to `strings` command */
+ private static class StringsIterator implements Iterator<String>, AutoCloseable {
+ private final BufferedReader reader;
+ private final StringBuilder sb = new StringBuilder(1000);
+ private StringsIterator(Path path) throws IOException {
+ this.reader = new BufferedReader(new InputStreamReader(Files.newInputStream(path), UTF_8));
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (!sb.isEmpty()) return true;
+ try {
+ for (int r; (r = reader.read()) != -1; ) {
+ if (r < 0x20 || r >= 0x7F) {
+ if (sb.isEmpty()) continue; // Still haven't encountered any real data
+ if (sb.length() > 5) break; // We (probably) found some real data
+ sb.setLength(0); // Probably some random binary data that happened to be a printable character, reset
+ } else sb.append((char) r);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ return !sb.isEmpty();
+ }
+
+ @Override
+ public String next() {
+ String next = sb.toString();
+ sb.setLength(0);
+ return next;
+ }
+
+ @Override
+ public void close() throws Exception {
+ reader.close();
+ }
+ }
+
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
index 52d4c85bcaf..aa8ff1245d7 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java
@@ -32,6 +32,25 @@ import static org.junit.Assert.assertTrue;
public class AutoscalingTest {
@Test
+ public void test_autoscaling_with_gpu() {
+ var resources = new NodeResources(8, 32, 225, 0.1, fast, StorageType.local, NodeResources.Architecture.x86_64, new NodeResources.GpuResources(1, 16));
+ var min = new ClusterResources( 8, 1, resources);
+ var now = new ClusterResources(12, 1, resources);
+ var max = new ClusterResources(12, 1, resources);
+ var fixture = DynamicProvisioningTester.fixture()
+ .awsProdSetup(true)
+ .clusterType(ClusterSpec.Type.container)
+ .initialResources(Optional.of(now))
+ .capacity(Capacity.from(min, max))
+ .build();
+ fixture.tester.clock().advance(Duration.ofDays(2));
+ fixture.loader().applyLoad(new Load(0.8f, 0.17, 0.12), 1, true, true, 100);
+ var result = fixture.autoscale();
+ assertTrue(result.resources().isEmpty());
+ assertEquals(Autoscaling.Status.insufficient, result.status());
+ }
+
+ @Test
public void test_autoscaling_nodes_only() {
var resources = new NodeResources(16, 32, 200, 0.1);
var min = new ClusterResources( 8, 1, resources);
@@ -112,7 +131,7 @@ public class AutoscalingTest {
fixture.loader().applyLoad(new Load(0.1, 0.1, 0.1), 3);
fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 1);
fixture.tester().assertResources("Scaling up since resource usage is too high",
- 8, 1, 5.3, 17.5, 75.4,
+ 8, 1, 5.3, 17.0, 75.1,
fixture.autoscale());
}
@@ -173,7 +192,7 @@ public class AutoscalingTest {
fixture.setScalingDuration(Duration.ofHours(12)); // Fixture sets last completion to be 1 day into the past
fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0), 10);
fixture.tester().assertResources("Scaling up (only) since resource usage is too high",
- 5, 1, 11.7, 15.4, 132.0,
+ 5, 1, 11.7, 14.9, 131.5,
fixture.autoscale());
}
@@ -185,7 +204,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(Duration.ofDays(2));
fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0), 10);
fixture.tester().assertResources("Scaling cpu and disk up and memory down",
- 5, 1, 11.7, 4.0, 132.0,
+ 5, 1, 11.7, 4.0, 131.5,
fixture.autoscale());
}
@@ -208,7 +227,7 @@ public class AutoscalingTest {
fixture.loader().applyCpuLoad(0.70, 1);
fixture.loader().applyCpuLoad(0.01, 100);
fixture.tester().assertResources("Scaling up since peak resource usage is too high",
- 5, 1, 7.1, 12.3, 50.7,
+ 5, 1, 7.1, 11.9, 50.5,
fixture.autoscale());
}
@@ -355,7 +374,7 @@ public class AutoscalingTest {
fixture.tester().clock().advance(Duration.ofDays(2));
fixture.loader().applyLoad(new Load(0.05f, 0.05f, 0.05f), 120);
fixture.tester().assertResources("Scaling down to limit since resource usage is low",
- 4, 1, 1.8, 7.4, 23.5,
+ 4, 1, 1.8, 7.4, 23.4,
fixture.autoscale());
}
@@ -459,7 +478,7 @@ public class AutoscalingTest {
fixture.tester().clock().advance(Duration.ofDays(2));
fixture.loader().applyCpuLoad(1.0, 120);
fixture.tester().assertResources("Suggesting above capacity limit",
- 5, 1, 10.2, 12.3, 50.7,
+ 5, 1, 10.2, 11.9, 50.5,
fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min));
}
@@ -663,7 +682,7 @@ public class AutoscalingTest {
fixture.tester().clock().advance(Duration.ofHours(12 * 3 + 1));
fixture.loader().applyCpuLoad(0.02, 5);
fixture.tester().assertResources("Scaling down since enough time has passed",
- 5, 1, 1.0, 12.3, 50.7,
+ 5, 1, 1.0, 11.9, 50.5,
fixture.autoscale());
}
@@ -707,7 +726,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.25, 200);
fixture.tester().assertResources("Scale up since we assume we need 2x cpu for growth when no scaling time data",
- 5, 1, 2.6, 12.3, 50.7,
+ 5, 1, 2.6, 11.9, 50.5,
fixture.autoscale());
fixture.setScalingDuration(Duration.ofHours(8));
@@ -716,7 +735,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.20, 200);
fixture.tester().assertResources("Scale down since observed growth is slower than scaling time",
- 5, 1, 1.6, 12.3, 50.7,
+ 5, 1, 1.6, 11.9, 50.5,
fixture.autoscale());
fixture.setScalingDuration(Duration.ofHours(8));
@@ -727,7 +746,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.25, 200);
fixture.tester().assertResources("Scale up since observed growth is faster than scaling time",
- 5, 1, 2.4, 12.3, 50.7,
+ 5, 1, 2.4, 11.9, 50.5,
fixture.autoscale());
}
@@ -744,7 +763,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.7, 200);
fixture.tester().assertResources("Scale up slightly since observed growth is faster than scaling time, but we are not confident",
- 5, 1, 2.2, 12.3, 50.7,
+ 5, 1, 2.2, 11.9, 50.5,
fixture.autoscale());
}
@@ -763,7 +782,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.4, 200);
fixture.tester.assertResources("Query and write load is equal -> scale up somewhat",
- 5, 1, 2.9, 12.3, 50.7,
+ 5, 1, 2.9, 11.9, 50.5,
fixture.autoscale());
fixture.tester().clock().advance(Duration.ofDays(2));
@@ -772,7 +791,7 @@ public class AutoscalingTest {
fixture.loader().addCpuMeasurements(0.4, 200);
// TODO: Ackhually, we scale up less here - why?
fixture.tester().assertResources("Query load is 4x write load -> scale up more",
- 5, 1, 2.2, 12.3, 50.7,
+ 5, 1, 2.2, 11.9, 50.5,
fixture.autoscale());
fixture.tester().clock().advance(Duration.ofDays(2));
@@ -780,7 +799,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.4, 200);
fixture.tester().assertResources("Write load is 10x query load -> scale down",
- 5, 1, 1.3, 12.3, 50.7,
+ 5, 1, 1.3, 11.9, 50.5,
fixture.autoscale());
fixture.tester().clock().advance(Duration.ofDays(2));
@@ -788,7 +807,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.4, 200);
fixture.tester().assertResources("Query only -> larger",
- 5, 1, 3.5, 12.3, 50.7,
+ 5, 1, 3.5, 11.9, 50.5,
fixture.autoscale());
fixture.tester().clock().advance(Duration.ofDays(2));
@@ -796,7 +815,7 @@ public class AutoscalingTest {
fixture.tester.clock().advance(timeAdded.negated());
fixture.loader().addCpuMeasurements(0.4, 200);
fixture.tester().assertResources("Write only -> smallest possible",
- 5, 1, 1.0, 12.3, 50.7,
+ 5, 1, 1.0, 11.9, 50.5,
fixture.autoscale());
}
@@ -825,7 +844,7 @@ public class AutoscalingTest {
fixture.tester().clock().advance(Duration.ofDays(2));
fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0), 200);
fixture.tester().assertResources("Scale only to a single node and group since this is dev",
- 1, 1, 0.1, 23.6, 105.6,
+ 1, 1, 0.1, 22.9, 105.2,
fixture.autoscale());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java
index be7bc3c44a8..f2b80adc513 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java
@@ -32,7 +32,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.1, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 3.4, 7.4, 29.0,
+ 8, 1, 3.4, 7.2, 28.8,
fixture.autoscale());
// Higher query rate
@@ -40,7 +40,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(200, 1.1, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 6.8, 7.4, 29.0,
+ 8, 1, 6.8, 7.2, 28.8,
fixture.autoscale());
// Higher headroom
@@ -48,7 +48,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.3, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 4.0, 7.4, 29.0,
+ 8, 1, 4.0, 7.2, 28.8,
fixture.autoscale());
// Higher per query cost
@@ -56,7 +56,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.1, 0.45));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 5.1, 7.4, 29.0,
+ 8, 1, 5.1, 7.2, 28.8,
fixture.autoscale());
// Bcp elsewhere is 0 - use local only
@@ -64,7 +64,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(0, 1.1, 0.45));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling using local info",
- 8, 1, 1, 7.4, 29.0,
+ 8, 1, 1, 7.2, 28.8,
fixture.autoscale());
}
@@ -85,7 +85,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.1, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 3, 3, 11.7, 43.2, 190.0,
+ 3, 3, 11.7, 41.8, 189.3,
fixture.autoscale());
// Higher query rate
@@ -93,7 +93,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(200, 1.1, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 3, 3, 23.1, 43.2, 190.0,
+ 3, 3, 23.1, 41.8, 189.3,
fixture.autoscale());
// Higher headroom
@@ -101,7 +101,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.3, 0.3));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 3, 3, 13.8, 43.2, 190.0,
+ 3, 3, 13.8, 41.8, 189.3,
fixture.autoscale());
// Higher per query cost
@@ -109,7 +109,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(100, 1.1, 0.45));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 3, 3, 17.4, 43.2, 190.0,
+ 3, 3, 17.4, 41.8, 189.3,
fixture.autoscale());
}
@@ -186,7 +186,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.store(new BcpGroupInfo(200, 1.3, 0.45));
fixture.loader().addCpuMeasurements(0.7f, 10);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 11.9, 7.4, 29.0,
+ 8, 1, 11.9, 7.2, 28.8,
fixture.autoscale());
// Some local traffic
@@ -196,7 +196,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration1.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 10.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 6.8, 7.4, 29.0,
+ 8, 1, 6.8, 7.2, 28.8,
fixture.autoscale());
// Enough local traffic to get half the votes
@@ -206,7 +206,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration2.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 50.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 3.0, 7.4, 29.0,
+ 8, 1, 3.0, 7.2, 28.8,
fixture.autoscale());
// Mostly local
@@ -216,7 +216,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration3.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 90.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 2.2, 7.4, 29.0,
+ 8, 1, 2.2, 7.2, 28.8,
fixture.autoscale());
// Local only
@@ -226,7 +226,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration4.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 100.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 2.1, 7.4, 29.0,
+ 8, 1, 2.1, 7.2, 28.8,
fixture.autoscale());
// No group info, should be the same as the above
@@ -236,7 +236,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration5.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 100.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 2.1, 7.4, 29.0,
+ 8, 1, 2.1, 7.2, 28.8,
fixture.autoscale());
// 40 query rate, no group info (for reference to the below)
@@ -246,7 +246,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration6.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 40.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 1.5, 7.4, 29.0,
+ 8, 1, 1.5, 7.2, 28.8,
fixture.autoscale());
// Local query rate is too low but global is even lower so disregard it, giving the same as above
@@ -256,7 +256,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration7.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 40.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 1.5, 7.4, 29.0,
+ 8, 1, 1.5, 7.2, 28.8,
fixture.autoscale());
// Local query rate is too low to be fully confident, and so is global but as it is slightly larger, incorporate it slightly
@@ -266,7 +266,7 @@ public class AutoscalingUsingBcpGroupInfoTest {
fixture.tester().clock().advance(duration8.negated());
fixture.loader().addQueryRateMeasurements(10, __ -> 40.0);
fixture.tester().assertResources("Scaling up cpu using bcp group cpu info",
- 8, 1, 1.8, 7.4, 29.0,
+ 8, 1, 1.8, 7.2, 28.8,
fixture.autoscale());
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/AwsNodeTypes.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/AwsNodeTypes.java
index df7c468f035..6225982af42 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/AwsNodeTypes.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/AwsNodeTypes.java
@@ -11,11 +11,12 @@ import java.util.Optional;
import static com.yahoo.config.provision.NodeResources.Architecture.arm64;
import static com.yahoo.config.provision.NodeResources.Architecture.x86_64;
import static com.yahoo.config.provision.NodeResources.DiskSpeed.fast;
+import static com.yahoo.config.provision.NodeResources.GpuResources;
import static com.yahoo.config.provision.NodeResources.StorageType.local;
import static com.yahoo.config.provision.NodeResources.StorageType.remote;
/**
- * Returns the information about all AWS node types supported on Vespa Cloud as of 2022-10-31.
+ * Returns the information about all AWS node types supported on Vespa Cloud as of 2023-09-28.
*
* @author bratseth
*/
@@ -45,13 +46,34 @@ public class AwsNodeTypes {
new VespaFlavor("m5d_16xlarge", 64.0, 64.0, 256.0, 246.0, 2400.0, 10.0, fast, local, x86_64),
new VespaFlavor("m5_24xlarge", 96.0, 96.0, 384.0, 370.0, 16384.0, 10.0, fast, remote, x86_64),
new VespaFlavor("m5d_24xlarge", 96.0, 96.0, 384.0, 370.0, 3600.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_large", 2.0, 2.0, 8.0, 7.3, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_large", 2.0, 2.0, 8.0, 7.3, 118.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_xlarge", 4.0, 4.0, 16.0, 15.1, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_xlarge", 4.0, 4.0, 16.0, 15.1, 237.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_2xlarge", 8.0, 8.0, 32.0, 30.5, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_2xlarge", 8.0, 8.0, 32.0, 30.5, 474.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_4xlarge", 16.0, 16.0, 64.0, 61.3, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_4xlarge", 16.0, 16.0, 64.0, 61.3, 950.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_8xlarge", 32.0, 32.0, 128.0, 123.0, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_8xlarge", 32.0, 32.0, 128.0, 123.0, 1900.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_12xlarge", 48.0, 48.0, 192.0, 185.0, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_12xlarge", 48.0, 48.0, 192.0, 185.0, 2850.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m6i_16xlarge", 64.0, 64.0, 256.0, 246.0, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("m6id_16xlarge", 64.0, 64.0, 256.0, 246.0, 3800.0, 10.0, fast, local, x86_64),
new VespaFlavor("m6g_large", 2.0, 2.0, 8.0, 7.3, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_large", 2.0, 2.0, 8.0, 7.3, 118.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_xlarge", 4.0, 4.0, 16.0, 15.1, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_xlarge", 4.0, 4.0, 16.0, 15.1, 237.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_2xlarge", 8.0, 8.0, 32.0, 30.5, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_2xlarge", 8.0, 8.0, 32.0, 30.5, 474.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_4xlarge", 16.0, 16.0, 64.0, 61.3, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_4xlarge", 16.0, 16.0, 64.0, 61.3, 950.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_8xlarge", 32.0, 32.0, 128.0, 123.0, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_8xlarge", 32.0, 32.0, 128.0, 123.0, 1900.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_12xlarge", 48.0, 48.0, 192.0, 185.0, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_12xlarge", 48.0, 48.0, 192.0, 185.0, 2850.0, 10.0, fast, local, arm64),
new VespaFlavor("m6g_16xlarge", 64.0, 64.0, 256.0, 246.0, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("m6gd_16xlarge", 64.0, 64.0, 256.0, 246.0, 3800.0, 10.0, fast, local, arm64),
new VespaFlavor("c5_large", 2.0, 2.0, 4.0, 3.5, 16384.0, 10.0, fast, remote, x86_64),
new VespaFlavor("c5d_large", 2.0, 2.0, 4.0, 3.5, 50.0, 10.0, fast, local, x86_64),
new VespaFlavor("c5_xlarge", 4.0, 4.0, 8.0, 7.3, 16384.0, 10.0, fast, remote, x86_64),
@@ -68,10 +90,44 @@ public class AwsNodeTypes {
new VespaFlavor("c5d_18xlarge", 72.0, 72.0, 144.0, 137.0, 1800.0, 10.0, fast, local, x86_64),
new VespaFlavor("c5_24xlarge", 96.0, 96.0, 192.0, 185.0, 16384.0, 10.0, fast, remote, x86_64),
new VespaFlavor("c5d_24xlarge", 96.0, 96.0, 192.0, 185.0, 3600.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_large", 2.0, 2.0, 4.0, 3.5, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_large", 2.0, 2.0, 4.0, 3.5, 118.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_xlarge", 4.0, 4.0, 8.0, 7.4, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_xlarge", 4.0, 4.0, 8.0, 7.4, 237.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_2xlarge", 8.0, 8.0, 16.0, 15.1, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_2xlarge", 8.0, 8.0, 16.0, 15.1, 474.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_4xlarge", 16.0, 16.0, 32.0, 30.6, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_4xlarge", 16.0, 16.0, 32.0, 30.6, 950.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_8xlarge", 32.0, 32.0, 64.0, 61.7, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_8xlarge", 32.0, 32.0, 64.0, 61.7, 1900.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_12xlarge", 48.0, 48.0, 96.0, 92.6, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_12xlarge", 48.0, 48.0, 96.0, 92.6, 2850.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_16xlarge", 64.0, 64.0, 128.0, 123.0, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_16xlarge", 64.0, 64.0, 128.0, 123.0, 3800.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6i_24xlarge", 96.0, 96.0, 192.0, 185.6, 16384.0, 10.0, fast, remote, x86_64),
+ new VespaFlavor("c6id_24xlarge", 96.0, 96.0, 192.0, 185.6, 5700.0, 10.0, fast, local, x86_64),
new VespaFlavor("c5ad_8xlarge", 32.0, 32.0, 64.0, 62.0, 1200.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("c6g_large", 2.0, 2.0, 4.0, 3.35, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c6gd_large", 2.0, 2.0, 4.0, 3.35, 118.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_xlarge", 4.0, 4.0, 8.0, 7.3, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c6gd_xlarge", 4.0, 4.0, 8.0, 7.3, 237.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_2xlarge", 8.0, 8.0, 16.0, 15.1, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c6gd_2xlarge", 8.0, 8.0, 16.0, 15.1, 475.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_4xlarge", 16.0, 16.0, 32.0, 30.8, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c6gd_4xlarge", 16.0, 16.0, 32.0, 30.8, 950.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_8xlarge", 32.0, 32.0, 64.0, 62.3, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c6gd_8xlarge", 32.0, 32.0, 64.0, 62.3, 1900.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_12xlarge", 48.0, 48.0, 96.0, 93.0, 16384.0, 10.0, fast, remote, arm64),
new VespaFlavor("c6gd_12xlarge", 48.0, 48.0, 96.0, 93.0, 2850.0, 10.0, fast, local, arm64),
+ new VespaFlavor("c6g_16xlarge", 64.0, 64.0, 128.0, 125.0, 16384.0, 10.0, fast, remote, arm64),
new VespaFlavor("c6gd_16xlarge", 64.0, 64.0, 128.0, 125.0, 3800.0, 10.0, fast, local, arm64),
- new VespaFlavor("c6id_16xlarge", 64.0, 64.0, 128.0, 123.0, 3800.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("m7g_8xlarge", 32.0, 32.0, 128.0, 123.0, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_large", 2.0, 2.0, 4.0, 3.35, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_xlarge", 4.0, 4.0, 8.0, 7.2, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_2xlarge", 8.0, 8.0, 16.0, 15.1, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_4xlarge", 16.0, 16.0, 32.0, 30.8, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_8xlarge", 32.0, 32.0, 64.0, 62.3, 16384.0, 10.0, fast, remote, arm64),
+ new VespaFlavor("c7g_12xlarge", 48.0, 48.0, 96.0, 92.6, 16384.0, 10.0, fast, remote, arm64),
new VespaFlavor("c7g_16xlarge", 64.0, 64.0, 128.0, 125.0, 16384.0, 10.0, fast, remote, arm64),
new VespaFlavor("r5_large", 2.0, 2.0, 16.0, 15.2, 16384.0, 10.0, fast, remote, x86_64),
new VespaFlavor("r5d_large", 2.0, 2.0, 16.0, 15.2, 75.0, 10.0, fast, local, x86_64),
@@ -89,14 +145,7 @@ public class AwsNodeTypes {
new VespaFlavor("r5d_16xlarge", 64.0, 64.0, 512.0, 498.0, 2400.0, 10.0, fast, local, x86_64),
new VespaFlavor("r5_24xlarge", 96.0, 96.0, 768.0, 748.0, 16384.0, 10.0, fast, remote, x86_64),
new VespaFlavor("r5d_24xlarge", 96.0, 96.0, 768.0, 748.0, 3600.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1_16xlarge", 64.0, 64.0, 976.0, 946.0, 1920.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1_32xlarge", 128.0, 128.0, 1952.0, 1893.0, 3840.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_xlarge", 4.0, 4.0, 122.0, 118.0, 120.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_2xlarge", 8.0, 8.0, 244.0, 237.0, 240.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_4xlarge", 16.0, 16.0, 488.0, 474.0, 480.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_8xlarge", 32.0, 32.0, 976.0, 946.0, 960.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_16xlarge", 64.0, 64.0, 1952.0, 1893.0, 1920.0, 10.0, fast, local, x86_64),
- new VespaFlavor("x1e_32xlarge", 128.0, 128.0, 3904.0, 3786.0, 3840.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("r6id_xlarge", 4.0, 4.0, 32.0, 30.8, 237.0, 10.0, fast, local, x86_64),
new VespaFlavor("z1d_6xlarge", 24.0, 24.0, 192.0, 185.0, 900.0, 10.0, fast, local, x86_64),
new VespaFlavor("i4i_large", 2.0, 2.0, 16.0, 15.1, 468.0, 10.0, fast, local, x86_64),
new VespaFlavor("i4i_xlarge", 4.0, 4.0, 32.0, 30.5, 937.0, 10.0, fast, local, x86_64),
@@ -104,7 +153,9 @@ public class AwsNodeTypes {
new VespaFlavor("i4i_4xlarge", 16.0, 16.0, 128.0, 123.0, 3750.0, 10.0, fast, local, x86_64),
new VespaFlavor("i4i_8xlarge", 32.0, 32.0, 256.0, 246.0, 7500.0, 10.0, fast, local, x86_64),
new VespaFlavor("i4i_16xlarge", 64.0, 64.0, 512.0, 498.0, 15000.0, 10.0, fast, local, x86_64),
- new VespaFlavor("i4i_32xlarge", 128.0, 128.0, 1024.0, 996.0, 30000.0, 10.0, fast, local, x86_64));
+ new VespaFlavor("i4i_32xlarge", 128.0, 128.0, 1024.0, 996.0, 30000.0, 10.0, fast, local, x86_64),
+ new VespaFlavor("g4dn_xlarge", 4.0, 4.0, 16.0, 15.1, 125.0, 10.0, fast, local, x86_64, new GpuResources(1, 16.0)),
+ new VespaFlavor("g4dn_2xlarge", 8.0, 8.0, 32.0, 30.5, 225.0, 10.0, fast, local, x86_64, new GpuResources(1, 16.0)));
public static List<VespaFlavor> asVespaFlavors() { return sorted(hostFlavors); }
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/VespaFlavor.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/VespaFlavor.java
index c42b61988e9..2e0a92a38af 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/VespaFlavor.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/awsnodes/VespaFlavor.java
@@ -23,9 +23,23 @@ public class VespaFlavor {
NodeResources.DiskSpeed diskSpeed,
NodeResources.StorageType storageType,
NodeResources.Architecture architecture) {
+ this(name, advertisedVcpu, realVcpu, advertisedMemoryGb, realMemoryGb, diskGb, bandwidthGbps, diskSpeed, storageType, architecture, NodeResources.GpuResources.zero());
+ }
+
+ public VespaFlavor(String name,
+ double advertisedVcpu,
+ double realVcpu,
+ double advertisedMemoryGb,
+ double realMemoryGb,
+ double diskGb,
+ double bandwidthGbps,
+ NodeResources.DiskSpeed diskSpeed,
+ NodeResources.StorageType storageType,
+ NodeResources.Architecture architecture,
+ NodeResources.GpuResources gpuResources) {
this.name = name;
- this.realResources = new NodeResources(realVcpu, realMemoryGb, diskGb, bandwidthGbps, diskSpeed, storageType, architecture);
- this.advertisedResources = new NodeResources(advertisedVcpu, advertisedMemoryGb, diskGb, bandwidthGbps, diskSpeed, storageType, architecture);
+ this.realResources = new NodeResources(realVcpu, realMemoryGb, diskGb, bandwidthGbps, diskSpeed, storageType, architecture, gpuResources);
+ this.advertisedResources = new NodeResources(advertisedVcpu, advertisedMemoryGb, diskGb, bandwidthGbps, diskSpeed, storageType, architecture, gpuResources);
}
public String name() { return name; }
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
index 6dc681ae5c8..b5257e23d9e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/persistence/LoadBalancerSerializerTest.java
@@ -40,6 +40,7 @@ public class LoadBalancerSerializerTest {
Optional.of(new LoadBalancerInstance(
Optional.of(DomainName.of("lb-host")),
Optional.empty(),
+ Optional.empty(),
Optional.of(new DnsZone("zone-id-1")),
Set.of(4080, 4443),
Set.of("10.2.3.4/24"),
@@ -73,6 +74,7 @@ public class LoadBalancerSerializerTest {
Optional.of(new LoadBalancerInstance(
Optional.empty(),
Optional.of("1.2.3.4"),
+ Optional.of("fd00::1"),
Optional.of(new DnsZone("zone-id-1")),
Set.of(4443),
Set.of("10.2.3.4/24", "12.3.2.1/30"),
@@ -86,6 +88,8 @@ public class LoadBalancerSerializerTest {
var serialized = LoadBalancerSerializer.fromJson(LoadBalancerSerializer.toJson(loadBalancer));
assertEquals(loadBalancer.id(), serialized.id());
assertEquals(loadBalancer.instance().get().hostname(), serialized.instance().get().hostname());
+ assertEquals(loadBalancer.instance().get().ip4Address(), serialized.instance().get().ip4Address());
+ assertEquals(loadBalancer.instance().get().ip6Address(), serialized.instance().get().ip6Address());
assertEquals(loadBalancer.instance().get().dnsZone(), serialized.instance().get().dnsZone());
assertEquals(loadBalancer.instance().get().ports(), serialized.instance().get().ports());
assertEquals(loadBalancer.instance().get().networks(), serialized.instance().get().networks());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java
index ebac6071a14..1ef89f2d53d 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicProvisioningTester.java
@@ -289,6 +289,11 @@ public class DynamicProvisioningTester {
return flavorResources.compatibleWith(resources);
}
+ @Override
+ public boolean satisfies(Flavor flavor, NodeResources resources) {
+ return hostResourcesCalculator.advertisedResourcesOf(flavor).satisfies(resources);
+ }
+
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json
index 928e91861a2..54a0e7e9757 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/cfg1.json
@@ -119,6 +119,10 @@
],
"additionalIpAddresses": [],
"cloudAccount": "aws:111222333444",
- "wireguardPubkey":"lololololololololololololololololololololoo=",
+ "wireguard": {
+ "key": "lololololololololololololololololololololoo=",
+ "timestamp": 456
+ },
+ "wireguardPubkey": "lololololololololololololololololololololoo=",
"wireguardKeyTimestamp": 456
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json
index 72b5483d849..d3f1a8082ae 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/docker-node2.json
@@ -117,6 +117,10 @@
"ipAddresses": ["127.0.101.1", "::101:1"],
"additionalIpAddresses": ["::101:2", "::101:3", "::101:4"],
"cloudAccount": "aws:777888999000",
+ "wireguard": {
+ "key": "000011112222333344445555666677778888999900c=",
+ "timestamp": 123
+ },
"wireguardPubkey": "000011112222333344445555666677778888999900c=",
"wireguardKeyTimestamp": 123
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json
index d0d6df71fc1..404cf9a9a80 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/node4-wg.json
@@ -118,6 +118,10 @@
"ipAddresses": ["127.0.4.1", "::4:1"],
"additionalIpAddresses": [],
"cloudAccount": "aws:111222333444",
+ "wireguard": {
+ "key": "lololololololololololololololololololololoo=",
+ "timestamp": 123
+ },
"wireguardPubkey": "lololololololololololololololololololololoo=",
"wireguardKeyTimestamp": 123
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/wireguard.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/wireguard.json
index 7bee06adc87..8e9af7f680f 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/wireguard.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/responses/wireguard.json
@@ -4,7 +4,11 @@
"hostname": "cfg1.yahoo.com",
"wireguardPubkey": "lololololololololololololololololololololoo=",
"wireguardKeyTimestamp":456,
- "ipAddresses": ["::201:1"]
+ "ipAddresses": ["::201:1"],
+ "wireguard": {
+ "key": "lololololololololololololololololololololoo=",
+ "timestamp": 456
+ }
}
]
}