You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/10/11 17:11:07 UTC
[GitHub] dangogh closed pull request #2912: Converted CIAB ORT script into
more manageable package
dangogh closed pull request #2912: Converted CIAB ORT script into more manageable package
URL: https://github.com/apache/trafficcontrol/pull/2912
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 3f5384e8d..71cdc4742 100755
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -27,8 +27,8 @@
#
import os
import sys
-ortPath = os.path.dirname(__file__)
-ortPath = os.path.join(ortPath, '..', '..', 'infrastructure', 'cdn-in-a-box', 'edge')
+here = os.path.dirname(__file__)
+ortPath = os.path.join(here, '..', '..', 'infrastructure', 'cdn-in-a-box', 'ort')
ortPath = os.path.abspath(ortPath)
sys.path.insert(0, ortPath)
@@ -72,10 +72,12 @@ class DNSLexer(RegexLexer):
copyright = '2018, Apache Traffic Control'
author = 'Apache Traffic Control'
-# The short X.Y version
-version = ''
+with open(os.path.abspath(os.path.join(here, '..', '..', 'VERSION'))) as fd:
+ # The short X.Y version
+ version = fd.read().strip()
+
# The full version, including alpha/beta/rc tags
-release = '3'
+release = version
# -- General configuration ---------------------------------------------------
@@ -171,7 +173,6 @@ class DNSLexer(RegexLexer):
# The font size ('10pt', '11pt' or '12pt').
#
'pointsize': '12pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst
index 3fb0f2d11..04f12f0cd 100644
--- a/docs/source/development/index.rst
+++ b/docs/source/development/index.rst
@@ -23,7 +23,7 @@ Use this guide to start developing applications that consume the Traffic Control
building
traffic_ops
- ort/modules
+ ort/traffic_ops_ort
traffic_portal
traffic_router
traffic_monitor
diff --git a/docs/source/development/ort/traffic_ops_ort.configuration.rst b/docs/source/development/ort/traffic_ops_ort.configuration.rst
new file mode 100644
index 000000000..7ae908a60
--- /dev/null
+++ b/docs/source/development/ort/traffic_ops_ort.configuration.rst
@@ -0,0 +1,25 @@
+..
+..
+.. Licensed under the Apache License, Version 2.0 (the "License");
+.. you may not use this file except in compliance with the License.
+.. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+..
+
+traffic\_ops\_ort.configuration module
+======================================
+
+.. autodata:: traffic_ops_ort.configuration.HOSTNAME
+ :annotation:
+
+.. automodule:: traffic_ops_ort.configuration
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.main_routines.rst b/docs/source/development/ort/traffic_ops_ort.main_routines.rst
new file mode 100644
index 000000000..9d82c7621
--- /dev/null
+++ b/docs/source/development/ort/traffic_ops_ort.main_routines.rst
@@ -0,0 +1,22 @@
+..
+..
+.. Licensed under the Apache License, Version 2.0 (the "License");
+.. you may not use this file except in compliance with the License.
+.. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+..
+
+traffic\_ops\_ort.main\_routines module
+=======================================
+
+.. automodule:: traffic_ops_ort.main_routines
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.packaging.rst b/docs/source/development/ort/traffic_ops_ort.packaging.rst
new file mode 100644
index 000000000..72631685b
--- /dev/null
+++ b/docs/source/development/ort/traffic_ops_ort.packaging.rst
@@ -0,0 +1,22 @@
+..
+..
+.. Licensed under the Apache License, Version 2.0 (the "License");
+.. you may not use this file except in compliance with the License.
+.. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+..
+
+traffic\_ops\_ort.packaging module
+==================================
+
+.. automodule:: traffic_ops_ort.packaging
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/source/development/ort/traffic_ops_ort.rst b/docs/source/development/ort/traffic_ops_ort.rst
index c7bcae59e..b73897c0c 100644
--- a/docs/source/development/ort/traffic_ops_ort.rst
+++ b/docs/source/development/ort/traffic_ops_ort.rst
@@ -13,10 +13,22 @@
.. limitations under the License.
..
-traffic\_ops\_ort module
-========================
+traffic\_ops\_ort package
+=========================
-.. autodata:: traffic_ops_ort
+Submodules
+----------
+
+.. toctree::
+
+ traffic_ops_ort.configuration
+ traffic_ops_ort.main_routines
+ traffic_ops_ort.packaging
+ traffic_ops_ort.to_api
+ traffic_ops_ort.utils
+
+Module contents
+---------------
.. automodule:: traffic_ops_ort
:members:
diff --git a/docs/source/development/ort/traffic_ops_ort.to_api.rst b/docs/source/development/ort/traffic_ops_ort.to_api.rst
new file mode 100644
index 000000000..c1bc920dc
--- /dev/null
+++ b/docs/source/development/ort/traffic_ops_ort.to_api.rst
@@ -0,0 +1,22 @@
+..
+..
+.. Licensed under the Apache License, Version 2.0 (the "License");
+.. you may not use this file except in compliance with the License.
+.. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+..
+
+traffic\_ops\_ort.to\_api module
+================================
+
+.. automodule:: traffic_ops_ort.to_api
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/source/development/ort/modules.rst b/docs/source/development/ort/traffic_ops_ort.utils.rst
similarity index 78%
rename from docs/source/development/ort/modules.rst
rename to docs/source/development/ort/traffic_ops_ort.utils.rst
index c9788110b..ad7433ac4 100644
--- a/docs/source/development/ort/modules.rst
+++ b/docs/source/development/ort/traffic_ops_ort.utils.rst
@@ -13,10 +13,10 @@
.. limitations under the License.
..
-edge
-====
+traffic\_ops\_ort.utils module
+==============================
-.. toctree::
- :maxdepth: 4
-
- traffic_ops_ort
+.. automodule:: traffic_ops_ort.utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/infrastructure/cdn-in-a-box/Makefile b/infrastructure/cdn-in-a-box/Makefile
index c553be4aa..583b7d562 100644
--- a/infrastructure/cdn-in-a-box/Makefile
+++ b/infrastructure/cdn-in-a-box/Makefile
@@ -54,7 +54,7 @@ TR_SOURCE := $(wildcard ../../traffic_router/**/*)
.PHONY: clean very-clean all nearly-all
# Default target; builds all pre-requisite rpms from source trees
-all: traffic_monitor/traffic_monitor.rpm traffic_portal/traffic_portal.rpm traffic_ops/traffic_ops.rpm mid/traffic_ops_ort.rpm edge/traffic_ops_ort.rpm traffic_router/traffic_router.rpm traffic_router/tomcat.rpm
+all: traffic_monitor/traffic_monitor.rpm traffic_portal/traffic_portal.rpm traffic_ops/traffic_ops.rpm traffic_router/traffic_router.rpm traffic_router/tomcat.rpm
# Actual output rpm recipies
traffic_monitor/traffic_monitor.rpm: ../../dist/traffic_monitor-$(SPECIAL_SAUCE)
diff --git a/infrastructure/cdn-in-a-box/cache/Dockerfile b/infrastructure/cdn-in-a-box/cache/Dockerfile
index 56584342b..5258b0555 100644
--- a/infrastructure/cdn-in-a-box/cache/Dockerfile
+++ b/infrastructure/cdn-in-a-box/cache/Dockerfile
@@ -35,7 +35,7 @@ RUN pip3 install --upgrade pip && pip3 install requests urllib3 distro
ADD traffic_server/plugins/astats_over_http/astats_over_http.c traffic_server/plugins/astats_over_http/Makefile.am /
RUN tsxs -v -c astats_over_http.c -o astats_over_http.so
-RUN mkdir -p /usr/libexec/trafficserver && tsxs -v -o astats_over_http.so -i
+RUN mkdir -p /usr/libexec/trafficserver /opt/ort && tsxs -v -o astats_over_http.so -i
RUN yum remove -y gcc-c++ glibc-devel autoconf automake libtool && rm -f /astats_over_http.c /Makefile.am
@@ -48,9 +48,10 @@ RUN mkdir -p /var/trafficserver /opt/ort && \
RUN setcap CAP_NET_BIND_SERVICE=+eip /bin/traffic_server && setcap CAP_NET_BIND_SERVICE=+eip /bin/traffic_manager && setcap CAP_NET_BIND_SERVICE=+eip /bin/trafficserver && setcap CAP_NET_BIND_SERVICE=+eip /bin/traffic_cop
-ADD infrastructure/cdn-in-a-box/edge/traffic_ops_ort.py /opt/ort/
-ADD infrastructure/cdn-in-a-box/cache/crontab /etc/cron.d/traffic_ops_ort-cron-template
+ADD infrastructure/cdn-in-a-box/ort /opt/ort/
-RUN touch /var/log/ort.log
+WORKDIR /opt/ort
+
+RUN touch /var/log/ort.log && pip3 install . && cp traffic_ops_ort.crontab /etc/cron.d/traffic_ops_ort-cron-template
CMD exit
diff --git a/infrastructure/cdn-in-a-box/edge/run.sh b/infrastructure/cdn-in-a-box/edge/run.sh
index d84e6d604..affb597ff 100755
--- a/infrastructure/cdn-in-a-box/edge/run.sh
+++ b/infrastructure/cdn-in-a-box/edge/run.sh
@@ -57,19 +57,13 @@ done
to-enroll edge $CDN || (while true; do echo "enroll failed."; sleep 3 ; done)
-function testenrolled() {
- local tmp="$(to-get 'api/1.3/servers?name=edge')"
- tmp=$(echo $tmp | jq '.response[]|select(.hostName=="edge")')
- echo "$tmp"
-}
-
while [[ -z "$(testenrolled)" ]]; do
echo "waiting on enrollment"
sleep 3
done
# Leaves the container hanging open in the event of a failure for debugging purposes
-/opt/ort/traffic_ops_ort.py BADASS ALL "https://$TO_FQDN:$TO_PORT" "$TO_ADMIN_USER:$TO_ADMIN_PASSWORD" || { echo "Failed"; }
+traffic_ops_ort -k BADASS ALL "https://$TO_FQDN:$TO_PORT" "$TO_ADMIN_USER:$TO_ADMIN_PASSWORD" || { echo "Failed"; }
envsubst < "/etc/cron.d/traffic_ops_ort-cron-template" > "/var/spool/cron/root" && rm -f "/etc/cron.d/traffic_ops_ort-cron-template"
crontab "/var/spool/cron/root"
@@ -82,4 +76,4 @@ done
crontab -r
touch /var/log/trafficserver/diags.log
-tail -F /var/log/trafficserver/diags.log
+tail -Fn +1 /var/log/trafficserver/diags.log
diff --git a/infrastructure/cdn-in-a-box/edge/traffic_ops_ort.py b/infrastructure/cdn-in-a-box/edge/traffic_ops_ort.py
deleted file mode 100755
index 810a4d317..000000000
--- a/infrastructure/cdn-in-a-box/edge/traffic_ops_ort.py
+++ /dev/null
@@ -1,1461 +0,0 @@
-#!/usr/bin/env python3
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-
-"""
-This script aims to be a drop-in replacement for the aged
-``traffic_ops_ort.pl`` script. Its primary purpose is for
-management of a cache server via configuration from
-Traffic Ops. This script will install/upgrade packages
-as necessary, will ensure services that ought to be running
-are running, and sets up ATS and ATS Plugin configuration files.
-"""
-
-
-import argparse
-import datetime
-import sys
-import os
-import platform
-import typing
-import logging
-import enum
-import subprocess
-import time
-import re
-
-needInstall = []
-
-try:
- import requests
-except ImportError:
- logging.error("You must have the 'requests' package installed to use this script.")
- logging.warning("(Hint: try `pip3 install requests`)")
- needInstall.append("requests")
-
-try:
- import urllib3
- urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
-except ImportError:
- logging.error("You must have the `urllib3` library installed to use this script.")
- logging.warning("(Needed by the `requests` package)")
- logging.warning("(Hint: try `pip3 install urllib3`)")
- needInstall.append("urllib3")
-
-try:
- import distro
- DISTRO = distro.LinuxDistribution().id()
-except ImportError:
- logging.error("You must have the `distro` package installed to use this script.")
- logging.warning("Hint: try `pip3 install distro`)")
- needInstall.append("distro")
-
-try:
- import psutil
-except ImportError:
- logging.error("You must have the `psutil` package installed to use this script.")
- logging.warning("(Hint: try `pip3 install psutil`)")
- needInstall.append("psutil")
-
-__version__ = "0.1"
-
-#: Holds the full URL including schema (e.g. 'http') and port that points at Traffic Ops
-TO_URL = None
-
-#: Holds the Traffic Ops login information as a JSON-encoded string
-TO_LOGIN = None
-
-#: Holds the Mojolicious cookie returned by Traffic Ops on successful login, and needed for
-#: subsequent requests.
-TO_COOKIE = None
-
-#: An absolute path to the root installation directory of Apache Trafficserver
-TS_ROOT = None
-
-#: A map of command-line log level options to :mod:`logging` log level constants
-LOG_LEVELS = {"ALL": logging.NOTSET,
- "DEBUG": logging.DEBUG,
- "INFO": logging.INFO,
- "WARN": logging.WARNING,
- "ERROR": logging.ERROR,
- "FATAL": logging.CRITICAL}
-
-#: A format specifier for logging output
-FMT = "%(levelname)s: line %(lineno)d in %(module)s.%(funcName)s: %(message)s"
-
-#: Contains the host's hostname as a tuple of ``(short_hostname, full_hostname)``
-HOSTNAME = (platform.node().split('.')[0], platform.node())
-
-class Modes(enum.IntEnum):
- """
- Enumerated run modes
- """
- REPORT = 0 #: Do nothing, only report what would be done
- INTERACTIVE = 1 #: Ask for user confirmation before modifying the system
- REVALIDATE = 2 #: Only check for config file changes and content revalidations
- SYNCDS = 3 #: Check for and apply Delivery Service changes
- BADASS = 4 #: Apply all settings specified in Traffic Ops, and attempt to solve all problems
-
- def __str__(self) -> str:
- """
- Implements ``str(self)`` by returning enum member's name
- """
- return self.name
-
-#: Stores the current Run Mode
-MODE = None
-
-class ORTException(Exception):
- """Represents an error while processing ORT API responses, etc."""
- pass
-
-#: This is the set of files which will require an ATS restart when changed
-ATS_FILES = {"records.config",
- "remap.config",
- "parent.config",
- "cache.config",
- "hosting.config",
- "astats.config",
- "logs_xml.config",
- "ssl_multicert.config"}
-
-#: Global state variable that tracks whether or not ATS should be restarted
-ATS_NEEDS_RESTART = False
-
-###############################################################################
-##### #####
-##### PYTHON DEPENDENCY HANDLING #####
-##### #####
-###############################################################################
-def installPythonPackages(packages:typing.List[str]) -> bool:
- """
- Attempts to install the packages listed in ``packages`` and
- add them to the global scope.
-
- :param packages: A list of missing Python dependencies
-
- :return: a truthy value indicating success.
- """
- logging.info("Attempting install of %s", ','.join(packages))
-
- # Ensure `pip` is installed
- try:
- import pip
- except ImportError as e:
- logging.info("`pip` package not installed. Attempting install with `ensurepip` module")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- import ensurepip
- try:
- ensurepip.bootstrap(altinstall=True)
- except (EnvironmentError, PermissionError) as err:
- logging.info("Permission Denied, attempting user-level install")
- logging.debug("%s", err, exc_info=True, stack_info=True)
- ensurepip.bootstrap(altinstall=True, user=True)
- import pip
-
- # Get main pip function
- try:
- pipmain = pip.main
- except AttributeError as e: # This happens when using a version of pip >= 10.0
- from pip._internal import main as pipmain
-
-
- # Attempt package install
- ret = pipmain(["install"] + packages)
- if ret == 1:
- logging.info("Possible 'Permission Denied' error, attempting user-level install")
- ret = pipmain(["install", "--user"] + packages)
-
- logging.debug("Pip return code was %d", ret)
- if not ret:
- import importlib
- for package in packages:
- try:
- globals()[package] = importlib.import_module(package)
- except ImportError:
- logging.error("Failed to import %s", package)
- logging.warning("Install appeared succesful - subsequent run may succeed")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return False
-
- urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
- globals()["DISTRO"] = distro.LinuxDistribution().id()
-
- return not ret
-
-def handleMissingPythonPackages(packages:typing.List[str]) -> bool:
- """
- Handles the case of missing packages, by installing them in :attr:`Modes.BADASS` mode,
- asking the user for confirmation in :attr:`Modes.INTERACTIVE` mode, and failing in all
- other run modes.
-
- Installs packages by calling :func:`installPythonPackages`.
-
- :param packages: A list of missing Python dependencies
- :return: A boolean indicator of success regarding the installation of missing dependencies
- """
- logging.info("Packages needed for this script but not installed: %s", ','.join(packages))
-
- if MODE == Modes.BADASS:
- logging.warning("Mode is BADASS - attempting to install missing packages")
- doInstall = True
- elif MODE == Modes.INTERACTIVE:
- print("The following packages are needed to run this script, but are not installed:")
- print(','.join(packages))
- choice = input("Would you like the script to attempt to install them now? [y/N]: ")
-
- while choice and choice.lower() not in {'y', 'n', 'yes', 'no'}:
- print("Invalid choice:", choice, file=sys.stderr)
- choice = input("Would you like the script to attempt to install them now? [y/N]: ")
-
- doInstall = choice and choice.lower() in {'y', 'yes'}
- else:
- logging.error("Cannot install packages in current run mode.")
- return False
-
- if doInstall:
- logging.warning("Installing python packages: %s", ','.join(packages))
- if installPythonPackages(packages):
- logging.info("Python packages installed successfully.")
- else:
- logging.critical("Missing Python packages could not be installed.")
- return False
- else:
- logging.critical("Packages %s missing and will not be installed - cannot continue",
- ','.join(packages))
- return False
-
- return True
-
-
-###############################################################################
-##### #####
-##### UTILITIES #####
-##### #####
-###############################################################################
-def getJSONResponse(uri:str, expectedStatus:int = 200) -> typing.Optional[object]:
- """
- Gets a JSON-encoded response to a Traffic Ops API ``GET`` request
-
- :param uri: The request URI, relative to :data:`TO_URL`
- :param expectedStatus: The expected status code of the response. If the actual response doesn't
- match, this function will return :const:`None`.
-
- :returns: On success, a parsed JSON object - or :const:`None` on failure.
- """
- global TO_URL, TO_COOKIE
-
- logging.info("Getting json response via 'HTTP GET %s%s", TO_URL, uri)
-
- response = requests.get(TO_URL + uri, cookies=TO_COOKIE, verify=False)
-
- if response.status_code != expectedStatus:
- logging.error("Failed to get a response from '%s': server returned status code %d",
- uri,
- response.status_code)
- logging.debug("Response: %s\n%r\n%r", response, response.headers, response.content)
- # For some applications, empty responses may be valid, so returning None rather than exiting.
- return None
-
- return response.json()
-
-def getRawResponse(uri:str,
- expectedStatus:int = 200,
- TOrelative:bool = True,
- verify:bool = False) -> typing.Optional[str]:
- """
- Gets the raw response body of an HTTP ``GET`` request - optionally one that is relative to
- :data:`TO_URL`.
-
- .. note:: Actually encodes to utf-8 string
-
- :param uri: The full (unless ``Torelative`` is :const:`True`) path to a resource for the request
- :param expectedStatus: The expected status code of the response. If the actual response doesn't
- match, this function will return :const:`None`
- :param TOrelative: If true, the ``uri`` will be treated as relative to :data:`TO_URL`
- :param verify: If true, the SSL keys used to communicate with the full URI will be verified
-
- :return: The body of the response on success, :const:`None` on failure
- """
- global TO_URL, TO_COOKIE
-
- if TOrelative:
- uri = TO_URL + uri
-
- response = requests.get(uri, cookies=TO_COOKIE, verify=verify)
- if response.status_code != expectedStatus:
- logging.error("Failed to get a response from '%s': server returned status code %d",
- uri,
- response.status_code)
- logging.debug("Response: %s\n%r\n%r", response, response.headers, response.content)
- return None
-
- return response.text
-
-def setStatusFile(statusDir:str, status:str, create:bool = False):
- """
- Removes all files in ``statusDir`` that aren't ``status``, and creates ``status``
- if it doesn't exist and `create` is True.
-
- :param statusDir: The absolute path to the directory for Traffic Ops status files
- :param status: The name of the status to be set
- :param create: If :const:`True`, a non-existant ``statusDir/status`` file will be created
- :raises OSError: when reading or writing to the status file fails
- """
- global MODE
-
- logging.info("Setting status file")
-
- if not os.path.isdir(statusDir):
- logging.info("Creating directory %s", statusDir)
- if MODE:
- os.mkdir(statusDir)
- else:
- try:
- statuses = getJSONResponse("/api/1.3/statuses")['response']
- except (KeyError, AttributeError) as e:
- logging.error("Bad API response from /api/1.3/statuses")
- logging.warning("Terminating status file creation/cleanup prematurely.")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return
-
- for stat in statuses:
- fname = os.path.join(statusDir, stat["name"])
- if stat != status and os.path.isfile(fname):
- logging.info("Removing %s", fname)
- if not MODE == Modes.REPORT:
- os.remove(fname)
-
- fname = os.path.join(statusDir, status)
- if create and not os.path.isfile(fname):
- logging.info("creating %s", fname)
- if MODE:
- with open(os.path.join(statusDir, status), "x"):
- pass
-
-#pylint: disable=R1710
-def startDaemon(args:typing.List[str], stdout:str='/dev/null', stderr:str='/dev/null') -> bool:
- """
- Starts a daemon process to execute an external command
-
- .. note:: this can only indicate the success of the first fork.
-
- The first fork will exit successfully as long as the second fork doesn't
- raise an OSError. The second fork will exit with the same returncode as
- the exec'd process.
-
- :param args: The command line to be executed. ``args[0]`` should be the name of the executable
- :param stdout: A filename to which the command's stdout will be re-directed
- :param stderr: A filename to which the command's stderr will be re-directed
-
- :returns: whether or not the fork succeeded
- """
-
- logging.debug("Forking a process - argv: '%s'", ' '.join(args))
-
- try:
- pid = os.fork()
- except OSError as e:
- logging.error("First fork failed - aborting")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return False
-
- if pid:
- # This is the parent
- return True
-
- # De-couple from parent environment
- os.chdir('/')
- try:
- os.setsid()
- except PermissionError:
- logging.debug("Failure to `setsid`: pid=%d, pgid=%d", os.getpid(), os.getpgid(os.getpid()))
- logging.debug("", exc_info=True, stack_info=True)
- os.umask(0)
- sys.stdin = open('/dev/null')
- sys.stdout = open(stdout, 'w')
- sys.stdout = open(stderr, 'w')
-
- # Do the second fork magic
-
- try:
- pid = os.fork()
- except OSError as e:
- logging.error("Error in forked process: %s", e)
- logging.debug("", exc_info=True, stack_info=True)
- exit(1)
-
- if pid:
- # This is the parent
- exit(0)
-
- # Now actually exec the program
- try:
- os.execvp(args[0], args[1:])
- except OSError:
- logging.critical("Failure to start %s", args[0])
- logging.debug("", exc_info=True, stack_info=True)
-
- # If somehow we get down here, it's time to bail
- exit(1)
-#pylint: enable=R1710
-
-def setATSStatus(status:bool, restart:bool = False) -> bool:
- """
- Sets the status of the system's ATS process.
-
- :param status: Specifies whether ATS should be running (:const:`True`) or not (:const:`False`)
- :param restart: If this is :const:`True`, then ATS will be restarted if it is already running
-
- .. note:: ``restart`` has no effect if ``status`` is :const:`False`
-
- :returns: whether or not the status setting was successful (or unnecessary)
- """
- global MODE, TS_ROOT
-
- logging.debug("Iterating process list")
-
- arg = None
- for process in psutil.process_iter():
-
- # Found an ATS process
- if process.name() == "[TS_MAIN]":
- logging.debug("ATS process found (pid: %d)", process.pid)
- ATSAlreadyRunning = process.status() in {psutil.STATUS_RUNNING, psutil.STATUS_SLEEPING}
-
- if status and ATSAlreadyRunning and restart:
- logging.info("ATS process found; restarting")
- arg = "restart"
- elif status and ATSAlreadyRunning:
- logging.info("ATS already running; nothing to do.")
- elif status:
- logging.warning("ATS process is running, but status is '%s' - restarting", process.status())
- arg = "restart"
- else:
- logging.warning("ATS is running; stopping ATS")
- arg = "stop"
-
- break
- else:
- if status:
- logging.warning("ATS not already running; starting ATS.")
- arg = "start"
- else:
- logging.info("ATS already not running; nothing to do.")
-
- if arg and MODE != "REPORT":
- tsexe = os.path.join(TS_ROOT, "bin", "trafficserver")
- sub = subprocess.Popen([tsexe, arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.error("Failed to start trafficserver!")
- logging.warning("Is the 'trafficserver' script located at %s?", tsexe)
- logging.debug(out.decode())
- logging.debug(err.decode())
- return False
-
- return True
-
-def getHeaderComment() -> str:
- """
- Gets the header for the Traffic Ops system
-
- :returns: The ``toolname`` field of the Traffic Ops header
- """
- response = getJSONResponse("/api/1.3/system/info.json")
- logging.debug("system/info.json response: %s", response)
-
- if response is None or \
- "response" not in response or \
- "parameters" not in response["response"] or \
- "tm.toolname" not in response["response"]["parameters"]:
- logging.error("Did not find tm.toolname!")
- return ''
-
- tmToolname = response["response"]["parameters"]["tm.toolname"]
- logging.info("Found tm.toolname: %s", tmToolname)
-
- return tmToolname
-
-def setTO_LOGIN(login:str) -> str:
- """
- Parses and returns a JSON-encoded login string for the Traffic Ops API.
- This will set :data:`TO_COOKIE` if login is successful.
-
- :param login: The raw login info as passed on the command line (e.g. 'username:password')
- :raises PermissionError: if the provided credentials are refused
- :returns: a JSON-encoded login object suitable for passing to the Traffic Ops API's login endpoint
- """
- global TO_COOKIE
-
- try:
- login = '{{"u": "{0}", "p": "{1}"}}'.format(*login.split(':'))
- except IndexError as e:
- logging.critical("Bad Traffic_Ops_Login: '%s' - should be like 'username:password'", login)
- raise ORTException()
-
- logging.debug("TO_LOGIN: %s", login)
-
- # Obtain login cookie
- cookie = requests.post(TO_URL + '/api/1.3/user/login', data=login, verify=False)
-
- if not cookie.cookies or 'mojolicious' not in cookie.cookies:
- logging.critical("Login credentials rejected by Traffic Ops")
- logging.error("Response code: %d", cookie.status_code)
- logging.warning("Response Headers: %s", cookie.headers)
- logging.debug("Response: %s", cookie.content)
- raise ORTException()
-
- TO_COOKIE = {"mojolicious": cookie.cookies["mojolicious"]}
-
- return login
-
-def getYesNoResponse(prmpt:str, default:str = None) -> bool:
- """
- Utility function to get an interactive yes/no response to the prompt `prmpt`
-
- :param prmpt: The prompt to display to users
- :param default: The default response; should be one of ``'y'``, ``"yes"``, ``'n'`` or ``"no"``
- (case insensitive)
- :returns: the parsed response as a boolean
- """
- if default:
- prmpt = prmpt.rstrip().rstrip(':') + '['+default+"]:"
- while True:
- choice = input(prmpt).lower()
-
- if choice in {'y', 'yes'}:
- return True
- elif choice in {'n', 'no'}:
- return False
- elif not choice and default is not None:
- return default.lower() in {'y', 'yes'}
-
- print("Please enter a yes/no response.", file=sys.stderr)
-
-###############################################################################
-##### #####
-##### MAIN MODE ROUTINES #####
-##### #####
-###############################################################################
-def syncDSState() -> bool:
- """
- Queries Traffic Ops for the Delivery Service's sync state.
-
- :raises ORTException: All possible errors are coalesced to this with a suitable error message
- :returns: :const:`True` if an update is needed, :const:`False` if it isn't.
- """
- global HOSTNAME
-
- logging.info("starting syncDS State fetch")
-
- try:
- updateStatus = getJSONResponse("/api/1.3/servers/%s/update_status" % HOSTNAME[0])[0]
- except IndexError as e:
- logging.critical("Server not found in Traffic Ops config")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- raise ORTException("Failed to contact API endpoint.")
-
- try:
- if not updateStatus['upd_pending']:
- logging.info("No update pending.")
- return False
-
- statusDir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "status")
- setStatusFile(statusDir, updateStatus['status'], create=True)
- except (KeyError, AttributeError) as e:
- logging.critical("Unsupported Traffic Ops version.")
- logging.warning("%s", e, exc_info=True)
- logging.debug("", stack_info=True)
- raise ORTException("Traffic Ops version not supported")
-
- return True
-
-def revalidate() -> int:
- """
- Performs revalidation.
-
- :returns: ``0`` indicates success, ``1`` indicates no revalidation was pending and ``2``
- indicates failure
- """
- global HOSTNAME
-
- logging.info("starting revalidation")
-
- try:
- updateStatus = getJSONResponse("/api/1.3/servers/%s/update_status" % HOSTNAME[0])[0]
- except IndexError as e:
- logging.critical("Server not found in Traffic Ops config")
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return 2
-
- logging.debug("updateStatus raw response: %s", updateStatus)
-
- try:
- if not updateStatus['reval_pending']:
- logging.info("No revalidation pending.")
- return 1
-
- if updateStatus['parent_reval_pending']:
- logging.critical("Parent revalidation is pending.")
- return 1
-
- statusDir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "status")
- setStatusFile(statusDir, updateStatus['status'])
- except (KeyError, AttributeError):
- logging.critical("Unsupported Traffic Ops version")
- logging.warning("%s", e, exc_info=True)
- logging.debug("%s", e, stack_info=True)
- return 2
-
- return 0
-
-def updateOps() -> int:
- """
- Updates Traffic Ops as needed
-
- :returns: An exit code for the main routine
- """
- global MODE, HOSTNAME, TO_URL, TO_COOKIE
-
- revalPending = revalidate() == 0
-
- if (MODE==Modes.INTERACTIVE and getYesNoResponse("Update Traffic Ops?", 'Y'))\
- or MODE!=Modes.REVALIDATE:
-
- logging.info("starting Traffic Ops update for upd_pending")
- payload = {"updated": False, "reval_updated": False}
- response = requests.post(TO_URL+"/update/%s" % HOSTNAME[0],
- cookies=TO_COOKIE,
- verify=False,
- data=payload)
-
- logging.debug("Raw response from Traffic Ops: %s\n%s\n%s",
- response,
- response.headers,
- response.content)
-
- elif MODE == Modes.REVALIDATE:
- logging.info("starting Traffic Ops update for reval_pending")
- payload = {"updated": False, "reval_updated": True}
- response = requests.post(TO_URL+"/update/%s" % HOSTNAME[0],
- cookies=TO_COOKIE,
- verify=False,
- data=payload)
-
- logging.debug("Raw response from Traffic Ops: %s\n%s\n%s",
- response,
- response.headers,
- response.content)
-
- else:
- logging.warning("Update will not be performed at this time; you should do this manually")
- return 0
-
-#: run modes mapped to handler functions
-HANDLERS = {"revalidate": revalidate,
- "syncds": lambda: None}
-
-
-###############################################################################
-##### #####
-##### PACKAGE MANAGEMENT #####
-##### #####
-###############################################################################
-
-########################
-### RedHat ###
-########################
-def RedHatInstalled(package:str, version:str = None) -> typing.List[str]:
- """
- RedHat-specific function to check for the existence of a package on the system
-
- :param package: the package name for which to check
- :param version: an optional version specification
-
- :returns: the list of packages installed by the name ``package``
- """
- logging.debug("Checking for RedHat-like package %s", package)
- arg = package if not version else package + '-' + version
-
- # This should never be done, but CentOS insists on being behind the rest of the
- # world, so done it must be.
- sub = subprocess.Popen(["/bin/rpm", "-q", arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- # logging.error("Failed to query rpm database for %s", package)
- logging.debug(out.decode())
- logging.debug(err.decode())
- return []
-
- return out.decode().split()
-
-def RedHatInstall(packages:typing.List[str]) -> bool:
- """
- RedHat-specific function to install a list of packages.
-
- :param packages: A list of package names (optionally concatenated with versions) to be installed
- :returns: whether or not all packages could be successfully installed
- """
- sub = subprocess.Popen(["/bin/yum", "install", "-y"] + packages,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.debug("yum stdout: %s", out.decode())
- logging.debug("yum stderr: %s", err.decode())
- return False
-
- logging.info("Successfully installed packages: %s", ", ".join(packages))
- return True
-
-def RedHatUninstall(packages:typing.List[str]) -> bool:
- """
- RedHat-specific function to uninstall a list of packages.
-
- :param packages: A list of packages to be uninstalled
- :returns: whether or not all packages could be successfully installed
- """
- sub = subprocess.Popen(["/bin/yum", "remove", "-y"] + packages,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.debug("yum stdout: %s", out.decode())
- logging.debug("yum stderr: %s", err.decode())
- return False
-
- logging.info("Successfully uninstalled packages: %s", ", ".join(packages))
- return True
-
-########################
-### Ubuntu ###
-########################
-def UbuntuInstalled(package:str, version:str = None) -> typing.List[str]:
- """
- Ubuntu-specific function to check for the existence of a package on the system
-
- :param package: the package name for which to check
- :param version: an optional version specification
-
- :returns: the list of packages installed by the name ``package``
- """
- logging.debug("Checking for Ubuntu-like package %s", package)
-
- sub = subprocess.Popen(["/usr/bin/dpkg", "-l", package],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.debug("dpkg stdout: %s", out.decode())
- logging.debug("dpkg stderr: %s", err.decode())
- return []
-
- try:
- out = [(p.split()[1], p.split()[2]) for p in out[5:].decode().splitlines() if p]
-
- if version is not None:
- # TODO - better version checking
- out = [p for p in out if version in p[1]]
-
- return [p[0] for p in out]
- except IndexError:
- logging.warning("Error encountered while processing installed Debian packages")
- logging.debug("Package: %s", package, exc_info=True, stack_info=True)
-
- return []
-
-def UbuntuInstall(packages:typing.List[str]) -> bool:
- """
- Ubuntu-specific function to install a list of packages.
-
- :param packages: A list of package names (optionally concatenated with versions) to be installed
- :returns: whether or not all packages could be successfully installed
- """
- sub = subprocess.Popen(["/usr/bin/apt-get", "install", "-y"] + packages,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.debug("apt-get stdout: %s", out.decode())
- logging.debug("apt-get stderr: %s", err.decode())
- return False
-
- logging.info("Successfully installed packages: %s", ", ".join(packages))
- return True
-
-def UbuntuUninstall(packages:typing.List[str]) -> bool:
- """
- Ubuntu-specific function to uninstall a list of packages.
-
- :param packages: A list of packages to be uninstalled
- :returns: whether or not all packages could be successfully installed
- """
- sub = subprocess.Popen(["/usr/bin/apt-get", "purge", "-y"] + packages,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- out, err = sub.communicate()
-
- if sub.returncode:
- logging.debug("apt-get stdout: %s", out.decode())
- logging.debug("apt-get stderr: %s", err.decode())
- return False
-
- logging.info("Successfully uninstalled packages: %s", ", ".join(packages))
- return True
-
-########################
-### Platform Mapping ###
-########################
-#: Maps distro names to functions that check for the existence of packages on those distros
-packageIsInstalled = {'centos': RedHatInstalled,
- 'fedora': RedHatInstalled,
- 'rhel': RedHatInstalled,
- 'ubuntu': UbuntuInstalled,
- 'linuxmint': UbuntuInstalled}
-
-#: Maps distro names to functions that install packages on those distros
-installPackage = {'centos': RedHatInstall,
- 'fedora': RedHatInstall,
- 'rhel': RedHatInstall,
- 'ubuntu': UbuntuInstall,
- 'linuxmint': UbuntuInstall}
-
-#: Maps distro names to functions that uninstall packages on those distros
-uninstallPackage = {'centos': RedHatUninstall,
- 'fedora': RedHatUninstall,
- 'rhel': RedHatUninstall,
- 'ubuntu': UbuntuUninstall,
- 'linuxmint': UbuntuUninstall}
-
-#: Maps distro names to the symbols that concatenate package names with version semantics for said
-#: distros
-packageConcat = {'centos': '-',
- 'fedora': '-',
- 'rhel': '-',
- 'ubuntu': '=',
- 'linuxmint': '='}
-
-def processPackages() -> bool:
- """
- Manages the packages that Traffic Ops reports are required for this server.
-
- :returns: whether or not the package processing was successfully completed
- """
- global HOSTNAME, DISTRO, MODE, packageIsInstalled, installPackage, packageConcat
-
- logging.info("Fetching packages from Traffic Ops")
- packages = getJSONResponse("/ort/%s/packages" % (HOSTNAME[0],))
- logging.info("Response: %s", packages)
-
- if packages is None:
- raise ConnectionError("Server or server packages not found on server!")
-
- install, uninstall = {p['name'] + packageConcat[DISTRO] + p['version'] for p in packages}, set()
- for package in packages:
- similarPackages = packageIsInstalled[DISTRO](package['name'])
-
- # An error occurred, and the package query failed (different than empty response)
- if similarPackages is None:
- logging.critical("Failed to check packages against system.")
- return False
-
- logging.debug("List of packages similar to %r: %r", package, similarPackages)
-
- # We check for the pre-existence of packages in two ways; one for
- # RedHat-based distros, and one for Debian/Ubuntu-based distros
-
- if any(p.startswith(
- package['name']+packageConcat[DISTRO]+package['version'])
- for p in similarPackages):
- logging.info("package %s is installed", package['name'])
- p = package['name'] + packageConcat[DISTRO] + package['version']
- logging.info("%s is no longer marked for install", p)
- install.remove(p)
- else:
- logging.info("%r all marked for uninstall", similarPackages)
- uninstall.update(similarPackages)
-
- logging.info("Marked %d packages for install and %d packages for uninstall.",
- len(install), len(uninstall))
-
- if not MODE == Modes.REPORT:
-
- logging.info("Installing packages...")
- if install:
- prompt = "Would you like to install the following packages: %s ?" % (", ".join(install))
- if MODE == Modes.INTERACTIVE and not getYesNoResponse(prompt):
- logging.critical("User chose not to install packages - cannot continue!")
- return False
-
- if not installPackage[DISTRO](list(install)):
- logging.critical("Failed to install packages, possibly permission denied?")
- return False
-
- logging.info("Done.")
-
-
- logging.info("Uninstalling packages...")
- if uninstall:
- prompt = "Would you like to remove the following packages: %s ?" % (", ".join(uninstall))
- if MODE == Modes.INTERACTIVE and not getYesNoResponse(prompt):
- logging.critical("User chose not to remove packages - cannot continue!")
- return False
-
- if not uninstallPackage[DISTRO](list(uninstall)):
- logging.critical("Failed to uninstall packages, possibly permission denied?")
- return False
-
- logging.info("Done.")
-
- return True
-
-def processChkconfig() -> bool:
- """
- Process the list of services Traffic Ops reports ought to be running on this system
-
- :returns: whether or not all services could be processed
-
- .. warning:: This actually only handles Apache Traffic Server at the moment
- """
- global HOSTNAME, MODE, DISTRO
-
- logging.info("Processesing Chkconfig...")
- chkconfig = getJSONResponse("/ort/%s/chkconfig" % HOSTNAME[0])
-
- if chkconfig is None:
- raise ConnectionError("Server or server chkconfig not found on server!")
-
- logging.debug("chkconfig response: %r", chkconfig)
-
- for item in chkconfig:
- logging.debug("Processing item: %r", item)
-
- # A special catch for ATS so we don't need to deal with systemd.
- if item['name'] == "trafficserver":
- if not setATSStatus("on" in item['value']):
- logging.critical("Failed to set ATS Status")
- return False
- else:
- logging.info("checking on service: %s", item['name'])
-
-
- return True
-
-
-###############################################################################
-##### #####
-##### CONFIGURATION #####
-##### #####
-###############################################################################
-def getConfigFiles() -> typing.List[str]:
- """
- Gets the list of configuration files used by this server's profile
-
- :returns: The list of configuration files used by this server as reported by Traffic Ops
- """
- global HOSTNAME
-
- logging.info("Retrieving configuration files.")
-
- files = getJSONResponse("/api/1.3/servers/%s/configfiles/ats" % (HOSTNAME[0],))
-
- if not files:
- logging.critical("Could not retrieve configuration files.")
- return None
-
- logging.debug("Config Files raw response: %s", files)
-
- return files
-
-def initBackup() -> bool:
- """
- Initializes a backup directory as a subdirectory of the directory containing
- this ORT script.
-
- :returns: whether or not the backup directory was successfully initialized
- """
- global MODE
-
- here = os.path.abspath(os.path.dirname(__file__))
- backupdir = os.path.join(here, "backup")
-
- logging.info("Initializing backup dir %s", backupdir)
-
- if not os.path.isdir(backupdir):
- if MODE != Modes.REPORT:
- try:
- os.mkdir(backupdir)
- except OSError:
- logging.error("Couldn't create backup dir")
- logging.warning("%s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
- else:
- logging.error("Cannot create non-existent backup dir in REPORT mode!")
- return True
-
- logging.info("Backup dir already exists - nothing to do")
- return True
-
-def mkbackup(fname:str, contents:str) -> bool:
- """
- Creates a backup of a specific file with its original contents.
-
- :param fname: The name of the file being backed up (basename only)
- :param contents: The file's original contents
- :returns: whether or not the backup succeeded
-
- .. note: will always return :const:`True` in :attr:`Modes.REPORT` mode.
- """
- global MODE
-
- if MODE == Modes.REPORT:
- logging.info("REPORT mode - nothing to do")
- return True
-
- backupfile = os.path.join(os.path.abspath(os.path.dirname(__file__)), "backup", fname)
- if os.path.isfile(backupfile):
- logging.warning("Clobbering existing backup file '%s'!", backupfile)
-
- try:
- with open(backupfile, 'w') as fd:
- fd.write(contents)
- except OSError as e:
- logging.warning("Failed to write backup file: %s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
-
- logging.info("Backup of %s written to %s", fname, backupfile)
- return True
-
-def stripComments(s) -> str:
- """
- Strips comments from a string
- """
- return re.sub(r'(?m)^\s*^ *<!--.*\n?', '', s)
-
-def updateConfig(directory:str, fname:str, contents:str) -> bool:
- """
- Updates a single configuration file
-
- This will make a backup in the `backup` subdirectory of the directory
- containing this script if the file on disk differs from ``contents``.
-
- :param directory: The directory which contains the configuration file
- :param fname: The basename of the configuration file
- :param contents: The contents which this file will hold
- :returns: whether or not the update was successful
-
- .. note:: "Success" is defined as being able to write the file contents and create any
- necessary backups if the run mode is not :attr:`Modes.BADASS` - in which case failure
- to back the file up is 'acceptable'.
-
- """
- global MODE, ATS_FILES, ATS_NEEDS_RESTART
-
- file = os.path.join(directory, fname)
-
- logging.info("Updating config file '%s'", file)
-
- if not os.path.isfile(file):
- if MODE != Modes.REPORT:
- logging.info("File does not exist - creating")
- try:
- with open(file, 'w') as fd:
- fd.write(contents)
- except OSError as e:
- logging.error("Couldn't write to file")
- logging.warning("%s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
-
- logging.info("File written.")
-
- return True
-
- logging.debug("Reading in file on disk")
- try:
- with open(file) as fd:
- diskContents = ''.join([line for line in fd.readlines()\
- if line and not line.startswith("# DO NOT EDIT")\
- and not line.startswith("# TRAFFIC OPS NOTE:")])
- except OSError:
- logging.warning("Couldn't read on-disk file: %s", e)
- logging.debug("", exc_info=True, stack_info=True)
- if MODE != Modes.BADASS:
- return False
-
- # Certain headers from Traffic Ops shouldn't be considered when checking for equality
- importantContents = '\n'.join([l for l in contents.split('\n')\
- if l and not l.startswith("# DO NOT EDIT")\
- and not l.startswith("# TRAFFIC OPS NOTE:")])
-
- if stripComments(diskContents.strip()) == stripComments(importantContents.strip()):
- logging.info("on-disk contents match Traffic Ops - nothing to do")
- return True
-
- if not mkbackup(os.path.basename(file), diskContents) and MODE != Modes.BADASS:
- logging.error("Failed to create backup.")
- return False
-
- try:
- with open(file, 'w') as fd:
- fd.write(contents + '\n' if not contents.endswith('\n') else contents)
- except OSError as e:
- logging.error("Failed to update config file '%s'", file)
- logging.warning("%s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
-
- # If update was needed and successful, then check if ats should be restarted
- if fname in ATS_FILES:
- ATS_NEEDS_RESTART = True
-
- logging.info("%s has been updated", file)
- return True
-
-def sanitizeContents(contents:str) -> str:
- """
- Sanitizes the input `contents` string to be a well-behaved config file.
- """
- out = []
- for line in contents.splitlines():
- tmp=(" ".join(line.split())).strip() #squeezes spaces and trims leading and trailing spaces
- tmp=tmp.replace("&", '&') #decodes HTML-encoded ampersands
- tmp=tmp.replace(">", '>') #decodes HTML-encoded greater-than symbols
- tmp=tmp.replace("<", '<') #decodes HTML-encoded less-than symbols
- out.append(tmp)
-
- return "\n".join(out)
-
-def processConfigFile(file:dict, port:int, ip:str) -> bool:
- """
- Process a given configuration file object to produce the specified contents
-
- :param file: An object representing a configuration file
- :param port: This server's TCP port
- :param ip: This server's IPv4 address
- :returns: whether or not the update was successful
- """
- global MODE, HOSTNAME, TO_URL
-
- try:
- fname = file['fnameOnDisk']
- scope = file['scope']
- location = file['location']
- uri, contents = None, None
- if 'apiUri' in file:
- uri = TO_URL + file['apiUri']
- elif 'url' in file:
- uri = file['url']
- else:
- contents = file['contents']
- except KeyError as e:
- logging.error("Malformed config file")
- logging.warning("%s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
-
- logging.info("======== Start processing config file: %s ========", fname)
-
- if not os.path.isdir(location):
- if MODE != Modes.REPORT:
- logging.debug("location '%s' doesn't exist; creating.")
-
- try:
- os.makedirs(location)
- except OSError as e:
- logging.error("Couldn't create directory %s", location)
- logging.warning("%s", e)
- logging.debug("", exc_info=True, stack_info=True)
- return False
- else:
- # Even though nothing was done and an error gets reported, we return a success here
- # because presumably everything would go fine were this not REPORT mode.
- logging.error("Cannot create dirs in REPORT mode!")
- return True
-
- # `contents` should only be `None` if `uri` is defined
- if contents is None:
- contents = getRawResponse(uri, TOrelative=False)
-
- if contents is None: #still...
- return False
-
- contents = contents.replace("__HOSTNAME__", HOSTNAME[0])
- contents = contents.replace("__FULL_HOSTNAME__", HOSTNAME[1])
- contents = contents.replace("__RETURN__", '\n')
- contents = contents.replace("__CACHE_IPV4__", ip)
-
- # Don't ask me why, but the reference ORT implementation just strips these ones out
- # if the tcp port is 80.
- contents = contents.replace("__SERVER_TCP_PORT__", str(port) if port != 80 else "")
-
- contents = sanitizeContents(contents)
-
- logging.debug("Sanitized file contents from Traffic Ops database:\n%s\n" % contents)
-
- logging.warning("Skipping pre-requisite checks - plugins may not be installed!!")
- logging.info("Dependent packages should be specified as profile parameters.")
-
- updateConfig(location, fname, contents)
-
- logging.info("======== End processing config file: %s ========", fname)
-
- return True
-
-def processConfigFiles(files:list, port:int, ip:str) -> bool:
- """
- Processes the passed JSON object containing configuration file definitions
-
- :param files: A list of configuration file objects
- :param port: This server's TCP port
- :param ip: This server's IPv4 address
- :returns: whether or not all configuration files could be processed
- """
- global MODE
-
- if not initBackup():
- return False
-
- for file in files:
- if not processConfigFile(file, port, ip):
- logging.error("Failed to process config file '%s'", file)
-
- if MODE != Modes.BADASS:
- return False
-
- logging.warning("We're in BADASS mode, attempting to continue")
-
- return True
-
-
-###############################################################################
-##### #####
-##### MAIN FLOW #####
-##### #####
-###############################################################################
-def doMain() -> int:
- """
- Performs operations based on the run mode.
- This can be thought of as the "true" main function.
-
- :returns: an exit code for the script
- """
- global MODE, ATS_NEEDS_RESTART
-
- headerComment = getHeaderComment()
-
- try:
- DSUpdateNeeded = syncDSState()
- except ORTException as e:
- logging.critical("Failed to get Update Pending from Traffic Ops: %s", e)
- return 1
-
- myFiles = getConfigFiles()
- if myFiles is None:
- return 1
- if "configFiles" not in myFiles or "info" not in myFiles:
- logging.critical("Malformed response from configfiles/ats endpoint - unable to continue")
- return 1
-
- try:
- # This is needed for templated responses from the config file API endpoints
- tcpPort = myFiles["info"]["serverTcpPort"]
- serverIpv4 = myFiles["info"]["serverIpv4"]
- except KeyError:
- logging.critical("Malformed response from configfiles/ats endpoint - unable to continue")
- logging.debug("", exc_info=True, stack_info=True)
- return 1
-
-
- try:
- if MODE == Modes.REVALIDATE:
- logging.info("======== Revalidating, no package processing needed ========")
- reval = revalidate()
- if reval:
- # Bail, possibly with an exit code
- return reval - 1
-
- else:
- logging.info("======== Start processing packages ========")
- if not processPackages():
- logging.critical("Unrecoverable error occurred when processing packages.")
- return 1
- logging.info("======== Start processing services ========")
- if not processChkconfig():
- logging.critical("Unrecoverable error occurred when processing services.")
- return 1
-
- if not processConfigFiles(myFiles["configFiles"], tcpPort, serverIpv4):
- logging.critical("Unrecoverable error occurred when processing config files")
- return 1
- except ConnectionError:
- logging.critical("Couldn't reach /ort/%s/* endpoints - "\
- "ensure %s points to Traffic OPS not Traffic PORTAL",
- HOSTNAME[0],
- TO_URL)
- return 1
-
- if ATS_NEEDS_RESTART:
- logging.info("Restarting ATS")
- if not setATSStatus(True, restart=True):
- logging.critical("Failed to restart ATS")
- return 1
- else:
- logging.info("ATS Restart unnecessary")
-
- if MODE != Modes.REPORT and DSUpdateNeeded:
- return updateOps()
-
- logging.info("Ops update unnecessary; exiting.")
-
- return 0
-
-def main() -> int:
- """
- Runs the program
-
- :returns: an exit code for the script
- """
- global TO_COOKIE, TO_LOGIN, TO_URL, LOG_LEVELS, MODE, needInstall, DISTRO, TS_ROOT, FMT
-
- # I have no idea why, but the old ORT script does this on every run.
- print(datetime.datetime.utcnow().strftime("%a %b %d %H:%M:%S UTC %Y"))
-
- parser = argparse.ArgumentParser(description="A Python-based TO_ORT implementation",
- epilog="Doesn't support the 'TRACE' or 'NONE' log levels.",
- formatter_class=argparse.ArgumentDefaultsHelpFormatter)
-
- parser.add_argument("Mode",
- help="REPORT: Do nothing, but print what would be done\n"\
- "")
- parser.add_argument("Log_Level",
- help="ALL, DEBUG, INFO, WARN, ERROR, FATAL",
- type=str)
- parser.add_argument("Traffic_Ops_URL",
- help="URL to Traffic Ops host. Example: https://trafficops.company.net",
- type=str)
- parser.add_argument("Traffic_Ops_Login",
- help="Example: 'username:password'")
- parser.add_argument("--dispersion",
- help="wait a random number between 0 and <dispersion> before starting.",
- type=int,
- default=300)
- parser.add_argument("--login_dispersion",
- help="wait a random number between 0 and <login_dispersion> before login.",
- type=int,
- default=0)
- parser.add_argument("--retries",
- help="retry connection to Traffic Ops URL <retries> times.",
- type=int,
- default=3)
- parser.add_argument("--wait_for_parents",
- help="do not update if parent_pending = 1 in the update json.",
- type=int,
- default=1)
- parser.add_argument("--rev_proxy_disabled",
- help="bypass the reverse proxy even if one has been configured.",
- type=int,
- default=0)
- parser.add_argument("--ts_root",
- help="Specify the root directory at which Apache Traffic Server is installed"\
- " (e.g. '/opt/trafficserver')",
- type=str,
- default="/")
- parser.add_argument("-v", "--version",
- action="version",
- version="%(prog)s v"+__version__,
- help="Print version information and exit.")
-
- args = parser.parse_args()
-
- logLevel = args.Log_Level.upper()
- if logLevel not in LOG_LEVELS:
- print("Unrecognized/Unsupported log level:", args.Log_Level, file=sys.stderr)
- return 1
-
- logging.basicConfig(level=LOG_LEVELS[logLevel], format=FMT)
- logging.getLogger().setLevel(LOG_LEVELS[logLevel])
-
- try:
- MODE = Modes[args.Mode.upper()]
- except KeyError as e:
- logging.critical("Unknown mode '%s'", args.Mode)
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return 1
-
- logging.info("Running in %s mode", MODE)
-
- if needInstall:
- if not handleMissingPythonPackages(needInstall):
- return 1
-
- tsroot = args.ts_root.strip()
- tsbin = os.path.join(tsroot, "bin", "traffic_server")
- if not os.path.isdir(tsroot) or not os.path.isfile(tsbin):
- logging.critical("Unable to find root Apache Traffic Server installation")
- logging.error("No such directory: '%s' or no such file: '%s", tsroot, tsbin)
- return 1
-
- TS_ROOT = args.ts_root
- logging.info(\
- "Traffic Server root is at %s\n\tDistro detected as '%s'\n\tHostname detected as '%s'",
- TS_ROOT,
- DISTRO,
- HOSTNAME[1])
-
- TO_URL = args.Traffic_Ops_URL.rstrip('/')
-
- logging.info("Traffic_Ops_URL: %s", TO_URL)
-
- if not TO_URL.startswith("http"):
- logging.critical("Malformed Traffic_Ops_URL: '%s' - "\
- "must include scheme (e.g. http://traffic.ops)", TO_URL)
- return 1
-
- # Litmus test to make sure the server exists and can be reached
- try:
- _ = requests.head(TO_URL, verify=False)
- except requests.exceptions.RequestException as e:
- logging.critical("Malformed or Invalid Traffic_Ops_URL")
- logging.error("%s", e)
- logging.debug("%s", e, exc_info=True, stack_info=True)
- return 1
-
- try:
- TO_LOGIN = setTO_LOGIN(args.Traffic_Ops_Login)
- except ORTException:
- return 1
-
- return doMain()
-
-
-if __name__ == '__main__':
- try:
- exit(main())
- except requests.exceptions.ConnectionError as e:
- print("Failed to connect to Traffic Ops:", e, file=sys.stderr)
- exit(1)
diff --git a/infrastructure/cdn-in-a-box/mid/run.sh b/infrastructure/cdn-in-a-box/mid/run.sh
index 27cf2b6ba..b707bc9f7 100755
--- a/infrastructure/cdn-in-a-box/mid/run.sh
+++ b/infrastructure/cdn-in-a-box/mid/run.sh
@@ -57,19 +57,13 @@ done
to-enroll mid $CDN || (while true; do echo "enroll failed."; sleep 3 ; done)
-function testenrolled() {
- local tmp="$(to-get 'api/1.3/servers?name=mid')"
- tmp=$(echo $tmp | jq '.response[]|select(.hostName=="mid")')
- echo "$tmp"
-}
-
while [[ -z "$(testenrolled)" ]]; do
echo "waiting on enrollment"
sleep 3
done
# Leaves the container hanging open in the event of a failure for debugging purposes
-/opt/ort/traffic_ops_ort.py BADASS ALL "https://$TO_FQDN:$TO_PORT" "$TO_ADMIN_USER:$TO_ADMIN_PASSWORD" || { echo "Failed"; }
+traffic_ops_ort -k BADASS ALL "https://$TO_FQDN:$TO_PORT" "$TO_ADMIN_USER:$TO_ADMIN_PASSWORD" || { echo "Failed"; }
envsubst < "/etc/cron.d/traffic_ops_ort-cron-template" > "/etc/cron.d/traffic_ops_ort-cron" && rm -f "/etc/cron.d/traffic_ops_ort-cron-template"
chmod "0644" "/etc/cron.d/traffic_ops_ort-cron" && crontab "/etc/cron.d/traffic_ops_ort-cron"
@@ -77,4 +71,4 @@ chmod "0644" "/etc/cron.d/traffic_ops_ort-cron" && crontab "/etc/cron.d/traffic_
crond -im off
touch /var/log/trafficserver/diags.log
-tail -F /var/log/trafficserver/diags.log
+tail -Fn +1 /var/log/trafficserver/diags.log
diff --git a/infrastructure/cdn-in-a-box/ort/README.rst b/infrastructure/cdn-in-a-box/ort/README.rst
new file mode 100644
index 000000000..4c8ac5b10
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/README.rst
@@ -0,0 +1,20 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing,
+.. software distributed under the License is distributed on an
+.. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+.. KIND, either express or implied. See the License for the
+.. specific language governing permissions and limitations
+.. under the License.
+
+********************************************
+Traffic Ops Operational Readiness Test (ORT)
+********************************************
diff --git a/infrastructure/cdn-in-a-box/ort/setup.py b/infrastructure/cdn-in-a-box/ort/setup.py
new file mode 100755
index 000000000..3589889ec
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/setup.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python3
+
+# Copyright 2018 Comcast Cable Communications Management, LLC
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+The setuptools-based install script for Traffic Ops ORT
+"""
+
+import os
+import sys
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(here)
+import traffic_ops_ort
+
+with open(os.path.join(here, 'README.rst')) as f:
+ long_description = f.read()
+
+setup(
+ name='traffic_ops_ort',
+ version=traffic_ops_ort.__version__,
+ description="The Traffic Ops Operational Readiness Test, checks for and applies changes from "\
+ "Traffic Ops to a server",
+ long_description=long_description,
+ url='https://github.com/ocket8888/trafficcontrol/tree/ort-without-systemd/infrastructure/cdn-in-a-box/ort',
+ author='Brennan Fieck',
+ author_email='Brennan_WilliamFieck@comcast.com',
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Environment :: Console',
+ 'Intended Audience :: Telecommunications Industry',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Topic :: Internet',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Internet :: Log Analysis',
+ 'Topic :: Utilities'
+ ],
+ keywords='network connection configuration TrafficControl',
+ packages=find_packages(exclude=['contrib', 'docs', 'tests']),
+ install_requires=['setuptools', 'typing', 'requests', 'urllib3', 'distro', 'psutil'],
+ # data_files=[('etc/crontab', ['traffic_ops_ort.crontab'])],
+ entry_points={
+ 'console_scripts': [
+ 'traffic_ops_ort=traffic_ops_ort:main',
+ ],
+ },
+ python_requires='~=3.4'
+)
diff --git a/infrastructure/cdn-in-a-box/cache/crontab b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
similarity index 93%
rename from infrastructure/cdn-in-a-box/cache/crontab
rename to infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
index e2690f527..ccb522cbd 100644
--- a/infrastructure/cdn-in-a-box/cache/crontab
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort.crontab
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-*/1 * * * * /opt/ort/traffic_ops_ort.py SYNCDS ALL https://$TO_FQDN $TO_ADMIN_USER:$TO_ADMIN_PASSWORD >> /var/log/ort.log 2>> /var/log/ort.log
+*/1 * * * * /usr/bin/traffic_ops_ort -k SYNCDS ALL https://$TO_FQDN $TO_ADMIN_USER:$TO_ADMIN_PASSWORD >> /var/log/ort.log 2>> /var/log/ort.log
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py
new file mode 100644
index 000000000..1083f32d6
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/__init__.py
@@ -0,0 +1,138 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This package is meant to fully implement the Traffic Ops Operational
+Readiness Test - which was originally written in a single, chickenscratch
+Perl script. When the :func:`main` function is run, it acts (more or less)
+exactly like that legacy script, with the ability to set system configuration
+files and start, stop, and restart HTTP cache servers etc.
+"""
+
+__version__ = "0.0.2"
+__author__ = "Brennan Fieck"
+
+import argparse
+import datetime
+import sys
+import logging
+
+def doMain(args:argparse.Namespace) -> int:
+ """
+ Runs the main routine based on the parsed arguments to the script
+
+ :param args: A parsed argument list as returned from :meth:`argparse.ArgumentParser.parse_args`
+ :returns: an exit code for the script.
+ :raises AttributeError: when the namespace is missing required arguments
+ """
+ from . import configuration
+
+ if not configuration.setLogLevel(args.Log_Level):
+ print("Unrecognized log level:", args.Log_Level, file=sys.stderr)
+ return 1
+
+ logging.info("Distribution detected as: '%s'", configuration.DISTRO)
+ logging.info("Hostname detected as: '%s'", configuration.HOSTNAME[1])
+
+ if not configuration.setMode(args.Mode):
+ logging.critical("Unrecognized Mode: %s", args.Mode)
+ return 1
+
+ logging.info("Running in %s mode", configuration.MODE)
+
+ if not configuration.setTSRoot(args.ts_root):
+ logging.critical("Failed to set TS_ROOT, seemingly invalid path: '%s'", args.ts_root)
+ return 1
+
+ logging.info("ATS root installation directory set to: '%s'", configuration.TS_ROOT)
+
+ configuration.VERIFY = not args.insecure
+
+ if not configuration.setTOURL(args.Traffic_Ops_URL):
+ logging.critical("Malformed or invalid Traffic_Ops_URL: '%s'", args.Traffic_Ops_URL)
+ return 1
+
+ logging.info("Traffic Ops URL '%s' set and verified", configuration.TO_URL)
+
+ if not configuration.setTOCredentials(args.Traffic_Ops_Login):
+ logging.critical("Traffic Ops login credentials invalid or incorrect.")
+ return 1
+
+ logging.info("Got TO Cookie - valid until %s",
+ datetime.datetime.fromtimestamp(configuration.TO_COOKIE.expires))
+
+ configuration.WAIT_FOR_PARENTS = args.wait_for_parents
+
+ from . import main_routines
+
+ return main_routines.run()
+
+def main():
+ """
+ The ORT entrypoint, parses argv before handing it off to :func:`doMain`.
+ """
+ # I have no idea why, but the old ORT script does this on every run.
+ print(datetime.datetime.utcnow().strftime("%a %b %d %H:%M:%S UTC %Y"))
+
+ parser = argparse.ArgumentParser(description="A Python-based TO_ORT implementation",
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+
+ parser.add_argument("Mode",
+ help="REPORT: Do nothing, but print what would be done\n"\
+ "")
+ parser.add_argument("Log_Level",
+ help="ALL/TRACE, DEBUG, INFO, WARN, ERROR, FATAL/CRITICAL, NONE",
+ type=str)
+ parser.add_argument("Traffic_Ops_URL",
+ help="URL to Traffic Ops host. Example: https://trafficops.company.net",
+ type=str)
+ parser.add_argument("Traffic_Ops_Login",
+ help="Example: 'username:password'")
+ parser.add_argument("--dispersion",
+ help="wait a random number between 0 and <dispersion> before starting.",
+ type=int,
+ default=300)
+ parser.add_argument("--login_dispersion",
+ help="wait a random number between 0 and <login_dispersion> before login.",
+ type=int,
+ default=0)
+ parser.add_argument("--retries",
+ help="retry connection to Traffic Ops URL <retries> times.",
+ type=int,
+ default=3)
+ parser.add_argument("--wait_for_parents",
+ help="do not update if parent_pending = 1 in the update json.",
+ action="store_true")
+ parser.add_argument("--rev_proxy_disabled",
+ help="bypass the reverse proxy even if one has been configured.",
+ type=int,
+ default=0)
+ parser.add_argument("--ts_root",
+ help="Specify the root directory at which Apache Traffic Server is installed"\
+ " (e.g. '/opt/trafficserver')",
+ type=str,
+ default="/")
+ parser.add_argument("-k", "--insecure",
+ help="Skip verification of SSL certificates for Traffic Ops connections. "\
+ "DON'T use this in production!",
+ action="store_true")
+ parser.add_argument("-v", "--version",
+ action="version",
+ version="%(prog)s v"+__version__,
+ help="Print version information and exit.")
+
+ exit(doMain(parser.parse_args()))
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/config_files.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/config_files.py
new file mode 100644
index 000000000..fd82c233b
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/config_files.py
@@ -0,0 +1,292 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module deals with the management of configuration files,
+presumably for a cache server
+"""
+
+import os
+import logging
+import typing
+
+#: Holds a set of service names that need reloaded configs, mapped to a boolean which indicates
+#: whether (:const:`True`) or not (:const:`False`) a full restart is required.
+RELOADS_REQUIRED = set()
+
+#: A constant that holds the absolute path to the backup directory for configuration files
+BACKUP_DIR = "/opt/ort/backups"
+
+class ConfigurationError(Exception):
+ """
+ Represents an error updating configuration files
+ """
+ pass
+
+class ConfigFile():
+ """
+ Represents a configuration file on a host system.
+ """
+
+ fname = "" #: The base name of the file
+ location = "" #: An absolute path to the directory containing the file
+ URI = "" #: A URI where the actual file contents can be found
+ contents = "" #: The full contents of the file - as configured in TO, not the on-disk contents
+
+ def __init__(self, raw:dict):
+ """
+ Constructs a :class:`ConfigFile` object from a raw API response
+
+ :param raw: A raw config file from an API response
+ :raises ValueError: if ``raw`` does not faithfully represent a configuration file
+
+ >>> ConfigFile({"fnameOnDisk": "test",
+ ... "location": "/path/to",
+ ... "apiURI": "http://test",
+ ... "scope": "servers"}))
+ ConfigFile(path='/path/to/test', URI='http://test', scope='servers')
+ """
+ from .configuration import TO_URL
+
+ try:
+ self.fname = raw["fnameOnDisk"]
+ self.location = raw["location"]
+ if "apiUri" in raw:
+ self.URI = '/'.join((TO_URL, raw["apiUri"].lstrip('/')))
+ else:
+ self.URI = raw["url"]
+ self.scope = raw["scope"]
+ except (KeyError, TypeError, IndexError) as e:
+ raise ValueError from e
+
+ self.path = os.path.join(self.location, self.fname)
+
+ def __repr__(self) -> str:
+ """
+ Implements ``repr(self)``
+
+ >>> repr(ConfigFile({"fnameOnDisk": "test",
+ ... "location": "/path/to",
+ ... "apiURI": "http://test",
+ ... "scope": "servers"}))
+ "ConfigFile(path='/path/to/test', URI='http://test', scope='servers')"
+ """
+ return "ConfigFile(path=%r, URI=%r, scope=%r)" %\
+ (self.path, self.URI if self.URI else None, self.scope)
+
+ def __str__(self) -> str:
+ """
+ Implements ``str(self)``
+
+ :returns: The contents of the file, fetched using :meth:`fetchContents` if necessary
+ """
+ if self.contents:
+ return self.contents
+
+ try:
+ self.fetchContents()
+ except ConnectionError as e:
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+
+ return self.contents
+
+ def fetchContents(self):
+ """
+ Fetches the file contents from :attr:`URI` if possible. Sets :attr:`contents` when
+ successful.
+
+ :raises ConnectionError: if something goes wrong fetching the file contents from Traffic
+ Ops
+ """
+ from . import configuration as conf, utils
+ logging.info("Fetching file %s", self.fname)
+
+ try:
+ # You can't really check this any earlier, since even a 'url' field could, potentially,
+ # point at Traffic Ops
+ if self.URI.startswith(conf.TO_URL):
+ cookies = {conf.TO_COOKIE.name: conf.TO_COOKIE.value}
+ else:
+ cookies = None
+
+ self.contents = utils.getTextResponse(self.URI, cookies=cookies, verify=conf.VERIFY)
+ except ValueError as e:
+ raise ConnectionError from e
+
+ logging.info("fetched")
+
+ def backup(self, contents:str):
+ """
+ Creates a backup of this file under the :data:`BACKUP_DIR` directory
+
+ :param contents: The actual, on-disk contents from the original file
+ :raises OSError: if the backup directory does not exist, or a backup of this file
+ could not be written into it.
+ """
+ from .configuration import MODE, Modes
+ from .utils import getYesNoResponse
+
+ backupfile = os.path.join(BACKUP_DIR, self.fname)
+ willClobber = False
+ if os.path.isfile(backupfile):
+ willClobber = True
+
+ if MODE is Modes.INTERACTIVE:
+ prmpt = ("Write backup file %s%%s?" % backupfile)
+ prmpt %= " - will clobber existing file by the same name - " if willClobber else ''
+ if not getYesNoResponse(prmpt, default='Y'):
+ return
+
+ elif willClobber:
+ logging.warning("Clobbering existing backup file '%s'!", backupfile)
+
+ if MODE is not Modes.REPORT:
+ with open(backupfile, 'w') as fp:
+ fp.write(contents)
+
+ logging.info("Backup File written")
+
+
+ def update(self):
+ """
+ Updates the file if required, backing up as necessary
+
+ :raises OSError: when reading/writing files fails for some reason
+ """
+ from . import utils
+ from .configuration import MODE, Modes, SERVER_INFO
+ from .services import NEEDED_RELOADS, FILES_THAT_REQUIRE_RELOADS
+
+ finalContents = sanitizeContents(str(self))
+ # Ensure POSIX-compliant files
+ if not finalContents.endswith('\n'):
+ finalContents += '\n'
+ logging.info("Sanitized output: \n%s", finalContents)
+
+ if not os.path.isdir(self.location):
+ if MODE is Modes.INTERACTIVE and\
+ not utils.getYesNoResponse("Create configuration directory %s?" % self.path, 'Y'):
+ logging.warning("%s will not be created - some services may not work properly!",
+ self.path)
+ return
+
+ logging.info("Directory %s will be created", self.location)
+ logging.info("File %s will be created", self.path)
+
+ if MODE is not Modes.REPORT:
+ os.makedirs(self.location)
+ with open(self.path, 'x') as fp:
+ fp.write(finalContents)
+ return
+
+ if not os.path.isfile(self.path):
+ if MODE is Modes.INTERACTIVE and\
+ not utils.getYesNoResponse("Create configuration file %s?"%self.path, default='Y'):
+ logging.warning("%s will not be created - some services may not work properly!",
+ self.path)
+ return
+
+ logging.info("File %s will be created", self.path)
+
+ if MODE is not Modes.REPORT:
+ with open(self.path, 'x') as fp:
+ fp.write(finalContents)
+ return
+
+ with open(self.path, 'r+') as fp:
+ onDiskContents = fp.readlines()
+ if filesDiffer(finalContents.splitlines(), onDiskContents):
+ self.backup(''.join(onDiskContents))
+ if MODE is not Modes.REPORT:
+ fp.seek(0)
+ fp.truncate()
+
+
+ fp.write(finalContents)
+ if self.fname in FILES_THAT_REQUIRE_RELOADS:
+ NEEDED_RELOADS.add(FILES_THAT_REQUIRE_RELOADS[self.fname])
+ logging.info("File written to %s", self.path)
+ else:
+ logging.info("File doesn't differ from disk; nothing to do")
+
+def filesDiffer(a:typing.List[str], b:typing.List[str]) -> bool:
+ """
+ Compares two files for meaningingful differences. Traffic Ops Headers are
+ stripped out of the file contents before comparison. Trailing whitespace
+ is ignored
+
+ :param a: The contents of the first file, as a list of its lines
+ :param b: The contents of the second file, as a list of its lines
+ :returns: :const:`True` if the files have any differences, :const:`False`
+ """
+ a = [l.rstrip() for l in a if l.rstrip() and not l.startswith("# DO NOT EDIT") and\
+ not l.startswith("# TRAFFIC OPS NOTE:")]
+ b = [l.rstrip() for l in b if l.rstrip() and not l.startswith("# DO NOT EDIT") and\
+ not l.startswith("# TRAFFIC OPS NOTE:")]
+
+ if len(a) != len(b):
+ return True
+
+ for i, l in enumerate(a):
+ if l != b[i]:
+ return True
+
+ return False
+
+def sanitizeContents(raw:str) -> str:
+ """
+ Performs pre-processing on a raw configuration file
+
+ :param raw: The raw contents of the file as returned by a request to its URL
+ :returns: The same contents, but with special replacement strings parsed out and HTML-encoded
+ symbols decoded to their literal values
+ """
+ from .configuration import SERVER_INFO
+ out = []
+
+ # These double curly braces escape the behaviour of Python's `str.format` method to attempt
+ # to use curly brace-enclosed text as a key into a dictonary of its arguments. They'll be
+ # rendered into single braces in the output of `.format`, leaving the string ultimately
+ # unchanged in that respect.
+ for line in raw.replace('{', "{{").replace('}', "}}").format(SERVER_INFO).splitlines():
+ tmp=(" ".join(line.split())).strip() #squeezes spaces and trims leading and trailing spaces
+ tmp=tmp.replace("&", '&') #decodes HTML-encoded ampersands
+ tmp=tmp.replace(">", '>') #decodes HTML-encoded greater-than symbols
+ tmp=tmp.replace("<", '<') #decodes HTML-encoded less-than symbols
+ out.append(tmp)
+
+ return '\n'.join(out)
+
+def initBackupDir():
+ """
+ Initializes a backup directory as a subdirectory of the directory containing
+ this ORT script.
+
+ :raises OSError: if the backup directory initialization fails
+ """
+ global BACKUP_DIR
+ from . import configuration as conf
+
+ logging.info("Initializing backup dir %s", BACKUP_DIR)
+
+ if not os.path.isdir(BACKUP_DIR):
+ if conf.MODE != conf.Modes.REPORT:
+ os.mkdir(BACKUP_DIR)
+ else:
+ logging.error("Cannot create non-existent backup dir in REPORT mode!")
+ else:
+ logging.info("Backup dir already exists - nothing to do")
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py
new file mode 100644
index 000000000..15c349775
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/configuration.py
@@ -0,0 +1,273 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module is responsible for holding information related to
+the configuration of the ORT script; it has constants that
+hold and set up the log level, run modes, Traffic Ops login
+credentials etc.
+"""
+
+import datetime
+import enum
+import logging
+import os
+import platform
+import typing
+
+import distro
+import requests
+
+#: Contains the host's hostname as a tuple of ``(short_hostname, full_hostname)``
+HOSTNAME = (platform.node().split('.')[0], platform.node())
+
+#: contains identifying information about the host system's Linux distribution
+DISTRO = distro.LinuxDistribution().id()
+
+#: Holds information about the host system, required for processing configuration files,
+#: and also possibly useful in other situations
+SERVER_INFO = None
+
+#: This sets whether or not to verify SSL certificates when communicated with Traffic Ops.
+#: Does not affect non-Traffic Ops servers
+VERIFY = True
+
+#: If set to :const:`True`, this script will not apply updates until all of its parents have
+#: finished applying their updates
+WAIT_FOR_PARENTS = False
+
+
+class Modes(enum.IntEnum):
+ """
+ Enumerated run modes
+ """
+ REPORT = 0 #: Do nothing, only report what would be done
+ INTERACTIVE = 1 #: Ask for user confirmation before modifying the system
+ REVALIDATE = 2 #: Only check for configuration file changes and content revalidations
+ SYNCDS = 3 #: Check for and apply Delivery Service changes
+ BADASS = 4 #: Apply all settings specified in Traffic Ops, and attempt to solve all problems
+
+ def __str__(self) -> str:
+ """
+ Implements ``str(self)`` by returning enum member's name
+ """
+ return self.name
+
+#: Holds the current run mode
+MODE = None
+
+def setMode(mode:str) -> bool:
+ """
+ Sets the script's run mode in the global variable :data:`MODE`
+
+ :param mode: Expected to be the name of a :class:`Modes` constant.
+ :returns: whether or not the run mode could be set successfully
+ :raises ValueError: when ``mode`` is not a :const:`str`
+ """
+ try:
+ mode = Modes[mode.upper()]
+ except KeyError:
+ return False
+ except (AttributeError, ValueError) as e:
+ raise ValueError from e
+
+ global MODE
+ MODE = mode
+
+ return True
+
+
+class LogLevels(enum.IntEnum):
+ """
+ Enumerated Log levels
+ """
+ ALL = logging.NOTSET #: Outputs all logging information
+ TRACE = logging.NOTSET #: Synonym for :attr:`ALL`
+ DEBUG = logging.DEBUG #: Outputs debugging information as well as all higher log levels
+ INFO = logging.INFO #: Outputs informational messages as well as all higher log levels
+ WARN = logging.WARNING #: Outputs warnings, errors and fatal messages
+ ERROR = logging.ERROR #: Errors - but not more verbose warnings - will be output
+ FATAL = logging.CRITICAL #: Outputs only reasons why the script exited prematurely
+ CRITICAL = logging.CRITICAL #: Synonym for :attr:`FATAL`
+ NONE = logging.CRITICAL+1 #: Silent mode - no output at all
+
+ def __str__(self) -> str:
+ """
+ Implements ``str(self)`` by returning the enum member's name.
+ (Coalesces synonyms to their legacy names)
+ """
+ return self.name if self != logging.CRITICAL else "FATAL"
+
+#: A format specifier for logging output. Propagates to all imported modules.
+LOG_FORMAT = "%(levelname)s: %(asctime)s line %(lineno)d in %(module)s.%(funcName)s: %(message)s"
+
+def setLogLevel(level:str) -> bool:
+ """
+ Sets the global logger's log level to the desired name.
+
+ :param level: Expected to be the name of a :class:`LogLevels` constant.
+ :returns: whether or not the log level could be set successfully
+ :raises ValueError: when the type of ``level`` is not :const:`str`
+ """
+ try:
+ level = LogLevels[level.upper()]
+ except KeyError:
+ return False
+ except (AttributeError, ValueError) as e:
+ raise ValueError from e
+
+ logging.basicConfig(level=level, format=LOG_FORMAT)
+ logging.getLogger().setLevel(level)
+
+ return True
+
+
+#: An absolute path to the root installation directory of the Apache Trafficserver installation
+TS_ROOT = None
+
+def setTSRoot(tsroot:str) -> bool:
+ """
+ Sets the global variable :data:`TS_ROOT`.
+
+ :param tsroot: Should be an absolute path to the directory containing the system's Apache
+ Trafficserver installation.
+ :returns: whether or not the installation path could be set successfully
+ :raises ValueError: if ``tsroot`` is not a :const:`str`
+
+ """
+ try:
+ tsroot = tsroot.strip()
+
+ if tsroot != '/' and tsroot.endswith('/'):
+ tsroot = tsroot.rstrip('/')
+
+ if not os.path.isdir(tsroot) or\
+ not os.path.isfile(os.path.join(tsroot, 'bin', 'trafficserver')):
+
+ return False
+ except (OSError, AttributeError, ValueError) as e:
+ raise ValueError from e
+
+ global TS_ROOT
+ TS_ROOT = tsroot
+ return True
+
+
+#: Holds the full URL including schema (e.g. 'http') and port that points at Traffic Ops
+TO_URL = None
+
+def setTOURL(url:str) -> bool:
+ """
+ Sets the :data:`TO_URL` global variable and verifies it
+
+ :param url: A full URL (including schema - and port when necessary) specifying the location of
+ a running Traffic Ops server
+ :returns: whether or not the URL could be set successfully
+ :raises ValueError: when ``url`` is not a :const:`str`
+ """
+ global VERIFY
+ try:
+ url = url.rstrip('/')
+ _ = requests.head(url, verify=VERIFY)
+ except requests.exceptions.RequestException as e:
+ logging.error("%s", e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ except (AttributeError, ValueError) as e:
+ raise ValueError from e
+
+ global TO_URL
+ TO_URL = url
+
+ return True
+
+
+#: Holds a Mojolicious cookie for validating connections to Traffic Ops
+TO_COOKIE = None
+
+#: Holds the login information for re-obtaining a cookie when the one in :data:`TO_COOKIE` expires
+TO_LOGIN = None
+
+def setTOCredentials(login:str) -> bool:
+ """
+ Parses and returns a JSON-encoded login string for the Traffic Ops API.
+ This will set :data:`TO_COOKIE` and :data:`TO_LOGIN` if login is successful.
+
+ :param login: The raw login info as passed on the command line (e.g. 'username:password')
+ :raises ValueError: if ``login`` is not a :const:`str`.
+ :returns: whether or not the login could be set and validated successfully
+ """
+ try:
+ login = '{{"u": "{0}", "p": "{1}"}}'.format(*login.split(':'))
+ except IndexError:
+ logging.critical("Bad Traffic_Ops_Login: '%s' - should be like 'username:password'", login)
+ return False
+ except (AttributeError, ValueError) as e:
+ raise ValueError from e
+
+ global TO_LOGIN
+ TO_LOGIN = login
+
+ try:
+ getNewTOCookie()
+ except PermissionError:
+ return False
+
+ return True
+
+def getNewTOCookie():
+ """
+ Re-obtains a cookie from Traffic Ops based on the login credentials in :data:`TO_LOGIN`
+
+ :raises PermissionError: if :data:`TO_LOGIN` or :data:`TO_URL` are unset, invalid,
+ or the wrong type
+ """
+ global TO_URL, TO_LOGIN, VERIFY, TO_COOKIE
+ if TO_URL is None or not isinstance(TO_URL, str) or\
+ TO_LOGIN is None or not isinstance(TO_LOGIN, str):
+ raise PermissionError("TO_URL and TO_LOGIN must be set prior to calling this function!")
+
+ try:
+ # Obtain login cookie
+ cookie = requests.post(TO_URL + '/api/1.3/user/login', data=TO_LOGIN, verify=VERIFY)
+ except requests.exceptions.RequestException as e:
+ logging.critical("Login credentials rejected by Traffic Ops")
+ raise PermissionError from e
+
+ if not cookie.cookies or 'mojolicious' not in cookie.cookies:
+ logging.error("Response code: %d", cookie.status_code)
+ logging.warning("Response Headers: %s", cookie.headers)
+ logging.debug("Response: %s", cookie.content)
+ raise PermissionError("Login credentials rejected by Traffic Ops")
+
+ TO_COOKIE = [c for c in cookie.cookies if c.name == "mojolicious"][0]
+
+def getTOCookie() -> typing.Dict[str, str]:
+ """
+ A small, convenience wrapper for getting a current, valid Traffic Ops authentication cookie. If
+ :data:`TO_COOKIE` is expired, this function requests a new one from Traffic Ops
+
+ :returns: A cookie dataset that may be passed directly to :mod:`requests` functions
+ :raises PermissionError: if :data:`TO_LOGIN` and/or :data:`TO_URL` are unset, invalid, or the
+ wrong type
+ """
+ global TO_COOKIE
+
+ if datetime.datetime.now().timestamp() >= TO_COOKIE.expires:
+ getNewTOCookie()
+
+ return {TO_COOKIE.name: TO_COOKIE.value}
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/main_routines.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/main_routines.py
new file mode 100644
index 000000000..d95b7c4b2
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/main_routines.py
@@ -0,0 +1,366 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module is meant to run the main routines of the script,
+and performs a variety of operations based on the run mode.
+"""
+
+import os
+import logging
+import requests
+
+#: A constant that holds the absolute path to the status file directory
+STATUS_FILE_DIR = "/opt/ort/status"
+
+class ORTException(Exception):
+ """Signifies an ORT related error"""
+ pass
+
+def syncDSState() -> bool:
+ """
+ Queries Traffic Ops for the Delivery Service's sync state
+
+ :raises ORTException: when something goes wrong
+ :returns: whether or not an update is needed
+ """
+ from . import to_api, configuration
+ logging.info("starting syncDS state fetch")
+
+ try:
+ updateStatus = to_api.getUpdateStatus(configuration.HOSTNAME[0])[0]
+ except (IndexError, ConnectionError, requests.exceptions.RequestException) as e:
+ logging.critical("Server configuration not found in Traffic Ops!")
+ raise ORTException from e
+ except PermissionError as e:
+ logging.critical("Failed to authenticate with the Traffic Ops server!")
+ raise ORTException from e
+
+ logging.debug("Retrieved raw update status: %r", updateStatus)
+
+ return 'upd_pending' in updateStatus and updateStatus['upd_pending']
+
+def revalidateState() -> bool:
+ """
+ Checks the revalidation status of this server in Traffic Ops
+
+ :returns: whether or not this server has a revalidation pending
+ :raises ORTException:
+ """
+ from . import to_api, configuration as conf
+ logging.info("starting revalidation state fetch")
+
+ try:
+ to_api.getUpdateStatus(conf.HOSTNAME[0])[0]
+ except (IndexError, ConnectionError, requests.exceptions.RequestException) as e:
+ logging.critical("Server configuration not found in Traffic Ops!")
+ raise ORTException from e
+ except PermissionError as e:
+ logging.critical("Failed to authenticate with the Traffic Ops server!")
+ raise ORTException from e
+
+ logging.debug("Retrieved raw revalidation status: %r", updateStatus)
+ if conf.WAIT_FOR_PARENTS and "parent_reval_pending" in updateStatus and updateStatus["parent_reval_pending"]:
+ logging.info("Parent revalidation is pending - waiting for parent")
+ return False
+
+ return "reval_pending" in updateStatus and updateStatus["reval_pending"]
+
+def deleteOldStatusFiles(myStatus:str):
+ """
+ Attempts to delete any and all old status files
+
+ :param myStatus: the current status - files by this name will not be deleted
+ :raises ConnectionError: if there's an issue retrieving a list of statuses from
+ Traffic Ops
+ :raises OSError: if a file cannot be deleted for any reason
+ """
+ from .configuration import MODE, Modes
+ from . import to_api, utils
+
+ logging.info("Deleting old status files (those that are not %s)", myStatus)
+
+ doDeleteFiles = MODE is not Modes.REPORT
+
+ for status in to_api.getStatuses():
+
+ # Only the status name matters
+ try:
+ status = status["name"]
+ except KeyError as e:
+ logging.debug("Bad status object: %r", status)
+ logging.debug("Original error: %s", e, exc_info=True, stack_info=True)
+ raise ConnectionError from e
+
+ if doDeleteFiles and status != myStatus:
+ fname = os.path.join("/opt/ORTstatus", status)
+ if not os.path.isfile(fname):
+ continue
+ logging.info("File '%s' to be deleted", fname)
+
+ # check for user confirmation before deleting files in 'INTERACTIVE' mode
+ if MODE != Modes.INTERACTIVE or utils.getYesNoResponse("Delete file %s?" % fname):
+ logging.warning("Deleting file '%s'!", fname)
+ os.remove(fname)
+
+def setStatusFile() -> bool:
+ """
+ Attempts to set the status file according to this server's reported status in Traffic Ops.
+
+ .. warning:: This will create the directory '/opt/ORTstatus' if it does not exist, and may
+ delete files there without warning!
+
+ :returns: whether or not the status file could be set properly
+ """
+ global STATUS_FILE_DIR
+ from .configuration import MODE, Modes
+ from . import to_api, utils
+ logging.info("Setting status file")
+
+ if not isinstance(MODE, Modes):
+ logging.error("MODE is not set to a valid Mode (from traffic_ops_ort.configuration.Modes)!")
+ return False
+
+ try:
+ myStatus = to_api.getMyStatus()
+ except ConnectionError as e:
+ logging.error("Failed to set status file - Traffic Ops connection failed")
+ return False
+
+ if not os.path.isdir(STATUS_FILE_DIR):
+ logging.warning("status directory does not exist, creating...")
+ doMakeDir = MODE is not Modes.REPORT
+
+ # Check for user confirmation if in 'INTERACTIVE' mode
+ if doMakeDir and (MODE is not Modes.INTERACTIVE or\
+ utils.getYesNoResponse("Create status directory '%s'?" % STATUS_FILE_DIR, default='Y')):
+ try:
+ os.makedirs(STATUS_FILE_DIR)
+ return False
+ except OSError as e:
+ logging.error("Failed to create status directory '%s' - %s", STATUS_FILE_DIR, e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ else:
+ try:
+ deleteOldStatusFiles(myStatus)
+ except ConnectionError as e:
+ logging.error("Failed to delete old status files - Traffic Ops connection failed.")
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ except OSError as e:
+ logging.error("Failed to delete old status files - %s", e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ fname = os.path.join(STATUS_FILE_DIR, myStatus)
+ if not os.path.isfile(fname):
+ logging.info("File '%s' to be created", fname)
+ if MODE is not Modes.REPORT and\
+ (MODE is not Modes.INTERACTIVE or utils.getYesNoResponse("Create file '%s'?", 'y')):
+
+ try:
+ with open(fname, 'x'):
+ pass
+ except OSError as e:
+ logging.error("Failed to create status file - %s", e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ return True
+
+def processPackages() -> bool:
+ """
+ Manages the packages that Traffic Ops reports are required for this server.
+
+ :returns: whether or not the package processing was successfully completed
+ """
+ from . import to_api
+ from .configuration import Modes, MODE
+
+ try:
+ myPackages = to_api.getMyPackages()
+ except (ConnectionError, PermissionError) as e:
+ logging.error("Failed to fetch package list from Traffic Ops - %s", e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ except ValueError as e:
+ logging.error("Got malformed response from Traffic Ops! - %s", e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ for package in myPackages:
+ if package.install():
+ if MODE is not Modes.BADASS:
+ return False
+ logging.warning("Failed to install %s, but we're BADASS, so moving on!", package)
+
+ return True
+
+def processServices() -> bool:
+ """
+ Manages the running processes of the server, according to an ancient system known as 'chkconfig'
+
+ :returns: whether or not the service processing was completed successfully
+ """
+ from . import services
+ from .to_api import getMyChkconfig
+
+ chkconfig = getMyChkconfig()
+
+ logging.debug("/ort/<hostname>/chkconfig response: %r", chkconfig)
+
+ for item in chkconfig:
+ logging.debug("Processing item %r", item)
+
+ if not services.setServiceStatus(item):
+ return False
+
+ return True
+
+def processConfigurationFiles() -> bool:
+ """
+ Updates and backs up all of a server's configuration files.
+
+ :returns: whether or not the configuration changes were successful
+ """
+ from . import config_files, to_api, configuration
+
+ try:
+ config_files.initBackupDir()
+ except OSError as e:
+ logging.error("Couldn't create backup directory!")
+ logging.warning("%s", e)
+ logging.debug("", exc_info=True, stack_info=True)
+ return False
+
+ try:
+ myFiles = to_api.getMyConfigFiles()
+ except ConnectionError as e:
+ logging.error("Failed to fetch configuration files - Traffic Ops connection failed! %s",e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ except ValueError as e:
+ logging.error("Malformed configuration file response from Traffic Ops!")
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ for file in myFiles:
+ try:
+ file = config_files.ConfigFile(file)
+ logging.info("\n============ Processing File: %s ============", file.fname)
+ file.update()
+ logging.info("\n============================================\n")
+
+ # A bad object could just reflect an inconsistent reply structure from the API, so BADASSes
+ # will attempt to continue. However, an issue updating a valid configuration is not
+ # recoverable, even for BADASSes
+ except config_files.ConfigurationError as e:
+ logging.error("An error occurred while trying to update %s", file.name)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+ except ValueError as e:
+ logging.error("%s does not appear to be a valid 'configfile' object!")
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ if configuration.MODE is not configuration.Modes.BADASS:
+ return False
+ logging.warning("Moving on because we're BADASS")
+
+ return True
+
+def run() -> int:
+ """
+ This function is the entrypoint into the script's main flow from :func:`traffic_ops_ort.doMain`
+ It runs the appropriate actions depending on the run mode
+
+ :returns: an exit code for the script
+ """
+ from . import configuration, to_api, utils, services
+
+ # If this is just a revalidation, then we can exit if there's no revalidation pending
+ if configuration.MODE == configuration.Modes.REVALIDATE:
+ try:
+ updateRequired = revalidateState()
+ except ORTException as e:
+ logging.debug("%r", e, exc_info=True, stack_info=True)
+ return 2
+
+ if not updateRequired:
+ logging.info("No revalidation pending")
+ return 0
+
+ logging.info("in REVALIDATE mode; skipping package/service processing")
+
+ # In all other cases, we check for an update to the Delivery Service and apply any found
+ # changes
+ else:
+ try:
+ updateRequired = syncDSState()
+ except ORTException as e:
+ logging.debug("%r", e, exc_info=True, stack_info=True)
+ return 2
+
+ # Bail on failures - unless this script is BADASS!
+ if not setStatusFile():
+ if configuration.MODE is not configuration.Modes.BADASS:
+ logging.critical("Failed to set status as specified by Traffic Ops")
+ return 2
+ logging.warning("Failed to set status but we're BADASS, so moving on.")
+
+ logging.info("\nProcessing Packages...")
+ if not processPackages():
+ logging.critical("Failed to process packages")
+ if configuration.MODE is not configuration.Modes.BADASS:
+ return 2
+ logging.warning("Package processing failed but we're BADASS, so attempting to move on")
+ logging.info("Done.\n")
+
+ logging.info("\nProcessing Services...")
+ if not processServices():
+ logging.critical("Failed to process services.")
+ if configuration.MODE is not configuration.Modes.BADASS:
+ return 2
+ logging.warning("Service processing failed but we're BADASS, so attempting to move on")
+ logging.info("Done.\n")
+
+
+ # All modes process configuration files
+ logging.info("\nProcessing Configuration Files...")
+ if not processConfigurationFiles():
+ logging.critical("Failed to process configuration files.")
+ return 2
+ logging.info("Done.\n")
+
+ if updateRequired:
+ if configuration.MODE is not configuration.Modes.INTERACTIVE or\
+ utils.getYesNoResponse("Update Traffic Ops?", default='Y'):
+
+ logging.info("\nUpdating Traffic Ops...")
+ to_api.updateTrafficOps()
+ logging.info("Done.\n")
+ else:
+ logging.warning("Traffic Ops was not notified of changes. You should do this manually.")
+
+ return 0
+
+ logging.info("Traffic Ops update not necessary")
+
+ if services.NEEDED_RELOADS and not services.doReloads():
+ logging.critical("Failed to reload all configuration changes")
+ return 2
+
+ return 0
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/packaging.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/packaging.py
new file mode 100644
index 000000000..bc3ae1d94
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/packaging.py
@@ -0,0 +1,190 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module deals with managing packages installed on the host system.
+It attempts to do so in a distribution-agnostic way, but actually only
+support a strict set of distributions with well-known package managers.
+"""
+
+import logging
+import subprocess
+
+class _MetaPackage(type):
+ """
+ This factory is responsible for constructing a :class:`Package` class which properly
+ utilizes the host system's package management platform.
+ """
+
+ def __new__(mcs, name, bases, dct) -> type:
+ """
+ Customization point for distribution-dependent functionality
+ """
+ from .configuration import DISTRO
+ pack = super().__new__(mcs, name, bases, dct)
+
+ if DISTRO in {'fedora', 'centos', 'rhel'}:
+ concat = '-'
+ pack.checkInstallList = lambda x: [p for p in subprocess.Popen(["/bin/rpm", "-q", x.name], stdout=subprocess.PIPE).communicate()[0].decode().splitlines() if not p.endswith("is not installed")]
+ pack.installArgs = ["/bin/yum", "install", "-y"]
+ pack.uninstallArgs = ["/bin/yum", "remove", "-y"]
+ elif DISTRO in {'ubuntu', 'linuxmint', 'debian'}:
+ concat = '='
+ pack.checkInstallList = lambda x: ["{1}={2}".format(*p.split()) for p in subprocess.Popen(["/usr/bin/dpkg", "-l", x.name], stdout=subprocess.PIPE).communicate()[0].decode().splitlines()[5:] if p]
+ pack.installArgs = ["/usr/bin/apt-get", "install", "-y"]
+ pack.uninstallArgs = ["/usr/bin/apt-get", "purge", "-y"]
+
+ # TODO - is this reasonable? I mean, I KNOW it's unreasonable because this whole module
+ # shouldn't exist, but is this a good fallback since it DOES exist?
+ else:
+ concat = " v"
+ pack.checkInstallList = lambda x: []
+ pack.installArgs = ["/bin/true"]
+ pack.uninstallArgs = ["/bin/true"]
+ pack.__str__ = lambda x: concat.join((x.name, x.version)) if x.version else x.name
+
+ return pack
+
+
+
+
+class Package(metaclass=_MetaPackage):
+ """
+ Represents a package installed (or about to be installed) on the host system
+ """
+
+ #: The package's name
+ name = None
+
+ #: Optionally, a specific version of the package
+ version = None
+
+ def __init__(self, pkg:dict):
+ """
+ Constructs a :class:`Package` object from a raw JSON response
+
+ :param pkg: a parsed JSON response, expected to contain a ``"name"`` key and optionally a
+ ``"version"`` key.
+ :raises ValueError: if ``pkg`` does not faithfully represent a package
+ """
+ if "name" not in pkg:
+ raise ValueError("%r does not represent a package!" % pkg)
+
+ self.name = pkg["name"]
+ self.version = pkg["version"] if "version" in pkg else ""
+
+ def __repr__(self) -> str:
+ """
+ Implements ``repr(self)``
+ """
+ if self.version:
+ return "Package(name=%r, version=%r)" % (self.name, self.version)
+ return "Package(name=%r)" % (self.name,)
+
+
+
+ def isInstalled(self) -> bool:
+ """
+ Checks if this package is already present on the system
+
+ :returns: whether or not the package could be found
+ """
+ for pkg in self.checkInstallList():
+ if (self.version and pkg == str(self)) or pkg.startswith(self.name):
+ return True
+ return False
+
+ def install(self) -> int:
+ """
+ Installs this package.
+
+ :returns: the exit code of the install process
+ """
+ from .configuration import MODE, Modes
+ from .utils import getYesNoResponse as getYN
+
+ if self.isInstalled():
+ logging.info("%s is already installed - nothing to do", self)
+ return 0
+
+ if MODE is Modes.INTERACTIVE and not getYN("Install %s?" % self, default='Y'):
+ logging.warning("%s will not be installed, dependencies may be unsatisfied!", self)
+ return 0
+
+ logging.info("Installing %s", self)
+
+ if MODE is Modes.REPORT:
+ return 0
+
+ try:
+ sub = subprocess.Popen(self.installArgs + [str(self)],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = sub.communicate(timeout=60)
+ except subprocess.CalledProcessError as e:
+ logging.debug("%r", e, stack_info=True, exc_info=True)
+ logging.error("%s could not be installed!", self)
+ return -1
+ except TimeoutError as e:
+ logging.debug("%r", e, stack_info=True, exc_info=True)
+ logging.error("Package install timed out!")
+ return -1
+
+ logging.debug("STDOUT: %s", out.decode())
+ logging.debug("STDERR: %s", err.decode())
+
+ return sub.returncode
+
+ def uninstall(self) -> int:
+ """
+ Uninstalls this package
+
+ :returns: the exit code of the uninstall process
+ """
+ from .configuration import MODE, Modes
+ from .utils import getYesNoResponse as getYN
+
+ if not self.isInstalled():
+ logging.info("%s is not installed - nothing to do", self)
+ return 0
+
+ if MODE is Modes.INTERACTIVE and not getYN("Uninstall %s?" % self, default='Y'):
+ logging.warning("%s will not be installed, dependencies may be out of date!", self)
+ return 0
+
+ logging.info("Uninstalling %s", self)
+
+ if MODE is Modes.REPORT:
+ return 0
+
+ try:
+ sub = subprocess.Popen(self.uninstallArgs + [str(self)],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = sub.communicate(timeout=60)
+ except subprocess.CalledProcessError as e:
+ logging.debug("%r", e, stack_info=True, exc_info=True)
+ logging.error("%s could not be uninstalled!", self)
+ return -1
+ except TimeoutError as e:
+ logging.debug("%r", e, stack_info=True, exc_info=True)
+ logging.error("Package uninstall timed out!")
+ return -1
+
+ logging.debug("STDOUT: %s", out.decode())
+ logging.debug("STDERR: %s", err.decode())
+ return sub.returncode
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/services.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/services.py
new file mode 100644
index 000000000..ddd6bc3f2
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/services.py
@@ -0,0 +1,254 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module handles the reloading of service configuration files when they are changed.
+in :mod:`config_files`, when a configuration file is changed, its base name is looked up
+in this module's :data:`FILES_THAT_REQUIRE_RELOADS` map, and - if found - the function to
+which it is mapped will be added to the :data:`NEEDED_RELOADS` set. Thus, to implement this
+for a new service, all that need be done is to write a function to perform configuration
+reloads, then add the names of configuration files to the map, pointing at the new function.
+"""
+
+import logging
+import os
+import subprocess
+import typing
+import psutil
+
+#: Holds the list of reloads needed due to configuration file changes
+NEEDED_RELOADS = set()
+
+#: True if the host system has systemd D-Bus - actual value set at runtime
+HAS_SYSTEMD = False
+
+try:
+ output = subprocess.check_output(["systemctl", "--no-pager"], stderr=subprocess.STDOUT)
+except subprocess.CalledProcessError:
+ logging.debug("Host system does NOT have systemd - stack trace:", exc_info=True,stack_info=True)
+else:
+ HAS_SYSTEMD = True
+
+def reloadATSConfigs() -> bool:
+ """
+ This function will reload configuration files for the Apache Trafficserver caching HTTP
+ proxy. It does this by calling ``traffic_ctl config reload`
+
+ :returns: whether or not the reload succeeded (as indicated by the exit code of
+ ``traffic_ctl``)
+ :raises OSError: when something goes wrong executing the child process
+ """
+ from .configuration import MODE, Modes, TS_ROOT
+ from .utils import getYesNoResponse as getYN
+
+ # First of all, ATS must be running for this to work
+ if not setATSStatus(True):
+ logging.error("Cannot reload configs, ATS not running!")
+ return False
+
+ cmd = [os.path.join(TS_ROOT, "bin", "traffic_ctl"), "config", "reload"]
+ cmdStr = ' '.join(cmd)
+
+ if MODE is Modes.INTERACTIVE and not getYN("Run command '%s' to reload configuration?",cmdStr):
+ logging.warning("Configuration will not be reloaded for Apache Trafficserver!")
+ logging.warning("Changes will NOT be applied!")
+ return True
+
+ logging.info("Apache Trafficserver configuration reload will be done via: %s", cmdStr)
+
+ if MODE is Modes.REPORT:
+ return True
+
+ sub = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = sub.communicate()
+
+ if sub.returncode:
+ logging.debug("========== PROCESS STDOUT ==========")
+ logging.debug("%s", out.decode())
+ logging.debug("========== PROCESS STDERR ==========")
+ logging.debug("%s", err.decode())
+ logging.debug("====================================")
+ return False
+ return True
+
+#: A big ol' map of filenames to the services which require reloads when said files change
+FILES_THAT_REQUIRE_RELOADS = {"records.config": reloadATSConfigs,
+ "remap.config": reloadATSConfigs,
+ "parent.config": reloadATSConfigs,
+ "cache.config": reloadATSConfigs,
+ "hosting.config": reloadATSConfigs,
+ "astats.config": reloadATSConfigs,
+ "logs_xml.config": reloadATSConfigs,
+ "ssl_multicert.config": reloadATSConfigs}
+
+def doReloads() -> bool:
+ """
+ Performs all necessary service restarts/configuration reloads
+
+ :returns: whether or not the reloads/restarts went successfully
+ """
+ global NEEDED_RELOADS
+
+ for reload in NEEDED_RELOADS:
+ try:
+ if not reload():
+ return False
+ except OSError as e:
+ logging.error("An error occurred when reloading service configuration files: %s",e)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ return True
+
+def getProcessesIfRunning(name:str) -> typing.Optional[psutil.Process]:
+ """
+ Retrieves a process by name, if it exists.
+
+ .. warning:: Process names don't have to be unique, this will return the process with the
+ lowest PID that matches ``name``. This can also only return processes visible to the
+ user running the Python interpreter.
+
+ :param name: the name for which to search
+ :returns: a process if one is found that matches ``name``, else :const:`None`
+ :raises OSError: if the process table cannot be iterated
+ """
+ logging.debug("Iterating process list - looking for %s", name)
+ for process in psutil.process_iter():
+
+ # Found
+ if process.name() == name:
+ logging.debug("Running process found (pid: %d)", process.pid)
+ return process
+
+ logging.debug("No process named '%s' was found", name)
+
+ return None
+
+def setATSStatus(status:bool, restart:bool = False) -> bool:
+ """
+ Sets the status of the system's ATS process.
+
+ :param status: Specifies whether ATS should be running (:const:`True`) or not (:const:`False`)
+ :param restart: If this is :const:`True`, then ATS will be restarted if it is already running
+
+ .. note:: ``restart`` has no effect if ``status`` is :const:`False`
+
+ :returns: whether or not the status setting was successful (or unnecessary)
+ :raises OSError: when there is a problem executing the subprocess
+ """
+ from .configuration import MODE, Modes, TS_ROOT
+ from .utils import getYesNoResponse as getYN
+
+ existingProcess = getProcessesIfRunning("[TS_MAIN]")
+
+ # ATS is not running
+ if existingProcess is None:
+ if not status:
+ logging.info("ATS already stopped - nothing to do")
+ return True
+ logging.info("ATS not running, will be started")
+ arg = "start"
+
+
+ # ATS is running, but has a bad status
+ elif status and existingProcess.status() not in {psutil.STATUS_RUNNING, psutil.STATUS_SLEEPING}:
+ logging.warning("ATS already running, but status is %s - restarting",
+ existingProcess.status())
+ arg = "restart"
+
+ # ATS is running and should be stopped
+ elif not status:
+ logging.info("ATS is running, will be stopped")
+ arg = "stop"
+
+ # ATS is running fine, but we want to restart it
+ elif restart:
+ logging.info("ATS process found - restarting")
+ arg = "restart"
+
+ # ATS is running fine already
+ else:
+ logging.info("ATS already running - nothing to do")
+ return True
+
+ tsexe = os.path.join(TS_ROOT, "bin", "trafficserver")
+ if MODE is Modes.INTERACTIVE and not getYN("Run command '%s %s'?" % (tsexe, arg)):
+ logging.warning("ATS status will not be set - Traffic Ops may not expect this!")
+ return True
+
+ logging.info("ATS status will be set using: %s %s", tsexe, arg)
+
+ if MODE is not Modes.REPORT:
+
+ sub = subprocess.Popen([tsexe, arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = sub.communicate()
+
+ if sub.returncode:
+ logging.error("Failed to start/stop/restart trafficserver!")
+ logging.warning("Is the 'trafficserver' script located at %s?", tsexe)
+ logging.debug(out.decode())
+ logging.debug(err.decode())
+ return False
+ return True
+
+def setServiceStatus(chkconfig:dict) -> bool:
+ """
+ Sets the status of a service based on its 'chkconfig'.
+ A 'chkconfig' consists of a list of run-levels with either 'on' or 'off' as values.
+ This allowed specifying what run-levels needed a service. It's now totally deprecated,
+ but the Traffic Ops back-end doesn't know that yet...
+
+ .. warning:: This function currently ONLY checks for 'trafficserver' chkconfigs.
+
+ :param chkconfig: A single chkconfig
+ :returns: whether or not the service's status was set successfully
+ """
+ global HAS_SYSTEMD
+ from .utils import getYesNoResponse as getYN
+ from .configuration import MODE, Modes
+
+ if not HAS_SYSTEMD:
+ logging.warning("This system doesn't have systemd, services cannot be enabled/disabled")
+ return True
+
+ try:
+ status = "enable" if "on" in chkconfig.value else "disable"
+ service = chkconfig['name']
+ except KeyError as e:
+ logging.error("'%r' could not be parsed as a chkconfig object!", chkconfig)
+ logging.debug("%s", e, exc_info=True, stack_info=True)
+ return False
+
+ if MODE is Modes.INTERACTIVE and not getYN("%s %s?" % (service, status), default='Y'):
+ logging.warning("%s will not be %sd - some things may break!", service, status)
+ return True
+
+ logging.info("%s will be %sd", service, status)
+
+ if MODE is not Modes.REPORT:
+ try:
+ sub = subprocess.Popen(["systemctl", status, service],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out, err = sub.communicate()
+ logging.debug("output")
+ except (OSError, subprocess.CalledProcessError) as e:
+ logging.error("An error occurred when %sing %s: %s", status[:-1], service, e)
+ logging.debug("%r", e, exc_info=True, stack_info=True)
+ return False
+
+ return True
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py
new file mode 100644
index 000000000..5dcd84cd1
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/to_api.py
@@ -0,0 +1,360 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module contains functionality for dealing with the Traffic Ops ReST API
+"""
+
+import datetime
+import typing
+import logging
+import requests
+
+from . import packaging
+
+#: Caches update statuses mapped by hostnames
+CACHED_UPDATE_STATUS = {}
+
+#: Caches the names of statuses supported by Traffic Ops
+CACHED_STATUSES = []
+
+#: Maps Traffic Ops alert levels to logging levels
+API_LOGGERS = {"error": lambda x: logging.error("Traffic Ops API alert: %s", x),
+ "warning": lambda x: logging.warning("Traffic Ops API alert: %s", x),
+ "info": lambda x: logging.info("Traffic Ops API alert: %s", x),
+ "success": lambda x: logging.info("Traffic Ops API alert: %s", x)}
+
+class ServerInfo():
+ """
+ Holds information about a server, as returned by the Traffic Ops API
+ ``api/1.x/servers/<hostname>/configfiles/ats`` endpoint
+ """
+
+ cdnId = -1 #: A database primary key for the CDN to which this server is assigned
+ cdnName = "" #: The name of the CDN to which this server is assigned
+ profileName = "" #: The name of the profile in use by this server
+ profileId = -1 #: A database primary key for this server's profile's information
+ serverId = -1 #: A database primary key for this server's information
+ serverIpv4 = "" #: This server's IPv4 address
+ serverName = "" #: This server's short hostname
+ serverTcpPort = 80 #: The port on which the caching proxy of this server listens
+ toUrl = "" #: The Traffic Ops URL... not sure what that's for...
+
+ #: This specifies the url of a reverse proxy that should be used for future requests to the
+ #: Traffic Ops API - if present.
+ toRevProxyUrl = ""
+
+ def __init__(self, raw:dict):
+ """
+ Constructs a server object out of some kind of raw API response
+
+ :param raw: some kind of ungodly huge JSON object from one API endpoint or
+ another. Attempts will be made to resolve inconsistent naming accross
+ endpoints.
+ :raises ValueError: when the passed object doesn't have all required fields
+ """
+ try:
+ self.cdnId = raw["cdnId"]
+ self.cdnName = raw["cdnName"]
+ self.profileName = raw["profileName"]
+ self.profileId = raw["profileId"]
+ self.serverId = raw["serverId"]
+ self.serverIpv4 = raw["serverIpv4"]
+ self.serverName = raw["serverName"]
+ self.serverTcpPort = raw["serverTcpPort"]
+ self.toUrl = raw["toUrl"]
+
+ # This may or may not exist
+ if "toRevProxyUrl" in raw:
+ self.toRevProxyUrl = raw["toRevProxyUrl"]
+ except (KeyError, TypeError) as e:
+ raise ValueError from e
+
+
+ def __repr__(self) -> str:
+ """
+ Implements ``str(self)``
+ """
+ out = "Server(%s)"
+ return out % ', '.join(("%s=%r" % (a, self.__getattribute__(a))\
+ for a in dir(self)\
+ if not a.startswith('_')))
+
+ def __format__(self, fmt:str) -> str:
+ """
+ Implements ``str.format(self)``
+ """
+ from .configuration import HOSTNAME
+ fmt = fmt.replace("__HOSTNAME__", HOSTNAME[0])
+ fmt = fmt.replace("__FULL_HOSTNAME__", HOSTNAME[1])
+ fmt = fmt.replace("__RETURN__", '\n')
+ fmt = fmt.replace("__CACHE_IPV4__", self.serverIpv4)
+
+ # Don't ask me why, but the reference ORT implementation just strips these ones out
+ # if the tcp port is 80.
+ return fmt.replace("__SERVER_TCP_PORT__", str(self.serverTcpPort)\
+ if self.serverTcpPort != 80 else "")
+
+def TOPost(uri:str, data:dict) -> str:
+ """
+ POSTs the passed data in a request to the specified API endpoint
+
+ :param uri: The Traffic Ops URL-relative path to an API endpoint, e.g. if the intention is
+ to post to ``https://TO_URL:TO_PORT/api/1.3/users``, this should just be
+ ``'api/1.3/users'``
+
+ .. note:: This function will ensure the proper concatenation of the Traffic Ops URL
+ to the request path; callers need not worry about whether the ``uri`` ought to
+ begin with a slash.
+
+ :returns: The Traffic Ops server's response to the POST request - possibly empty - as a UTF-8
+ string
+ :raises ConnectionError: when an error occurs trying to communicate with Traffic Ops
+ """
+ from . import configuration as conf
+
+ uri = '/'.join((conf.TO_URL, uri.lstrip('/')))
+ logging.info("POSTing %r to %s", data, uri)
+
+ try:
+ resp = requests.post(uri, cookies=conf.getTOCookie(), verify=conf.VERIFY, data=data)
+ except (PermissionError, requests.exceptions.RequestException) as e:
+ raise ConnectionError from e
+
+ logging.debug("Raw response from Traffic Ops: %s\n%s\n%s", resp, resp.headers, resp.content)
+
+ return resp.text
+
+def getTOJSONResponse(uri:str) -> dict:
+ """
+ A wrapper around :func:`traffic_ops_ort.utils.getJSONResponse` that handles cookies and
+ tacks on the top-level Traffic Ops URL.
+
+ :param uri: The Traffic Ops URL-relative path to a JSON API endpoint, e.g. if the intention
+ is to get ``https://TO_URL:TO_PORT/api/1.3/ping``, this should just be ``'api/1.3/ping'``
+
+ .. note:: This function will ensure the proper concatenation of the Traffic Ops URL
+ to the request path; callers need not worry about whether the ``uri`` ought to
+ begin with a slash.
+
+ :returns: The decoded JSON response as an object
+
+ .. note:: If the API response containes a 'response' object, this function will
+ only return that object. Also, if the API response contains an 'alerts' object,
+ they will be logged appropriately
+
+ :raises ConnectionError: when an error occurs trying to communicate with Traffic Ops
+ :raises ValueError: when the request completes successfully, but the response body
+ does not represent a JSON-encoded object.
+ """
+ global API_LOGGERS
+ from . import configuration as conf, utils
+
+ uri = '/'.join((conf.TO_URL, uri.lstrip('/')))
+ logging.info("Fetching Traffic Ops API response: %s", uri)
+
+ if datetime.datetime.now().timestamp() >= conf.TO_COOKIE.expires:
+ try:
+ conf.getNewTOCookie()
+ except PermissionError as e:
+ raise ConnectionError from e
+
+ resp = utils.getJSONResponse(uri,
+ cookies = {conf.TO_COOKIE.name:conf.TO_COOKIE.value},
+ verify = conf.VERIFY)
+
+ if "response" in resp:
+ if "alerts" in resp:
+ for alert in resp["alerts"]:
+ if "level" in alert:
+ msg = alert["text"] if "text" in alert else "Unkown"
+ API_LOGGERS[alert["level"]](msg)
+ elif "text" in alert:
+ logging.warning("Traffic Ops API alert: %s", alert["text"])
+ logging.debug("Weird alert encountered: %r", alert)
+
+
+ return resp["response"]
+
+ return resp
+
+def getUpdateStatus(host:str) -> dict:
+ """
+ Gets the update status of a server.
+
+ .. note:: If the global :data:`CACHED_UPDATE_STATUS` cached response is set, this function will
+ default to that object. If it is *not* set, then this function will set it.
+
+ :param host: The (short) hostname of the server to query
+ :raises ValueError: if ``host`` is not a :const:`str`
+ :raises PermissionError: if a new cookie is required, but fails to be aquired
+ :returns: An object representing the API's response
+ """
+ global CACHED_UPDATE_STATUS
+
+ logging.info("Fetching update status for %s from Traffic Ops", host)
+ if not isinstance(host, str):
+ raise ValueError("First argument ('host') must be 'str', not '%s'" % type(host))
+
+ if host in CACHED_UPDATE_STATUS:
+ return CACHED_UPDATE_STATUS[host]
+
+ CACHED_UPDATE_STATUS[host] = getTOJSONResponse("api/1.3/servers/%s/update_status" % host)
+
+ return CACHED_UPDATE_STATUS[host]
+
+def getMyStatus() -> str:
+ """
+ Fetches the status of this server as set in Traffic Ops
+
+ :raises ConnectionError: if fetching the status fails
+ :raises ValueError: if the :data:`traffic_ops_ort.configuration.HOSTNAME` is not properly set,
+ or a weird value is stored in the global :data:`CACHED_UPDATE_STATUS` response cache.
+ :returns: the name of the status to which this server is set in the Traffic Ops configuration
+
+ .. note:: If the global :data:`CACHED_UPDATE_STATUS` cached response is set, this function will
+ default to the status provided by that object.
+ """
+ global CACHED_UPDATE_STATUS
+ from .configuration import HOSTNAME
+
+ try:
+ if HOSTNAME[0] in CACHED_UPDATE_STATUS:
+ myStatus = CACHED_UPDATE_STATUS[HOSTNAME[0]]
+ if "status" in CACHED_UPDATE_STATUS[HOSTNAME[0]]:
+ return CACHED_UPDATE_STATUS[HOSTNAME[0]]["status"]
+
+ logging.warning("CACHED_UPDATE_STATUS possibly set improperly")
+ logging.warning("clearing this server's cached entry!")
+ logging.debug("value was %r", myStatus)
+ del CACHED_UPDATE_STATUS[HOSTNAME[0]]
+
+ except (IndexError, KeyError) as e:
+ raise ValueError from e
+
+ myStatus = getUpdateStatus(HOSTNAME[0])
+
+ try:
+ return myStatus[0]["status"]
+ except (IndexError, KeyError) as e:
+ logging.error("Malformed response from Traffic Ops to update status request!")
+ raise ConnectionError from e
+
+def getStatuses() -> typing.Generator[str, None, None]:
+ """
+ Yields a successive list of statuses supported by Traffic Ops.
+
+ .. note:: This is implemented by iterating the :data:`CACHED_STATUSES` global cache -
+ first populating it if it is empty - and so the validity of its outputs
+ depends on the validity of the data stored therein
+
+ :raises ValueError: if a response from the TO API is successful, but cannot be parsed as
+ JSON
+ :raises TypeError: if :data:`CACHED_STATUSES` is not iterable
+ :raises ConnectionError: if something goes wrong contacting the Traffic Ops API
+ :returns: an iterable generator that yields status names as strings
+ """
+ global CACHED_STATUSES
+
+ logging.info("Retrieving statuses from Traffic Ops")
+
+ if CACHED_STATUSES:
+ logging.debug("Using cached statuses: %r", CACHED_STATUSES)
+ yield from CACHED_STATUSES
+ else:
+ statuses = getTOJSONResponse("api/1.3/statuses")
+ yield from statuses
+
+def getMyPackages() -> typing.List[packaging.Package]:
+ """
+ Fetches a list of the packages specified by Traffic Ops that should exist on this server.
+
+ :returns: all of the packages which this system must have, according to Traffic Ops.
+ :raises ConnectionError: if fetching the package list fails
+ :raises ValueError: if the API endpoint returns a malformed response that can't be parsed
+ """
+ from .configuration import HOSTNAME
+
+ logging.info("Fetching this server's package list from Traffic Ops")
+
+ myPackages=getTOJSONResponse('/'.join(("ort", HOSTNAME[0], "packages")))
+
+ logging.debug("Raw package response: %r", myPackages)
+
+ return [packaging.Package(p) for p in myPackages]
+
+def updateTrafficOps():
+ """
+ Updates Traffic Ops's knowledge of this server's update status.
+ """
+ from .configuration import MODE, Modes, HOSTNAME
+ from .utils import getYesNoResponse as getYN
+
+ if MODE is Modes.INTERACTIVE and not getYN("Update Traffic Ops?", default='Y'):
+ logging.warning("Update will not be performed; you should do this manually")
+ return
+
+ logging.info("Updating Traffic Ops")
+
+ if MODE is Modes.REPORT:
+ return
+
+ payload = {"updated": False, "reval_updated": False}
+ response = TOPost("/update/%s" % HOSTNAME[0], payload)
+
+ if response:
+ logging.info("Traffic Ops response: %s", response)
+
+def getMyConfigFiles() -> typing.List[dict]:
+ """
+ Fetches configuration files constructed by Traffic Ops for this server
+
+ .. note:: This function will set the :data:`traffic_ops_ort.configuration.SERVER_INFO`
+ object to an instance of :class:`ServerInfo` with the provided information.
+
+ :returns: A list of constructed config file objects
+ :raises ConnectionError: when something goes wrong communicating with Traffic Ops
+ :raises ValueError: when a response was successfully obtained from the Traffic Ops API, but the
+ response could not successfully be parsed as JSON, or was missing information
+ """
+ from . import configuration
+
+ uri = "/api/1.3/servers/%s/configfiles/ats" % configuration.HOSTNAME[0]
+
+ myFiles = getTOJSONResponse(uri)
+
+ try:
+ configuration.SERVER_INFO = ServerInfo(myFiles["info"])
+ return myFiles["configFiles"]
+ except KeyError as e:
+ raise ValueError from e
+
+def getMyChkconfig() -> typing.List[dict]:
+ """
+ Fetches the 'chkconfig' for this server
+
+ :returns: An iterable list of 'chkconfig' entries
+ :raises ConnectionError: when something goes wrong communicating with Traffic Ops
+ :raises ValueError: when a response was successfully obtained from the Traffic Ops API, but the
+ response could not successfully be parsed as JSON, or was missing information
+ """
+ from . import configuration
+
+ uri = "/ort/%s/chkconfig" % configuration.HOSTNAME[0]
+ logging.info("Fetching chkconfig from %s", uri)
+
+ return getTOJSONResponse(uri)
diff --git a/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/utils.py b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/utils.py
new file mode 100644
index 000000000..fa8c75b8b
--- /dev/null
+++ b/infrastructure/cdn-in-a-box/ort/traffic_ops_ort/utils.py
@@ -0,0 +1,98 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+This module contains miscellaneous utilities, typically dealing with string
+manipulation or user input/output
+"""
+import logging
+from sys import stderr
+import requests
+
+def getYesNoResponse(prmpt:str, default:str = None) -> bool:
+ """
+ Utility function to get an interactive yes/no response to the prompt `prmpt`
+
+ :param prmpt: The prompt to display to users
+ :param default: The default response; should be one of ``'y'``, ``"yes"``, ``'n'`` or ``"no"``
+ (case insensitive)
+ :raises AttributeError: if 'prmpt' and/or 'default' is/are not strings
+ :returns: the parsed response as a boolean
+ """
+ if default:
+ prmpt = prmpt.rstrip().rstrip(':') + '['+default+"]:"
+ while True:
+ choice = input(prmpt).lower()
+
+ if choice in {'y', 'yes'}:
+ return True
+ if choice in {'n', 'no'}:
+ return False
+ if not choice and default is not None:
+ return default.lower() in {'y', 'yes'}
+
+ print("Please enter a yes/no response.", file=stderr)
+
+def getTextResponse(uri:str, cookies:dict = None, verify:bool = True) -> str:
+ """
+ Gets the plaintext response body of an HTTP ``GET`` request
+
+ :param uri: The full path to a resource for the request
+ :param cookies: An optional dictionary of cookie names mapped to values
+ :param verify: If :const:`True`, the SSL keys used to communicate with the full URI will be
+ verified
+
+ :raises ConnectionError: when an error occurs trying to communicate with the server
+ :raises ValueError: if the server's response cannot be interpreted as a UTF-8 string - e.g.
+ when the response body is raw binary data but the response headers claim it's UTF-16
+ """
+ logging.info("Getting plaintext response via 'HTTP GET %s'", uri)
+
+ response = requests.get(uri, cookies=cookies, verify=verify)
+
+ if response.status_code not in range(200, 300):
+ logging.warning("Status code (%d) seems to indicate failure!", response.status_code)
+ logging.debug("Response: %r\n%r", response.headers, response.content)
+
+ return response.text
+
+def getJSONResponse(uri:str, cookies:dict = None, verify:bool = True) -> dict:
+ """
+ Retrieves a JSON object from some HTTP API
+
+ :param uri: The URI to fetch
+ :param cookies: A dictionary of cookie names mapped to values
+ :param verify: If this is :const:`True`, the SSL keys will be verified during handshakes with
+ 'https' URIs
+ :returns: The decoded JSON object
+ :raises ConnectionError: when an error occurs trying to communicate with the server
+ :raises ValueError: when the request completes successfully, but the response body
+ does not represent a JSON-encoded object.
+ """
+
+ logging.info("Getting JSON response via 'HTTP GET %s", uri)
+
+ try:
+ response = requests.get(uri, cookies=cookies, verify=verify)
+ except (ValueError, ConnectionError, requests.exceptions.RequestException) as e:
+ raise ConnectionError from e
+
+ if response.status_code not in range(200, 300):
+ logging.warning("Status code (%d) seems to indicate failure!", response.status_code)
+ logging.debug("Response: %r\n%r", response.headers, response.content)
+
+ return response.json()
diff --git a/infrastructure/cdn-in-a-box/traffic_ops/to-access.sh b/infrastructure/cdn-in-a-box/traffic_ops/to-access.sh
index e6147d0c0..712ff5a6b 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops/to-access.sh
+++ b/infrastructure/cdn-in-a-box/traffic_ops/to-access.sh
@@ -43,6 +43,8 @@ export CURLOPTS=${CURLOPTS:--LfsS}
export CURLAUTH=${CURLAUTH:--k}
export COOKIEJAR=$(mktemp)
+export MY_HOSTNAME="$(hostname -s)"
+
login=$(mktemp)
cleanup() {
@@ -109,7 +111,7 @@ to-post() {
fi
to-auth && \
curl $CURLAUTH $CURLOPTS --cookie "$COOKIEJAR" -X POST $data "$TO_URL/$1"
- [[ -n $t ]] && rm "$t"
+ [[ -n $t ]] && rm "$t"
}
to-put() {
@@ -134,13 +136,13 @@ to-delete() {
# serverType - the type of the server to be created; one of "edge", "mid", "tm"
to-enroll() {
- while true; do
+ while true; do
[ -d "$ENROLLER_DIR" ] && break
echo "Waiting for $ENROLLER_DIR ..."
sleep 2
done
- while true; do
+ while true; do
[ "$serverType" = "to" ] && break
[ -f "$ENROLLER_DIR/initial-load-done" ] && break
echo "Waiting for traffic-ops to do initial load ..."
@@ -159,7 +161,6 @@ to-enroll() {
fi
export MY_NET_INTERFACE='eth0'
- export MY_HOSTNAME="$(hostname -s)"
export MY_DOMAINNAME="$(dnsdomainname)"
export MY_IP="$(ifconfig $MY_NET_INTERFACE | grep 'inet ' | tr -s ' ' | cut -d ' ' -f 3)"
export MY_GATEWAY="$(route -n | grep $MY_NET_INTERFACE | grep -E '^0\.0\.0\.0' | tr -s ' ' | cut -d ' ' -f2)"
@@ -198,7 +199,7 @@ to-enroll() {
export MY_CACHE_GROUP="CDN_in_a_Box_Edge"
fi
;;
- "to" )
+ "to" )
export MY_TYPE="TRAFFIC_OPS"
export MY_PROFILE="TRAFFIC_OPS"
export MY_STATUS="ONLINE"
@@ -250,3 +251,10 @@ to-enroll() {
sleep 3
}
+
+# Tests that this server exists in Traffic Ops
+function testenrolled() {
+ local tmp="$(to-get 'api/1.3/servers?name='$MY_HOSTNAME'')"
+ tmp=$(echo $tmp | jq '.response[]|select(.hostName=="'"$MY_HOSTNAME"'")')
+ echo "$tmp"
+}
diff --git a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/010-ATS_EDGE_TIER_CACHE.json b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/010-ATS_EDGE_TIER_CACHE.json
index 78cacef13..2f2b8902c 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/010-ATS_EDGE_TIER_CACHE.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/010-ATS_EDGE_TIER_CACHE.json
@@ -1,1704 +1,402 @@
{
- "cdnName": "CDN-in-a-Box",
- "description": "Edge Cache - Apache Traffic Server",
- "name": "ATS_EDGE_TIER_CACHE",
- "routingDisabled": false,
- "type": "ATS_PROFILE",
- "params": [
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.proxy_name",
- "secure": false,
- "value": "STRING __HOSTNAME__"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.config_dir",
- "secure": false,
- "value": "STRING /etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.proxy_binary_opts",
- "secure": false,
- "value": "STRING -M"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.temp_dir",
- "secure": false,
- "value": "STRING /tmp"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.autoconfig.scale",
- "secure": false,
- "value": "FLOAT 1.5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.accept_threads",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.admin.user_id",
- "secure": false,
- "value": "STRING ats"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.admin.autoconf_port",
- "secure": false,
- "value": "INT 8083"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.process_manager.mgmt_port",
- "secure": false,
- "value": "INT 8084"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.alarm.abs_path",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.server_ports",
- "secure": false,
- "value": "STRING 80 80:ipv6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_ports",
- "secure": false,
- "value": "STRING 443 563"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_request_via_str",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_response_via_str",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.response_server_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_age_in_response",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.enable_url_expandomatic",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.no_dns_just_forward_to_parent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.uncacheable_requests_bypass_parent",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_enabled_in",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_enabled_out",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.chunking_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.send_http11_requests",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.share_server_sessions",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.origin_server_pipeline",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.user_agent_pipeline",
- "secure": false,
- "value": "INT 8"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_filter",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_format_redirect",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_default_redirect",
- "secure": false,
- "value": "STRING http://www.example.com/"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy_routing_enable",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.retry_time",
- "secure": false,
- "value": "INT 60"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.forward.proxy_auth_to_parent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_no_activity_timeout_in",
- "secure": false,
- "value": "INT 115"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_no_activity_timeout_out",
- "secure": false,
- "value": "INT 120"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_no_activity_timeout_in",
- "secure": false,
- "value": "INT 30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_no_activity_timeout_out",
- "secure": false,
- "value": "INT 30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_active_timeout_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.accept_no_activity_timeout",
- "secure": false,
- "value": "INT 120"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_max_retries",
- "secure": false,
- "value": "INT 6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_max_retries_dead_server",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_rr_retries",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_timeout",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.post_connect_attempts_timeout",
- "secure": false,
- "value": "INT 1800"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.down_server.cache_time",
- "secure": false,
- "value": "INT 300"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.down_server.abort_threshold",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.congestion_control.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_from",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_referer",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_user_agent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_cookie",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_client_ip",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_insert_client_ip",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_other_header_list",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_squid_x_forwarded_for",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.push_method_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.http",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_client_no_cache",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ims_on_client_no_cache",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_server_no_cache",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.normalize_ae_gzip",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.cache_responses_to_cookies",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_authentication",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.enable_default_vary_headers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.when_to_revalidate",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.when_to_add_no_cache_to_msie_requests",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.required_headers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.max_stale_age",
- "secure": false,
- "value": "INT 604800"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.range.lookup",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_min_lifetime",
- "secure": false,
- "value": "INT 3600"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_max_lifetime",
- "secure": false,
- "value": "INT 86400"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_lm_factor",
- "secure": false,
- "value": "FLOAT 0.10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.fuzz.time",
- "secure": false,
- "value": "INT 240"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.fuzz.probability",
- "secure": false,
- "value": "FLOAT 0.005"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_text",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_images",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_other",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.enable_http_stats",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.enable_logging",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.response_suppression_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.connections_throttle",
- "secure": false,
- "value": "INT 500000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.defer_accept",
- "secure": false,
- "value": "INT 45"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.local.cluster.type",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.cluster_port",
- "secure": false,
- "value": "INT 8086"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.rsport",
- "secure": false,
- "value": "INT 8088"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mcport",
- "secure": false,
- "value": "INT 8089"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mc_group_addr",
- "secure": false,
- "value": "STRING 224.0.1.37"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mc_ttl",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.log_bogus_mc_msgs",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.ethernet_interface",
- "secure": false,
- "value": "STRING lo"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.permit.pinning",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.algorithm",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.use_seen_filter",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.compress",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.limits.http.max_alts",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.max_doc_size",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.mutex_retry_delay",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.search_default_domains",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.splitDNS.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.max_dns_in_flight",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.url_expansions",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.round_robin_nameservers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.nameservers",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.resolv_conf",
- "secure": false,
- "value": "STRING /etc/resolv.conf"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.validate_query_name",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.timeout",
- "secure": false,
- "value": "INT 1440"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.strict_round_robin",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logging_enabled",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_secs_per_buffer",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_for_logs",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_for_orphan_logs",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_headroom",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.hostname",
- "secure": false,
- "value": "STRING localhost"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logfile_dir",
- "secure": false,
- "value": "STRING /var/log/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logfile_perm",
- "secure": false,
- "value": "STRING rw-r--r--"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.custom_logs_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.squid_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.common_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.extended_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.separate_icp_logs",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.separate_host_logs",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.local.log.collation_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_host",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_port",
- "secure": false,
- "value": "INT 8085"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_secret",
- "secure": false,
- "value": "STRING foobar"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_host_tagged",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_retry_sec",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_interval_sec",
- "secure": false,
- "value": "INT 86400"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_offset_hr",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_size_mb",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.auto_delete_rolled_files",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.sampling_frequency",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.reverse_proxy.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.header.parse.no_host_url_redirect",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.default_to_server_pac",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.default_to_server_pac_port",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.pristine_host_hdr",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.number.threads",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.SSLv2",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.TLSv1",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.compression",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.certification_level",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cert_chain.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.CA.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.verify.server",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.private_key.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.CA.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.icp_interface",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.icp_port",
- "secure": false,
- "value": "INT 3130"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.multicast_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.query_timeout",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.force",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.retry_count",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.retry_interval",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.concurrent_updates",
- "secure": false,
- "value": "INT 100"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_send_buffer_size_in",
- "secure": false,
- "value": "INT 262144"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_recv_buffer_size_in",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_send_buffer_size_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_recv_buffer_size_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.core_limit",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.debug.enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.debug.tags",
- "secure": false,
- "value": "STRING http|dns"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dump_mem_info_frequency",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.slow.log.threshold",
- "secure": false,
- "value": "INT 10000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.task_threads",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "cache.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "hosting.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "parent.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "plugin.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "records.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "remap.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "storage.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "volume.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.remap_required",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.file",
- "secure": false,
- "value": "STRING parent.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.filename",
- "secure": false,
- "value": "STRING remap.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.cluster_configuration ",
- "secure": false,
- "value": "STRING cluster.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.loadavg",
- "secure": false,
- "value": "25.0"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.availableBandwidthInKbps",
- "secure": false,
- "value": ">1750000"
- },
- {
- "configFile": "rascal.properties",
- "name": "history.count",
- "secure": false,
- "value": "30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.control.filename",
- "secure": false,
- "value": "STRING cache.config"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingEnabled",
- "secure": false,
- "value": "3"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingIntervalSec",
- "secure": false,
- "value": "86400"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingOffsetHr",
- "secure": false,
- "value": "11"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingSizeMb",
- "secure": false,
- "value": "4"
- },
- {
- "configFile": "logs_xml.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.xml_configFile",
- "secure": false,
- "value": "STRING logs_xml.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.queryTime",
- "secure": false,
- "value": "1000"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.polling.url",
- "secure": false,
- "value": "http://${hostname}/_astats?application=&inf.name=${interface_name}"
- },
- {
- "configFile": "storage.config",
- "name": "Disk_Volume",
- "secure": false,
- "value": "1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.hosting_filename",
- "secure": false,
- "value": "STRING hosting.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.connection.timeout",
- "secure": false,
- "value": "2000"
- },
- {
- "configFile": "12M_facts",
- "name": "location",
- "secure": false,
- "value": "/opt/ort"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_accept_encoding_mismatch",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "chkconfig",
- "name": "trafficserver",
- "secure": false,
- "value": "0:off\t1:off\t2:on\t3:on\t4:on\t5:on\t6:off"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.debug_filter",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.enable_reclaim",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.max_overage",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.show_location",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.allow_empty_doc",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.config.cache.interim.storage",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "plugin.config",
- "name": "regex_revalidate.so",
- "secure": false,
- "value": "--config regex_revalidate.config"
- },
- {
- "configFile": "regex_revalidate.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.stack_dump_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.ttl_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.lookup_timeout",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.serve_stale_for",
- "secure": false,
- "value": "INT 6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.enable_read_while_writer",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.background_fill_active_timeout",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.background_fill_completed_threshold",
- "secure": false,
- "value": "FLOAT 0.0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.extended2_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.affinity",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.autoconfig",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.limit",
- "secure": false,
- "value": "INT 8"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.thread_freelist_size",
- "secure": false,
- "value": "INT 1024"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.mlock_enabled",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogFormat.Format",
- "secure": false,
- "value": "%<cqtq> chi=%<chi> phn=%<phn> php=%<php> shn=%<shn> url=%<cquuc> cqhm=%<cqhm> cqhv=%<cqhv> pssc=%<pssc> ttms=%<ttms> b=%<pscl> sssc=%<sssc> sscl=%<sscl> cfsc=%<cfsc> pfsc=%<pfsc> crc=%<crc> phr=%<phr> pqsn=%<pqsn> uas=\"%<{User-Agent}cqh>\" "
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogFormat.Name",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.Format",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.Filename",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "plugin.config",
- "name": "astats_over_http.so",
- "secure": false,
- "value": ""
- },
- {
- "configFile": "astats.config",
- "name": "allow_ip",
- "secure": false,
- "value": "127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
- },
- {
- "configFile": "astats.config",
- "name": "allow_ip6",
- "secure": false,
- "value": "::1/128,fc01:9400:1000:8::/64"
- },
- {
- "configFile": "astats.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "astats.config",
- "name": "path",
- "secure": false,
- "value": "_astats"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.http.compatibility.4-2-0-fixup",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cipher_suite",
- "secure": false,
- "value": "STRING ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2:@STRENGTH"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.honor_cipher_order",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.private_key.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.CA.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.private_key.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.CA.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.SSLv3",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.multicert.filename",
- "secure": false,
- "value": "STRING ssl_multicert.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.negative_caching_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "astats.config",
- "name": "record_types",
- "secure": false,
- "value": "122"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_active_timeout_in",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.enable_customizations",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.negative_caching_lifetime",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.template_sets_dir",
- "secure": false,
- "value": "STRING /etc/trafficserver/body_factory"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ip_allow.filename",
- "secure": false,
- "value": "STRING ip_allow.config"
- },
- {
- "configFile": "parent.config",
- "name": "weight",
- "secure": false,
- "value": "1.2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.fail_threshold",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.connect_attempts_timeout",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.per_parent_connect_attempts",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.total_connect_attempts",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "storage.config",
- "name": "Drive_Letters",
- "secure": false,
- "value": "cache"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.hostdb.sync_frequency",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.storage_size",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.size",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.guaranteed_max_lifetime",
- "secure": false,
- "value": "INT 2592000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_client_cc_max_age",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.default_inactivity_timeout",
- "secure": false,
- "value": "INT 180"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.mark_down_hostdb",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.dontdump_iobuffers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "ip_allow.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "storage.config",
- "name": "Drive_Prefix",
- "secure": false,
- "value": "/var/trafficserver/"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.logfile.rolling_size_mb",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.logfile.rolling_enabled",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "set_dscp_0.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_10.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_12.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_14.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_18.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_20.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_22.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_26.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_28.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_30.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_34.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_36.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_38.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_8.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_16.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_24.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_32.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_40.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_48.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_56.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_37.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- }
- ]
+ "cdnName": "CDN-in-a-Box",
+ "description": "Edge Cache - Apache Traffic Server",
+ "name": "ATS_EDGE_TIER_CACHE",
+ "routingDisabled": false,
+ "type": "ATS_PROFILE",
+ "params": [
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.proxy_name",
+ "secure": false,
+ "value": "STRING __HOSTNAME__"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.config_dir",
+ "secure": false,
+ "value": "STRING /etc/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.admin.user_id",
+ "secure": false,
+ "value": "STRING ats"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.server_ports",
+ "secure": false,
+ "value": "STRING 80 80:ipv6"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.insert_response_via_str",
+ "secure": false,
+ "value": "INT 3"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.parent_proxy_routing_enable",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.parent_proxy.retry_time",
+ "secure": false,
+ "value": "INT 60"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.connect_attempts_timeout",
+ "secure": false,
+ "value": "INT 10"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.cache.required_headers",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.enable_http_stats",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.dns.round_robin_nameservers",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.max_space_mb_for_logs",
+ "secure": false,
+ "value": "INT 512"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.max_space_mb_headroom",
+ "secure": false,
+ "value": "INT 50"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.logfile_dir",
+ "secure": false,
+ "value": "STRING /var/log/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.reverse_proxy.enabled",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.diags.debug.enabled",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.slow.log.threshold",
+ "secure": false,
+ "value": "INT 10000"
+ },
+ {
+ "configFile": "cache.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "hosting.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "parent.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "records.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "remap.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "volume.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.url_remap.remap_required",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.loadavg",
+ "secure": false,
+ "value": "25.0"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.availableBandwidthInKbps",
+ "secure": false,
+ "value": ">1750000"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "history.count",
+ "secure": false,
+ "value": "30"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.queryTime",
+ "secure": false,
+ "value": "1000"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.polling.url",
+ "secure": false,
+ "value": "http://${hostname}/_astats?application=&inf.name=${interface_name}"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Disk_Volume",
+ "secure": false,
+ "value": "1"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.connection.timeout",
+ "secure": false,
+ "value": "2000"
+ },
+ {
+ "configFile": "chkconfig",
+ "name": "trafficserver",
+ "secure": false,
+ "value": "0:off\t1:off\t2:on\t3:on\t4:on\t5:on\t6:off"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "regex_revalidate.so",
+ "secure": false,
+ "value": "--config regex_revalidate.config"
+ },
+ {
+ "configFile": "regex_revalidate.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.exec_thread.autoconfig",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "astats_over_http.so",
+ "secure": false,
+ "value": ""
+ },
+ {
+ "configFile": "astats.config",
+ "name": "allow_ip",
+ "secure": false,
+ "value": "127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "allow_ip6",
+ "secure": false,
+ "value": "::1/128,fc01:9400:1000:8::/64"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "path",
+ "secure": false,
+ "value": "_astats"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "record_types",
+ "secure": false,
+ "value": "122"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.transaction_active_timeout_in",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.body_factory.template_sets_dir",
+ "secure": false,
+ "value": "STRING /etc/trafficserver/body_factory"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Drive_Letters",
+ "secure": false,
+ "value": "cache"
+ },
+ {
+ "configFile": "ip_allow.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Drive_Prefix",
+ "secure": false,
+ "value": "/var/trafficserver/"
+ },
+ {
+ "configFile": "set_dscp_0.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_10.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_12.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_14.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_18.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_20.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_22.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_26.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_28.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_30.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_34.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_36.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_38.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_8.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_16.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_24.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_32.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_40.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_48.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_56.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_37.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ }
+ ]
}
diff --git a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/020-ATS_MID_TIER_CACHE.json b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/020-ATS_MID_TIER_CACHE.json
index a14abccb2..5eb37bbe7 100644
--- a/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/020-ATS_MID_TIER_CACHE.json
+++ b/infrastructure/cdn-in-a-box/traffic_ops_data/profiles/020-ATS_MID_TIER_CACHE.json
@@ -1,1704 +1,402 @@
{
- "cdnName": "CDN-in-a-Box",
- "description": "Mid Cache - Apache Traffic Server",
- "name": "ATS_MID_TIER_CACHE",
- "routingDisabled": false,
- "type": "ATS_PROFILE",
- "params": [
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.proxy_name",
- "secure": false,
- "value": "STRING __HOSTNAME__"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.config_dir",
- "secure": false,
- "value": "STRING /etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.proxy_binary_opts",
- "secure": false,
- "value": "STRING -M"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.temp_dir",
- "secure": false,
- "value": "STRING /tmp"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.autoconfig.scale",
- "secure": false,
- "value": "FLOAT 1.5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.accept_threads",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.admin.user_id",
- "secure": false,
- "value": "STRING ats"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.admin.autoconf_port",
- "secure": false,
- "value": "INT 8083"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.process_manager.mgmt_port",
- "secure": false,
- "value": "INT 8084"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.alarm.abs_path",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.server_ports",
- "secure": false,
- "value": "STRING 80 80:ipv6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_ports",
- "secure": false,
- "value": "STRING 443 563"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_request_via_str",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_response_via_str",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.response_server_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_age_in_response",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.enable_url_expandomatic",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.no_dns_just_forward_to_parent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.uncacheable_requests_bypass_parent",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_enabled_in",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_enabled_out",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.chunking_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.send_http11_requests",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.share_server_sessions",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.origin_server_pipeline",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.user_agent_pipeline",
- "secure": false,
- "value": "INT 8"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_filter",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_format_redirect",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.referer_default_redirect",
- "secure": false,
- "value": "STRING http://www.example.com/"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy_routing_enable",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.retry_time",
- "secure": false,
- "value": "INT 60"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.forward.proxy_auth_to_parent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_no_activity_timeout_in",
- "secure": false,
- "value": "INT 115"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.keep_alive_no_activity_timeout_out",
- "secure": false,
- "value": "INT 120"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_no_activity_timeout_in",
- "secure": false,
- "value": "INT 30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_no_activity_timeout_out",
- "secure": false,
- "value": "INT 30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_active_timeout_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.accept_no_activity_timeout",
- "secure": false,
- "value": "INT 120"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_max_retries",
- "secure": false,
- "value": "INT 6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_max_retries_dead_server",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_rr_retries",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.connect_attempts_timeout",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.post_connect_attempts_timeout",
- "secure": false,
- "value": "INT 1800"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.down_server.cache_time",
- "secure": false,
- "value": "INT 300"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.down_server.abort_threshold",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.congestion_control.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_from",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_referer",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_user_agent",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_cookie",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_remove_client_ip",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_insert_client_ip",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.anonymize_other_header_list",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.insert_squid_x_forwarded_for",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.push_method_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.http",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_client_no_cache",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ims_on_client_no_cache",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_server_no_cache",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.normalize_ae_gzip",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.cache_responses_to_cookies",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_authentication",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.enable_default_vary_headers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.when_to_revalidate",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.when_to_add_no_cache_to_msie_requests",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.required_headers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.max_stale_age",
- "secure": false,
- "value": "INT 604800"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.range.lookup",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_min_lifetime",
- "secure": false,
- "value": "INT 3600"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_max_lifetime",
- "secure": false,
- "value": "INT 86400"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.heuristic_lm_factor",
- "secure": false,
- "value": "FLOAT 0.10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.fuzz.time",
- "secure": false,
- "value": "INT 240"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.fuzz.probability",
- "secure": false,
- "value": "FLOAT 0.005"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_text",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_images",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.vary_default_other",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.enable_http_stats",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.enable_logging",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.response_suppression_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.connections_throttle",
- "secure": false,
- "value": "INT 500000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.defer_accept",
- "secure": false,
- "value": "INT 45"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.local.cluster.type",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.cluster_port",
- "secure": false,
- "value": "INT 8086"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.rsport",
- "secure": false,
- "value": "INT 8088"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mcport",
- "secure": false,
- "value": "INT 8089"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mc_group_addr",
- "secure": false,
- "value": "STRING 224.0.1.37"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.mc_ttl",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.log_bogus_mc_msgs",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.ethernet_interface",
- "secure": false,
- "value": "STRING lo"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.permit.pinning",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.algorithm",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.use_seen_filter",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ram_cache.compress",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.limits.http.max_alts",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.max_doc_size",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.mutex_retry_delay",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.search_default_domains",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.splitDNS.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.max_dns_in_flight",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.url_expansions",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.round_robin_nameservers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.nameservers",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.resolv_conf",
- "secure": false,
- "value": "STRING /etc/resolv.conf"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.validate_query_name",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.timeout",
- "secure": false,
- "value": "INT 1440"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.strict_round_robin",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logging_enabled",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_secs_per_buffer",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_for_logs",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_for_orphan_logs",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.max_space_mb_headroom",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.hostname",
- "secure": false,
- "value": "STRING localhost"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logfile_dir",
- "secure": false,
- "value": "STRING /var/log/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.logfile_perm",
- "secure": false,
- "value": "STRING rw-r--r--"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.custom_logs_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.squid_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.common_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.extended_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.separate_icp_logs",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.separate_host_logs",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.local.log.collation_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_host",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_port",
- "secure": false,
- "value": "INT 8085"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_secret",
- "secure": false,
- "value": "STRING foobar"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_host_tagged",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.collation_retry_sec",
- "secure": false,
- "value": "INT 5"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_interval_sec",
- "secure": false,
- "value": "INT 86400"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_offset_hr",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.rolling_size_mb",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.auto_delete_rolled_files",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.sampling_frequency",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.reverse_proxy.enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.header.parse.no_host_url_redirect",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.default_to_server_pac",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.default_to_server_pac_port",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.pristine_host_hdr",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.number.threads",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.SSLv2",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.TLSv1",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.compression",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.certification_level",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cert_chain.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.CA.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.verify.server",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.private_key.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.CA.cert.filename",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.icp_interface",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.icp_port",
- "secure": false,
- "value": "INT 3130"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.multicast_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.icp.query_timeout",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.force",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.retry_count",
- "secure": false,
- "value": "INT 10"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.retry_interval",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.update.concurrent_updates",
- "secure": false,
- "value": "INT 100"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_send_buffer_size_in",
- "secure": false,
- "value": "INT 262144"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_recv_buffer_size_in",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_send_buffer_size_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.sock_recv_buffer_size_out",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.core_limit",
- "secure": false,
- "value": "INT -1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.debug.enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.debug.tags",
- "secure": false,
- "value": "STRING http|dns"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dump_mem_info_frequency",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.slow.log.threshold",
- "secure": false,
- "value": "INT 10000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.task_threads",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "cache.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "hosting.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "parent.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "plugin.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "records.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "remap.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "storage.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "volume.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver/"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.remap_required",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.file",
- "secure": false,
- "value": "STRING parent.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.url_remap.filename",
- "secure": false,
- "value": "STRING remap.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cluster.cluster_configuration ",
- "secure": false,
- "value": "STRING cluster.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.loadavg",
- "secure": false,
- "value": "25.0"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.availableBandwidthInKbps",
- "secure": false,
- "value": ">1750000"
- },
- {
- "configFile": "rascal.properties",
- "name": "history.count",
- "secure": false,
- "value": "30"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.control.filename",
- "secure": false,
- "value": "STRING cache.config"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingEnabled",
- "secure": false,
- "value": "3"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingIntervalSec",
- "secure": false,
- "value": "86400"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingOffsetHr",
- "secure": false,
- "value": "11"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.RollingSizeMb",
- "secure": false,
- "value": "4"
- },
- {
- "configFile": "logs_xml.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.xml_configFile",
- "secure": false,
- "value": "STRING logs_xml.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.threshold.queryTime",
- "secure": false,
- "value": "1000"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.polling.url",
- "secure": false,
- "value": "http://${hostname}/_astats?application=&inf.name=${interface_name}"
- },
- {
- "configFile": "storage.config",
- "name": "Disk_Volume",
- "secure": false,
- "value": "1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.hosting_filename",
- "secure": false,
- "value": "STRING hosting.config"
- },
- {
- "configFile": "rascal.properties",
- "name": "health.connection.timeout",
- "secure": false,
- "value": "2000"
- },
- {
- "configFile": "12M_facts",
- "name": "location",
- "secure": false,
- "value": "/opt/ort"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_accept_encoding_mismatch",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "chkconfig",
- "name": "trafficserver",
- "secure": false,
- "value": "0:off\t1:off\t2:on\t3:on\t4:on\t5:on\t6:off"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.debug_filter",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.enable_reclaim",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.max_overage",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.show_location",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.allow_empty_doc",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "LOCAL proxy.config.cache.interim.storage",
- "secure": false,
- "value": "STRING NULL"
- },
- {
- "configFile": "plugin.config",
- "name": "regex_revalidate.so",
- "secure": false,
- "value": "--config regex_revalidate.config"
- },
- {
- "configFile": "regex_revalidate.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.stack_dump_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.ttl_mode",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.dns.lookup_timeout",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.serve_stale_for",
- "secure": false,
- "value": "INT 6"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.enable_read_while_writer",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.background_fill_active_timeout",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.background_fill_completed_threshold",
- "secure": false,
- "value": "FLOAT 0.0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.log.extended2_log_enabled",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.affinity",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.autoconfig",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.exec_thread.limit",
- "secure": false,
- "value": "INT 8"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.thread_freelist_size",
- "secure": false,
- "value": "INT 1024"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.mlock_enabled",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogFormat.Format",
- "secure": false,
- "value": "%<cqtq> chi=%<chi> phn=%<phn> php=%<php> shn=%<shn> url=%<cquuc> cqhm=%<cqhm> cqhv=%<cqhv> pssc=%<pssc> ttms=%<ttms> b=%<pscl> sssc=%<sssc> sscl=%<sscl> cfsc=%<cfsc> pfsc=%<pfsc> crc=%<crc> phr=%<phr> pqsn=%<pqsn> uas=\"%<{User-Agent}cqh>\" "
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogFormat.Name",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.Format",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "logs_xml.config",
- "name": "LogObject.Filename",
- "secure": false,
- "value": "custom_ats_2"
- },
- {
- "configFile": "plugin.config",
- "name": "astats_over_http.so",
- "secure": false,
- "value": ""
- },
- {
- "configFile": "astats.config",
- "name": "allow_ip",
- "secure": false,
- "value": "127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
- },
- {
- "configFile": "astats.config",
- "name": "allow_ip6",
- "secure": false,
- "value": "::1/128,fc01:9400:1000:8::/64"
- },
- {
- "configFile": "astats.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "astats.config",
- "name": "path",
- "secure": false,
- "value": "_astats"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.http.compatibility.4-2-0-fixup",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cipher_suite",
- "secure": false,
- "value": "STRING ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2:@STRENGTH"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.honor_cipher_order",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.private_key.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.CA.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.private_key.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.client.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.CA.cert.path",
- "secure": false,
- "value": "STRING etc/trafficserver/ssl"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.SSLv3",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.ssl.server.multicert.filename",
- "secure": false,
- "value": "STRING ssl_multicert.config"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.negative_caching_enabled",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "astats.config",
- "name": "record_types",
- "secure": false,
- "value": "122"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.transaction_active_timeout_in",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.enable_customizations",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.negative_caching_lifetime",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.body_factory.template_sets_dir",
- "secure": false,
- "value": "STRING /etc/trafficserver/body_factory"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.ip_allow.filename",
- "secure": false,
- "value": "STRING ip_allow.config"
- },
- {
- "configFile": "parent.config",
- "name": "weight",
- "secure": false,
- "value": "1.2"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.fail_threshold",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.connect_attempts_timeout",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.per_parent_connect_attempts",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.total_connect_attempts",
- "secure": false,
- "value": "INT 3"
- },
- {
- "configFile": "storage.config",
- "name": "Drive_Letters",
- "secure": false,
- "value": "cache"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.cache.hostdb.sync_frequency",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.storage_size",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.hostdb.size",
- "secure": false,
- "value": "INT 2048"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.guaranteed_max_lifetime",
- "secure": false,
- "value": "INT 2592000"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.cache.ignore_client_cc_max_age",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.net.default_inactivity_timeout",
- "secure": false,
- "value": "INT 180"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.http.parent_proxy.mark_down_hostdb",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.allocator.dontdump_iobuffers",
- "secure": false,
- "value": "INT 0"
- },
- {
- "configFile": "ip_allow.config",
- "name": "location",
- "secure": false,
- "value": "/etc/trafficserver"
- },
- {
- "configFile": "storage.config",
- "name": "Drive_Prefix",
- "secure": false,
- "value": "/var/trafficserver"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.logfile.rolling_size_mb",
- "secure": false,
- "value": "INT 1"
- },
- {
- "configFile": "records.config",
- "name": "CONFIG proxy.config.diags.logfile.rolling_enabled",
- "secure": false,
- "value": "INT 2"
- },
- {
- "configFile": "set_dscp_0.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_10.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_12.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_14.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_18.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_20.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_22.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_26.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_28.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_30.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_34.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_36.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_38.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_8.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_16.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_24.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_32.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_40.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_48.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_56.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- },
- {
- "configFile": "set_dscp_37.config",
- "name": "location",
- "value": "/etc/trafficserver/dscp"
- }
- ]
+ "cdnName": "CDN-in-a-Box",
+ "description": "Mid Cache - Apache Traffic Server",
+ "name": "ATS_MID_TIER_CACHE",
+ "routingDisabled": false,
+ "type": "ATS_PROFILE",
+ "params": [
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.proxy_name",
+ "secure": false,
+ "value": "STRING __HOSTNAME__"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.config_dir",
+ "secure": false,
+ "value": "STRING /etc/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.admin.user_id",
+ "secure": false,
+ "value": "STRING ats"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.server_ports",
+ "secure": false,
+ "value": "STRING 80 80:ipv6"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.insert_response_via_str",
+ "secure": false,
+ "value": "INT 3"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.parent_proxy_routing_enable",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.parent_proxy.retry_time",
+ "secure": false,
+ "value": "INT 60"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.connect_attempts_timeout",
+ "secure": false,
+ "value": "INT 10"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.cache.required_headers",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.enable_http_stats",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.dns.round_robin_nameservers",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.max_space_mb_for_logs",
+ "secure": false,
+ "value": "INT 512"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.max_space_mb_headroom",
+ "secure": false,
+ "value": "INT 50"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.log.logfile_dir",
+ "secure": false,
+ "value": "STRING /var/log/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.reverse_proxy.enabled",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.diags.debug.enabled",
+ "secure": false,
+ "value": "INT 1"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.slow.log.threshold",
+ "secure": false,
+ "value": "INT 10000"
+ },
+ {
+ "configFile": "cache.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "hosting.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "parent.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "records.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "remap.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "volume.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver/"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.url_remap.remap_required",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.loadavg",
+ "secure": false,
+ "value": "25.0"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.availableBandwidthInKbps",
+ "secure": false,
+ "value": ">1750000"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "history.count",
+ "secure": false,
+ "value": "30"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.threshold.queryTime",
+ "secure": false,
+ "value": "1000"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.polling.url",
+ "secure": false,
+ "value": "http://${hostname}/_astats?application=&inf.name=${interface_name}"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Disk_Volume",
+ "secure": false,
+ "value": "1"
+ },
+ {
+ "configFile": "rascal.properties",
+ "name": "health.connection.timeout",
+ "secure": false,
+ "value": "2000"
+ },
+ {
+ "configFile": "chkconfig",
+ "name": "trafficserver",
+ "secure": false,
+ "value": "0:off\t1:off\t2:on\t3:on\t4:on\t5:on\t6:off"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "regex_revalidate.so",
+ "secure": false,
+ "value": "--config regex_revalidate.config"
+ },
+ {
+ "configFile": "regex_revalidate.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.exec_thread.autoconfig",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "plugin.config",
+ "name": "astats_over_http.so",
+ "secure": false,
+ "value": ""
+ },
+ {
+ "configFile": "astats.config",
+ "name": "allow_ip",
+ "secure": false,
+ "value": "127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "allow_ip6",
+ "secure": false,
+ "value": "::1/128,fc01:9400:1000:8::/64"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "path",
+ "secure": false,
+ "value": "_astats"
+ },
+ {
+ "configFile": "astats.config",
+ "name": "record_types",
+ "secure": false,
+ "value": "122"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.http.transaction_active_timeout_in",
+ "secure": false,
+ "value": "INT 0"
+ },
+ {
+ "configFile": "records.config",
+ "name": "CONFIG proxy.config.body_factory.template_sets_dir",
+ "secure": false,
+ "value": "STRING /etc/trafficserver/body_factory"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Drive_Letters",
+ "secure": false,
+ "value": "cache"
+ },
+ {
+ "configFile": "ip_allow.config",
+ "name": "location",
+ "secure": false,
+ "value": "/etc/trafficserver"
+ },
+ {
+ "configFile": "storage.config",
+ "name": "Drive_Prefix",
+ "secure": false,
+ "value": "/var/trafficserver/"
+ },
+ {
+ "configFile": "set_dscp_0.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_10.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_12.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_14.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_18.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_20.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_22.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_26.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_28.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_30.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_34.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_36.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_38.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_8.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_16.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_24.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_32.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_40.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_48.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_56.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ },
+ {
+ "configFile": "set_dscp_37.config",
+ "name": "location",
+ "value": "/etc/trafficserver/dscp"
+ }
+ ]
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
With regards,
Apache Git Services