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