From 0d6a9242c11b99ddadcfb6e86a850b6ba487530a Mon Sep 17 00:00:00 2001 From: Kevin Pulo Date: Wed, 7 Feb 2018 05:26:36 +0000 Subject: SERVER-25746 store advisoryHostFQDNs in config.mongos (cherry picked from commit 75c8414afea212e79b27dae42cfd2930bdfd6eea) --- src/mongo/s/catalog/type_mongos.cpp | 27 ++++++++++ src/mongo/s/catalog/type_mongos.h | 9 ++++ src/mongo/s/catalog/type_mongos_test.cpp | 90 +++++++++++++++++++++++++++----- src/mongo/s/sharding_uptime_reporter.cpp | 17 ++++-- 4 files changed, 124 insertions(+), 19 deletions(-) diff --git a/src/mongo/s/catalog/type_mongos.cpp b/src/mongo/s/catalog/type_mongos.cpp index c656f59b4ee..c5e02a69f15 100644 --- a/src/mongo/s/catalog/type_mongos.cpp +++ b/src/mongo/s/catalog/type_mongos.cpp @@ -43,6 +43,7 @@ const BSONField MongosType::uptime("up"); const BSONField MongosType::waiting("waiting"); const BSONField MongosType::mongoVersion("mongoVersion"); const BSONField MongosType::configVersion("configVersion"); +const BSONField MongosType::advisoryHostFQDNs("advisoryHostFQDNs"); StatusWith MongosType::fromBSON(const BSONObj& source) { MongosType mt; @@ -95,6 +96,26 @@ StatusWith MongosType::fromBSON(const BSONObj& source) { mt._configVersion = mtConfigVersion; } + if (source.hasField(advisoryHostFQDNs.name())) { + mt._advisoryHostFQDNs = std::vector(); + BSONElement array; + Status status = bsonExtractTypedField(source, advisoryHostFQDNs.name(), Array, &array); + if (!status.isOK()) + return status; + + BSONObjIterator it(array.Obj()); + while (it.more()) { + BSONElement arrayElement = it.next(); + if (arrayElement.type() != String) { + return Status(ErrorCodes::TypeMismatch, + str::stream() << "Elements in \"" << advisoryHostFQDNs.name() + << "\" array must be strings but found " + << typeName(arrayElement.type())); + } + mt._advisoryHostFQDNs->push_back(arrayElement.String()); + } + } + return mt; } @@ -133,6 +154,8 @@ BSONObj MongosType::toBSON() const { builder.append(mongoVersion.name(), getMongoVersion()); if (_configVersion) builder.append(configVersion.name(), getConfigVersion()); + if (_advisoryHostFQDNs) + builder.append(advisoryHostFQDNs.name(), getAdvisoryHostFQDNs()); return builder.obj(); } @@ -163,6 +186,10 @@ void MongosType::setConfigVersion(const long long configVersion) { _configVersion = configVersion; } +void MongosType::setAdvisoryHostFQDNs(const std::vector& advisoryHostFQDNs) { + _advisoryHostFQDNs = advisoryHostFQDNs; +} + std::string MongosType::toString() const { return toBSON().toString(); } diff --git a/src/mongo/s/catalog/type_mongos.h b/src/mongo/s/catalog/type_mongos.h index 02e7fea601b..e0fb0ea84b1 100644 --- a/src/mongo/s/catalog/type_mongos.h +++ b/src/mongo/s/catalog/type_mongos.h @@ -30,6 +30,7 @@ #include #include +#include #include "mongo/db/jsobj.h" #include "mongo/util/time_support.h" @@ -53,6 +54,7 @@ public: static const BSONField waiting; static const BSONField mongoVersion; static const BSONField configVersion; + static const BSONField advisoryHostFQDNs; /** * Returns the BSON representation of the entry. @@ -112,6 +114,11 @@ public: } void setConfigVersion(const long long configVersion); + std::vector getAdvisoryHostFQDNs() const { + return _advisoryHostFQDNs.value_or(std::vector()); + } + void setAdvisoryHostFQDNs(const std::vector& advisoryHostFQDNs); + private: // Convention: (M)andatory, (O)ptional, (S)pecial rule. @@ -127,6 +134,8 @@ private: boost::optional _mongoVersion; // (O) the config version of the pinging mongos boost::optional _configVersion; + // (O) the results of hostname canonicalization on the pinging mongos + boost::optional> _advisoryHostFQDNs; }; } // namespace mongo diff --git a/src/mongo/s/catalog/type_mongos_test.cpp b/src/mongo/s/catalog/type_mongos_test.cpp index 8fc449ab6f7..dad38d140cf 100644 --- a/src/mongo/s/catalog/type_mongos_test.cpp +++ b/src/mongo/s/catalog/type_mongos_test.cpp @@ -39,21 +39,24 @@ namespace { using namespace mongo; TEST(Validity, MissingName) { - BSONObj obj = - BSON(MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::uptime(100) - << MongosType::waiting(false) - << MongosType::mongoVersion("x.x.x") - << MongosType::configVersion(0)); + BSONObj obj = BSON(MongosType::ping(Date_t::fromMillisSinceEpoch(1)) + << MongosType::uptime(100) + << MongosType::waiting(false) + << MongosType::mongoVersion("x.x.x") + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_EQ(ErrorCodes::NoSuchKey, mongosTypeResult.getStatus()); } TEST(Validity, MissingPing) { - BSONObj obj = BSON(MongosType::name("localhost:27017") << MongosType::uptime(100) - << MongosType::waiting(false) - << MongosType::mongoVersion("x.x.x") - << MongosType::configVersion(0)); + BSONObj obj = BSON(MongosType::name("localhost:27017") + << MongosType::uptime(100) + << MongosType::waiting(false) + << MongosType::mongoVersion("x.x.x") + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_EQ(ErrorCodes::NoSuchKey, mongosTypeResult.getStatus()); @@ -64,7 +67,8 @@ TEST(Validity, MissingUp) { << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::waiting(false) << MongosType::mongoVersion("x.x.x") - << MongosType::configVersion(0)); + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_EQ(ErrorCodes::NoSuchKey, mongosTypeResult.getStatus()); @@ -75,7 +79,8 @@ TEST(Validity, MissingWaiting) { << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::uptime(100) << MongosType::mongoVersion("x.x.x") - << MongosType::configVersion(0)); + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_EQ(ErrorCodes::NoSuchKey, mongosTypeResult.getStatus()); @@ -86,7 +91,8 @@ TEST(Validity, MissingMongoVersion) { << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::uptime(100) << MongosType::waiting(false) - << MongosType::configVersion(0)); + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_OK(mongosTypeResult.getStatus()); @@ -104,7 +110,8 @@ TEST(Validity, MissingConfigVersion) { << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::uptime(100) << MongosType::waiting(false) - << MongosType::mongoVersion("x.x.x")); + << MongosType::mongoVersion("x.x.x") + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); auto mongosTypeResult = MongosType::fromBSON(obj); ASSERT_OK(mongosTypeResult.getStatus()); @@ -117,7 +124,7 @@ TEST(Validity, MissingConfigVersion) { ASSERT_OK(mtype.validate()); } -TEST(Validity, Valid) { +TEST(Validity, MissingAdvisoryHostFQDNs) { BSONObj obj = BSON(MongosType::name("localhost:27017") << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) << MongosType::uptime(100) @@ -126,8 +133,59 @@ TEST(Validity, Valid) { << MongosType::configVersion(0)); auto mongosTypeResult = MongosType::fromBSON(obj); + ASSERT_OK(mongosTypeResult.getStatus()); + MongosType& mType = mongosTypeResult.getValue(); + // advisoryHostFQDNs is optional + ASSERT_OK(mType.validate()); +} +TEST(Validity, EmptyAdvisoryHostFQDNs) { + BSONObj obj = BSON(MongosType::name("localhost:27017") + << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) + << MongosType::uptime(100) + << MongosType::waiting(false) + << MongosType::mongoVersion("x.x.x") + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSONArrayBuilder().arr())); + + auto mongosTypeResult = MongosType::fromBSON(obj); + ASSERT_OK(mongosTypeResult.getStatus()); + + MongosType& mType = mongosTypeResult.getValue(); + ASSERT_OK(mType.validate()); + + ASSERT_EQUALS(mType.getAdvisoryHostFQDNs().size(), 0UL); +} + +TEST(Validity, BadTypeAdvisoryHostFQDNs) { + BSONObj obj = BSON(MongosType::name("localhost:27017") + << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) + << MongosType::uptime(100) + << MongosType::waiting(false) + << MongosType::mongoVersion("x.x.x") + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSON_ARRAY("foo" << 0 << "baz"))); + + auto mongosTypeResult = MongosType::fromBSON(obj); + ASSERT_EQ(ErrorCodes::TypeMismatch, mongosTypeResult.getStatus()); +} + +TEST(Validity, Valid) { + BSONObj obj = BSON(MongosType::name("localhost:27017") + << MongosType::ping(Date_t::fromMillisSinceEpoch(1)) + << MongosType::uptime(100) + << MongosType::waiting(false) + << MongosType::mongoVersion("x.x.x") + << MongosType::configVersion(0) + << MongosType::advisoryHostFQDNs(BSON_ARRAY("foo" + << "bar" + << "baz"))); + + auto mongosTypeResult = MongosType::fromBSON(obj); + ASSERT_OK(mongosTypeResult.getStatus()); + + MongosType& mType = mongosTypeResult.getValue(); ASSERT_OK(mType.validate()); ASSERT_EQUALS(mType.getName(), "localhost:27017"); @@ -136,6 +194,10 @@ TEST(Validity, Valid) { ASSERT_EQUALS(mType.getWaiting(), false); ASSERT_EQUALS(mType.getMongoVersion(), "x.x.x"); ASSERT_EQUALS(mType.getConfigVersion(), 0); + ASSERT_EQUALS(mType.getAdvisoryHostFQDNs().size(), 3UL); + ASSERT_EQUALS(mType.getAdvisoryHostFQDNs()[0], "foo"); + ASSERT_EQUALS(mType.getAdvisoryHostFQDNs()[1], "bar"); + ASSERT_EQUALS(mType.getAdvisoryHostFQDNs()[2], "baz"); } TEST(Validity, BadType) { diff --git a/src/mongo/s/sharding_uptime_reporter.cpp b/src/mongo/s/sharding_uptime_reporter.cpp index 61a438dd93e..a7eefc14e03 100644 --- a/src/mongo/s/sharding_uptime_reporter.cpp +++ b/src/mongo/s/sharding_uptime_reporter.cpp @@ -42,6 +42,7 @@ #include "mongo/util/exit.h" #include "mongo/util/log.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/net/hostname_canonicalization.h" #include "mongo/util/net/sock.h" #include "mongo/util/version.h" @@ -50,15 +51,18 @@ namespace { const Seconds kUptimeReportInterval(10); -std::string constructInstanceIdString() { - return str::stream() << getHostNameCached() << ":" << serverGlobalParams.port; +std::string constructInstanceIdString(const std::string& hostName) { + return str::stream() << hostName << ":" << serverGlobalParams.port; } /** * Reports the uptime status of the current instance to the config.pings collection. This method * is best-effort and never throws. */ -void reportStatus(OperationContext* txn, const std::string& instanceId, const Timer& upTimeTimer) { +void reportStatus(OperationContext* txn, + const std::string& instanceId, + const std::string& hostName, + const Timer& upTimeTimer) { MongosType mType; mType.setName(instanceId); mType.setPing(jsTime()); @@ -66,6 +70,8 @@ void reportStatus(OperationContext* txn, const std::string& instanceId, const Ti // balancer is never active in mongos. Here for backwards compatibility only. mType.setWaiting(true); mType.setMongoVersion(VersionInfoInterface::instance().version().toString()); + mType.setAdvisoryHostFQDNs( + getHostFQDNs(hostName, HostnameCanonicalizationMode::kForwardAndReverse)); try { Grid::get(txn)->catalogClient(txn)->updateConfigDocument( @@ -95,13 +101,14 @@ void ShardingUptimeReporter::startPeriodicThread() { _thread = stdx::thread([this] { Client::initThread("Uptime reporter"); - const std::string instanceId(constructInstanceIdString()); + const std::string hostName(getHostNameCached()); + const std::string instanceId(constructInstanceIdString(hostName)); const Timer upTimeTimer; while (!inShutdown()) { { auto txn = cc().makeOperationContext(); - reportStatus(txn.get(), instanceId, upTimeTimer); + reportStatus(txn.get(), instanceId, hostName, upTimeTimer); auto status = Grid::get(txn.get())->getBalancerConfiguration()->refreshAndCheck(txn.get()); -- cgit v1.2.1