summaryrefslogtreecommitdiff
path: root/jstests/free_mon/libs
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/free_mon/libs')
-rw-r--r--jstests/free_mon/libs/free_mon.js331
-rw-r--r--jstests/free_mon/libs/mock_http_common.py24
-rw-r--r--jstests/free_mon/libs/mock_http_control.py52
-rw-r--r--jstests/free_mon/libs/mock_http_server.py306
4 files changed, 0 insertions, 713 deletions
diff --git a/jstests/free_mon/libs/free_mon.js b/jstests/free_mon/libs/free_mon.js
deleted file mode 100644
index 269f1e65306..00000000000
--- a/jstests/free_mon/libs/free_mon.js
+++ /dev/null
@@ -1,331 +0,0 @@
-
-/**
- * Control the Free Monitoring Mock Webserver.
- */
-
-// These faults must match the list of faults in mock_http_server.py, see the
-// SUPPORTED_FAULT_TYPES list in mock_http_server.py
-const FAULT_FAIL_REGISTER = "fail_register";
-const FAULT_INVALID_REGISTER = "invalid_register";
-const FAULT_HALT_METRICS_5 = "halt_metrics_5";
-const FAULT_PERMANENTLY_DELETE_AFTER_3 = "permanently_delete_after_3";
-const FAULT_RESEND_REGISTRATION_AT_3 = "resend_registration_at_3";
-const FAULT_RESEND_REGISTRATION_ONCE = "resend_registration_once";
-
-const DISABLE_FAULTS = "disable_faults";
-const ENABLE_FAULTS = "enable_faults";
-
-class FreeMonWebServer {
- /**
- * Create a new webserver.
- *
- * @param {string} fault_type
- * @param {bool} disableFaultsOnStartup optionally disable fault on startup
- */
- constructor(fault_type, disableFaultsOnStartup) {
- this.python = "python3";
- this.disableFaultsOnStartup = disableFaultsOnStartup || false;
- this.fault_type = fault_type;
-
- if (_isWindows()) {
- this.python = "python.exe";
- }
-
- print("Using python interpreter: " + this.python);
- this.web_server_py = "jstests/free_mon/libs/mock_http_server.py";
- this.control_py = "jstests/free_mon/libs/mock_http_control.py";
-
- this.pid = undefined;
- this.port = -1;
- }
-
- /**
- * Get the Port.
- *
- * @return {number} port number of http server
- */
- getPort() {
- return port;
- }
-
- /**
- * Get the URL.
- *
- * @return {string} url of http server
- */
- getURL() {
- return "http://localhost:" + this.port;
- }
-
- /**
- * Start the Mock HTTP Server.
- */
- start() {
- this.port = allocatePort();
- print("Mock Web server is listening on port: " + this.port);
-
- let args = [this.python, "-u", this.web_server_py, "--port=" + this.port];
- if (this.fault_type) {
- args.push("--fault=" + this.fault_type);
- if (this.disableFaultsOnStartup) {
- args.push("--disable-faults");
- }
- }
-
- clearRawMongoProgramOutput();
-
- this.pid = _startMongoProgram({args: args});
-
- assert(checkProgram(this.pid));
-
- // Wait for the web server to start
- assert.soon(function() {
- return rawMongoProgramOutput().search("Mock Web Server Listening") !== -1;
- });
-
- print("Mock HTTP Server sucessfully started.");
- }
-
- /**
- * Stop the Mock HTTP Server.
- */
- stop() {
- stopMongoProgramByPid(this.pid);
- }
-
- /**
- * Query the HTTP server.
- *
- * @param {string} query type
- *
- * @return {object} Object representation of JSON from the server.
- */
- query(query) {
- const out_file = "out_" + this.port + ".txt";
- const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
- " --query=" + query + " > " + out_file;
-
- let ret = 0;
- if (_isWindows()) {
- ret = runProgram('cmd.exe', '/c', python_command);
- } else {
- ret = runProgram('/bin/sh', '-c', python_command);
- }
-
- assert.eq(ret, 0);
-
- const result = cat(out_file);
-
- try {
- return JSON.parse(result);
- } catch (e) {
- jsTestLog("Failed to parse: " + result + "\n" + result);
- throw e;
- }
- }
-
- /**
- * Control the HTTP server.
- *
- * @param {string} query type
- */
- control(query) {
- const out_file = "out_" + this.port + ".txt";
- const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
- " --query=" + query + " > " + out_file;
-
- let ret = 0;
- if (_isWindows()) {
- ret = runProgram('cmd.exe', '/c', python_command);
- } else {
- ret = runProgram('/bin/sh', '-c', python_command);
- }
-
- assert.eq(ret, 0);
- }
-
- /**
- * Disable Faults
- */
- disableFaults() {
- this.control(DISABLE_FAULTS);
- }
-
- /**
- * Enable Faults
- */
- enableFaults() {
- this.control(ENABLE_FAULTS);
- }
-
- /**
- * Query the stats page for the HTTP server.
- *
- * @return {object} Object representation of JSON from the server.
- */
- queryStats() {
- return this.query("stats");
- }
-
- /**
- * Wait for N register calls to be received by web server.
- *
- * @throws assert.soon() exception
- */
- waitRegisters(count) {
- const qs = this.queryStats.bind(this);
- const port = this.port;
- // Wait for registration to occur
- assert.soon(function() {
- const stats = qs();
- print("w" + port + "| waiting for registers >= (" + count + ") QS : " + tojson(stats));
- return stats.registers >= count;
- }, "Failed to web server register", 60 * 1000);
- }
-
- /**
- * Wait for N metrics calls to be received by web server.
- *
- * @throws assert.soon() exception
- */
- waitMetrics(count) {
- const qs = this.queryStats.bind(this);
- const port = this.port;
- // Wait for metrics uploads to occur
- assert.soon(function() {
- const stats = qs();
- print("w" + port + "| waiting for metrics >= (" + count + ") QS : " + tojson(stats));
- return stats.metrics >= count;
- }, "Failed to web server metrics", 60 * 1000);
- }
-
- /**
- * Wait for N fault calls to e received by web server.
- *
- * @throws assert.soon() exception
- */
- waitFaults(count) {
- const qs = this.queryStats.bind(this);
- const port = this.port;
- // Wait for faults to be triggered
- assert.soon(function() {
- const stats = qs();
- print("w" + port + "| waiting for faults >= (" + count + ") QS : " + tojson(stats));
- return stats.faults >= count;
- }, "Failed to web server faults", 60 * 1000);
- }
-}
-
-/**
- * Wait for registration information to be populated in the database.
- *
- * @param {object} conn
- * @param {string} state
- */
-function WaitForDiskState(conn, state) {
- 'use strict';
-
- const admin = conn.getDB("admin");
-
- // Wait for registration to occur
- assert.soon(function() {
- const docs = admin.system.version.find({_id: "free_monitoring"});
- const da = docs.toArray();
- return da.length === 1 && da[0].state === state;
- }, "Failed to disk state", 60 * 1000);
-}
-
-/**
- * Wait for registration information to be populated in the database.
- *
- * @param {object} conn
- */
-function WaitForRegistration(conn) {
- WaitForDiskState(conn, 'enabled');
-}
-
-/**
- * Wait for unregistration information to be populated in the database.
- *
- * @param {object} conn
- */
-function WaitForUnRegistration(conn) {
- WaitForDiskState(conn, 'disabled');
-}
-
-/**
- * Get registration document.
- *
- * @param {object} registration document
- */
-function FreeMonGetRegistration(conn) {
- 'use strict';
-
- const admin = conn.getDB("admin");
- const docs = admin.system.version.find({_id: "free_monitoring"});
- const da = docs.toArray();
- return da[0];
-}
-
-/**
- * Get current Free Monitoring Status via serverStatus.
- *
- * @param {object} serverStatus.freeMonitoring section
- */
-function FreeMonGetServerStatus(conn) {
- 'use strict';
-
- const admin = conn.getDB("admin");
- return assert.commandWorked(admin.runCommand({serverStatus: 1})).freeMonitoring;
-}
-
-/**
- * Get current Free Monitoring Status via getFreeMonitoringStatus.
- *
- * @param {object} getFreeMonitoringStatus document
- */
-function FreeMonGetStatus(conn) {
- 'use strict';
-
- const admin = conn.getDB("admin");
- return assert.commandWorked(admin.runCommand({getFreeMonitoringStatus: 1}));
-}
-
-/**
- * Wait for server status state
- *
- * @param {object} conn
- * @param {string} state
- */
-function WaitForFreeMonServerStatusState(conn, state) {
- 'use strict';
-
- // Wait for registration to occur
- assert.soon(
- function() {
- let status = FreeMonGetServerStatus(conn).state;
- return status === state;
- },
- "Failed to find expected server status state: expected: '" + state +
- "', actual: " + tojson(FreeMonGetServerStatus(conn)),
- 20 * 1000);
-}
-
-/**
- * Validate Free Monitoring Replica Set consistency
- * WARNING: Not valid if secondary is started with enableFreeMonitoring since it registers before it
- * joins the replica set.
- *
- * @param {object} rst
- */
-function ValidateFreeMonReplicaSet(rst) {
- 'use strict';
-
- const primary_status = FreeMonGetStatus(rst.getPrimary());
- const primary_url = primary_status.url;
- const secondary_status = FreeMonGetStatus(rst.getSecondary());
- const secondary_url = secondary_status.url;
- assert.eq(primary_url,
- secondary_url,
- `DUMP ${tojson(primary_status)} == ${tojson(secondary_status)}`);
-}
diff --git a/jstests/free_mon/libs/mock_http_common.py b/jstests/free_mon/libs/mock_http_common.py
deleted file mode 100644
index 14cc6ba5a21..00000000000
--- a/jstests/free_mon/libs/mock_http_common.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""Common code for mock free monitoring http endpoint."""
-import json
-
-URL_PATH_STATS = "/stats"
-URL_PATH_LAST_REGISTER = "/last_register"
-URL_PATH_LAST_METRICS = "/last_metrics"
-URL_DISABLE_FAULTS = "/disable_faults"
-URL_ENABLE_FAULTS = "/enable_faults"
-
-
-class Stats:
- """Stats class shared between client and server."""
-
- def __init__(self):
- self.register_calls = 0
- self.metrics_calls = 0
- self.fault_calls = 0
-
- def __repr__(self):
- return json.dumps({
- 'metrics': self.metrics_calls,
- 'registers': self.register_calls,
- 'faults': self.fault_calls,
- })
diff --git a/jstests/free_mon/libs/mock_http_control.py b/jstests/free_mon/libs/mock_http_control.py
deleted file mode 100644
index 778450dd374..00000000000
--- a/jstests/free_mon/libs/mock_http_control.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#! /usr/bin/env python3
-"""
-Python script to interact with mock free monitoring HTTP server.
-"""
-
-import argparse
-import json
-import logging
-import sys
-import urllib.request
-
-import mock_http_common
-
-
-def main():
- """Main entry point."""
- parser = argparse.ArgumentParser(description='MongoDB Mock Free Monitoring Endpoint.')
-
- parser.add_argument('-p', '--port', type=int, default=8000, help="Port to listen on")
-
- parser.add_argument('-v', '--verbose', action='count', help="Enable verbose tracing")
-
- parser.add_argument('--query', type=str, help="Query endpoint <name>")
-
- args = parser.parse_args()
- if args.verbose:
- logging.basicConfig(level=logging.DEBUG)
-
- url_str = "http://localhost:" + str(args.port)
- if args.query == "stats":
- url_str += mock_http_common.URL_PATH_STATS
- elif args.query == "last_register":
- url_str += mock_http_common.URL_PATH_LAST_REGISTER
- elif args.query == "last_metrics":
- url_str += mock_http_common.URL_PATH_LAST_METRICS
- elif args.query == "disable_faults":
- url_str += mock_http_common.URL_DISABLE_FAULTS
- elif args.query == "enable_faults":
- url_str += mock_http_common.URL_ENABLE_FAULTS
- else:
- print("Unknown query type")
- sys.exit(1)
-
- with urllib.request.urlopen(url_str) as f:
- print(f.read().decode('utf-8'))
-
- sys.exit(0)
-
-
-if __name__ == '__main__':
-
- main()
diff --git a/jstests/free_mon/libs/mock_http_server.py b/jstests/free_mon/libs/mock_http_server.py
deleted file mode 100644
index 7bfd8974c59..00000000000
--- a/jstests/free_mon/libs/mock_http_server.py
+++ /dev/null
@@ -1,306 +0,0 @@
-#! /usr/bin/env python3
-"""Mock Free Monitoring Endpoint."""
-
-import argparse
-import collections
-import http.server
-import json
-import logging
-import socketserver
-import sys
-import urllib.parse
-
-import bson
-from bson.codec_options import CodecOptions
-from bson.json_util import dumps
-import mock_http_common
-
-# Pass this data out of band instead of storing it in FreeMonHandler since the
-# BaseHTTPRequestHandler does not call the methods as object methods but as class methods. This
-# means there is not self.
-stats = mock_http_common.Stats()
-last_metrics = None
-last_register = None
-disable_faults = False
-fault_type = None
-"""Fault which causes the server to return an HTTP failure on register."""
-FAULT_FAIL_REGISTER = "fail_register"
-"""Fault which causes the server to return a response with a document with a bad version."""
-FAULT_INVALID_REGISTER = "invalid_register"
-"""Fault which causes metrics to return halt after 5 metric uploads have occurred."""
-FAULT_HALT_METRICS_5 = "halt_metrics_5"
-"""Fault which causes metrics to return permanentlyDelete = true after 3 uploads."""
-FAULT_PERMANENTLY_DELETE_AFTER_3 = "permanently_delete_after_3"
-"""Fault which causes metrics to trigger resentRegistration at 3 uploads."""
-FAULT_RESEND_REGISTRATION_AT_3 = "resend_registration_at_3"
-"""Fault which causes metrics to trigger resentRegistration once."""
-FAULT_RESEND_REGISTRATION_ONCE = "resend_registration_once"
-
-# List of supported fault types
-SUPPORTED_FAULT_TYPES = [
- FAULT_FAIL_REGISTER,
- FAULT_INVALID_REGISTER,
- FAULT_HALT_METRICS_5,
- FAULT_PERMANENTLY_DELETE_AFTER_3,
- FAULT_RESEND_REGISTRATION_AT_3,
- FAULT_RESEND_REGISTRATION_ONCE,
-]
-
-# Supported POST URL types
-URL_POST_REGISTER = '/register'
-URL_POST_METRICS = '/metrics'
-
-
-class FreeMonHandler(http.server.BaseHTTPRequestHandler):
- """
- Handle requests from Free Monitoring and test commands
- """
-
- def do_GET(self):
- """Serve a Test GET request."""
- parts = urllib.parse.urlsplit(self.path)
- path = parts[2]
-
- if path == mock_http_common.URL_PATH_STATS:
- self._do_stats()
- elif path == mock_http_common.URL_PATH_LAST_REGISTER:
- self._do_last_register()
- elif path == mock_http_common.URL_PATH_LAST_METRICS:
- self._do_last_metrics()
- elif path == mock_http_common.URL_DISABLE_FAULTS:
- self._do_disable_faults()
- elif path == mock_http_common.URL_ENABLE_FAULTS:
- self._do_enable_faults()
- else:
- self.send_response(http.HTTPStatus.NOT_FOUND)
- self.end_headers()
- self.wfile.write("Unknown URL".encode())
-
- def do_POST(self):
- """Serve a Free Monitoring POST request."""
- parts = urllib.parse.urlsplit(self.path)
- path = parts[2]
-
- if path == URL_POST_REGISTER:
- self._do_registration()
- elif path == URL_POST_METRICS:
- self._do_metrics()
- else:
- self.send_response(http.HTTPStatus.NOT_FOUND)
- self.end_headers()
- self.wfile.write("Unknown URL".encode())
-
- def _send_header(self):
- self.send_response(http.HTTPStatus.OK)
- self.send_header("content-type", "application/octet-stream")
- self.end_headers()
-
- def _do_registration(self):
- global stats
- global last_register
- clen = int(self.headers.get('content-length'))
-
- stats.register_calls += 1
-
- raw_input = self.rfile.read(clen)
- decoded_doc = bson.BSON.decode(raw_input)
- last_register = dumps(decoded_doc)
-
- if not disable_faults and fault_type == FAULT_FAIL_REGISTER:
- stats.fault_calls += 1
- self.send_response(http.HTTPStatus.INTERNAL_SERVER_ERROR)
- self.send_header("content-type", "application/octet-stream")
- self.end_headers()
- self.wfile.write("Internal Error of some sort.".encode())
- return
-
- if not disable_faults and fault_type == FAULT_INVALID_REGISTER:
- stats.fault_calls += 1
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(42),
- 'haltMetricsUploading': False,
- 'id': '',
- 'informationalURL': 'http://www.example.com/123',
- 'message': 'Welcome to the Mock Free Monitoring Endpoint',
- 'reportingInterval': bson.int64.Int64(1),
- })
- else:
- reg_id = 'mock123_' + str(stats.register_calls)
- if 'id' in decoded_doc:
- reg_id = decoded_doc['id']
-
- data = bson.BSON.encode({
- 'version':
- bson.int64.Int64(1),
- 'haltMetricsUploading':
- False,
- 'id':
- reg_id,
- 'informationalURL':
- 'http://www.example.com/' + reg_id,
- 'message':
- 'Welcome to the Mock Free Monitoring Endpoint',
- 'reportingInterval':
- bson.int64.Int64(1),
- 'userReminder':
- """To see your monitoring data, navigate to the unique URL below.
-Anyone you share the URL with will also be able to view this page.
-
-https://localhost:8080/someUUID6v5jLKTIZZklDvN5L8sZ
-
-You can disable monitoring at any time by running db.disableFreeMonitoring().""",
- })
-
- self._send_header()
-
- self.wfile.write(data)
-
- def _do_metrics(self):
- global stats
- global last_metrics
- clen = int(self.headers.get('content-length'))
-
- stats.metrics_calls += 1
-
- raw_input = self.rfile.read(clen)
- decoded_doc = bson.BSON.decode(raw_input)
- last_metrics = dumps(decoded_doc)
-
- if not disable_faults and \
- stats.metrics_calls > 5 and \
- fault_type == FAULT_HALT_METRICS_5:
- stats.fault_calls += 1
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(1),
- 'haltMetricsUploading': True,
- 'permanentlyDelete': False,
- 'id': 'mock123',
- 'reportingInterval': bson.int64.Int64(1),
- 'message': 'Thanks for all the metrics',
- })
- elif not disable_faults and \
- stats.metrics_calls > 3 and fault_type == FAULT_PERMANENTLY_DELETE_AFTER_3:
- stats.fault_calls += 1
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(1),
- 'haltMetricsUploading': False,
- 'permanentlyDelete': True,
- 'id': 'mock123',
- 'reportingInterval': bson.int64.Int64(1),
- 'message': 'Thanks for all the metrics',
- })
- elif not disable_faults and \
- stats.metrics_calls > 3 and \
- stats.fault_calls < 1 and fault_type == FAULT_RESEND_REGISTRATION_ONCE:
- stats.fault_calls += 1
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(2),
- 'haltMetricsUploading': False,
- 'permanentlyDelete': False,
- 'id': 'mock123',
- 'reportingInterval': bson.int64.Int64(1),
- 'message': 'Thanks for all the metrics',
- 'resendRegistration': True,
- })
- elif not disable_faults and \
- stats.metrics_calls == 3 and fault_type == FAULT_RESEND_REGISTRATION_AT_3:
- stats.fault_calls += 1
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(2),
- 'haltMetricsUploading': False,
- 'permanentlyDelete': False,
- 'id': 'mock123',
- 'reportingInterval': bson.int64.Int64(1),
- 'message': 'Thanks for all the metrics',
- 'resendRegistration': True,
- })
- else:
- data = bson.BSON.encode({
- 'version': bson.int64.Int64(1),
- 'haltMetricsUploading': False,
- 'permanentlyDelete': False,
- 'id': decoded_doc['id'],
- 'reportingInterval': bson.int64.Int64(1),
- 'message': 'Thanks for all the metrics',
- })
-
- # TODO: test what if header is sent first?
- self._send_header()
-
- self.wfile.write(data)
-
- def _do_stats(self):
- self._send_header()
-
- self.wfile.write(str(stats).encode('utf-8'))
-
- def _do_last_register(self):
- self._send_header()
-
- self.wfile.write(str(last_register).encode('utf-8'))
-
- def _do_last_metrics(self):
- self._send_header()
-
- self.wfile.write(str(last_metrics).encode('utf-8'))
-
- def _do_disable_faults(self):
- global disable_faults
- disable_faults = True
- self._send_header()
-
- def _do_enable_faults(self):
- global disable_faults
- disable_faults = False
- self._send_header()
-
-
-def run(port, server_class=http.server.HTTPServer, handler_class=FreeMonHandler):
- """Run web server."""
- server_address = ('', port)
-
- http.server.HTTPServer.protocol_version = "HTTP/1.1"
-
- httpd = server_class(server_address, handler_class)
-
- print("Mock Web Server Listening on %s" % (str(server_address)))
-
- httpd.serve_forever()
-
-
-def main():
- """Main Method."""
- global fault_type
- global disable_faults
-
- parser = argparse.ArgumentParser(description='MongoDB Mock Free Monitoring Endpoint.')
-
- parser.add_argument('-p', '--port', type=int, default=8000, help="Port to listen on")
-
- parser.add_argument('-v', '--verbose', action='count', help="Enable verbose tracing")
-
- parser.add_argument('--fault', type=str, help="Type of fault to inject")
-
- parser.add_argument('--disable-faults', action='store_true', help="Disable faults on startup")
-
- args = parser.parse_args()
- if args.verbose:
- logging.basicConfig(level=logging.DEBUG)
-
- if args.fault:
- if args.fault not in SUPPORTED_FAULT_TYPES:
- print("Unsupported fault type %s, supports types are %s" % (args.fault,
- SUPPORTED_FAULT_TYPES))
- sys.exit(1)
-
- fault_type = args.fault
-
- if args.disable_faults:
- disable_faults = True
-
- run(args.port)
-
-
-if __name__ == '__main__':
-
- main()