throw invalid_tenant_configuration and add to metacluster management test
This commit is contained in:
parent
bfd2d138f7
commit
e3f54dba2f
|
@ -96,7 +96,8 @@ void applyConfigurationToSpecialKeys(Reference<ITransaction> tr,
|
|||
std::map<Standalone<StringRef>, Optional<Value>> configuration) {
|
||||
for (auto [configName, value] : configuration) {
|
||||
if (configName == "assigned_cluster"_sr) {
|
||||
throw invalid_option();
|
||||
fmt::print(stderr, "ERROR: assigned_cluster is only valid in metacluster configuration.\n");
|
||||
throw invalid_tenant_configuration();
|
||||
}
|
||||
if (value.present()) {
|
||||
tr->set(makeConfigKey(tenantName, configName), value.get());
|
||||
|
|
|
@ -1074,8 +1074,12 @@ struct CreateTenantImpl {
|
|||
// Parameter set if tenant creation permanently fails on the data cluster
|
||||
Optional<int64_t> replaceExistingTenantId;
|
||||
|
||||
CreateTenantImpl(Reference<DB> managementDb, bool preferAssignedCluster, TenantName tenantName, TenantMapEntry tenantEntry)
|
||||
: ctx(managementDb), preferAssignedCluster(preferAssignedCluster), tenantName(tenantName), tenantEntry(tenantEntry) {}
|
||||
CreateTenantImpl(Reference<DB> managementDb,
|
||||
bool preferAssignedCluster,
|
||||
TenantName tenantName,
|
||||
TenantMapEntry tenantEntry)
|
||||
: ctx(managementDb), preferAssignedCluster(preferAssignedCluster), tenantName(tenantName),
|
||||
tenantEntry(tenantEntry) {}
|
||||
|
||||
ACTOR static Future<ClusterName> checkClusterAvailability(Reference<IDatabase> dataClusterDb,
|
||||
ClusterName clusterName) {
|
||||
|
@ -1153,46 +1157,43 @@ struct CreateTenantImpl {
|
|||
|
||||
if (groupEntry.present()) {
|
||||
ASSERT(groupEntry.get().assignedCluster.present());
|
||||
if (self->preferAssignedCluster) {
|
||||
ASSERT(groupEntry.get().assignedCluster.get() == self->tenantEntry.assignedCluster.get());
|
||||
if (self->preferAssignedCluster &&
|
||||
groupEntry.get().assignedCluster.get() != self->tenantEntry.assignedCluster.get()) {
|
||||
throw invalid_tenant_configuration();
|
||||
}
|
||||
return std::make_pair(groupEntry.get().assignedCluster.get(), true);
|
||||
}
|
||||
}
|
||||
|
||||
state std::vector<Future<Reference<IDatabase>>> dataClusterDbs;
|
||||
state std::vector<ClusterName> dataClusterNames;
|
||||
state std::vector<Future<ClusterName>> clusterAvailabilityChecks;
|
||||
// Get a set of the most full clusters that still have capacity
|
||||
// If preferred cluster is specified, look for that one.
|
||||
state std::vector<Future<Reference<IDatabase>>> dataClusterDbs;
|
||||
state std::vector<Future<ClusterName>> clusterAvailabilityChecks;
|
||||
if (self->preferAssignedCluster) {
|
||||
dataClusterDbs.push_back(getAndOpenDatabase(tr, self->tenantEntry.assignedCluster.get()));
|
||||
wait(waitForAll(dataClusterDbs));
|
||||
clusterAvailabilityChecks.push_back(
|
||||
checkClusterAvailability(dataClusterDbs[0].get(), self->tenantEntry.assignedCluster.get()));
|
||||
} else {
|
||||
state KeyBackedSet<Tuple>::RangeResultType availableClusters =
|
||||
wait(ManagementClusterMetadata::clusterCapacityIndex.getRange(
|
||||
tr,
|
||||
{},
|
||||
{},
|
||||
CLIENT_KNOBS->METACLUSTER_ASSIGNMENT_CLUSTERS_TO_CHECK,
|
||||
Snapshot::False,
|
||||
Reverse::True));
|
||||
state KeyBackedSet<Tuple>::RangeResultType availableClusters =
|
||||
wait(ManagementClusterMetadata::clusterCapacityIndex.getRange(
|
||||
tr, {}, {}, CLIENT_KNOBS->METACLUSTER_ASSIGNMENT_CLUSTERS_TO_CHECK, Snapshot::False, Reverse::True));
|
||||
if (availableClusters.results.empty()) {
|
||||
throw metacluster_no_capacity();
|
||||
}
|
||||
|
||||
if (availableClusters.results.empty()) {
|
||||
throw metacluster_no_capacity();
|
||||
bool preferredClusterPresent = false;
|
||||
for (auto clusterTuple : availableClusters.results) {
|
||||
if (self->preferAssignedCluster && self->tenantEntry.assignedCluster.get() != clusterTuple.getString(1)) {
|
||||
continue;
|
||||
}
|
||||
preferredClusterPresent = true;
|
||||
dataClusterDbs.push_back(getAndOpenDatabase(tr, clusterTuple.getString(1)));
|
||||
dataClusterNames.push_back(clusterTuple.getString(1));
|
||||
}
|
||||
if (self->preferAssignedCluster && !preferredClusterPresent) {
|
||||
throw metacluster_no_capacity();
|
||||
}
|
||||
wait(waitForAll(dataClusterDbs));
|
||||
|
||||
for (auto clusterTuple : availableClusters.results) {
|
||||
dataClusterDbs.push_back(getAndOpenDatabase(tr, clusterTuple.getString(1)));
|
||||
}
|
||||
wait(waitForAll(dataClusterDbs));
|
||||
|
||||
// Check the availability of our set of clusters
|
||||
for (int i = 0; i < availableClusters.results.size(); ++i) {
|
||||
clusterAvailabilityChecks.push_back(
|
||||
checkClusterAvailability(dataClusterDbs[i].get(), availableClusters.results[i].getString(1)));
|
||||
}
|
||||
// Check the availability of our set of clusters
|
||||
for (int i = 0; i < dataClusterDbs.size(); ++i) {
|
||||
clusterAvailabilityChecks.push_back(checkClusterAvailability(dataClusterDbs[i].get(), dataClusterNames[i]));
|
||||
}
|
||||
|
||||
// Wait for a successful availability check from some cluster. We prefer the most full cluster, but if it
|
||||
|
|
|
@ -388,12 +388,25 @@ struct MetaclusterManagementWorkload : TestWorkload {
|
|||
state bool exists = itr != self->createdTenants.end();
|
||||
state bool hasCapacity = self->createdTenants.size() < self->totalTenantGroupCapacity;
|
||||
state bool retried = false;
|
||||
state bool preferAssignedCluster = deterministicRandom()->coinflip();
|
||||
|
||||
try {
|
||||
loop {
|
||||
try {
|
||||
Future<Void> createFuture =
|
||||
MetaclusterAPI::createTenant(self->managementDb, tenant, TenantMapEntry());
|
||||
TenantMapEntry entry;
|
||||
if (preferAssignedCluster) {
|
||||
loop {
|
||||
ClusterName clusterName = self->chooseClusterName();
|
||||
DataClusterData* dataDb = &self->dataDbs[clusterName];
|
||||
// Choose a registered cluster
|
||||
// Still possible that the chosen cluster has no capacity.
|
||||
if (dataDb->registered) {
|
||||
entry.assignedCluster = clusterName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Future<Void> createFuture = MetaclusterAPI::createTenant(self->managementDb, tenant, entry);
|
||||
Optional<Void> result = wait(timeout(createFuture, deterministicRandom()->randomInt(1, 30)));
|
||||
if (result.present()) {
|
||||
break;
|
||||
|
@ -431,7 +444,7 @@ struct MetaclusterManagementWorkload : TestWorkload {
|
|||
ASSERT(exists);
|
||||
return Void();
|
||||
} else if (e.code() == error_code_metacluster_no_capacity) {
|
||||
ASSERT(!hasCapacity && !exists);
|
||||
ASSERT((!hasCapacity && !exists) || preferAssignedCluster);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue